From d0bcf59e0d54efaf953f308a82e5ec6f80cdacc0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 09:05:16 +0000 Subject: [PATCH 1/3] 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> --- package.json | 2 +- pnpm-lock.yaml | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index f038380880f69d..65da6c86eb034b 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "fanfou-sdk": "5.0.0", "form-data": "4.0.1", "googleapis": "144.0.0", - "hono": "4.6.15", + "hono": "4.6.16", "html-to-text": "9.0.5", "http-cookie-agent": "6.0.8", "https-proxy-agent": "7.0.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 73cccc627c7bd2..1429ebea982a66 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,10 +23,10 @@ importers: version: 4.2.0 '@hono/node-server': specifier: 1.13.7 - version: 1.13.7(hono@4.6.15) + version: 1.13.7(hono@4.6.16) '@hono/zod-openapi': specifier: 0.18.3 - version: 0.18.3(hono@4.6.15)(zod@3.24.1) + version: 0.18.3(hono@4.6.16)(zod@3.24.1) '@notionhq/client': specifier: 2.2.15 version: 2.2.15 @@ -59,7 +59,7 @@ importers: version: 0.0.23 '@scalar/hono-api-reference': specifier: 0.5.165 - version: 0.5.165(hono@4.6.15) + version: 0.5.165(hono@4.6.16) '@sentry/node': specifier: 7.119.1 version: 7.119.1 @@ -118,8 +118,8 @@ importers: specifier: 144.0.0 version: 144.0.0 hono: - specifier: 4.6.15 - version: 4.6.15 + specifier: 4.6.16 + version: 4.6.16 html-to-text: specifier: 9.0.5 version: 9.0.5 @@ -3418,8 +3418,8 @@ packages: hmacsha1@1.0.0: resolution: {integrity: sha512-4FP6J0oI8jqb6gLLl9tSwVdosWJ/AKSGJ+HwYf6Ixe4MUcEkst4uWzpVQrNOCin0fzTRQbXV8ePheU8WiiDYBw==} - hono@4.6.15: - resolution: {integrity: sha512-OiQwvAOAaI2JrABBH69z5rsctHDzFzIKJge0nYXgtzGJ0KftwLWcBXm1upJC23/omNRtnqM0gjRMbtXshPdqhQ==} + hono@4.6.16: + resolution: {integrity: sha512-iE6xOPwDYlfnZFwk6BfIMMIH4WZm3pPhz6rc1uJM/OPew0pjG5K6p8WTLaMBY1/szF/T0TaEjprMpwn16BA0NQ==} engines: {node: '>=16.9.0'} hookable@5.5.3: @@ -6706,20 +6706,20 @@ snapshots: dependencies: levn: 0.4.1 - '@hono/node-server@1.13.7(hono@4.6.15)': + '@hono/node-server@1.13.7(hono@4.6.16)': dependencies: - hono: 4.6.15 + hono: 4.6.16 - '@hono/zod-openapi@0.18.3(hono@4.6.15)(zod@3.24.1)': + '@hono/zod-openapi@0.18.3(hono@4.6.16)(zod@3.24.1)': dependencies: '@asteasolutions/zod-to-openapi': 7.2.0(zod@3.24.1) - '@hono/zod-validator': 0.4.1(hono@4.6.15)(zod@3.24.1) - hono: 4.6.15 + '@hono/zod-validator': 0.4.1(hono@4.6.16)(zod@3.24.1) + hono: 4.6.16 zod: 3.24.1 - '@hono/zod-validator@0.4.1(hono@4.6.15)(zod@3.24.1)': + '@hono/zod-validator@0.4.1(hono@4.6.16)(zod@3.24.1)': dependencies: - hono: 4.6.15 + hono: 4.6.16 zod: 3.24.1 '@humanfs/core@0.19.1': {} @@ -7143,10 +7143,10 @@ snapshots: '@rss3/api-core': 0.0.23 '@rss3/api-utils': 0.0.23 - '@scalar/hono-api-reference@0.5.165(hono@4.6.15)': + '@scalar/hono-api-reference@0.5.165(hono@4.6.16)': dependencies: '@scalar/types': 0.0.25 - hono: 4.6.15 + hono: 4.6.16 '@scalar/openapi-types@0.1.5': {} @@ -9054,7 +9054,7 @@ snapshots: hmacsha1@1.0.0: {} - hono@4.6.15: {} + hono@4.6.16: {} hookable@5.5.3: {} From 6034780548086cda72d79294a93d6fe489fb0a0a Mon Sep 17 00:00:00 2001 From: zhangpeng2k <1028158677@qq.com> Date: Mon, 6 Jan 2025 20:41:46 +0800 Subject: [PATCH 2/3] feat(route): add overwatch-cn --- lib/routes/overwatch-cn/namespace.ts | 7 +++ lib/routes/overwatch-cn/news.ts | 71 ++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 lib/routes/overwatch-cn/namespace.ts create mode 100644 lib/routes/overwatch-cn/news.ts diff --git a/lib/routes/overwatch-cn/namespace.ts b/lib/routes/overwatch-cn/namespace.ts new file mode 100644 index 00000000000000..e5398efb040bac --- /dev/null +++ b/lib/routes/overwatch-cn/namespace.ts @@ -0,0 +1,7 @@ +import type { Namespace } from '@/types'; + +export const namespace: Namespace = { + name: '守望先锋国服官方网站新闻', + url: 'ow.blizzard.cn/news', + lang: 'zh-CN', +}; diff --git a/lib/routes/overwatch-cn/news.ts b/lib/routes/overwatch-cn/news.ts new file mode 100644 index 00000000000000..c168ce7a221cb2 --- /dev/null +++ b/lib/routes/overwatch-cn/news.ts @@ -0,0 +1,71 @@ +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', + categories: ['game'], + example: '/overwatch-cn/news', + features: { + requireConfig: false, + requirePuppeteer: false, + antiCrawler: false, + supportBT: false, + supportPodcast: false, + supportScihub: false, + }, + radar: [ + { + source: ['ow.blizzard.cn', 'ow.blizzard.cn/news'], + target: '/news', + }, + ], + name: 'News', + maintainers: ['zhangpeng2k'], + handler, +}; + +async function handler() { + const rootUrl = `https://ow.blizzard.cn/news`; + + const response = await ofetch(rootUrl); + const $ = load(response); + + const list = $('.list-data-container .list-item-container') + .toArray() + .map((item) => { + item = $(item); + const title = item.find('.content-title').text(); + const link = item.find('.fill-link').attr('href'); + const description = item.find('.content-intro').text(); + const pubDate = parseDate(item.find('.content-date').text()); + const image = item.find('.item-pic').attr('src'); + + return { + title, + link, + description, + image, + pubDate, + }; + }); + + const items = await Promise.all( + list.map((item) => + cache.tryGet(item.link, async () => { + const response = await ofetch(item.link); + const $ = load(response); + item.description = $('.detail-content-box').first().html(); + return item; + }) + ) + ); + + return { + title: `守望先锋官方网站新闻`, + link: `https://ow.blizzard.cn/news`, + item: items, + }; +}; From 899973dfa239c85cf16183eef90c7c917b17d476 Mon Sep 17 00:00:00 2001 From: zhangpeng2k <1028158677@qq.com> Date: Wed, 8 Jan 2025 16:41:10 +0800 Subject: [PATCH 3/3] feat(route): remove overwatch-cn to blizzard/news-cn --- lib/routes/blizzard/news-cn.ts | 146 +++++++++++++++++++++++++++ lib/routes/overwatch-cn/namespace.ts | 7 -- lib/routes/overwatch-cn/news.ts | 71 ------------- 3 files changed, 146 insertions(+), 78 deletions(-) create mode 100644 lib/routes/blizzard/news-cn.ts delete mode 100644 lib/routes/overwatch-cn/namespace.ts delete mode 100644 lib/routes/overwatch-cn/news.ts diff --git a/lib/routes/blizzard/news-cn.ts b/lib/routes/blizzard/news-cn.ts new file mode 100644 index 00000000000000..f2f4b02494b86f --- /dev/null +++ b/lib/routes/blizzard/news-cn.ts @@ -0,0 +1,146 @@ +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: ($) => $('.detail-content-box').first().html(), + hs: ($) => $('.article').first().html(), + wow: ($) => $('.detail').first().html(), +}; + +function getList(category, $) { + return parsers[category] ? parsers[category]($) : []; +} + +async function fetchDetail(item, category) { + return cache.tryGet(item.link, async () => { + const response = await ofetch(item.link); + const $ = load(response); + + const parseDetail = detailParsers[category]; + if (parseDetail) { + item.description = parseDetail($); + } else { + item.description = '无法解析详情内容'; + } + + return item; + }); +} + +async function handler(ctx) { + const category = ctx.req.param('category') || 'ow'; + if (!categoryNames[category]) { + return { + title: '错误的类别', + description: '您请求的类别不存在。', + item: [], + }; + } + + const rootUrl = `https://${category}.blizzard.cn/news`; + + try { + const response = await ofetch(rootUrl); + const $ = load(response); + + const list = getList(category, $); + if (!list.length) { + return { + title: `${categoryNames[category]}新闻`, + description: '未找到相关新闻。', + item: [], + }; + } + + const items = await Promise.all( + list.map((item) => fetchDetail(item, category)) + ); + + return { + title: `${categoryNames[category]}新闻`, + link: rootUrl, + item: items, + }; + } catch (error) { + return { + title: `${categoryNames[category]}新闻`, + description: '抓取新闻时出错。', + item: [], + }; + } +} diff --git a/lib/routes/overwatch-cn/namespace.ts b/lib/routes/overwatch-cn/namespace.ts deleted file mode 100644 index e5398efb040bac..00000000000000 --- a/lib/routes/overwatch-cn/namespace.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Namespace } from '@/types'; - -export const namespace: Namespace = { - name: '守望先锋国服官方网站新闻', - url: 'ow.blizzard.cn/news', - lang: 'zh-CN', -}; diff --git a/lib/routes/overwatch-cn/news.ts b/lib/routes/overwatch-cn/news.ts deleted file mode 100644 index c168ce7a221cb2..00000000000000 --- a/lib/routes/overwatch-cn/news.ts +++ /dev/null @@ -1,71 +0,0 @@ -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', - categories: ['game'], - example: '/overwatch-cn/news', - features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, - }, - radar: [ - { - source: ['ow.blizzard.cn', 'ow.blizzard.cn/news'], - target: '/news', - }, - ], - name: 'News', - maintainers: ['zhangpeng2k'], - handler, -}; - -async function handler() { - const rootUrl = `https://ow.blizzard.cn/news`; - - const response = await ofetch(rootUrl); - const $ = load(response); - - const list = $('.list-data-container .list-item-container') - .toArray() - .map((item) => { - item = $(item); - const title = item.find('.content-title').text(); - const link = item.find('.fill-link').attr('href'); - const description = item.find('.content-intro').text(); - const pubDate = parseDate(item.find('.content-date').text()); - const image = item.find('.item-pic').attr('src'); - - return { - title, - link, - description, - image, - pubDate, - }; - }); - - const items = await Promise.all( - list.map((item) => - cache.tryGet(item.link, async () => { - const response = await ofetch(item.link); - const $ = load(response); - item.description = $('.detail-content-box').first().html(); - return item; - }) - ) - ); - - return { - title: `守望先锋官方网站新闻`, - link: `https://ow.blizzard.cn/news`, - item: items, - }; -};