feat(route): add 电影天堂 (#18200)
This commit is contained in:
parent
f193dfbddc
commit
a8bf6e6f37
|
|
@ -1,75 +1,318 @@
|
|||
import type { Route } from '@/types';
|
||||
import { type Data, type DataItem, type Route, ViewType } from '@/types';
|
||||
|
||||
import cache from '@/utils/cache';
|
||||
import got from '@/utils/got';
|
||||
import { load } from 'cheerio';
|
||||
import iconv from 'iconv-lite';
|
||||
import ofetch from '@/utils/ofetch';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import timezone from '@/utils/timezone';
|
||||
|
||||
import { type CheerioAPI, type Cheerio, type Element, load } from 'cheerio';
|
||||
import { type Context } from 'hono';
|
||||
|
||||
const domain: string = 'www.dydytt.net';
|
||||
const baseUrl: string = `https://${domain}`;
|
||||
|
||||
export const handler = async (ctx: Context): Promise<Data> => {
|
||||
const { category = 'gndy/dyzz' } = ctx.req.param();
|
||||
const limit: number = Number.parseInt(ctx.req.query('limit') ?? '25', 10);
|
||||
|
||||
const targetUrl: string = new URL(`html/${category.replace(/^html\//, '')}`, baseUrl).href;
|
||||
|
||||
const response = await ofetch(targetUrl, {
|
||||
responseType: 'arrayBuffer',
|
||||
});
|
||||
const $: CheerioAPI = load(iconv.decode(Buffer.from(response), 'gb2312'));
|
||||
const language = $('html').attr('lang') ?? 'zh-CN';
|
||||
|
||||
let items: DataItem[] = [];
|
||||
|
||||
items = $('div.co_content8 ul table')
|
||||
.slice(0, limit)
|
||||
.toArray()
|
||||
.map((el): Element => {
|
||||
const $el: Cheerio<Element> = $(el);
|
||||
|
||||
const $aEl: Cheerio<Element> = $el.find('a.ulink');
|
||||
|
||||
const title: string = $aEl.text();
|
||||
const description: string = $el.find('td').last().text();
|
||||
const pubDateStr: string | undefined = $el.find('font').last().text().split(/:/).pop();
|
||||
const linkUrl: string | undefined = $aEl.attr('href');
|
||||
const upDatedStr: string | undefined = pubDateStr;
|
||||
|
||||
const processedItem: DataItem = {
|
||||
title,
|
||||
description,
|
||||
pubDate: pubDateStr ? timezone(parseDate(pubDateStr), +8) : undefined,
|
||||
link: linkUrl ? new URL(linkUrl, baseUrl).href : undefined,
|
||||
doi: $el.find('meta[name="citation_doi"]').attr('content'),
|
||||
content: {
|
||||
html: description,
|
||||
text: description,
|
||||
},
|
||||
updated: upDatedStr ? timezone(parseDate(upDatedStr), +8) : undefined,
|
||||
language,
|
||||
};
|
||||
|
||||
return processedItem;
|
||||
});
|
||||
|
||||
items = (
|
||||
await Promise.all(
|
||||
items.map((item) => {
|
||||
if (!item.link) {
|
||||
return item;
|
||||
}
|
||||
|
||||
return cache.tryGet(item.link, async (): Promise<DataItem> => {
|
||||
const detailResponse = await ofetch(item.link, {
|
||||
responseType: 'arrayBuffer',
|
||||
});
|
||||
const $$: CheerioAPI = load(iconv.decode(Buffer.from(detailResponse), 'gb2312'));
|
||||
|
||||
const title: string = $$('div.title_all h1 font').text();
|
||||
|
||||
const $descriptionEl: Cheerio<Element> = $$('div#Zoom span').first();
|
||||
const childEls = $descriptionEl.contents().toArray();
|
||||
const centerIdx = childEls.findIndex((node) => node.type === 'tag' && node.name === 'center');
|
||||
const description: string = (centerIdx === -1 ? childEls : childEls.slice(0, centerIdx)).map((node) => $.html(node)).join('');
|
||||
|
||||
const pubDateStr: string | undefined = item.pubDate ? undefined : $descriptionEl.prev().text().split(/:/).pop();
|
||||
const image: string | undefined = $descriptionEl.find('img').first().attr('src');
|
||||
const upDatedStr: string | undefined = pubDateStr;
|
||||
|
||||
let processedItem: DataItem = {
|
||||
title,
|
||||
description,
|
||||
pubDate: pubDateStr ? parseDate(pubDateStr) : item.pubDate,
|
||||
content: {
|
||||
html: description,
|
||||
text: description,
|
||||
},
|
||||
image,
|
||||
banner: image,
|
||||
updated: upDatedStr ? parseDate(upDatedStr) : item.updated,
|
||||
language,
|
||||
};
|
||||
|
||||
const $enclosureEl: Cheerio<Element> = $descriptionEl.find('a[href^="magnet:"]').last();
|
||||
const enclosureUrl: string | undefined = $enclosureEl.attr('href');
|
||||
|
||||
if (enclosureUrl) {
|
||||
const enclosureType: string = 'application/x-bittorrent';
|
||||
const enclosureTitle: string = $enclosureEl.text();
|
||||
|
||||
processedItem = {
|
||||
...processedItem,
|
||||
enclosure_url: enclosureUrl,
|
||||
enclosure_type: enclosureType,
|
||||
enclosure_title: enclosureTitle || title,
|
||||
enclosure_length: undefined,
|
||||
itunes_duration: undefined,
|
||||
itunes_item_image: image,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...item,
|
||||
...processedItem,
|
||||
};
|
||||
});
|
||||
})
|
||||
)
|
||||
).filter((_): _ is DataItem => true);
|
||||
|
||||
const title: string = $('title').text();
|
||||
|
||||
return {
|
||||
title,
|
||||
description: $('META[name=description]').attr('content'),
|
||||
link: targetUrl,
|
||||
item: items,
|
||||
allowEmpty: true,
|
||||
image: new URL('images/logo.gif', baseUrl).href,
|
||||
author: title.split(/_/).pop(),
|
||||
language,
|
||||
id: targetUrl,
|
||||
};
|
||||
};
|
||||
|
||||
export const route: Route = {
|
||||
path: '/',
|
||||
path: '/:category{.+}?',
|
||||
name: '分类',
|
||||
url: domain,
|
||||
maintainers: ['junfengP', 'nczitzk'],
|
||||
handler,
|
||||
example: '/dytt/gndy/dyzz',
|
||||
parameters: {
|
||||
category: {
|
||||
description: '分类,默认为 `gndy/dyzz`,即最新影片,可在对应分类页 URL 中找到',
|
||||
options: [
|
||||
{
|
||||
label: '最新影片',
|
||||
value: 'gndy/dyzz',
|
||||
},
|
||||
{
|
||||
label: '经典影片',
|
||||
value: 'gndy',
|
||||
},
|
||||
{
|
||||
label: '国内电影',
|
||||
value: 'gndy/china',
|
||||
},
|
||||
{
|
||||
label: '欧美电影',
|
||||
value: 'gndy/oumei',
|
||||
},
|
||||
{
|
||||
label: '其它电影',
|
||||
value: 'gndy/rihan',
|
||||
},
|
||||
{
|
||||
label: '华语电视',
|
||||
value: 'tv/hytv',
|
||||
},
|
||||
{
|
||||
label: '欧美电视',
|
||||
value: 'tv/oumeitv',
|
||||
},
|
||||
{
|
||||
label: '最新综艺',
|
||||
value: 'zongyi2013',
|
||||
},
|
||||
{
|
||||
label: '旧版综艺',
|
||||
value: '2009zongyi',
|
||||
},
|
||||
{
|
||||
label: '动漫资源',
|
||||
value: 'dongman',
|
||||
},
|
||||
{
|
||||
label: '旧版游戏',
|
||||
value: 'game',
|
||||
},
|
||||
{
|
||||
label: '游戏下载',
|
||||
value: 'newgame',
|
||||
},
|
||||
{
|
||||
label: '日韩剧集专区',
|
||||
value: 'tv/rihantv',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
description: `:::tip
|
||||
若订阅 [最新影片](${baseUrl}/html/gndy/dyzz),网址为 \`${baseUrl}/html/gndy/dyzz\`,请截取 \`${baseUrl}/html/\` 到末尾的部分 \`gndy/dyzz\` 作为 \`category\` 参数填入,此时目标路由为 [\`/dytt/gndy/dyzz\`](https://rsshub.app/dytt/gndy/dyzz)。
|
||||
|
||||
:::
|
||||
|
||||
<details>
|
||||
<summary>更多分类</summary>
|
||||
|
||||
| 分类 | ID |
|
||||
| ----------------------------------------------------- | ------------------------------------------------ |
|
||||
| [最新影片](${baseUrl}/html/gndy/dyzz/index.html) | [gndy/dyzz](https://rsshub.app/dytt/gndy/dyzz) |
|
||||
| [经典影片](${baseUrl}/html/gndy/index.html) | [gndy](https://rsshub.app/dytt/gndy) |
|
||||
| [国内电影](${baseUrl}/html/gndy/china/index.html) | [gndy/china](https://rsshub.app/dytt/gndy/china) |
|
||||
| [欧美电影](${baseUrl}/html/gndy/oumei/index.html) | [gndy/oumei](https://rsshub.app/dytt/gndy/oumei) |
|
||||
| [其它电影](${baseUrl}/html/gndy/rihan/index.html) | [gndy/rihan](https://rsshub.app/dytt/gndy/rihan) |
|
||||
| [华语电视](${baseUrl}/html/tv/hytv/index.html) | [tv/hytv](https://rsshub.app/dytt/tv/hytv) |
|
||||
| [欧美电视](${baseUrl}/html/tv/oumeitv/index.html) | [tv/oumeitv](https://rsshub.app/dytt/tv/oumeitv) |
|
||||
| [最新综艺](${baseUrl}/html/zongyi2013/index.html) | [zongyi2013](https://rsshub.app/dytt/zongyi2013) |
|
||||
| [旧版综艺](${baseUrl}/html/2009zongyi/index.html) | [2009zongyi](https://rsshub.app/dytt/2009zongyi) |
|
||||
| [动漫资源](${baseUrl}/html/dongman/index.html) | [dongman](https://rsshub.app/dytt/dongman) |
|
||||
| [旧版游戏](${baseUrl}/html/game/index.html) | [game](https://rsshub.app/dytt/game) |
|
||||
| [游戏下载](${baseUrl}/html/newgame/index.html) | [newgame](https://rsshub.app/dytt/newgame) |
|
||||
| [日韩剧集专区](${baseUrl}/html/tv/rihantv/index.html) | [tv/rihantv](https://rsshub.app/dytt/tv/rihantv) |
|
||||
|
||||
</details>
|
||||
`,
|
||||
categories: ['multimedia'],
|
||||
example: '/dytt',
|
||||
parameters: {},
|
||||
features: {
|
||||
requireConfig: false,
|
||||
requirePuppeteer: false,
|
||||
antiCrawler: false,
|
||||
supportRadar: true,
|
||||
supportBT: true,
|
||||
supportPodcast: false,
|
||||
supportScihub: false,
|
||||
},
|
||||
radar: [
|
||||
{
|
||||
source: ['ygdy8.net/index.html'],
|
||||
source: ['${domain}/index.htm', `${domain}/html/:category`],
|
||||
target: (params) => {
|
||||
const category: string = params.category;
|
||||
|
||||
return `/dytt/html${category ? `/${category}` : ''}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '最新影片',
|
||||
source: [`${baseUrl}/html/gndy/dyzz/index.html`],
|
||||
target: '/gndy/dyzz',
|
||||
},
|
||||
{
|
||||
title: '经典影片',
|
||||
source: [`${baseUrl}/html/gndy/index.html`],
|
||||
target: '/gndy',
|
||||
},
|
||||
{
|
||||
title: '国内电影',
|
||||
source: [`${baseUrl}/html/gndy/china/index.html`],
|
||||
target: '/gndy/china',
|
||||
},
|
||||
{
|
||||
title: '欧美电影',
|
||||
source: [`${baseUrl}/html/gndy/oumei/index.html`],
|
||||
target: '/gndy/oumei',
|
||||
},
|
||||
{
|
||||
title: '其它电影',
|
||||
source: [`${baseUrl}/html/gndy/rihan/index.html`],
|
||||
target: '/gndy/rihan',
|
||||
},
|
||||
{
|
||||
title: '华语电视',
|
||||
source: [`${baseUrl}/html/tv/hytv/index.html`],
|
||||
target: '/tv/hytv',
|
||||
},
|
||||
{
|
||||
title: '欧美电视',
|
||||
source: [`${baseUrl}/html/tv/oumeitv/index.html`],
|
||||
target: '/tv/oumeitv',
|
||||
},
|
||||
{
|
||||
title: '最新综艺',
|
||||
source: [`${baseUrl}/html/zongyi2013/index.html`],
|
||||
target: '/zongyi2013',
|
||||
},
|
||||
{
|
||||
title: '旧版综艺',
|
||||
source: [`${baseUrl}/html/2009zongyi/index.html`],
|
||||
target: '/2009zongyi',
|
||||
},
|
||||
{
|
||||
title: '动漫资源',
|
||||
source: [`${baseUrl}/html/dongman/index.html`],
|
||||
target: '/dongman',
|
||||
},
|
||||
{
|
||||
title: '旧版游戏',
|
||||
source: [`${baseUrl}/html/game/index.html`],
|
||||
target: '/game',
|
||||
},
|
||||
{
|
||||
title: '游戏下载',
|
||||
source: [`${baseUrl}/html/newgame/index.html`],
|
||||
target: '/newgame',
|
||||
},
|
||||
{
|
||||
title: '日韩剧集专区',
|
||||
source: [`${baseUrl}/html/tv/rihantv/index.html`],
|
||||
target: '/tv/rihantv',
|
||||
},
|
||||
],
|
||||
name: '最新电影',
|
||||
maintainers: ['junfengP'],
|
||||
handler,
|
||||
view: ViewType.Articles,
|
||||
};
|
||||
|
||||
async function loadContent(link: string) {
|
||||
const response = await got.get(link, {
|
||||
responseType: 'buffer',
|
||||
});
|
||||
const data = iconv.decode(response.data, 'gb2312');
|
||||
const $ = load(data);
|
||||
return $('div#Zoom').html() || '';
|
||||
}
|
||||
|
||||
async function handler() {
|
||||
const baseURL = 'https://www.ygdy8.net/html/gndy/dyzz/index.html';
|
||||
const response = await got.get(baseURL, {
|
||||
responseType: 'buffer',
|
||||
});
|
||||
const data = iconv.decode(response.data, 'gb2312');
|
||||
|
||||
const $ = load(data);
|
||||
const list = $('.co_content8 table tr b a').toArray();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map(async (item) => {
|
||||
const link = $(item);
|
||||
const itemUrl = 'https://www.ygdy8.net' + link.attr('href');
|
||||
|
||||
return await cache.tryGet(itemUrl, async () => {
|
||||
const description = await loadContent(itemUrl);
|
||||
return {
|
||||
enclosure_url: description.match(/magnet:.*?(?=">)/) || '',
|
||||
enclosure_type: 'application/x-bittorrent',
|
||||
title: link.text(),
|
||||
description,
|
||||
pubDate: parseDate($(item).find('font').text()),
|
||||
link: itemUrl,
|
||||
};
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
return {
|
||||
title: '电影天堂/阳光电影',
|
||||
link: baseURL,
|
||||
description: '电影天堂RSS',
|
||||
item: items,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@ import type { Namespace } from '@/types';
|
|||
|
||||
export const namespace: Namespace = {
|
||||
name: '电影天堂',
|
||||
url: 'www.ygdy8.net',
|
||||
url: 'www.dydytt.net',
|
||||
lang: 'zh-CN',
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue