feat(route): add X岛匿名版 (#10678)

* feat(route): add X岛匿名版

* refactor(route): use template
This commit is contained in:
miles 2022-09-02 20:29:29 +08:00 committed by GitHub
parent e7d1a26b54
commit cf04b7e199
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 166 additions and 108 deletions

View File

@ -112,42 +112,6 @@ pageClass: routes
</Route>
## A 岛匿名版
### 串
<Route author="zcx1218029121" example="/adnmb/20" path="/adnmb/:pid" :paramsDesc="['板块 id 或者板块名称,例如`/adnmb/20`等价于`/adnmb/欢乐恶搞`,现有板块请参考下表']" >
| 时间线 | 综合版 1 | 围炉 | 欢乐恶搞 | 速报 2 | 推理 | 跑团 | 技术宅 | 料理 | 猫版 | 音乐 | 考试 | 社畜 |
| --- | ----- | --- | ---- | ---- | -- | --- | --- | -- | -- | -- | -- | --- |
| -1 | 4 | 120 | 20 | 121 | 11 | 111 | 30 | 32 | 40 | 35 | 56 | 110 |
| 科学 | 文学 | 创意 | 姐妹 1 | 数码 | 女装 | 日记 | 圈内 | 都市怪谈 | 买买买 | 动画 | 漫画 | 美漫 | 国漫 | 小说 |
| -- | --- | -- | ---- | -- | -- | -- | -- | ---- | --- | -- | -- | -- | -- | -- |
| 15 | 103 | 17 | 98 | 75 | 97 | 89 | 96 | 81 | 106 | 14 | 12 | 90 | 99 | 19 |
| 轻小说 | GALGAME | 东方 Project | 舰娘 | 虚拟偶像 | VOCALOID | 游戏 | DNF | SE | 手游 |
| --- | ------- | ---------- | -- | ---- | -------- | -- | --- | --- | -- |
| 87 | 64 | 5 | 93 | 101 | 6 | 2 | 72 | 124 | 3 |
| Steam | 索尼 | LOL | DOTA | 口袋妖怪 | 战争雷霆 | WOT | Minecraft | 怪物猎人 | 3A 游戏 |
| ----- | -- | --- | ---- | ---- | ---- | --- | --------- | ---- | ----- |
| 107 | 24 | 22 | 70 | 38 | 86 | 51 | 10 | 28 | 108 |
| 彩虹六号 | 暴雪游戏 | 卡牌桌游 | MUG | AC 大逃杀 | 任天堂 | AKB | SNH48 | COSPLAY | 声优 |
| ---- | ---- | ---- | --- | ------ | --- | --- | ----- | ------- | -- |
| 119 | 23 | 45 | 34 | 29 | 25 | 16 | 100 | 13 | 55 |
| 模型 | 影视 | 军武 | 体育 | 值班室 | 城墙 | 技术支持 | 询问 3 | 宠物 | 摄影 2 |
| -- | -- | -- | -- | --- | --- | ---- | ---- | --- | ---- |
| 39 | 31 | 37 | 33 | 18 | 112 | 117 | 114 | 118 | 115 |
| 主播 | 育儿 | 围炉 | 旅行 | 特摄 |
| --- | --- | --- | --- | -- |
| 116 | 113 | 120 | 125 | 9 |
</Route>
## Chiphell
### 子版块
@ -394,6 +358,30 @@ pageClass: routes
<Route author="liyefox" example="/v2ex/tab/hot" path="/v2ex/tab/:tabid" :paramsDesc="['tab标签ID,在 URL 可以找到']"/>
## X岛匿名版
### 串
<Route author="miles170" example="/nmbxd1/1" path="/nmbxd1/:id" :paramsDesc="['板块 id 或者板块名称,现有板块请参考下表']" >
| 综合线 | 非创作线 | 综合版 1 | 欢乐恶搞 | 买买买 (剁手) | 数码 (装机) | 技术 (码农) | 科学 (干货) | 二创 (画师) | 电影 / 电视 | ROLL 点 |
| ------ | -------- | -------- | -------- | ------------- | ----------- | ----------- | ----------- | ----------- | ----------- | ------- |
| 1 | 3 | 综合版1 | 欢乐恶搞 | 买买买 | 数码 | 技术宅 | 科学 | 二创 | 影视 | ROLL点 |
| 动画 | 漫画 | 主播 (UP) | 特摄 | 胶佬 (手办) | 小马 (美漫) | 东方 Project | 舰娘 | VOCALOID |
| ---- | ---- | --------- | ---- | ----------- | ----------- | ------------ | ---- | -------- |
| 动画 | 漫画 | 主播 | 特摄 | 胶佬 | 小马 | 东方Project | 舰娘 | VOCALOID |
| 游戏综合版 | 手游 | 卡牌桌游 | 任天堂 NS | LOL | SE(FF14) | DOTA & 自走棋 | 联机 (服务器发布) | 怪物猎人 | 鹰角游戏 | 米哈游 | 音乐游戏 |
| ---------- | ---- | -------- | --------- | --- | -------- | ------------- | --------------------- | -------- | -------- | ------ | -------- |
| 游戏 | 手游 | 卡牌桌游 | 任天堂 | LOL | SE | DOTA | 联机%28服务器发布%29 | 怪物猎人 | 鹰角游戏 | 米哈游 | 音游 |
| 跑团 | 规则怪谈 | 都市怪谈 (灵异) | 脑洞 (推理) | 料理 (美食) | 宠物 | 学业 (校园) | 社畜 | 育儿 | 摄影 (cos) | 文学 (推书) | 音乐 (推歌) | 技术支持 |
| ---- | -------- | --------------- | ----------- | ----------- | ---- | ----------- | ---- | ---- | ------------- | ----------- | ----------- | -------- |
| 跑团 | 规则怪谈 | 都市怪谈 | 推理 | 料理 | 宠物 | 考试 | 社畜 | 育儿 | 摄影%28cos%29 | 文学 | 音乐 | 技术支持 |
</Route>
## Zuvio
### 校園話題

View File

@ -2661,9 +2661,6 @@ router.get('/hbut/cs/:type', lazyloadRouteHandler('./routes/universities/hbut/cs
// acwifi
router.get('/acwifi', lazyloadRouteHandler('./routes/acwifi'));
// a岛匿名版
router.get('/adnmb/:pid', lazyloadRouteHandler('./routes/adnmb/index'));
// MIT科技评论
router.get('/mittrchina/:type', lazyloadRouteHandler('./routes/mittrchina'));

View File

@ -1,69 +0,0 @@
const got = require('@/utils/got');
const adnmbBaseUrl = 'https://adnmb3.com';
const cdnBaseUrl = 'https://nmbimg.fastmirror.org/image/';
async function getForumInfo(pid, ctx) {
const cache_key = `adnmb::forum::${pid}`;
const cache = await ctx.cache.get(cache_key);
if (cache) {
return JSON.parse(cache);
}
const forumListResponse = await got(`${adnmbBaseUrl}/Api/getForumList`);
const matchedForum = forumListResponse.data
.map((a) => a.forums)
.flat()
.filter((c) => c.id === pid || c.name === pid || c.showName === pid);
if (matchedForum.length === 0) {
throw 'Forum Not Found';
}
const basicForumInfo = (({ id, name, showName, msg }) => ({ id, name, showName, msg }))(matchedForum[0]);
ctx.cache.set(cache_key, JSON.stringify(basicForumInfo));
return basicForumInfo;
}
module.exports = async (ctx) => {
const pid = ctx.params.pid;
const forumInfo = await getForumInfo(pid, ctx);
const url = forumInfo.name === '时间线' ? `${adnmbBaseUrl}/Api/timeline?page=1` : `${adnmbBaseUrl}/Api/showf?id=${forumInfo.id}&page=1`;
const response = await got({
method: 'get',
url,
});
const data = response.data;
const items = [];
data.forEach((item) => {
const newItems = {
title: item.content,
pubDate: new Date(item.now.replace(/\(.*?\)/g, ' ') + ' +0800').toUTCString(),
link: `${adnmbBaseUrl}/t/${item.id}`,
};
const img = item.img !== '' ? '<img style="max-width: 100%" src="' + cdnBaseUrl + item.img + item.ext + '"/>' : '';
let replys = '';
item.replys.forEach((reply) => {
const replyImg = reply.img !== '' ? '<img style="max-width: 100%" src="' + cdnBaseUrl + reply.img + reply.ext + '"/>' : '';
replys += `<h4>${reply.title} ${reply.name} ${reply.now} ID:${reply.userid} No.${reply.id}</h4> </br>
${reply.content}
${replyImg}
<hr />
`;
});
newItems.description = `<h2>${item.title} ${item.name} ${item.now} ID:${item.userid} No.${item.id}</h2> </br>
${item.content}
${img}
<hr />
${replys}
`;
items.push(newItems);
});
ctx.state.data = {
title: `${forumInfo.showName ? forumInfo.showName : forumInfo.name} - A岛匿名版`,
link: `${adnmbBaseUrl}/f/${forumInfo.name}`,
description: forumInfo.msg,
item: items,
};
};

58
lib/v2/nmbxd1/forum.js Normal file
View File

@ -0,0 +1,58 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');
const timezone = require('@/utils/timezone');
const { art } = require('@/utils/render');
const path = require('path');
module.exports = async (ctx) => {
const id = ctx.params.id;
const rootUrl = 'https://www.nmbxd1.com';
const currentUrl = /^\d+$/.test(id) ? `${rootUrl}/Forum/timeline/id/${id}` : `${rootUrl}/f/${id}`;
const response = await got(currentUrl);
const $ = cheerio.load(response.data);
$('.h-threads-img-tool').remove();
$('.h-threads-item-reply-icon').remove();
$('.h-admin-tool').remove();
$('.h-threads-tips').remove();
$('.h-threads-info-report-btn').remove();
$('.h-threads-info-reply-btn').remove();
const items = $('.h-threads-item')
.get()
.map((item) => {
item = $(item);
// Do not remove the info element to keep the description style consistent.
const info = item.find('.h-threads-item-main .h-threads-info');
const title = info.find('.h-threads-info-title').text();
const author = [info.find('.h-threads-info-uid font'), info.find('.h-threads-info-uid')]
.find((elem) => elem.length > 0)
.contents()
.first()
.text()
.replace(/^ID:/, '');
const category = info.find('spam').text();
const link = new URL(rootUrl + info.find('.h-threads-info-id').attr('href'));
// cleanup query paramter
link.query = link.search = '';
const pubDate = timezone(parseDate(info.find('.h-threads-info-createdat').text().replace(/\(.\)/, ' ')), +8);
return {
title,
author,
category,
description: art(path.join(__dirname, 'templates/description.art'), {
item: item.html(),
}),
pubDate,
link: link.toString(),
};
});
ctx.state.data = {
title: $('title').text(),
link: currentUrl,
description: $('meta[name=description]').attr('content'),
item: items,
};
};

View File

@ -0,0 +1,3 @@
module.exports = {
'/:id': ['miles170'],
};

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

@ -0,0 +1,13 @@
module.exports = {
'nmbxd1.com': {
_name: 'X岛匿名版',
www: [
{
title: '串',
docs: 'https://docs.rsshub.app/bbs.html#x-dao-ni-ming-ban',
source: ['/Forum/timeline/id/:id', '/f/:id'],
target: '/nmbxd1/:id',
},
],
},
};

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

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

View File

@ -0,0 +1,65 @@
<div class="h-threads-item">
{{@ item }}
</div>
<style>
.h-threads-item {
display: block;
background: #ffe;
color: #800000;
}
.h-threads-item .h-threads-img-box {
display: inline;
position: relative;
margin: 3px 0;
}
.h-threads-item .h-threads-img-box .h-threads-img-a .h-threads-img {
padding: 0;
margin: 0 20px;
max-width: 250px;
}
.h-threads-item .h-threads-info .h-threads-info-title {
font-weight: bold;
color: #cc1105;
}
.h-threads-item .h-threads-info .h-threads-info-email {
font-weight: bold;
color: #117743;
}
.h-threads-item .h-threads-info .h-threads-info-email,
.h-threads-item .h-threads-info .h-threads-info-createdat,
.h-threads-item .h-threads-info .h-threads-info-uid,
.h-threads-item .h-threads-info .h-threads-info-id,
.h-threads-item .h-threads-info,
.h-threads-item .h-threads-info {
margin-left: 5px;
}
.h-threads-item .h-threads-info {
font-size: 12px;
}
.h-threads-item .h-threads-info a {
margin: 0 2px;
}
.h-threads-item .h-threads-content {
font-size: 16px;
line-height: 22px;
margin: 15px 40px;
}
.h-threads-item .h-threads-item-replies .h-threads-item-reply {
display: table;
margin-bottom: 3px;
}
.h-threads-item .h-threads-item-replies .h-threads-item-reply .h-threads-item-reply-main {
display: table-cell;
background: #f0e0d6;
}
</style>