feat(route): meteor (#10566)

* feat(route): meteor

* fix: skip find
This commit is contained in:
Tony 2022-08-23 01:13:35 +06:00 committed by GitHub
parent 3aae8f06bd
commit 8dfd93e515
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 190 additions and 0 deletions

View File

@ -250,6 +250,16 @@ pageClass: routes
<Route author="cssxsh" example="/mcbbs/post/915861/3038" path="/mcbbs/post/:tid/:authorid?" :paramsDesc="['贴子id可在帖子 URL 找到', '用户id此参数不为空时只看此作者']"/>
## Meteor
### 看板
<Route author="TonyRL" example="/meteor/board/all" path="/meteor/board/:board?" :paramsDesc="['看板 ID 或簡稱,可在 URL 或下方路由找到,預設為 `all`']" radar="1" rssbud="1"/>
### 看板列表
<Route author="TonyRL" example="/meteor/boards" path="/meteor/boards" radar="1" rssbud="1"/>
## Mobilism
### 论坛

11
lib/v2/meteor/boards.js Normal file
View File

@ -0,0 +1,11 @@
const { baseUrl, getBoards } = require('./utils');
module.exports = async (ctx) => {
const items = await getBoards(ctx.cache.tryGet);
ctx.state.data = {
title: '看板列表',
link: `${baseUrl}/board/all`,
item: items,
};
};

45
lib/v2/meteor/index.js Normal file
View File

@ -0,0 +1,45 @@
const got = require('@/utils/got');
const { parseDate } = require('@/utils/parse-date');
const { baseUrl, getBoards, renderDesc } = require('./utils');
module.exports = async (ctx) => {
let { board = 'all' } = ctx.params;
const boards = await getBoards(ctx.cache.tryGet);
let boardInfo;
if (board !== 'all') {
boardInfo = boards.find((b) => b.id === board || b.alias === board);
board = boardInfo.id;
}
const { data: response } = await got.post(`${baseUrl}/article/get_new_articles`, {
json: {
boardId: board,
isCollege: false,
page: 0,
pageSize: ctx.query.limit ? Number(ctx.query.limit) : 30,
},
});
const result = JSON.parse(decodeURIComponent(response.result));
const items = await Promise.all(
result.map((item) =>
ctx.cache.tryGet(`meteor:${item.id}`, () => ({
title: item.title,
description: renderDesc(item.content),
link: `${baseUrl}/article/${item.shortId}`,
author: item.authorAlias,
pubDate: parseDate(item.createdAt),
}))
)
);
ctx.state.data = {
title: `${board !== 'all' ? boardInfo.title : '全部看板'} | Meteor 學生社群`,
description: board !== 'all' ? boardInfo.feedDescription : null,
image: board !== 'all' ? (boardInfo.imgUrl !== 'not_set' ? boardInfo.imgUrl : null) : null,
link: `${board !== 'all' ? boardInfo.link : `${baseUrl}/board/all`}/new`,
item: items,
};
};

View File

@ -0,0 +1,4 @@
module.exports = {
'/boards': ['TonyRL'],
'/:board': ['TonyRL'],
};

19
lib/v2/meteor/radar.js Normal file
View File

@ -0,0 +1,19 @@
module.exports = {
'meteor.today': {
_name: 'Meteor',
'.': [
{
title: '看板',
docs: 'https://docs.rsshub.app/bbs.html#meteor',
source: ['/board/:board', '/board/:board/new'],
target: '/meteor/board/:board',
},
{
title: '看板列表',
docs: 'https://docs.rsshub.app/bbs.html#meteor',
source: ['/'],
target: '/meteor/boards',
},
],
},
};

4
lib/v2/meteor/router.js Normal file
View File

@ -0,0 +1,4 @@
module.exports = (router) => {
router.get('/boards', require('./boards'));
router.get('/:board', require('./index'));
};

View File

@ -0,0 +1,7 @@
{{ if youTube }}
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/{{ youTube }}" frameborder="0" allowfullscreen></iframe>
{{ else if img }}
<img src="{{ img }}">
{{ else if video }}
<video src="{{ video }}" controls></video>
{{ /if }}

90
lib/v2/meteor/utils.js Normal file
View File

@ -0,0 +1,90 @@
const got = require('@/utils/got');
const { art } = require('@/utils/render');
const path = require('path');
const baseUrl = 'https://meteor.today';
const getBoards = (tryGet) =>
tryGet('meteor:boards', async () => {
const { data: response } = await got.post(`${baseUrl}/board/get_boards`, {
json: {
isCollege: 'false',
},
});
return JSON.parse(decodeURIComponent(response.result)).map((item) => ({
title: `${item.category ? `${item.category} - ` : ''}${item.name}`,
description: item.id,
feedDescription: item.description,
category: item.articleCategory,
link: `${baseUrl}/board/${item.alias ? item.alias : item.name}`,
alias: item.alias,
imgUrl: item.imageUrl,
id: item.id,
}));
});
const renderDesc = (desc) => {
const youTube = /(?:https?:\/\/)?(?:www\.)?youtu\.?be(?:\.com)?\/?.*(?:watch|embed)?(?:.*v=|v\/|\/)([\w\-_]+)&?/g;
const matchYouTube = desc.match(youTube);
const matchImgur = desc.match(/https:\/\/i.imgur.com\/\w*.(jpg|png|gif|jpeg)/g);
const matchVideo = desc.match(/(https:\/\/storage\.meteor\.today\/video\/[0-9a-fA-F]{24}\.)(mp4|mov|avi|flv|wmv|mpeg|mkv)/gi);
const matchSticker = desc.match(/assets\/images\/stickers\/(duck|ep2|ep1)\/\w*.(jpg|png|gif|jpeg)/g);
const matchEmoji = desc.match(/assets\/images\/emoji\/\w*.(jpg|png|gif|jpeg)/g);
if (matchYouTube) {
desc = desc.replace(
youTube,
art(path.join(__dirname, 'templates/desc.art'), {
youTube: '$1',
})
);
}
if (matchImgur) {
for (const img of matchImgur) {
desc = desc.replace(
img,
art(path.join(__dirname, 'templates/desc.art'), {
img,
})
);
}
}
if (matchVideo) {
for (const video of matchVideo) {
desc = desc.replace(
video,
art(path.join(__dirname, 'templates/desc.art'), {
video,
})
);
}
}
if (matchSticker) {
for (const sticker of matchSticker) {
desc = desc.replace(
sticker,
art(path.join(__dirname, 'templates/desc.art'), {
img: sticker,
})
);
}
}
if (matchEmoji) {
for (const emoji of matchEmoji) {
desc = desc.replace(
emoji,
art(path.join(__dirname, 'templates/desc.art'), {
img: emoji,
})
);
}
}
return desc.replace(/\n/g, '<br>');
};
module.exports = {
baseUrl,
getBoards,
renderDesc,
};