From 8dfd93e515d9036d08cca65da2138faa16eb4221 Mon Sep 17 00:00:00 2001 From: Tony Date: Tue, 23 Aug 2022 01:13:35 +0600 Subject: [PATCH] feat(route): meteor (#10566) * feat(route): meteor * fix: skip find --- docs/bbs.md | 10 ++++ lib/v2/meteor/boards.js | 11 ++++ lib/v2/meteor/index.js | 45 ++++++++++++++++ lib/v2/meteor/maintainer.js | 4 ++ lib/v2/meteor/radar.js | 19 +++++++ lib/v2/meteor/router.js | 4 ++ lib/v2/meteor/templates/desc.art | 7 +++ lib/v2/meteor/utils.js | 90 ++++++++++++++++++++++++++++++++ 8 files changed, 190 insertions(+) create mode 100644 lib/v2/meteor/boards.js create mode 100644 lib/v2/meteor/index.js create mode 100644 lib/v2/meteor/maintainer.js create mode 100644 lib/v2/meteor/radar.js create mode 100644 lib/v2/meteor/router.js create mode 100644 lib/v2/meteor/templates/desc.art create mode 100644 lib/v2/meteor/utils.js diff --git a/docs/bbs.md b/docs/bbs.md index 86d225a45..c400a63b0 100644 --- a/docs/bbs.md +++ b/docs/bbs.md @@ -250,6 +250,16 @@ pageClass: routes +## Meteor + +### 看板 + + + +### 看板列表 + + + ## Mobilism ### 论坛 diff --git a/lib/v2/meteor/boards.js b/lib/v2/meteor/boards.js new file mode 100644 index 000000000..bcd2a74c7 --- /dev/null +++ b/lib/v2/meteor/boards.js @@ -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, + }; +}; diff --git a/lib/v2/meteor/index.js b/lib/v2/meteor/index.js new file mode 100644 index 000000000..af11f68c3 --- /dev/null +++ b/lib/v2/meteor/index.js @@ -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, + }; +}; diff --git a/lib/v2/meteor/maintainer.js b/lib/v2/meteor/maintainer.js new file mode 100644 index 000000000..e7167842b --- /dev/null +++ b/lib/v2/meteor/maintainer.js @@ -0,0 +1,4 @@ +module.exports = { + '/boards': ['TonyRL'], + '/:board': ['TonyRL'], +}; diff --git a/lib/v2/meteor/radar.js b/lib/v2/meteor/radar.js new file mode 100644 index 000000000..62ddb22e1 --- /dev/null +++ b/lib/v2/meteor/radar.js @@ -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', + }, + ], + }, +}; diff --git a/lib/v2/meteor/router.js b/lib/v2/meteor/router.js new file mode 100644 index 000000000..a864c3020 --- /dev/null +++ b/lib/v2/meteor/router.js @@ -0,0 +1,4 @@ +module.exports = (router) => { + router.get('/boards', require('./boards')); + router.get('/:board', require('./index')); +}; diff --git a/lib/v2/meteor/templates/desc.art b/lib/v2/meteor/templates/desc.art new file mode 100644 index 000000000..9639bc1c1 --- /dev/null +++ b/lib/v2/meteor/templates/desc.art @@ -0,0 +1,7 @@ +{{ if youTube }} + +{{ else if img }} + +{{ else if video }} + +{{ /if }} diff --git a/lib/v2/meteor/utils.js b/lib/v2/meteor/utils.js new file mode 100644 index 000000000..451b07ddd --- /dev/null +++ b/lib/v2/meteor/utils.js @@ -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, '
'); +}; + +module.exports = { + baseUrl, + getBoards, + renderDesc, +};