parent
3aae8f06bd
commit
8dfd93e515
10
docs/bbs.md
10
docs/bbs.md
|
|
@ -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
|
||||
|
||||
### 论坛
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = {
|
||||
'/boards': ['TonyRL'],
|
||||
'/:board': ['TonyRL'],
|
||||
};
|
||||
|
|
@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = (router) => {
|
||||
router.get('/boards', require('./boards'));
|
||||
router.get('/:board', require('./index'));
|
||||
};
|
||||
|
|
@ -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 }}
|
||||
|
|
@ -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,
|
||||
};
|
||||
Loading…
Reference in New Issue