From b1898047d76ee8235c7ce7a87edd2f56b4f7a569 Mon Sep 17 00:00:00 2001 From: CuCu <32725281+zhangpeng2k@users.noreply.github.com> Date: Sat, 11 Jan 2025 20:35:25 +0000 Subject: [PATCH] feat(route): add blizzard/news-cn route (#18058) * feat(route): add overwatch-cn * chore(deps): bump hono from 4.6.15 to 4.6.16 (#18056) Bumps [hono](https://github.com/honojs/hono) from 4.6.15 to 4.6.16. - [Release notes](https://github.com/honojs/hono/releases) - [Commits](https://github.com/honojs/hono/compare/v4.6.15...v4.6.16) --- updated-dependencies: - dependency-name: hono dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(route): add overwatch-cn * feat(route): remove overwatch-cn to blizzard/news-cn * chore: fix code for ESLint * chore: fix code for ESLint again * chore: remove overwatch-cn files * chore: Throw an exception instead of returning feed data. * chore: fix code for ESLint * Update lib/routes/blizzard/news-cn.ts Co-authored-by: Tony * Update lib/routes/blizzard/news-cn.ts Co-authored-by: Tony * Update lib/routes/blizzard/news-cn.ts --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- lib/routes/blizzard/news-cn.ts | 125 +++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 lib/routes/blizzard/news-cn.ts diff --git a/lib/routes/blizzard/news-cn.ts b/lib/routes/blizzard/news-cn.ts new file mode 100644 index 0000000000..8afa3616fe --- /dev/null +++ b/lib/routes/blizzard/news-cn.ts @@ -0,0 +1,125 @@ +import { Route } from '@/types'; +import { load } from 'cheerio'; +import cache from '@/utils/cache'; +import ofetch from '@/utils/ofetch'; +import { parseDate } from '@/utils/parse-date'; + +export const route: Route = { + path: '/news-cn/:category?', + categories: ['game'], + example: '/blizzard/news-cn/ow', + parameters: { category: '游戏类别, 默认为 ow' }, + features: { + requireConfig: false, + requirePuppeteer: false, + antiCrawler: false, + supportBT: false, + supportPodcast: false, + supportScihub: false, + }, + radar: [ + { + source: ['ow.blizzard.cn', 'wow.blizzard.cn', 'hs.blizzard.cn'], + target: '/news-cn/', + }, + ], + name: '暴雪游戏国服新闻', + maintainers: ['zhangpeng2k'], + description: ` +| 守望先锋 | 炉石传说 | 魔兽世界 | +|----------|----------|---------| +| ow | hs | wow | +`, + handler, +}; + +const categoryNames = { + ow: '守望先锋', + hs: '炉石传说', + wow: '魔兽世界', +}; + +/* 列表解析逻辑 */ +const parsers = { + ow: ($) => + $('.list-data-container .list-item-container').toArray().map((item) => { + item = $(item); + return { + title: item.find('.content-title').text(), + link: item.find('.fill-link').attr('href'), + description: item.find('.content-intro').text(), + pubDate: parseDate(item.find('.content-date').text()), + image: item.find('.item-pic').attr('src'), + }; + }), + hs: ($) => + $('.article-container>a').toArray().map((item) => { + item = $(item); + return { + title: item.find('.title').text(), + link: item.attr('href'), + description: item.find('.desc').text(), + pubDate: parseDate(item.find('.date').attr('data-time')), + image: item.find('.article-img img').attr('src'), + }; + }), + wow: ($) => $('.Pane-list>a').toArray().map((item) => { + item = $(item); + return { + title: item.find('.list-title').text(), + link: item.attr('href'), + description: item.find('.list-desc').text(), + pubDate: parseDate(item.find('.list-time').attr('data-time')), + image: item.find('.img-box img').attr('src'), + }; + }), +}; + +// 详情页解析逻辑 +const detailParsers = { + ow: ($) => $('.deatil-content').first().html(), + hs: ($) => $('.article').first().html(), + wow: ($) => $('.detail').first().html(), +}; + +function getList(category, $) { + return parsers[category] ? parsers[category]($) : []; +} + +async function fetchDetail(item, category) { + return await cache.tryGet(item.link, async () => { + const response = await ofetch(item.link); + const $ = load(response); + + const parseDetail = detailParsers[category]; + item.description = parseDetail($); + return item; + }); +} + +async function handler(ctx) { + const category = ctx.req.param('category') || 'ow'; + if (!categoryNames[category]) { + throw new Error('Invalid category'); + } + + const rootUrl = `https://${category}.blizzard.cn/news`; + + const response = await ofetch(rootUrl); + const $ = load(response); + + const list = getList(category, $); + if (!list.length) { + throw new Error('No news found'); + } + + const items = await Promise.all( + list.map((item) => fetchDetail(item, category)) + ); + + return { + title: `${categoryNames[category]}新闻`, + link: rootUrl, + item: items, + }; +}