From f23e93307f6d7bc6af97da5fef1fd881aeef08d3 Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 22 May 2024 14:24:02 +0800 Subject: [PATCH] fix(route): arknights (#15658) --- lib/routes/arknights/japan.ts | 50 -------- lib/routes/arknights/news.ts | 68 ---------- .../{arknights => hypergryph}/announce.ts | 51 ++++---- lib/routes/hypergryph/japan.ts | 78 ++++++++++++ .../{arknights => hypergryph}/namespace.ts | 5 +- lib/routes/hypergryph/news.ts | 118 ++++++++++++++++++ 6 files changed, 226 insertions(+), 144 deletions(-) delete mode 100644 lib/routes/arknights/japan.ts delete mode 100644 lib/routes/arknights/news.ts rename lib/routes/{arknights => hypergryph}/announce.ts (68%) create mode 100644 lib/routes/hypergryph/japan.ts rename lib/routes/{arknights => hypergryph}/namespace.ts (50%) create mode 100644 lib/routes/hypergryph/news.ts diff --git a/lib/routes/arknights/japan.ts b/lib/routes/arknights/japan.ts deleted file mode 100644 index 3e966b0b4..000000000 --- a/lib/routes/arknights/japan.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Route } from '@/types'; -import got from '@/utils/got'; -import { parseDate } from '@/utils/parse-date'; - -export const route: Route = { - path: '/japan', - categories: ['game'], - example: '/arknights/japan', - parameters: {}, - features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, - }, - radar: [ - { - source: ['ak.arknights.jp/news', 'ak.arknights.jp/'], - }, - ], - name: 'アークナイツ (日服新闻)', - maintainers: ['ofyark'], - handler, - url: 'ak.arknights.jp/news', -}; - -async function handler() { - const response = await got({ - method: 'get', - url: 'https://www.arknights.jp:10014/news?lang=ja&limit=9&page=1', - }); - - const items = response.data.data.items; - const newsList = items.map((item) => ({ - title: item.title, - description: item.content[0].value, - pubDate: parseDate(item.publishedAt), - link: `https://www.arknights.jp/news/${item.id}`, - })); - - return { - title: 'アークナイツ', - link: 'https://www.arknights.jp/news', - description: 'アークナイツ ニュース', - language: 'ja', - item: newsList, - }; -} diff --git a/lib/routes/arknights/news.ts b/lib/routes/arknights/news.ts deleted file mode 100644 index 7fa268b17..000000000 --- a/lib/routes/arknights/news.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Route } from '@/types'; -import cache from '@/utils/cache'; -import got from '@/utils/got'; -import { load } from 'cheerio'; -import { parseDate } from '@/utils/parse-date'; - -export const route: Route = { - path: '/news', - categories: ['game'], - example: '/arknights/news', - parameters: {}, - features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, - }, - radar: [ - { - source: ['ak-conf.hypergryph.com/*'], - }, - ], - name: '游戏公告与新闻', - maintainers: ['Astrian'], - handler, - url: 'ak-conf.hypergryph.com/*', -}; - -async function handler() { - const response = await got({ - method: 'get', - url: 'https://ak.hypergryph.com/news.html', - }); - - let newslist = response.data; - - const $ = load(newslist); - newslist = $('.articleItem > .articleItemLink'); - - newslist = await Promise.all( - newslist - .slice(0, 9) // limit article count to a single page - .map(async (index, item) => { - item = $(item); - const link = `https://ak.hypergryph.com${item.attr('href')}`; - const description = await cache.tryGet(link, async () => { - const result = await got(link); - const $ = load(result.data); - return $('.article-content').html(); - }); - return { - title: `[${item.find('.articleItemCate').first().text()}] ${item.find('.articleItemTitle').first().text()}`, - description, - link, - pubDate: parseDate(item.find('.articleItemDate').first().text()), - }; - }) - .get() - ); - - return { - title: '《明日方舟》游戏公告与新闻', - link: 'https://ak.hypergryph.com/news.html', - item: newslist, - }; -} diff --git a/lib/routes/arknights/announce.ts b/lib/routes/hypergryph/announce.ts similarity index 68% rename from lib/routes/arknights/announce.ts rename to lib/routes/hypergryph/announce.ts index 505601307..fd42f713c 100644 --- a/lib/routes/arknights/announce.ts +++ b/lib/routes/hypergryph/announce.ts @@ -1,23 +1,26 @@ import { Route } from '@/types'; import cache from '@/utils/cache'; -import got from '@/utils/got'; +import ofetch from '@/utils/ofetch'; import { load } from 'cheerio'; import { parseDate } from '@/utils/parse-date'; +import { config } from '@/config'; + +type AnnounceItem = { + announceId: string; + title: string; + isWebUrl: boolean; + webUrl: string; + day: number; + month: number; + group: string; +}; export const route: Route = { - path: '/announce/:platform?/:group?', + path: '/arknights/announce/:platform?/:group?', categories: ['game'], - example: '/arknights/announce', + example: '/hypergryph/arknights/announce', parameters: { platform: '平台,默认为 Android', group: '分组,默认为 ALL' }, - features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, - }, - name: '游戏内公告', + name: '明日方舟 - 游戏内公告', maintainers: ['swwind'], handler, description: `平台 @@ -36,24 +39,24 @@ export const route: Route = { async function handler(ctx) { const { platform = 'Android', group = 'ALL' } = ctx.req.param(); - let { - data: { announceList }, - } = await got({ - method: 'get', - url: `https://ak-conf.hypergryph.com/config/prod/announce_meta/${platform}/announcement.meta.json`, - }); + let announceList = (await cache.tryGet( + `hypergryph:arknights:announce_meta:${platform}`, + async () => { + const { announceList } = await ofetch(`https://ak-conf.hypergryph.com/config/prod/announce_meta/${platform}/announcement.meta.json`); + return announceList; + }, + config.cache.routeExpire, + false + )) as AnnounceItem[]; if (group !== 'ALL') { announceList = announceList.filter((item) => item.group === group); } - announceList = await Promise.all( + const items = await Promise.all( announceList.map((item) => cache.tryGet(item.webUrl, async () => { - const { data } = await got({ - method: 'get', - url: item.webUrl, - }); + const data = await ofetch(item.webUrl); const $ = load(data); let description = @@ -81,6 +84,6 @@ async function handler(ctx) { return { title: `《明日方舟》${group === 'SYSTEM' ? '系统' : group === 'ACTIVITY' ? '活动' : '全部'}公告`, link: 'https://ak.hypergryph.com/', - item: announceList, + item: items, }; } diff --git a/lib/routes/hypergryph/japan.ts b/lib/routes/hypergryph/japan.ts new file mode 100644 index 000000000..db96cae33 --- /dev/null +++ b/lib/routes/hypergryph/japan.ts @@ -0,0 +1,78 @@ +import { Route } from '@/types'; +import ofetch from '@/utils/ofetch'; +import { parseDate } from '@/utils/parse-date'; +import type { Context } from 'hono'; + +type ContentItem = { + key: string; + value: string; + bannerUrl: string; + bannerUrlMobile: string; + digest: string; + imgCount: number; + imgInfo: any[]; + ext_0: string; + ext_1: string; + ext_2: string; + ext_3: string; + ext_4: string; + ext_5: string; + ext_6: string; + ext_7: string; + ext_8: string; + ext_9: string; +}; + +type NewsDetail = { + id: string; + title: string; + category: number; + content: ContentItem[]; + lang: string; + highlight: number; + publishedAt: string; + ext1: null | string; + ext2: null | string; +}; + +export const route: Route = { + path: '/arknights/japan', + categories: ['game'], + example: '/hypergryph/arknights/japan', + radar: [ + { + source: ['ak.arknights.jp/news', 'ak.arknights.jp/'], + }, + ], + name: 'アークナイツ (日服新闻)', + maintainers: ['ofyark'], + handler, + url: 'ak.arknights.jp/news', +}; + +async function handler(ctx: Context) { + const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 9; + + const response = await ofetch('https://www.arknights.jp:10014/news', { + query: { + lang: 'ja', + limit, + page: 1, + }, + }); + + const newsList = (response.data.items as NewsDetail[]).map((item) => ({ + title: item.title, + description: item.content[0].value, + pubDate: parseDate(item.publishedAt), + link: `https://www.arknights.jp/news/${item.id}`, + })); + + return { + title: 'アークナイツ', + link: 'https://www.arknights.jp/news', + description: 'アークナイツ ニュース', + language: 'ja', + item: newsList, + }; +} diff --git a/lib/routes/arknights/namespace.ts b/lib/routes/hypergryph/namespace.ts similarity index 50% rename from lib/routes/arknights/namespace.ts rename to lib/routes/hypergryph/namespace.ts index 1750ce795..3f65c6cd4 100644 --- a/lib/routes/arknights/namespace.ts +++ b/lib/routes/hypergryph/namespace.ts @@ -1,6 +1,7 @@ import type { Namespace } from '@/types'; export const namespace: Namespace = { - name: '明日方舟', - url: 'ak.arknights.jp', + name: '鹰角网络', + url: 'www.hypergryph.com', + categories: ['game'], }; diff --git a/lib/routes/hypergryph/news.ts b/lib/routes/hypergryph/news.ts new file mode 100644 index 000000000..a85ec285a --- /dev/null +++ b/lib/routes/hypergryph/news.ts @@ -0,0 +1,118 @@ +import { Route } from '@/types'; +import cache from '@/utils/cache'; +import ofetch from '@/utils/ofetch'; +import * as cheerio from 'cheerio'; +import { parseDate } from '@/utils/parse-date'; +import { config } from '@/config'; + +type NewsItem = { + cid: string; + tab: string; + sticky: boolean; + title: string; + author: string; + displayTime: number; + cover: string; + extraCover: string; + brief: string; +}; + +type InitialData = { + LATEST: { + list: NewsItem[]; + total: number; + end: boolean; + map: Record; + }; + ANNOUNCEMENT: { + list: NewsItem[]; + total: number; + end: boolean; + map: Record; + }; + ACTIVITY: { + list: NewsItem[]; + total: number; + end: boolean; + map: Record; + }; + NEWS: { + list: NewsItem[]; + total: number; + end: boolean; + map: Record; + }; +}; + +const parseList = (list: NewsItem[]) => + list.map((item) => ({ + title: item.title, + author: item.author, + description: item.brief.trim().replaceAll('\n', '
'), + link: `https://ak.hypergryph.com/news/${item.cid}`, + pubDate: parseDate(item.displayTime, 'X'), + })); + +export const route: Route = { + path: '/arknights/news/:group?', + categories: ['game'], + example: '/hypergryph/arknights/news', + parameters: { group: '分组,默认为 `ALL`' }, + radar: [ + { + source: ['ak-conf.hypergryph.com/news'], + }, + ], + name: '明日方舟 - 游戏公告与新闻', + maintainers: ['Astrian'], + handler, + url: 'ak-conf.hypergryph.com/news', + description: ` + | 全部 | 最新 | 公告 | 活动 | 新闻 | + | ---- | ------ | ------------ | -------- | ---- | + | ALL | LATEST | ANNOUNCEMENT | ACTIVITY | NEWS |`, +}; + +async function handler(ctx) { + const { group = 'ALL' } = ctx.req.param(); + + const initialData: Promise = await cache.tryGet( + 'hypergryph:arknights:news', + async () => { + const response = await ofetch('https://ak.hypergryph.com/news'); + const $ = cheerio.load(response); + const renderData = JSON.parse( + $('script:contains("initialData")') + .first() + .text() + .match(/self\.__next_f\.push\((.+)\)/)?.[1] ?? '' + ); + return JSON.parse(renderData[1].slice(2))[3].initialData as InitialData; + }, + config.cache.routeExpire, + false + ); + + const list = group === 'ALL' ? Object.values(initialData).flatMap(({ list }) => parseList(list)) : parseList(initialData[group].list); + + const items = await Promise.all( + list.map((item) => + cache.tryGet(item.link, async () => { + const response = await ofetch(item.link); + const $ = cheerio.load(response); + + const description = $('div > div > div > div > div > div > div:nth-child(4)'); + item.description = description.length ? description.html() : item.description; + + return item; + }) + ) + ); + + return { + title: '《明日方舟》游戏公告与新闻', + link: 'https://ak.hypergryph.com/news', + item: items, + language: 'zh-cn', + }; +}