feat(route): add 海角社区 (#10403)
* feat(route): add 海角社区 * fix: limit to 15 * update lib/v2/hjedd/article.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * fix: limit to 5
This commit is contained in:
parent
269e8bcdc9
commit
0f4404a808
40
docs/bbs.md
40
docs/bbs.md
|
|
@ -466,6 +466,46 @@ pageClass: routes
|
|||
|
||||
</Route>
|
||||
|
||||
## 海角社区
|
||||
|
||||
### 热门
|
||||
|
||||
<Route author="nczitzk" example="/hjedd/hot" path="/hjedd/hot"/>
|
||||
|
||||
### 新闻
|
||||
|
||||
<Route author="nczitzk" example="/hjedd/news" path="/hjedd/news"/>
|
||||
|
||||
### 大事记
|
||||
|
||||
<Route author="nczitzk" example="/hjedd/event" path="/hjedd/event"/>
|
||||
|
||||
### 原创
|
||||
|
||||
<Route author="nczitzk" example="/hjedd/original" path="/hjedd/original"/>
|
||||
|
||||
### 精华
|
||||
|
||||
<Route author="nczitzk" example="/hjedd/top" path="/hjedd/top"/>
|
||||
|
||||
### 公告
|
||||
|
||||
<Route author="nczitzk" example="/hjedd/notice" path="/hjedd/notice"/>
|
||||
|
||||
### 最新
|
||||
|
||||
<Route author="nczitzk" example="/hjedd/latest" path="/hjedd/latest"/>
|
||||
|
||||
### 文章
|
||||
|
||||
<Route author="nczitzk" example="/hjedd/1288/1" path="/hjedd/:node?/:type?" :paramsDesc="['节点 id,可在对应节点页 URL 中找到,默认为 `258`,即 大事记', '类型 id,见下表,默认为 `0`,即 默认']">
|
||||
|
||||
| 默认 | 最新 | 热门 | 精华 | 悬赏 | 出售 |
|
||||
| -- | -- | -- | -- | -- | -- |
|
||||
| 0 | 1 | 2 | 3 | 4 | 5 |
|
||||
|
||||
</Route>
|
||||
|
||||
## 虎扑
|
||||
|
||||
### 首页
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
const got = require('@/utils/got');
|
||||
const { rootUrl, ProcessItems } = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const node = ctx.params.node ?? '258';
|
||||
const type = ctx.params.type ?? '1';
|
||||
|
||||
const currentUrl = rootUrl;
|
||||
const nodeUrl = `${rootUrl}/api/topic/node?nodeId=${node}`;
|
||||
const apiUrl = `${rootUrl}/api/topic/node/topics?page=1&nodeId=${node}&type=${type}&limit=${ctx.query.limit}`;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: nodeUrl,
|
||||
});
|
||||
|
||||
const data = response.data.data;
|
||||
|
||||
const items = await ProcessItems(apiUrl, ctx.query.limit, ctx.cache.tryGet);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `海角社区 - ${data.name}`,
|
||||
link: `${currentUrl}/article?nodeId=${node}`,
|
||||
item: items,
|
||||
description: data.description.replace(/<\/?p>/, ''),
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
const { rootUrl, ProcessItems } = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const currentUrl = rootUrl;
|
||||
const apiUrl = `${rootUrl}/api/topic/hot/topics?page=1`;
|
||||
|
||||
const items = await ProcessItems(apiUrl, ctx.query.limit, ctx.cache.tryGet);
|
||||
|
||||
ctx.state.data = {
|
||||
title: '海角社区 - 热门',
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
const { rootUrl, ProcessItems } = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const currentUrl = rootUrl;
|
||||
const apiUrl = `${rootUrl}/api/topic/node/topics?page=1&nodeId=0&type=1`;
|
||||
|
||||
const items = await ProcessItems(apiUrl, ctx.query.limit, ctx.cache.tryGet);
|
||||
|
||||
ctx.state.data = {
|
||||
title: '海角社区 - 最新',
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
module.exports = {
|
||||
'/event': ['nczitzk'],
|
||||
'/hot': ['nczitzk'],
|
||||
'/latest': ['nczitzk'],
|
||||
'/news': ['nczitzk'],
|
||||
'/notice': ['nczitzk'],
|
||||
'/original': ['nczitzk'],
|
||||
'/top': ['nczitzk'],
|
||||
'/:node?/:type?': ['nczitzk'],
|
||||
};
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
const { rootUrl, ProcessItems } = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const currentUrl = rootUrl;
|
||||
const apiUrl = `${rootUrl}/api/topic/node/news?page=1`;
|
||||
|
||||
const items = await ProcessItems(apiUrl, ctx.query.limit, ctx.cache.tryGet);
|
||||
|
||||
ctx.state.data = {
|
||||
title: '海角社区 - 新闻',
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
const { rootUrl, ProcessItems } = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const currentUrl = rootUrl;
|
||||
const apiUrl = `${rootUrl}/api/topic/node/topics?page=1&nodeId=14&type=0`;
|
||||
|
||||
const items = await ProcessItems(apiUrl, ctx.query.limit, ctx.cache.tryGet);
|
||||
|
||||
ctx.state.data = {
|
||||
title: '海角社区 - 公告',
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
const { rootUrl, ProcessItems } = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const currentUrl = rootUrl;
|
||||
const apiUrl = `${rootUrl}/api/topic/node/topics?page=1&type=7`;
|
||||
|
||||
const items = await ProcessItems(apiUrl, ctx.query.limit, ctx.cache.tryGet);
|
||||
|
||||
ctx.state.data = {
|
||||
title: '海角社区 - 原创',
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
module.exports = {
|
||||
'hjedd.com': {
|
||||
_name: '海角社区',
|
||||
'.': [
|
||||
{
|
||||
title: '热门',
|
||||
docs: 'https://docs.rsshub.app/bbs.html#hai-jiao-she-qu-re-men',
|
||||
source: ['/'],
|
||||
target: '/hjedd/hot',
|
||||
},
|
||||
{
|
||||
title: '新闻',
|
||||
docs: 'https://docs.rsshub.app/bbs.html#hai-jiao-she-qu-xin-wen',
|
||||
source: ['/'],
|
||||
target: '/hjedd/news',
|
||||
},
|
||||
{
|
||||
title: '大事记',
|
||||
docs: 'https://docs.rsshub.app/bbs.html#hai-jiao-she-qu-da-shi-ji',
|
||||
source: ['/article', '/'],
|
||||
target: '/hjedd/event',
|
||||
},
|
||||
{
|
||||
title: '原创',
|
||||
docs: 'https://docs.rsshub.app/bbs.html#hai-jiao-she-qu-da-yuan-chuang',
|
||||
source: ['/'],
|
||||
target: '/hjedd/original',
|
||||
},
|
||||
{
|
||||
title: '精华',
|
||||
docs: 'https://docs.rsshub.app/bbs.html#hai-jiao-she-qu-da-jing-hua',
|
||||
source: ['/'],
|
||||
target: '/hjedd/top',
|
||||
},
|
||||
{
|
||||
title: '公告',
|
||||
docs: 'https://docs.rsshub.app/bbs.html#hai-jiao-she-qu-da-gong-gao',
|
||||
source: ['/'],
|
||||
target: '/hjedd/notice',
|
||||
},
|
||||
{
|
||||
title: '最新',
|
||||
docs: 'https://docs.rsshub.app/bbs.html#hai-jiao-she-qu-da-zui-xin',
|
||||
source: ['/'],
|
||||
target: '/hjedd/latest',
|
||||
},
|
||||
{
|
||||
title: '文章',
|
||||
docs: 'https://docs.rsshub.app/bbs.html#hai-jiao-she-qu-da-wen-zhang',
|
||||
source: ['/article', '/'],
|
||||
target: (params, url) => `/hjedd/${new URL(url).searchParams.get('nodeId')}`,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
module.exports = function (router) {
|
||||
router.get('/event', require('./article'));
|
||||
router.get('/hot', require('./hot'));
|
||||
router.get('/latest', require('./latest'));
|
||||
router.get('/news', require('./news'));
|
||||
router.get('/notice', require('./notice'));
|
||||
router.get('/original', require('./original'));
|
||||
router.get('/top', require('./top'));
|
||||
router.get('/:node?/:type?', require('./article'));
|
||||
};
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{{ if attachment.category == 'video' }}
|
||||
<video poster="{{ attachment.data }}" controls>
|
||||
<source src="{{ attachment.remoteUrl }}" type="application/x-mpegURL">
|
||||
</video>
|
||||
{{ else }}
|
||||
<img src="{{ attachment.data }}">
|
||||
{{ /if }}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
const { rootUrl, ProcessItems } = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const currentUrl = rootUrl;
|
||||
const apiUrl = `${rootUrl}/api/topic/node/topics?page=1&nodeId=0&type=3`;
|
||||
|
||||
const items = await ProcessItems(apiUrl, ctx.query.limit, ctx.cache.tryGet);
|
||||
|
||||
ctx.state.data = {
|
||||
title: '海角社区 - 精华',
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const asyncPool = require('tiny-async-pool');
|
||||
const timezone = require('@/utils/timezone');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const { art } = require('@/utils/render');
|
||||
const path = require('path');
|
||||
|
||||
const rootUrl = 'https://www.hjedd.com';
|
||||
|
||||
const decodeImage = (text) => {
|
||||
const e = 'ABCD*EFGHIJKLMNOPQRSTUVWX#YZabcdefghijklmnopqrstuvwxyz1234567890';
|
||||
|
||||
let a,
|
||||
o,
|
||||
i,
|
||||
r,
|
||||
c,
|
||||
s,
|
||||
u = '',
|
||||
image = '',
|
||||
index = 0;
|
||||
|
||||
text = text.replace(/[^A-Za-z0-9*#]/g, '');
|
||||
|
||||
while (index < text.length) {
|
||||
r = e.indexOf(text.charAt(index++));
|
||||
c = e.indexOf(text.charAt(index++));
|
||||
s = e.indexOf(text.charAt(index++));
|
||||
u = e.indexOf(text.charAt(index++));
|
||||
a = (r << 2) | (c >> 4);
|
||||
o = ((15 & c) << 4) | (s >> 2);
|
||||
i = ((3 & s) << 6) | u;
|
||||
image += String.fromCharCode(a);
|
||||
64 !== s && (image += String.fromCharCode(o));
|
||||
64 !== u && (image += String.fromCharCode(i));
|
||||
}
|
||||
|
||||
return image;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
rootUrl,
|
||||
ProcessItems: async (apiUrl, limit, tryGet) => {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: apiUrl,
|
||||
});
|
||||
|
||||
const list = response.data.data.results.slice(0, limit ? parseInt(limit) : 5).map((item) => ({
|
||||
guid: item.topicId,
|
||||
title: item.title,
|
||||
link: `${rootUrl}/post/details?pid=${item.topicId}`,
|
||||
category: item.node?.name ?? [],
|
||||
author: item.user.nickname,
|
||||
pubDate: timezone(parseDate(item.createTime), +8),
|
||||
description: item.liteContent ? `<p>${item.liteContent}</p>` : '',
|
||||
}));
|
||||
|
||||
const items = [];
|
||||
for await (const item of asyncPool(5, list, (item) =>
|
||||
tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: `https://www.hjedd.com/api/topic/${item.guid}`,
|
||||
});
|
||||
|
||||
const content = cheerio.load(detailResponse.data.data.content);
|
||||
|
||||
content('.sell-btn').remove();
|
||||
|
||||
const attachments = detailResponse.data.data.attachments ?? [];
|
||||
|
||||
for await (const attachment of asyncPool(5, attachments, (attachment) =>
|
||||
tryGet(attachment.id, async () => {
|
||||
const attachmentResponse = await got({
|
||||
method: 'get',
|
||||
url: attachment.coverUrl ?? attachment.remoteUrl,
|
||||
});
|
||||
|
||||
attachment.data = decodeImage(attachmentResponse.data);
|
||||
|
||||
return attachment;
|
||||
})
|
||||
)) {
|
||||
if (content(`[data-id="${attachment.id}"]`).length === 0) {
|
||||
content('body').append(
|
||||
art(path.join(__dirname, 'templates/attachment.art'), {
|
||||
attachment,
|
||||
})
|
||||
);
|
||||
} else {
|
||||
content(`[data-id="${attachment.id}"]`).replaceWith(
|
||||
art(path.join(__dirname, 'templates/attachment.art'), {
|
||||
attachment,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
item.description = content('body').html();
|
||||
|
||||
return item;
|
||||
})
|
||||
)) {
|
||||
items.push(item);
|
||||
}
|
||||
|
||||
return items;
|
||||
},
|
||||
};
|
||||
Loading…
Reference in New Issue