diff --git a/docs/multimedia.md b/docs/multimedia.md index be83e7b12..7fa6780de 100644 --- a/docs/multimedia.md +++ b/docs/multimedia.md @@ -404,6 +404,20 @@ BT 之家的域名会变更,本路由以 为默认 +## DoMP4 影视 + +### 最近更新 + + + +### 剧集订阅 + + + +:::tip +由于大部分详情页是 `/html/xxx.html`,还有部分是 `/detail/123.html`,所以此处做了兼容,id 取 `xxx` 或者 `123` 都可以。 +::: + ## E-Hentai ### 分类 diff --git a/lib/v2/domp4/detail.js b/lib/v2/domp4/detail.js new file mode 100644 index 000000000..130160cc7 --- /dev/null +++ b/lib/v2/domp4/detail.js @@ -0,0 +1,67 @@ +const cheerio = require('cheerio'); +const got = require('@/utils/got'); +const { decodeCipherText, composeMagnetUrl } = require('./utils'); + +const baseUrl = 'https://www.domp4.cc'; + +function getItemList($, detailUrl) { + const encoded = $('.article script[type]') + .text() + .match(/return p}\('(.*)',(\d+),(\d+),'(.*)'.split\(/); + const data = JSON.parse( + decodeCipherText(encoded[1], encoded[2], encoded[3], encoded[4].split('|'), 0, {}) + .match(/var down_urls=\\'(.*)\\'/)[1] + .replace(/\\\\"/g, '"') + .replace(/\\\\\\/g, '') + ); + const { downurls } = data.Data[0]; + return downurls.map((item) => { + const [title, magnet] = item.split('$'); + return { + enclosure_url: composeMagnetUrl(magnet), + enclosure_length: '', + enclosure_type: 'application/x-bittorrent', + title, + link: detailUrl, + }; + }); +} + +function getMetaInfo($) { + const title = $('.article-header .text p').first().find('span').text(); + const cover = $('.article-header .pic img').attr('src'); + const description = $('.article-related.info p').text(); + return { + title, + cover, + description, + }; +} + +module.exports = async (ctx) => { + const { id } = ctx.params; + let pureId = id; + let detailType = 'html'; + // compatible for .html suffix in radar + if (id.endsWith('.html')) { + pureId = id.replace('.html', ''); + } + // compatible for /detail/123.html && /html/xxx.html + if (/^\d+$/.test(pureId)) { + detailType = 'detail'; + } + const detailUrl = `${baseUrl}/${detailType}/${pureId}.html`; + + const res = await got(detailUrl); + const $ = cheerio.load(res.data); + const list = getItemList($, detailUrl); + const meta = getMetaInfo($); + + ctx.state.data = { + link: detailUrl, + title: meta.title || 'domp4电影 - 详情', + image: meta.cover, + description: meta.description, + item: list, + }; +}; diff --git a/lib/v2/domp4/latest.js b/lib/v2/domp4/latest.js new file mode 100644 index 000000000..ffd0d8e5d --- /dev/null +++ b/lib/v2/domp4/latest.js @@ -0,0 +1,31 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); + +const baseUrl = 'https://www.domp4.cc'; +const latestUrl = 'https://www.domp4.cc/custom/update.html'; + +function getItemList($, type) { + const list = $(`#${type} .list-group-item`) + .toArray() + .map((item) => { + item = $(item); + return { + title: item.find('a').text(), + link: `${baseUrl}${item.find('a').attr('href')}`, + }; + }); + return list; +} + +module.exports = async (ctx) => { + const { type = 'vod' } = ctx.params; + const res = await got.get(latestUrl); + const $ = cheerio.load(res.data); + const list = getItemList($, type); + + ctx.state.data = { + link: latestUrl, + title: 'domp4电影', + item: list, + }; +}; diff --git a/lib/v2/domp4/maintainer.js b/lib/v2/domp4/maintainer.js new file mode 100644 index 000000000..c770ad8b8 --- /dev/null +++ b/lib/v2/domp4/maintainer.js @@ -0,0 +1,4 @@ +module.exports = { + '/detail/:id': ['savokiss'], + '/latest/:type?': ['savokiss'], +}; diff --git a/lib/v2/domp4/radar.js b/lib/v2/domp4/radar.js new file mode 100644 index 000000000..4fc38e9fe --- /dev/null +++ b/lib/v2/domp4/radar.js @@ -0,0 +1,25 @@ +module.exports = { + 'domp4.cc': { + _name: 'domp4电影', + '.': [ + { + title: '最近更新', + docs: 'https://docs.rsshub.app/multimedia.html#domp4-ying-shi', + source: ['/', '/custom/update.html'], + target: '/domp4/latest/:type?', + }, + { + title: '剧集订阅', + docs: 'https://docs.rsshub.app/multimedia.html#domp4-ying-shi', + source: '/html/:id', + target: '/domp4/detail/:id', + }, + { + title: '剧集订阅', + docs: 'https://docs.rsshub.app/multimedia.html#domp4-ying-shi', + source: '/detail/:id', + target: '/domp4/detail/:id', + }, + ], + }, +}; diff --git a/lib/v2/domp4/router.js b/lib/v2/domp4/router.js new file mode 100644 index 000000000..9528fd762 --- /dev/null +++ b/lib/v2/domp4/router.js @@ -0,0 +1,4 @@ +module.exports = function (router) { + router.get('/detail/:id', require('./detail')); + router.get('/latest/:type?', require('./latest')); +}; diff --git a/lib/v2/domp4/utils.js b/lib/v2/domp4/utils.js new file mode 100644 index 000000000..f4f694e70 --- /dev/null +++ b/lib/v2/domp4/utils.js @@ -0,0 +1,72 @@ +/** + * trackers from https://www.domp4.cc/Style/2020/js/base.js?v=2 + */ +const magnetTrackers = [ + 'https://tracker.iriseden.fr:443/announce', + 'https://tr.highstar.shop:443/announce', + 'https://tr.fuckbitcoin.xyz:443/announce', + 'https://tr.doogh.club:443/announce', + 'https://tr.burnabyhighstar.com:443/announce', + 'https://t.btcland.xyz:443/announce', + 'http://vps02.net.orel.ru:80/announce', + 'https://tracker.kuroy.me:443/announce', + 'http://tr.cili001.com:8070/announce', + 'http://t.overflow.biz:6969/announce', + 'http://t.nyaatracker.com:80/announce', + 'http://open.acgnxtracker.com:80/announce', + 'http://nyaa.tracker.wf:7777/announce', + 'http://home.yxgz.vip:6969/announce', + 'http://buny.uk:6969/announce', + 'https://tracker.tamersunion.org:443/announce', + 'https://tracker.nanoha.org:443/announce', + 'https://tracker.loligirl.cn:443/announce', + 'udp://bubu.mapfactor.com:6969/announce', + 'http://share.camoe.cn:8080/announce', + 'udp://movies.zsw.ca:6969/announce', + 'udp://ipv4.tracker.harry.lu:80/announce', + 'udp://tracker.sylphix.com:6969/announce', + 'http://95.216.22.207:9001/announce', +]; + +/** + * compose magnet url with trackers + */ +function composeMagnetUrl(magnet, trackers = magnetTrackers) { + return `${magnet}&tr=${trackers.join('&tr=')}`; +} + +/** + * method for generating magnet url + * from the detail page source + */ +function decodeCipherText(p, a, c, k, e, d) { + e = function (c) { + return (c < a ? '' : e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36)); + }; + if (!''.replace(/^/, String)) { + while (c--) { + d[e(c)] = k[c] || e(c); + } + k = [ + function (e) { + return d[e]; + }, + ]; + e = function () { + return '\\w+'; + }; + c = 1; + } + while (c--) { + if (k[c]) { + p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]); + } + } + return p; +} + +module.exports = { + magnetTrackers, + composeMagnetUrl, + decodeCipherText, +};