feat(route): add Luogu user blog (#11527)

* feat(route): add Luogu user blog

* used html as description instead

* Do not set pubDate if there isn't any.

* used Luogu API
This commit is contained in:
Xiaoxu Guo
2023-01-02 02:17:04 +08:00
committed by GitHub
parent 2ef5e8b526
commit 14503131bc
5 changed files with 66 additions and 0 deletions

View File

@@ -1013,6 +1013,10 @@ GitHub 官方也提供了一些 RSS:
<Route author="solstice23" example="/luogu/user/feed/1" path="/luogu/user/feed/:uid" :paramsDesc="['用户 UID']" radar="1" rssbud="1"/>
### 用户博客
<Route author="ftiasch" example="/luogu/user/blog/ftiasch" path="/luogu/user/blog/:username" :paramsDesc="['用户名']" radar="1" rssbud="1"/>
## 码农俱乐部
### 话题

View File

@@ -2,4 +2,5 @@ module.exports = {
'/contest': ['prnake'],
'/daily/:id?': ['LogicJake ', 'prnake ', 'nczitzk'],
'/user/feed/:uid': ['solstice23'],
'/user/blog/:username': ['ftiasch'],
};

View File

@@ -20,6 +20,12 @@ module.exports = {
source: ['/user/:uid'],
target: '/luogu/user/feed/:uid',
},
{
title: '用户博客',
docs: 'https://docs.rsshub.app/programming.html#luo-gu',
source: ['/blog/:username'],
target: '/luogu/user/blog/:username',
},
],
},
};

View File

@@ -2,4 +2,5 @@ module.exports = (router) => {
router.get('/contest', require('./contest'));
router.get('/daily/:id?', require('./daily'));
router.get('/user/feed/:uid', require('./userFeed'));
router.get('/user/blog/:username', require('./userBlog'));
};

54
lib/v2/luogu/userBlog.js Normal file
View File

@@ -0,0 +1,54 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
module.exports = async (ctx) => {
const username = ctx.params.username;
// Convert from `username` to `uid`
const userApiUrl = `https://www.luogu.com.cn/api/user/search?keyword=${username}`;
const uid = await ctx.cache.tryGet(userApiUrl, async () => {
const rsp = await got(userApiUrl).json();
return rsp.users[0].uid;
});
// Get the title and link from the sitemap
const sitemapUrl = `https://www.luogu.com.cn/blog/${username}/_sitemap`;
const { title: blogTitle, link: blogBaseUrl } = await ctx.cache.tryGet(sitemapUrl, async () => {
const rsp = await got(sitemapUrl);
const $ = cheerio.load(rsp.data);
const title = $('title').text();
const link = $('.am-alert > a').attr('href');
return {
title,
link,
};
});
const posts = (await got(`https://www.luogu.com.cn/api/blog/lists?uid=${uid}`).json()).data.result.map((r) => ({
title: r.title,
link: `${blogBaseUrl}${r.identifier}`,
pubDate: new Date(r.postTime * 1000),
}));
// Get the full text
const item = await Promise.all(
posts.map((post) =>
ctx.cache.tryGet(post.link, async () => {
const rsp = await got.get(post.link);
const $ = cheerio.load(rsp.data);
return {
title: post.title,
link: post.link,
pubDate: post.pubDate,
description: $('#article-content').html(),
};
})
)
);
ctx.state.data = {
title: blogTitle,
link: blogBaseUrl,
item,
};
};