diff --git a/lib/router.js b/lib/router.js index 8b4009cd6..f92100980 100644 --- a/lib/router.js +++ b/lib/router.js @@ -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')); diff --git a/lib/routes/4gamers/category.js b/lib/routes/4gamers/category.js deleted file mode 100644 index c059d235b..000000000 --- a/lib/routes/4gamers/category.js +++ /dev/null @@ -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: `

${item.intro}

`, - pubDate: new Date(item.createPublishedAt * 1), - link: item.canonicalUrl, - })), - }; -}; diff --git a/lib/routes/4gamers/tag.js b/lib/routes/4gamers/tag.js deleted file mode 100644 index bc9878bc2..000000000 --- a/lib/routes/4gamers/tag.js +++ /dev/null @@ -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: `

${item.intro}

`, - pubDate: new Date(item.createPublishedAt * 1), - link: item.canonicalUrl, - })), - }; -}; diff --git a/lib/routes/4gamers/topic.js b/lib/routes/4gamers/topic.js deleted file mode 100644 index abad24d4e..000000000 --- a/lib/routes/4gamers/topic.js +++ /dev/null @@ -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: `

${item.intro}

`, - pubDate: new Date(item.createPublishedAt * 1), - link: item.canonicalUrl, - })), - }; -}; diff --git a/lib/v2/4gamers/category.js b/lib/v2/4gamers/category.js new file mode 100644 index 000000000..7e23990e7 --- /dev/null +++ b/lib/v2/4gamers/category.js @@ -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, + }; +}; diff --git a/lib/v2/4gamers/maintainer.js b/lib/v2/4gamers/maintainer.js new file mode 100644 index 000000000..d264fb22c --- /dev/null +++ b/lib/v2/4gamers/maintainer.js @@ -0,0 +1,6 @@ +module.exports = { + '/': ['TonyRL'], + '/category/:category': ['hoilc'], + '/tag/:tag': ['hoilc'], + '/topic/:topic': ['bestpika'], +}; diff --git a/lib/v2/4gamers/radar.js b/lib/v2/4gamers/radar.js new file mode 100644 index 000000000..eadb04539 --- /dev/null +++ b/lib/v2/4gamers/radar.js @@ -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', + }, + ], + }, +}; diff --git a/lib/v2/4gamers/router.js b/lib/v2/4gamers/router.js new file mode 100644 index 000000000..d84b4ad17 --- /dev/null +++ b/lib/v2/4gamers/router.js @@ -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')); +}; diff --git a/lib/v2/4gamers/tag.js b/lib/v2/4gamers/tag.js new file mode 100644 index 000000000..8a85bd604 --- /dev/null +++ b/lib/v2/4gamers/tag.js @@ -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, + }; +}; diff --git a/lib/v2/4gamers/templates/description.art b/lib/v2/4gamers/templates/description.art new file mode 100644 index 000000000..5ba6f0220 --- /dev/null +++ b/lib/v2/4gamers/templates/description.art @@ -0,0 +1,3 @@ +
{{ intro }}
+
+{{@ content }} diff --git a/lib/v2/4gamers/templates/image.art b/lib/v2/4gamers/templates/image.art new file mode 100644 index 000000000..8a2290cb2 --- /dev/null +++ b/lib/v2/4gamers/templates/image.art @@ -0,0 +1,3 @@ +{{ each images img }} +{{ img.alt }}
+{{ /each }} diff --git a/lib/v2/4gamers/topic.js b/lib/v2/4gamers/topic.js new file mode 100644 index 000000000..cf9a8cfb9 --- /dev/null +++ b/lib/v2/4gamers/topic.js @@ -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, + }; +}; diff --git a/lib/v2/4gamers/utils.js b/lib/v2/4gamers/utils.js new file mode 100644 index 000000000..ebcf0c5bf --- /dev/null +++ b/lib/v2/4gamers/utils.js @@ -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, +}; diff --git a/website/docs/routes/game.mdx b/website/docs/routes/game.mdx index fb4fa34fa..22b7eb58e 100644 --- a/website/docs/routes/game.mdx +++ b/website/docs/routes/game.mdx @@ -18,19 +18,23 @@ | news | gl | resource | -## 4Gamers 新闻 {#4gamers-xin-wen} +## 4Gamers {#4gamers} -### 分类 {#4gamers-xin-wen-fen-lei} +### 最新消息 {#4gamers-zui-xin-xiao-xi} - + -### 标签 {#4gamers-xin-wen-biao-qian} +### 分类 {#4gamers-fen-lei} - + -### 主題 {#4gamers-xin-wen-zhu-ti} +### 标签 {#4gamers-biao-qian} - + + +### 主題 {#4gamers-zhu-ti} + + ## 5EPLAY {#5eplay}