fix(route): 4games full text (#14466)

* fix: 4games full text

* docs: add docs
This commit is contained in:
Tony 2024-02-15 23:03:29 +08:00 committed by GitHub
parent 5058906b85
commit 9d325ebbb1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 212 additions and 70 deletions

View File

@ -900,9 +900,9 @@ router.get('/zhishifenzi/depth', lazyloadRouteHandler('./routes/zhishifenzi/dept
router.get('/zhishifenzi/innovation/:type?', lazyloadRouteHandler('./routes/zhishifenzi/innovation'));
// 4Gamers
router.get('/4gamers/category/:category', lazyloadRouteHandler('./routes/4gamers/category'));
router.get('/4gamers/tag/:tag', lazyloadRouteHandler('./routes/4gamers/tag'));
router.get('/4gamers/topic/:topic', lazyloadRouteHandler('./routes/4gamers/topic'));
// router.get('/4gamers/category/:category', lazyloadRouteHandler('./routes/4gamers/category'));
// router.get('/4gamers/tag/:tag', lazyloadRouteHandler('./routes/4gamers/tag'));
// router.get('/4gamers/topic/:topic', lazyloadRouteHandler('./routes/4gamers/topic'));
// 大麦网
// router.get('/damai/activity/:city/:category/:subcategory/:keyword?', lazyloadRouteHandler('./routes/damai/activity'));

View File

@ -1,20 +0,0 @@
const got = require('@/utils/got');
module.exports = async (ctx) => {
const category = ctx.params.category;
const response = await got.get(`https://www.4gamers.com.tw/site/api/news/by-category/${category}?pageSize=25`);
const list = response.data.data.results;
ctx.state.data = {
title: `4Gamers - ${list[0].category.name}`,
link: `https://www.4gamers.com.tw/news/category/${category}/`,
item: list.map((item) => ({
title: item.title,
author: item.author.nickname,
description: `<img src="${item.smallBannerUrl}" /><p>${item.intro}</p>`,
pubDate: new Date(item.createPublishedAt * 1),
link: item.canonicalUrl,
})),
};
};

View File

@ -1,20 +0,0 @@
const got = require('@/utils/got');
module.exports = async (ctx) => {
const tag = ctx.params.tag;
const response = await got.get(`https://www.4gamers.com.tw/site/api/news/by-tag?tag=${encodeURIComponent(tag)}&pageSize=25`);
const list = response.data.data.results;
ctx.state.data = {
title: `4Gamers - #${tag}`,
link: `https://www.4gamers.com.tw/news/tag/${encodeURIComponent(tag)}`,
item: list.map((item) => ({
title: item.title,
author: item.author.nickname,
description: `<img src="${item.smallBannerUrl}" /><p>${item.intro}</p>`,
pubDate: new Date(item.createPublishedAt * 1),
link: item.canonicalUrl,
})),
};
};

View File

@ -1,20 +0,0 @@
const got = require('@/utils/got');
module.exports = async (ctx) => {
const topic = ctx.params.topic;
const response = await got.get(`https://www.4gamers.com.tw/site/api/news/option-cfg/${topic}?pageSize=25`);
const list = response.data.data.results;
ctx.state.data = {
title: `4Gamers - ${topic}`,
link: `https://www.4gamers.com.tw/news/option-cfg/${topic}`,
item: list.map((item) => ({
title: item.title,
author: item.author.nickname,
description: `<img src="${item.smallBannerUrl}" /><p>${item.intro}</p>`,
pubDate: new Date(item.createPublishedAt * 1),
link: item.canonicalUrl,
})),
};
};

View File

@ -0,0 +1,31 @@
const got = require('@/utils/got');
const { parseList, parseItem, getCategories } = require('./utils');
module.exports = async (ctx) => {
const { category } = ctx.params;
const limit = ctx.query.limit ? Number.parseInt(ctx.query.limit) : 25;
const isLatest = !category;
const { data: response } = await got(`https://www.4gamers.com.tw/site/api/news/${isLatest ? 'latest' : `by-category/${category}`}`, {
searchParams: {
nextStart: 0,
pageSize: limit,
},
});
const list = parseList(response.data.results);
const items = await Promise.all(list.map((item) => ctx.cache.tryGet(item.link, () => parseItem(item))));
let categories = [];
let categoryName = '最新消息';
if (!isLatest) {
categories = await getCategories(ctx.cache.tryGet);
categoryName = categories.find((c) => c.id === Number.parseInt(category)).name;
}
ctx.state.data = {
title: `4Gamers - ${categoryName}`,
link: `https://www.4gamers.com.tw/news${isLatest ? '' : `/category/${category}/${categoryName}`}`,
item: items,
};
};

View File

@ -0,0 +1,6 @@
module.exports = {
'/': ['TonyRL'],
'/category/:category': ['hoilc'],
'/tag/:tag': ['hoilc'],
'/topic/:topic': ['bestpika'],
};

31
lib/v2/4gamers/radar.js Normal file
View File

@ -0,0 +1,31 @@
module.exports = {
'4gamers.com.tw': {
_name: '4Gamers',
www: [
{
title: '最新消息',
docs: 'https://docs.rsshub.app/routes/game#4gamers',
source: ['/news', '/'],
target: '/4gamers',
},
{
title: '分类',
docs: 'https://docs.rsshub.app/routes/game#4gamers',
source: ['/news/category/:category/:categoryName'],
target: '/4gamers/category/:category',
},
{
title: '标签',
docs: 'https://docs.rsshub.app/routes/game#4gamers',
source: ['/news/tag/:tag'],
target: '/4gamers/tag/:tag',
},
{
title: '主題',
docs: 'https://docs.rsshub.app/routes/game#4gamers',
source: ['/news/option-cfg/:topic'],
target: '/4gamers/topic/:topic',
},
],
},
};

6
lib/v2/4gamers/router.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = (router) => {
router.get('/', require('./category'));
router.get('/category/:category', require('./category'));
router.get('/tag/:tag', require('./tag'));
router.get('/topic/:topic', require('./topic'));
};

23
lib/v2/4gamers/tag.js Normal file
View File

@ -0,0 +1,23 @@
const got = require('@/utils/got');
const { parseList, parseItem } = require('./utils');
module.exports = async (ctx) => {
const { tag } = ctx.params;
const limit = ctx.query.limit ? Number.parseInt(ctx.query.limit) : 25;
const { data: response } = await got(`https://www.4gamers.com.tw/site/api/news/by-tag`, {
searchParams: {
tag,
pageSize: limit,
},
});
const list = parseList(response.data.results);
const items = await Promise.all(list.map((item) => ctx.cache.tryGet(item.link, () => parseItem(item))));
ctx.state.data = {
title: `4Gamers - #${tag}`,
link: `https://www.4gamers.com.tw/news/tag/${tag}`,
item: items,
};
};

View File

@ -0,0 +1,3 @@
<blockquote>{{ intro }}</blockquote>
<br>
{{@ content }}

View File

@ -0,0 +1,3 @@
{{ each images img }}
<img src="{{ img.url }}" alt="{{ img.alt }}"><br>
{{ /each }}

22
lib/v2/4gamers/topic.js Normal file
View File

@ -0,0 +1,22 @@
const got = require('@/utils/got');
const { parseList, parseItem } = require('./utils');
module.exports = async (ctx) => {
const { topic } = ctx.params;
const limit = ctx.query.limit ? Number.parseInt(ctx.query.limit) : 25;
const { data: response } = await got(`https://www.4gamers.com.tw/site/api/news/option-cfg/${topic}`, {
searchParams: {
pageSize: limit,
},
});
const list = parseList(response.data.results);
const items = await Promise.all(list.map((item) => ctx.cache.tryGet(item.link, () => parseItem(item))));
ctx.state.data = {
title: `4Gamers - ${topic}`,
link: `https://www.4gamers.com.tw/news/option-cfg/${topic}`,
item: items,
};
};

73
lib/v2/4gamers/utils.js Normal file
View File

@ -0,0 +1,73 @@
const got = require('@/utils/got');
const path = require('path');
const { art } = require('@/utils/render');
const { parseDate } = require('@/utils/parse-date');
const getCategories = (tryGet) =>
tryGet('4gamers:categories', async () => {
const { data: response } = await got('https://www.4gamers.com.tw/site/api/news/category');
return response.data.map((category) => ({
id: category.id,
name: category.name,
}));
});
const parseList = (results) =>
results.map((item) => ({
title: item.title,
author: item.author.nickname,
intro: item.intro,
pubDate: parseDate(item.createPublishedAt, 'x'),
link: item.canonicalUrl,
category: [...new Set([item.category.name, ...item.tags])],
articleId: item.id,
}));
const parseItem = async (item) => {
const { data: response } = await got('https://www.4gamers.com.tw/site/api/news/find-section', {
searchParams: {
sub: item.articleId,
},
});
item.description = renderDescription(
item.intro,
response.data.contentSection.sections
.map((section) => {
switch (section['@type']) {
case 'ContentAdsSection':
case 'ScrollerAdsSection':
case 'textScrollerAdsSection':
return '';
case 'RawHtmlSection':
return section.html;
case 'ImageGroupSection':
return renderImages(section.items);
default:
throw new Error(`Unhandled section type: ${section['@type']} on ${item.link}`);
}
})
.join('')
);
return item;
};
const renderDescription = (intro, content) =>
art(path.join(__dirname, 'templates/description.art'), {
intro,
content,
});
const renderImages = (images) =>
art(path.join(__dirname, 'templates/image.art'), {
images,
});
module.exports = {
getCategories,
parseList,
parseItem,
renderDescription,
renderImages,
};

View File

@ -18,19 +18,23 @@
| news | gl | resource |
</Route>
## 4Gamers 新闻 {#4gamers-xin-wen}
## 4Gamers {#4gamers}
### 分类 {#4gamers-xin-wen-fen-lei}
### 最新消息 {#4gamers-zui-xin-xiao-xi}
<Route author="hoilc" example="/4gamers/category/352" path="/4gamers/category/:category" paramsDesc={['分类 ID, 可从分类 URL 中找到']} />
<Route author="TonyRL" example="/4gamers" path="/4gamers" radar="1" />
### 标签 {#4gamers-xin-wen-biao-qian}
### 分类 {#4gamers-fen-lei}
<Route author="hoilc" example="/4gamers/tag/英雄聯盟" path="/4gamers/tag/:tag" paramsDesc={['标签名, 可在标签 URL 中找到']} />
<Route author="hoilc" example="/4gamers/category/352" path="/4gamers/category/:category" paramsDesc={['分类 ID可从分类 URL 中找到']} radar="1" />
### 主題 {#4gamers-xin-wen-zhu-ti}
### 标签 {#4gamers-biao-qian}
<Route author="bestpika" example="/4gamers/topic/gentlemen-topic" path="/4gamers/topic/:topic" paramsDesc={['主题, 可在首页上方页面内找到']} />
<Route author="hoilc" example="/4gamers/tag/限時免費" path="/4gamers/tag/:tag" paramsDesc={['标签名,可在标签 URL 中找到']} radar="1" />
### 主題 {#4gamers-zhu-ti}
<Route author="bestpika" example="/4gamers/topic/gentlemen-topic" path="/4gamers/topic/:topic" paramsDesc={['主题,可在首页上方页面内找到']} radar="1" />
## 5EPLAY {#5eplay}