From 6c14613158758e1a21790e3d9cda1f09bf725099 Mon Sep 17 00:00:00 2001 From: Tony Date: Tue, 31 May 2022 08:46:43 +0800 Subject: [PATCH] feat(route): feng (#9858) --- docs/bbs.md | 12 +++++ lib/v2/feng/forum.js | 42 ++++++++++++++++ lib/v2/feng/radar.js | 13 +++++ lib/v2/feng/router.js | 3 ++ lib/v2/feng/templates/deleted.art | 2 + lib/v2/feng/templates/img.art | 6 +++ lib/v2/feng/utils.js | 80 +++++++++++++++++++++++++++++++ 7 files changed, 158 insertions(+) create mode 100644 lib/v2/feng/forum.js create mode 100644 lib/v2/feng/radar.js create mode 100644 lib/v2/feng/router.js create mode 100644 lib/v2/feng/templates/deleted.art create mode 100644 lib/v2/feng/templates/img.art create mode 100644 lib/v2/feng/utils.js diff --git a/docs/bbs.md b/docs/bbs.md index 2f27dee6a..d39c3f170 100644 --- a/docs/bbs.md +++ b/docs/bbs.md @@ -696,6 +696,18 @@ pageClass: routes +## 威锋 + +### 社区 + + + +| 最新回复 | 最新发布 | 热门 | 精华 | +| ------ | ---- | --- | ------- | +| newest | all | hot | essence | + + + ## 文学城 ### 博客 diff --git a/lib/v2/feng/forum.js b/lib/v2/feng/forum.js new file mode 100644 index 000000000..3d8727be1 --- /dev/null +++ b/lib/v2/feng/forum.js @@ -0,0 +1,42 @@ +const { parseDate } = require('@/utils/parse-date'); +const { baseUrl, getForumMeta, getThreads, getThread } = require('./utils'); +const { art } = require('@/utils/render'); +const path = require('path'); + +module.exports = async (ctx) => { + const topicId = Number(ctx.params.id); + const { type = 'all' } = ctx.params; + + const forumMeta = await getForumMeta(topicId, ctx); + const topicMeta = forumMeta.dataList.find((data) => data.topicId === topicId); + const threads = (await getThreads(topicId, type, ctx)).data.dataList.map((data) => ({ + title: data.title, + pubDate: parseDate(data.dateline * 1000), + author: data.userBaseInfo.userName, + link: `${baseUrl}/post/${data.tid}`, + tid: data.tid, + })); + + const posts = await Promise.all( + threads.map(async (item) => { + const thread = await getThread(item.tid, topicId, ctx); + if (thread.status.code === 0) { + const img = art(path.join(__dirname, 'templates/img.art'), { + images: thread.data.thread.fengTalkImage.length ? thread.data.thread.fengTalkImage : undefined, + }); + item.description = thread.data.thread.message + img; + } else { + item.description = art(path.join(__dirname, 'templates/deleted.art'), {}); + } + delete item.tid; + return item; + }) + ); + + ctx.state.data = { + title: `${topicMeta.topicName} - 社区 - 威锋 - 千万果粉大本营`, + description: topicMeta.topicDescription, + link: `${baseUrl}/forum/${topicId}`, + item: posts, + }; +}; diff --git a/lib/v2/feng/radar.js b/lib/v2/feng/radar.js new file mode 100644 index 000000000..e0cdfe355 --- /dev/null +++ b/lib/v2/feng/radar.js @@ -0,0 +1,13 @@ +module.exports = { + 'feng.com': { + _name: '威锋', + '.': [ + { + title: '社区', + docs: 'https://docs.rsshub.app/bbs.html#wei-feng', + source: ['/forum/photo/:id', '/forum/:id'], + target: '/feng/forum/:id', + }, + ], + }, +}; diff --git a/lib/v2/feng/router.js b/lib/v2/feng/router.js new file mode 100644 index 000000000..62249b47f --- /dev/null +++ b/lib/v2/feng/router.js @@ -0,0 +1,3 @@ +module.exports = (router) => { + router.get('/forum/:id/:type?', require('./forum')); +}; diff --git a/lib/v2/feng/templates/deleted.art b/lib/v2/feng/templates/deleted.art new file mode 100644 index 000000000..e87f889f1 --- /dev/null +++ b/lib/v2/feng/templates/deleted.art @@ -0,0 +1,2 @@ +威锋 +
帖子已被删除
diff --git a/lib/v2/feng/templates/img.art b/lib/v2/feng/templates/img.art new file mode 100644 index 000000000..a48c25f14 --- /dev/null +++ b/lib/v2/feng/templates/img.art @@ -0,0 +1,6 @@ +{{ if images }} +
+{{ each images }} + +{{ /each }} +{{ /if }} diff --git a/lib/v2/feng/utils.js b/lib/v2/feng/utils.js new file mode 100644 index 000000000..888a035c7 --- /dev/null +++ b/lib/v2/feng/utils.js @@ -0,0 +1,80 @@ +const CryptoJS = require('crypto-js'); +const got = require('@/utils/got'); +const config = require('@/config').value; +const apiUrl = 'https://api.wfdata.club'; +const baseUrl = 'https://www.feng.com'; +const KEY = '2b7e151628aed2a6'; + +// https://juejin.cn/post/6844904066468806664 +const getXRequestId = (apiUrl) => { + const path = new URL(apiUrl).pathname; // split search params + const plainText = CryptoJS.enc.Utf8.parse('url=' + path + '$time=' + Date.now() + '000000'); + const iv = CryptoJS.enc.Utf8.parse(KEY); + const encrypted = CryptoJS.AES.encrypt(plainText, iv, { + iv, + mode: CryptoJS.mode.CBC, + padding: CryptoJS.pad.Pkcs7, + }).toString(); + return encrypted; +}; + +const getCategory = (topicId, ctx) => { + const url = `${apiUrl}/v1/topic/category`; + return ctx.cache.tryGet( + url, + async () => { + const response = await got(url, { + headers: { + Referer: `${baseUrl}/forum/${topicId}`, + 'X-Request-Id': getXRequestId(url), + }, + }); + return response.data; + }, + config.cache.routeExpire, + false + ); +}; + +const getForumMeta = async (topicId, ctx) => { + const categoryData = await getCategory(topicId, ctx); + return Object.values(categoryData.data.dataList).find((item) => item.dataList.find((i) => i.topicId === topicId)); +}; + +const getThreads = (topicId, type, ctx) => { + const url = `${apiUrl}/v1/topic/${topicId}/thread?topicId=${topicId}&type=${type}&pageCount=50&order=${type === 'newest' ? 'replyTime' : 'postTime'}&page=1`; + return ctx.cache.tryGet( + url, + async () => { + const response = await got(url, { + headers: { + Referer: `${baseUrl}/forum/${topicId}`, + 'X-Request-Id': getXRequestId(url), + }, + }); + return response.data; + }, + config.cache.routeExpire, + false + ); +}; + +const getThread = (tid, topicId, ctx) => { + const url = `${apiUrl}/v1/thread/${tid}`; + return ctx.cache.tryGet(url, async () => { + const response = await got(url, { + headers: { + Referer: `${baseUrl}/forum/${topicId}`, + 'X-Request-Id': getXRequestId(url), + }, + }); + return response.data; + }); +}; + +module.exports = { + baseUrl, + getForumMeta, + getThreads, + getThread, +};