From 4789b53ef38e431e14d58cfad4ff16a84454cea3 Mon Sep 17 00:00:00 2001 From: miemieYaho Date: Sat, 22 Jun 2024 23:27:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(routes):=20add=20bt0(=E4=B8=8D=E5=A4=AA?= =?UTF-8?q?=E7=81=B5)=E7=9A=84=E6=9C=80=E6=96=B0=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E5=88=97=E8=A1=A8=20(#15968)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * bt0 * item.description --- lib/routes/bt0/mv.ts | 62 +++------------------------------- lib/routes/bt0/tlist.ts | 74 +++++++++++++++++++++++++++++++++++++++++ lib/routes/bt0/util.ts | 48 ++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 57 deletions(-) create mode 100644 lib/routes/bt0/tlist.ts create mode 100644 lib/routes/bt0/util.ts diff --git a/lib/routes/bt0/mv.ts b/lib/routes/bt0/mv.ts index 5c6e84939..0633761d7 100644 --- a/lib/routes/bt0/mv.ts +++ b/lib/routes/bt0/mv.ts @@ -1,15 +1,13 @@ import { Route } from '@/types'; import { load } from 'cheerio'; -import got from '@/utils/got'; import InvalidParameterError from '@/errors/types/invalid-parameter'; -import { CookieJar } from 'tough-cookie'; -const cookieJar = new CookieJar(); +import { doGot, genSize } from './util'; export const route: Route = { path: '/mv/:number/:domain?', categories: ['multimedia'], - example: '/mv/35575567/2', - parameters: { domain: '1-9,默认 2', number: '影视详情id' }, + example: '/bt0/mv/35575567/2', + parameters: { number: '影视详情id, 网页路径为`/mv/{id}.html`其中的id部分, 一般为8位纯数字', domain: '数字1-9, 比如1表示请求域名为 1bt0.com, 默认为 2' }, features: { requireConfig: false, requirePuppeteer: false, @@ -26,11 +24,6 @@ export const route: Route = { name: '影视资源下载列表', maintainers: ['miemieYaho'], handler, - description: `:::tip - (1-9)bt0.com 都能访问, 就拿 2bt0.com 为默认了 - 影视详情id 是\`https://www.2bt0.com/mv/{id}.html\`其中的 id 的值 - 可选参数\`domain\` 是 \`https://www.{domain}bt0.com\` 其中的 domain 的值,可以是 1-9,访问的都是同一个东西 - :::`, }; async function handler(ctx) { @@ -47,7 +40,7 @@ async function handler(ctx) { const host = `https://www.${domain}bt0.com`; const _link = `${host}/mv/${number}.html`; - const $ = await doGot(0, host, _link); + const $ = load(await doGot(0, host, _link)); const name = $('span.info-title.lh32').text(); const items = $('div.container .container .col-md-10.tex_l') .toArray() @@ -64,57 +57,12 @@ async function handler(ctx) { pubDate: item.find('.tag-sm.tag-download.text-center').eq(1).text(), enclosure_type: 'application/x-bittorrent', enclosure_url: item.find('.col-md-3 a').first().attr('href'), - enclosure_length: convertToBytes(len), + enclosure_length: genSize(len), }; }); - // browser.close(); return { title: name, link: _link, item: items, }; } - -async function doGot(num, host, link) { - if (num > 4) { - throw new Error('The number of attempts has exceeded 5 times'); - } - const response = await got.get(link, { - cookieJar, - }); - const $ = load(response.data); - const script = $('script').text(); - const regex = /document\.cookie\s*=\s*"([^"]*)"/; - const match = script.match(regex); - if (script && match) { - cookieJar.setCookieSync(match[1], host); - return doGot(++num, host, link); - } - return $; -} - -function convertToBytes(sizeStr) { - // 正则表达式,用于匹配数字和单位 GB 或 MB - const regex = /^(\d+(\.\d+)?)\s*(gb|mb)$/i; - const match = sizeStr.match(regex); - - if (!match) { - return 0; - } - - const value = Number.parseFloat(match[1]); - const unit = match[3].toUpperCase(); - - let bytes; - switch (unit) { - case 'GB': - bytes = Math.floor(value * 1024 * 1024 * 1024); - break; - case 'MB': - bytes = Math.floor(value * 1024 * 1024); - break; - default: - bytes = 0; - } - return bytes; -} diff --git a/lib/routes/bt0/tlist.ts b/lib/routes/bt0/tlist.ts new file mode 100644 index 000000000..aca921da2 --- /dev/null +++ b/lib/routes/bt0/tlist.ts @@ -0,0 +1,74 @@ +import { Route } from '@/types'; +import { load } from 'cheerio'; +import InvalidParameterError from '@/errors/types/invalid-parameter'; +import { doGot, genSize } from './util'; + +const categoryDict = { + 1: '电影', + 2: '电视剧', + 3: '周热门', + 4: '月热门', + 5: '年度热门', +}; + +export const route: Route = { + path: '/tlist/:sc/:domain?', + categories: ['multimedia'], + example: '/bt0/tlist/1', + parameters: { sc: '分类(1-5), 1:电影, 2:电视剧, 3:周热门, 4:月热门, 5:年度热门', domain: '数字1-9, 比如1表示请求域名为 1bt0.com, 默认为 2' }, + features: { + requireConfig: false, + requirePuppeteer: false, + antiCrawler: false, + supportBT: true, + supportPodcast: false, + supportScihub: false, + }, + radar: [ + { + source: ['2bt0.com/tlist/'], + }, + ], + name: '最新资源列表', + maintainers: ['miemieYaho'], + handler, +}; + +async function handler(ctx) { + const domain = ctx.req.param('domain') ?? '2'; + const sc = ctx.req.param('sc'); + if (!/^[1-9]$/.test(domain)) { + throw new InvalidParameterError('Invalid domain'); + } + if (!/^[1-5]$/.test(sc)) { + throw new InvalidParameterError('Invalid sc'); + } + + const host = `https://www.${domain}bt0.com`; + const _link = `${host}/tlist.php?sc=${sc}`; + + const $ = load(await doGot(0, host, _link)); + const items = $('div.left.bf100.hig90.ov_hid.po_rel.trall3.dou3') + .toArray() + .map((item) => { + item = $(item); + const ah = item.find('a'); + const _title = ah.eq(1).text(); + const ds = item.find('.huise2.fs12 .left'); + return { + title: _title, + guid: _title, + description: `${ds.eq(0).text()} ${ds.eq(1).text()}
${ds.eq(2).text()}
${ds.eq(3).text()}
${ds.eq(4).text()}`, + link: host + ah.eq(1).attr('href'), + pubDate: item.find('.bghuise9').first().text(), + enclosure_type: 'application/x-bittorrent', + enclosure_url: ah.eq(2).attr('href'), + enclosure_length: genSize(item.find('.marl10.bgzise').first().text()), + }; + }); + return { + title: `不太灵-最新资源列表-${categoryDict[sc]}`, + link: _link, + item: items, + }; +} diff --git a/lib/routes/bt0/util.ts b/lib/routes/bt0/util.ts new file mode 100644 index 000000000..1b8c58e64 --- /dev/null +++ b/lib/routes/bt0/util.ts @@ -0,0 +1,48 @@ +import { CookieJar } from 'tough-cookie'; +import got from '@/utils/got'; +const cookieJar = new CookieJar(); + +async function doGot(num, host, link) { + if (num > 4) { + throw new Error('The number of attempts has exceeded 5 times'); + } + const response = await got.get(link, { + cookieJar, + }); + const data = response.data; + const regex = /document\.cookie\s*=\s*"([^"]*)"/; + const match = data.match(regex); + if (match) { + cookieJar.setCookieSync(match[1], host); + return doGot(++num, host, link); + } + return data; +} + +const genSize = (sizeStr) => { + // 正则表达式,用于匹配数字和单位 GB 或 MB + const regex = /^(\d+(\.\d+)?)\s*(gb|mb)$/i; + const match = sizeStr.match(regex); + + if (!match) { + return 0; + } + + const value = Number.parseFloat(match[1]); + const unit = match[3].toUpperCase(); + + let bytes; + switch (unit) { + case 'GB': + bytes = Math.floor(value * 1024 * 1024 * 1024); + break; + case 'MB': + bytes = Math.floor(value * 1024 * 1024); + break; + default: + bytes = 0; + } + return bytes; +}; + +export { doGot, genSize };