feat(route): feng (#9858)

This commit is contained in:
Tony 2022-05-31 08:46:43 +08:00 committed by GitHub
parent cdb3ed67d4
commit 6c14613158
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 158 additions and 0 deletions

View File

@ -696,6 +696,18 @@ pageClass: routes
<Route author="nczitzk" example="/creaders/headline" path="/creaders/headline"/>
## 威锋
### 社区
<Route author="TonyRL" example="/feng/forum/1" path="/feng/forum/:id/:type?" :paramsDesc="['版块 ID可在版块 URL 找到', '排序,见下表,默认为 `all`']" radar="1" rssbud="1">
| 最新回复 | 最新发布 | 热门 | 精华 |
| ------ | ---- | --- | ------- |
| newest | all | hot | essence |
</Route>
## 文学城
### 博客

42
lib/v2/feng/forum.js Normal file
View File

@ -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,
};
};

13
lib/v2/feng/radar.js Normal file
View File

@ -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',
},
],
},
};

3
lib/v2/feng/router.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = (router) => {
router.get('/forum/:id/:type?', require('./forum'));
};

View File

@ -0,0 +1,2 @@
<img src="https://www.feng.com/_nuxt/img/yishanchu.368ead2.png" alt="威锋">
<div align="center">帖子已被删除</div>

View File

@ -0,0 +1,6 @@
{{ if images }}
<br>
{{ each images }}
<img src="{{ $value.split('?')[0] }}" alt="">
{{ /each }}
{{ /if }}

80
lib/v2/feng/utils.js Normal file
View File

@ -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,
};