From 35576d5b2165921154e12637e4f1a9c322954244 Mon Sep 17 00:00:00 2001
From: lyqluis <39592732+lyqluis@users.noreply.github.com>
Date: Thu, 21 Mar 2024 22:35:31 +0800
Subject: [PATCH 1/4] fix(route): douban/book/latest, add route optional
params, replace cheerio with mobile api (#14897)
---
lib/routes/douban/book/latest.ts | 66 ++++++++++++++++++++++++++
lib/routes/douban/other/latest-book.ts | 38 ---------------
2 files changed, 66 insertions(+), 38 deletions(-)
create mode 100644 lib/routes/douban/book/latest.ts
delete mode 100644 lib/routes/douban/other/latest-book.ts
diff --git a/lib/routes/douban/book/latest.ts b/lib/routes/douban/book/latest.ts
new file mode 100644
index 00000000000000..778791afbc704f
--- /dev/null
+++ b/lib/routes/douban/book/latest.ts
@@ -0,0 +1,66 @@
+import { Route } from '@/types';
+import got from '@/utils/got';
+
+const linkUrl = 'https://book.douban.com/latest';
+const baseUrl = 'https://m.douban.com/rexxar/api/v2/subject_collection';
+const params = 'items?start=0&count=10&mode=collection&for_mobile=1';
+
+export const route: Route = {
+ path: '/book/latest/:type?',
+ categories: ['social-media'],
+ example: '/douban/book/latest/fiction',
+ parameters: { type: '专题分类,可选,默认为 `all`' },
+ features: {
+ requireConfig: false,
+ requirePuppeteer: false,
+ antiCrawler: false,
+ supportBT: false,
+ supportPodcast: false,
+ supportScihub: false,
+ },
+ name: '新书速递',
+ maintainers: ['fengkx', 'lyqluis'],
+ description: `
+ | 文学 | 小说 | 历史文化 | 社会纪实 | 科学新知 | 艺术设计 | 商业经管 | 绘本漫画 |
+ | ------------ | ------- | -------- | --------- | -------- | -------- | -------- | -------- |
+ | prose_poetry | fiction | history | biography | science | art | business | comics |`,
+ handler,
+};
+
+const SUBCATS = {
+ all: '全部',
+ prose_poetry: '文学',
+ fiction: '小说',
+ history: '历史文化',
+ biography: '社会纪实',
+ science: '科学新知',
+ art: '艺术设计',
+ business: '商业经管',
+ comics: '绘本漫画',
+};
+
+async function handler(ctx) {
+ const type = ctx.req.param('type') ?? 'all';
+ const subUrl = `new_book_${type}`;
+ const url = `${baseUrl}/${subUrl}/${params}`;
+
+ const res = await got.get(url);
+ const items = res.data.items;
+
+ return {
+ title: `豆瓣新书速递${type === 'all' ? '' : '-' + SUBCATS[type]}`,
+ link: `${linkUrl}${type === 'all' ? '' : '?subcat=' + SUBCATS[type]}`,
+ item: items.map(({ title, url, card_subtitle, cards, pic, rating, null_rating_reason }) => {
+ const rate = rating.value ? `${rating.value}分` : null_rating_reason;
+ const img = ``;
+ const info = card_subtitle;
+ const description = `${img}
${title}
${info}
${cards[0]?.content ?? ''}
${rate}`;
+
+ return {
+ title,
+ description,
+ link: url,
+ };
+ }),
+ };
+}
diff --git a/lib/routes/douban/other/latest-book.ts b/lib/routes/douban/other/latest-book.ts
deleted file mode 100644
index 70b16692f4b22c..00000000000000
--- a/lib/routes/douban/other/latest-book.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import { Route } from '@/types';
-import got from '@/utils/got';
-import { load } from 'cheerio';
-
-const url = 'https://book.douban.com/latest';
-
-export const route: Route = {
- path: '/book/latest',
- categories: ['social-media'],
- example: '/douban/book/latest',
- parameters: {},
- features: {
- requireConfig: false,
- requirePuppeteer: false,
- antiCrawler: false,
- supportBT: false,
- supportPodcast: false,
- supportScihub: false,
- },
- name: '新书速递',
- maintainers: ['fengkx'],
- handler,
-};
-
-async function handler() {
- const res = await got.get(url);
- const $ = load(res.data);
- const list = $('#content').find('li').get();
- return {
- title: '豆瓣新书速递',
- link: url,
- item: list.map((item, index) => ({
- title: `${index < 20 ? '[虚构类]' : '[非虚构类]'}${$(item).find('h2').text().trim()}`,
- link: $(item).find('a').first().attr('href'),
- description: $(item).html(),
- })),
- };
-}
From 7d1448bd00f6806b418afe1ca6fbbbb12d2b207a Mon Sep 17 00:00:00 2001
From: Mg Pig
Date: Thu, 21 Mar 2024 22:58:54 +0800
Subject: [PATCH 2/4] =?UTF-8?q?feat(route):=20Add=20yxxc(=E6=B8=B8?=
=?UTF-8?q?=E6=88=8F=E6=98=9F=E8=BE=B0)=20(#14870)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat(route): Add yxxc(游戏星辰)
* feat(route): Move route yxxc to 2023game
---
lib/routes/2023game/index.ts | 69 ++++++++++++++++++++++++++++++++
lib/routes/2023game/namespace.ts | 6 +++
2 files changed, 75 insertions(+)
create mode 100644 lib/routes/2023game/index.ts
create mode 100644 lib/routes/2023game/namespace.ts
diff --git a/lib/routes/2023game/index.ts b/lib/routes/2023game/index.ts
new file mode 100644
index 00000000000000..03ae687a08ca97
--- /dev/null
+++ b/lib/routes/2023game/index.ts
@@ -0,0 +1,69 @@
+import { Data, DataItem, Route } from '@/types';
+import got from '@/utils/got';
+import { parseDate } from '@/utils/parse-date';
+import { load } from 'cheerio';
+import { Context } from 'hono';
+
+export const route: Route = {
+ path: '/:category?/:tab?',
+ categories: ['game'],
+ example: '/2023game/sgame/topicList',
+ parameters: {
+ category: '分类,见下表',
+ tab: '标签, 所有:all;最新:topicList;热门:jhcpb',
+ },
+ features: {
+ requireConfig: false,
+ requirePuppeteer: false,
+ antiCrawler: false,
+ supportBT: false,
+ supportPodcast: false,
+ supportScihub: false,
+ },
+ name: '游戏星辰',
+ maintainers: ['xzzpig'],
+ handler,
+ url: 'www.2023game.com/',
+ description: `分类
+
+ | PS4游戏 | switch游戏 | 3DS游戏 | PSV游戏 | Xbox360 | PS3游戏 | 世嘉MD/SS | PSP游戏 | PC周边 | 怀旧掌机 | 怀旧主机 | PS4教程 | PS4金手指 | switch金手指 | switch教程 | switch补丁 | switch主题 | switch存档 |
+ | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
+ | ps4 | sgame | 3ds | psv | jiaocheng | ps3yx | zhuji.md | zhangji.psp | pcgame | zhangji | zhuji | ps4.psjc | ps41.ps4pkg | nsaita.cundang | nsaita.pojie | nsaita.buding | nsaita.zhutie | nsaita.zhuti |`,
+};
+
+async function handler(ctx?: Context): Promise {
+ const category = (ctx!.req.param('category') ?? 'sgame').replaceAll('.', '/');
+ const tab = ctx?.req.param('tab') ?? 'all';
+
+ const currentUrl = `https://www.2023game.com/${category}/`;
+
+ const response = await got(currentUrl);
+ const $ = load(response.data as any);
+
+ let selector = `.news`;
+ if (tab !== 'all') {
+ selector = `#${tab} > ${selector}`;
+ }
+
+ const items: DataItem[] = $(selector)
+ .toArray()
+ .map((item) => {
+ const $item = $(item);
+ const href = $item.find('a').attr('href');
+ return {
+ title: $item.text().trim(),
+ guid: `2023game:${href}`,
+ link: href!,
+ pubDate: parseDate($item.find('.time_box').text().trim()),
+ description: $item.html() ?? '',
+ };
+ });
+
+ return {
+ title: $('title').text(),
+ link: currentUrl,
+ allowEmpty: true,
+ image: 'https://www.2023game.com/resources/img/logo.png',
+ item: items,
+ };
+}
diff --git a/lib/routes/2023game/namespace.ts b/lib/routes/2023game/namespace.ts
new file mode 100644
index 00000000000000..0405df7cc98a7b
--- /dev/null
+++ b/lib/routes/2023game/namespace.ts
@@ -0,0 +1,6 @@
+import type { Namespace } from '@/types';
+
+export const namespace: Namespace = {
+ name: '游戏星辰',
+ url: 'www.2023game.com',
+};
From fe798966156bc57ec9fcd89d5a3685c8c3008002 Mon Sep 17 00:00:00 2001
From: frankcwl <45101942+frankcwl@users.noreply.github.com>
Date: Thu, 21 Mar 2024 23:32:31 +0800
Subject: [PATCH 3/4] fix(route): fix priconne-redive and remove deprecated
route (#14893)
* fix(route): fix priconne-redive and remove deprecated route
* remove entries in router.js
---
lib/router.js | 5 ---
lib/routes-deprecated/pcr/news-cn.js | 28 ------------
lib/routes-deprecated/pcr/news-tw.js | 67 ----------------------------
lib/routes/priconne-redive/news.ts | 25 +++++++----
4 files changed, 17 insertions(+), 108 deletions(-)
delete mode 100644 lib/routes-deprecated/pcr/news-cn.js
delete mode 100644 lib/routes-deprecated/pcr/news-tw.js
diff --git a/lib/router.js b/lib/router.js
index ccc3a1bf365839..0661dad1386599 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -992,11 +992,6 @@ router.get('/ddrk/index', lazyloadRouteHandler('./routes/ddrk/list'));
router.get('/avgle/videos/:order?/:time?/:top?', lazyloadRouteHandler('./routes/avgle/videos.js'));
router.get('/avgle/search/:keyword/:order?/:time?/:top?', lazyloadRouteHandler('./routes/avgle/videos.js'));
-// 公主链接公告
-// router.get('/pcr/news', lazyloadRouteHandler('./routes/pcr/news'));
-router.get('/pcr/news-tw', lazyloadRouteHandler('./routes/pcr/news-tw'));
-router.get('/pcr/news-cn', lazyloadRouteHandler('./routes/pcr/news-cn'));
-
// project-zero issues
router.get('/project-zero-issues', lazyloadRouteHandler('./routes/project-zero-issues/index'));
diff --git a/lib/routes-deprecated/pcr/news-cn.js b/lib/routes-deprecated/pcr/news-cn.js
deleted file mode 100644
index 55986a9d1775cc..00000000000000
--- a/lib/routes-deprecated/pcr/news-cn.js
+++ /dev/null
@@ -1,28 +0,0 @@
-const got = require('@/utils/got');
-
-module.exports = async (ctx) => {
- const response = await got({
- method: 'get',
- url: `https://api.biligame.com/news/list?gameExtensionId=267&positionId=2&typeId=&pageNum=1&pageSize=5`,
- });
- const data = response.data;
- ctx.state.data = {
- title: '公主链接国服-最新公告',
- link: 'https://game.bilibili.com/pcr/news.html',
- item: data
- ? await Promise.all(
- data.data.map(async (item) => ({
- title: item.title,
- description: await ctx.cache.tryGet(`pcrcn_${item.id}`, async () => {
- const resp = await got({ method: 'get', url: `https://api.biligame.com/news/${item.id}` });
- return resp.data.data.content;
- }),
- link: `https://game.bilibili.com/pcr/news.html#detail=${item.id}`,
- pubDate: item.ctime ?? item.createTime,
- }))
- )
- : {
- title: '获取失败!',
- },
- };
-};
diff --git a/lib/routes-deprecated/pcr/news-tw.js b/lib/routes-deprecated/pcr/news-tw.js
deleted file mode 100644
index 327cbfbc2b5236..00000000000000
--- a/lib/routes-deprecated/pcr/news-tw.js
+++ /dev/null
@@ -1,67 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-
-const base = 'http://www.princessconnect.so-net.tw';
-
-module.exports = async (ctx) => {
- const url = `${base}/news`;
-
- const list_response = await got.get(url);
- const $ = cheerio.load(list_response.data);
-
- const list = $('.news_con dl dd').get();
-
- const parseContent = (htmlString) => {
- const $ = cheerio.load(htmlString);
-
- $('.news_con h2 > span').remove();
- const time = $('.news_con h2').text().trim();
- $('.news_con section h4').first().remove();
- const content = $('.news_con section');
-
- return {
- description: content.html(),
- pubDate: new Date(time),
- };
- };
-
- const out = await Promise.all(
- list.map(async (item) => {
- const $ = cheerio.load(item);
-
- const title = $('a');
- const path = title.attr('href');
-
- const link = base + path;
-
- const cache = await ctx.cache.get(link);
- if (cache) {
- return JSON.parse(cache);
- }
-
- const rssitem = {
- title: title.text().trim(),
- link,
- };
-
- try {
- const response = await got.get(link);
- const result = parseContent(response.data);
-
- rssitem.author = '《超異域公主連結☆Re:Dive》營運團隊';
- rssitem.description = result.description;
- rssitem.pubDate = result.pubDate;
- } catch {
- return '';
- }
- ctx.cache.set(link, JSON.stringify(rssitem));
- return rssitem;
- })
- );
-
- ctx.state.data = {
- title: '公主连结 - 台服公告',
- link: url,
- item: out.filter((item) => item !== ''),
- };
-};
diff --git a/lib/routes/priconne-redive/news.ts b/lib/routes/priconne-redive/news.ts
index 5c6fe734907a35..278885b8231459 100644
--- a/lib/routes/priconne-redive/news.ts
+++ b/lib/routes/priconne-redive/news.ts
@@ -5,10 +5,10 @@ import cache from '@/utils/cache';
import { load } from 'cheerio';
export const route: Route = {
- path: '/news/:location?',
+ path: '/news/:server?',
categories: ['game'],
example: '/priconne-redive/news',
- parameters: { location: '区域,默认日服' },
+ parameters: { server: '服务器,默认日服' },
features: {
requireConfig: false,
requirePuppeteer: false,
@@ -20,23 +20,32 @@ export const route: Route = {
radar: [
{
source: ['priconne-redive.jp/news'],
+ target: '/news/jp',
+ },
+ {
+ source: ['princessconnect.so-net.tw/news'],
+ target: '/news/zh-tw',
+ },
+ {
+ source: ['game.bilibili.com/pcr/news.html'],
+ target: '/news/zh-cn',
},
],
name: '最新公告',
maintainers: ['SayaSS', 'frankcwl'],
handler,
url: 'priconne-redive.jp/news',
- description: `location
+ description: `服务器
- | 国服 | 台服 | 日服 |
- | ----- | ----- | ---- |
- | zh-cn | zh-tw | jp |`,
+ | 国服 | 台服 | 日服 |
+ | ----- | ----- | ---- |
+ | zh-cn | zh-tw | jp |`,
};
async function handler(ctx) {
- const { location = 'jp' } = ctx.req.param();
+ const { server = 'jp' } = ctx.req.param();
- switch (location) {
+ switch (server) {
case 'jp': {
const parseContent = (htmlString) => {
const $ = load(htmlString);
From 3351e51f3cf7085a7c8ca79136e7ac0677b847f2 Mon Sep 17 00:00:00 2001
From: karasu
Date: Thu, 21 Mar 2024 23:45:34 +0800
Subject: [PATCH 4/4] =?UTF-8?q?fix(route):=20=E5=8D=97=E6=96=B9=E5=91=A8?=
=?UTF-8?q?=E6=9C=AB=20(#14886)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* fix(route): 南方周末
* update image
* update radar rules
* remove the deprecated content
* Update lib/routes/infzm/index.ts
Co-authored-by: Tony
* Update lib/routes/infzm/index.ts
Co-authored-by: Tony
* use cache.tryGet
---------
---
lib/router.js | 3 --
lib/routes-deprecated/infzm/news.js | 62 ------------------------
lib/routes/infzm/index.ts | 75 +++++++++++++++++++++++++++++
lib/routes/infzm/types.ts | 17 +++++++
4 files changed, 92 insertions(+), 65 deletions(-)
delete mode 100644 lib/routes-deprecated/infzm/news.js
create mode 100644 lib/routes/infzm/index.ts
create mode 100644 lib/routes/infzm/types.ts
diff --git a/lib/router.js b/lib/router.js
index 0661dad1386599..0c89d215ed33c4 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -34,9 +34,6 @@ router.get('/disqus/posts/:forum', lazyloadRouteHandler('./routes/disqus/posts')
// 极客时间
router.get('/geektime/column/:cid', lazyloadRouteHandler('./routes/geektime/column'));
-// 南方周末
-router.get('/infzm/:id', lazyloadRouteHandler('./routes/infzm/news'));
-
// Dribbble
// router.get('/dribbble/popular/:timeframe?', lazyloadRouteHandler('./routes/dribbble/popular'));
// router.get('/dribbble/user/:name', lazyloadRouteHandler('./routes/dribbble/user'));
diff --git a/lib/routes-deprecated/infzm/news.js b/lib/routes-deprecated/infzm/news.js
deleted file mode 100644
index 44662081afa7f9..00000000000000
--- a/lib/routes-deprecated/infzm/news.js
+++ /dev/null
@@ -1,62 +0,0 @@
-const config = require('@/config').value;
-const got = require('@/utils/got');
-const timezone = require('@/utils/timezone');
-const cheerio = require('cheerio');
-
-const baseUrl = 'http://www.infzm.com/contents';
-
-module.exports = async (ctx) => {
- const { id } = ctx.params;
- const link = `${baseUrl}?term_id=${id}`;
- const response = await got({
- method: 'get',
- url: `http://www.infzm.com/contents?term_id=${id}&page=1&format=json`,
- headers: {
- Referer: link,
- },
- });
- const data = response.data.data;
- const resultItem = await Promise.all(
- data.contents.map(async ({ id, subject, author, publish_time }) => {
- // the timezone is GMT+8
- const date = timezone(publish_time, +8);
- const link = `http://www.infzm.com/contents/${id}`;
- let description = '';
-
- const key = `infzm: ${link}`;
- const value = await ctx.cache.get(key);
-
- if (value) {
- description = value;
- } else {
- const cookie = config.infzm.cookie;
- const response = await got({
- method: 'get',
- url: `http://www.infzm.com/content/${id}`,
- headers: {
- Referer: link,
- Cookie: cookie || `passport_session=${Math.floor(Math.random() * 100)};`,
- },
- });
- const $ = cheerio.load(response.data);
- description = $('div.nfzm-content__content').html();
-
- ctx.cache.set(key, description);
- }
-
- return {
- title: subject,
- description,
- pubDate: date.toUTCString(),
- link,
- author,
- };
- })
- );
-
- ctx.state.data = {
- title: `南方周末-${data.current_term.title}`,
- link,
- item: resultItem,
- };
-};
diff --git a/lib/routes/infzm/index.ts b/lib/routes/infzm/index.ts
new file mode 100644
index 00000000000000..2b98371ec62fd1
--- /dev/null
+++ b/lib/routes/infzm/index.ts
@@ -0,0 +1,75 @@
+import type { Data, DataItem, Route } from '@/types';
+import type { ContentsResponse } from './types';
+import { config } from '@/config';
+import got from '@/utils/got';
+import { load } from 'cheerio';
+import timezone from '@/utils/timezone';
+import cache from '@/utils/cache';
+
+export const route: Route = {
+ path: '/:id',
+ parameters: { id: '南方周末频道 id, 可在该频道的 URL 中找到(即 https://www.infzm.com/contents?term_id=:id)' },
+ categories: ['traditional-media'],
+ example: '/infzm/1',
+ radar: [
+ {
+ source: ['infzm.com/contents'],
+ target: (_, url) => (url ? `/infzm/${url.match(/contents\?term_id=(\d*)/)?.[1]}` : ''),
+ },
+ ],
+ name: '频道',
+ maintainers: ['KarasuShin', 'ranpox', 'xyqfer'],
+ handler,
+ description: `下面给出部分参考:
+
+ | 推荐 | 新闻 | 观点 | 文化 | 人物 | 影像 | 专题 | 生活 | 视频 |
+ | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
+ | 1 | 2 | 3 | 4 | 7 | 8 | 6 | 5 | 131 |`,
+};
+
+const baseUrl = 'https://www.infzm.com/contents';
+
+async function handler(ctx): Promise {
+ const id = ctx.req.param('id');
+ const link = `${baseUrl}?term_id=${id}`;
+ const { data } = await got({
+ method: 'get',
+ url: `${baseUrl}?term_id=${id}&page=1&format=json`,
+ headers: {
+ Referer: link,
+ },
+ });
+
+ const resultItem = await Promise.all(
+ data.data.contents.map(({ id, subject, author, publish_time }) => {
+ const link = `${baseUrl}/${id}`;
+
+ return cache.tryGet(link, async () => {
+ const cookie = config.infzm.cookie;
+ const response = await got.get({
+ method: 'get',
+ url: link,
+ headers: {
+ Referer: link,
+ Cookie: cookie || `passport_session=${Math.floor(Math.random() * 100)};`,
+ },
+ });
+ const $ = load(response.data);
+ return {
+ title: subject,
+ description: $('div.nfzm-content__content').html() ?? '',
+ pubDate: timezone(publish_time, +8).toUTCString(),
+ link,
+ author,
+ };
+ });
+ })
+ );
+
+ return {
+ title: `南方周末-${data.data.current_term.title}`,
+ link,
+ image: 'https://www.infzm.com/favicon.ico',
+ item: resultItem as DataItem[],
+ };
+}
diff --git a/lib/routes/infzm/types.ts b/lib/routes/infzm/types.ts
new file mode 100644
index 00000000000000..1f6ba32da0bf51
--- /dev/null
+++ b/lib/routes/infzm/types.ts
@@ -0,0 +1,17 @@
+export interface ContentsResponse {
+ code: number;
+ msg: string;
+ data: {
+ contents: {
+ id: number;
+ subject: string;
+ author: string;
+ publish_time: string;
+ }[];
+ current_term: {
+ id: number;
+ title: string;
+ type: string;
+ };
+ };
+}