diff --git a/docs/bbs.md b/docs/bbs.md index 0ffe8eb2b..2783a08f5 100644 --- a/docs/bbs.md +++ b/docs/bbs.md @@ -384,6 +384,16 @@ pageClass: routes +## Zuvio + +### 校園話題 + + + +### 看板列表 + + + ## 巴哈姆特電玩資訊站 ### 熱門推薦 diff --git a/lib/v2/zuvio/boards.js b/lib/v2/zuvio/boards.js new file mode 100644 index 000000000..acb22c908 --- /dev/null +++ b/lib/v2/zuvio/boards.js @@ -0,0 +1,14 @@ +const { getBoards, rootUrl } = require('./utils'); + +module.exports = async (ctx) => { + const items = await getBoards(ctx.cache.tryGet); + + ctx.state.data = { + title: 'Zuvio 校園話題列表 - 大學生論壇', + description: 'Zuvio 校園話題,Zuvio 校園話題千種動物頭像交流心得。最萌的匿名論壇,上千種逗趣動物頭像隨你變換,點頭像立即私訊功能,讓你找到共同話題的小夥伴!多人分享配對心得、聊天交友心情在此,快加入17分享!', + image: 'https://s3.hicloud.net.tw/zuvio.public/public/system/images/irs_v4/chicken/shared/webshare.png', + link: `${rootUrl}/articles`, + item: items, + language: 'zh-Hant', + }; +}; diff --git a/lib/v2/zuvio/radar.js b/lib/v2/zuvio/radar.js new file mode 100644 index 000000000..edccab155 --- /dev/null +++ b/lib/v2/zuvio/radar.js @@ -0,0 +1,13 @@ +module.exports = { + 'zuvio.com.tw': { + _name: 'Zuvio', + irs: [ + { + title: '校園話題', + docs: 'https://docs.rsshub.app/bbs.html#zuvio', + source: ['/student5/chickenM/articles/:board', '/student5/chickenM/articles'], + target: (params) => `/zuvio/student5${params.board ? `/${params.board}` : ''}`, + }, + ], + }, +}; diff --git a/lib/v2/zuvio/router.js b/lib/v2/zuvio/router.js new file mode 100644 index 000000000..e0a3eb579 --- /dev/null +++ b/lib/v2/zuvio/router.js @@ -0,0 +1,4 @@ +module.exports = (router) => { + router.get('/student5/boards', require('./boards')); + router.get('/student5/:board?', require('./student5')); +}; diff --git a/lib/v2/zuvio/student5.js b/lib/v2/zuvio/student5.js new file mode 100644 index 000000000..a21efea6e --- /dev/null +++ b/lib/v2/zuvio/student5.js @@ -0,0 +1,58 @@ +const got = require('@/utils/got'); +const { parseDate } = require('@/utils/parse-date'); +const timezone = require('@/utils/timezone'); +const { token, apiUrl, rootUrl, renderDesc, getBoards } = require('./utils'); + +module.exports = async (ctx) => { + const { board = '' } = ctx.params; + const title = board ? (await getBoards(ctx.cache.tryGet)).find((i) => i.boardId === board).title : '全部'; + + const { data } = await got(`${apiUrl}/article`, { + searchParams: { + api_token: token, + user_id: '0', + board_id: board, + sort: 'time', + page: '1', + device: 'web', + my_school_opinion: '1', + }, + }); + + const items = data.articles.map((item) => ({ + title: item.title, + description: item.abstract, + pubDate: timezone(parseDate(item.created_at), +8), + link: `${rootUrl}/article/${item.id}`, + api: `${apiUrl}/article/${item.id}`, + author: `${item.university} ${item.user_name}`, + category: item.board_name, + })); + + await Promise.all( + items.map((item) => + ctx.cache.tryGet(item.link, async () => { + const { data } = await got(item.api, { + searchParams: { + api_token: token, + user_id: '0', + device: 'web', + ref: '', + }, + }); + item.description = renderDesc(data); + delete item.api; + return item; + }) + ) + ); + + ctx.state.data = { + title: `Zuvio 校園${title}話題 - 大學生論壇`, + description: 'Zuvio 校園話題千種動物頭像交流心得。最萌的匿名論壇,上千種逗趣動物頭像隨你變換,點頭像立即私訊功能,讓你找到共同話題的小夥伴!多人分享配對心得、聊天交友心情在此,快加入17分享!', + image: 'https://s3.hicloud.net.tw/zuvio.public/public/system/images/irs_v4/chicken/shared/webshare.png', + link: `${rootUrl}/articles`, + item: items, + language: 'zh-Hant', + }; +}; diff --git a/lib/v2/zuvio/templates/img.art b/lib/v2/zuvio/templates/img.art new file mode 100644 index 000000000..cabd91bee --- /dev/null +++ b/lib/v2/zuvio/templates/img.art @@ -0,0 +1,2 @@ + +
diff --git a/lib/v2/zuvio/templates/link.art b/lib/v2/zuvio/templates/link.art new file mode 100644 index 000000000..602771735 --- /dev/null +++ b/lib/v2/zuvio/templates/link.art @@ -0,0 +1,7 @@ +

+ + +

{{ section.title}}
+
{{ section.description}}
+
+

diff --git a/lib/v2/zuvio/templates/ref_article.art b/lib/v2/zuvio/templates/ref_article.art new file mode 100644 index 000000000..42e39281a --- /dev/null +++ b/lib/v2/zuvio/templates/ref_article.art @@ -0,0 +1,8 @@ +引用自: + + +
{{ ref_article.university }} {{ ref_article.user_name }} {{ ref_article.board_name }}
+
{{ ref_article.title }}
+
{{ ref_article.abstract }}
+
+
diff --git a/lib/v2/zuvio/templates/rss.art b/lib/v2/zuvio/templates/rss.art new file mode 100644 index 000000000..862f00342 --- /dev/null +++ b/lib/v2/zuvio/templates/rss.art @@ -0,0 +1 @@ +{{ id }} diff --git a/lib/v2/zuvio/templates/youtube.art b/lib/v2/zuvio/templates/youtube.art new file mode 100644 index 000000000..5c37a4a2c --- /dev/null +++ b/lib/v2/zuvio/templates/youtube.art @@ -0,0 +1,2 @@ + +
diff --git a/lib/v2/zuvio/utils.js b/lib/v2/zuvio/utils.js new file mode 100644 index 000000000..751f6e1d4 --- /dev/null +++ b/lib/v2/zuvio/utils.js @@ -0,0 +1,61 @@ +const { art } = require('@/utils/render'); +const path = require('path'); +const got = require('@/utils/got'); + +const token = + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0OTcyMzI1MjMsInN5c3RlbV9uYW1lIjoiZm9ydW0iLCJ6dXZpb19pZCI6LTk5OSwiZW1haWwiOm51bGwsIm5hbWUiOm51bGwsInVuaXZlcnNpdHlfaWQiOm51bGwsInVuaXZlcnNpdHlfbmFtZSI6bnVsbH0.0KoJiSnyazsJxLCNEnqnuNUdKsJFhBdCn3R2BJpoUtk'; +const apiUrl = 'https://forum.zuvio.com.tw/api'; +const rootUrl = 'https://irs.zuvio.com.tw/student5/chickenM'; + +const renderDesc = (data) => { + let output = ''; + if (data.ref_article) { + output += art(path.join(__dirname, 'templates/ref_article.art'), { + ref_article: data.ref_article, + }); + } + output += renderSections(data.sections); + return output; +}; + +const renderSections = (sections) => { + let output = ''; + for (const section of sections) { + if (section.type === 'text') { + output += section.content.replace(/\n/g, '
'); + } else if (section.type === 'img') { + output += art(path.join(__dirname, 'templates/img.art'), { section }); + } else if (section.type === 'youtube') { + output += art(path.join(__dirname, 'templates/youtube.art'), { section }); + } else if (section.type === 'link') { + output += art(path.join(__dirname, 'templates/link.art'), { section }); + } + } + return output; +}; + +const getBoards = (tryGet) => + tryGet('zuvio:boards', async () => { + const { data } = await got(`${apiUrl}/board`, { + searchParams: { + api_token: token, + user_id: '0', + }, + }); + + return data.map((item) => ({ + title: item.name, + description: art(path.join(__dirname, 'templates/rss.art'), { id: item.id }), + boardId: item.id, + link: `${rootUrl}/articles/${item.id}`, + })); + }); + +module.exports = { + token, + apiUrl, + rootUrl, + renderDesc, + renderSections, + getBoards, +};