diff --git a/lib/routes/luogu/daily.ts b/lib/routes/luogu/daily.ts index b48affaab1c139..09be4c19bc3de5 100644 --- a/lib/routes/luogu/daily.ts +++ b/lib/routes/luogu/daily.ts @@ -23,7 +23,7 @@ export const route: Route = { }, ], name: '日报', - maintainers: ['LogicJake ', 'prnake ', 'nczitzk'], + maintainers: ['LogicJake', 'prnake', 'nczitzk'], handler, url: 'luogu.com.cn/discuss/47327', }; diff --git a/lib/routes/luogu/user-article.ts b/lib/routes/luogu/user-article.ts new file mode 100644 index 00000000000000..401d59b03443b7 --- /dev/null +++ b/lib/routes/luogu/user-article.ts @@ -0,0 +1,75 @@ +import { Route } from '@/types'; +import cache from '@/utils/cache'; +import ofetch from '@/utils/ofetch'; +import * as cheerio from 'cheerio'; +import { getUserInfoFromUID } from './utils'; +import { parseDate } from '@/utils/parse-date'; + +export const route: Route = { + path: '/user/article/:uid', + categories: ['programming'], + example: '/luogu/user/article/1', + parameters: { name: '用户 UID' }, + features: { + requireConfig: false, + requirePuppeteer: false, + antiCrawler: false, + supportBT: false, + supportPodcast: false, + supportScihub: false, + }, + radar: [ + { + source: ['luogu.com/user/:uid'], + }, + { + source: ['luogu.com.cn/user/:uid'], + }, + ], + name: '用户文章', + maintainers: ['TonyRL'], + handler, +}; + +const baseUrl = 'https://www.luogu.com'; + +async function handler(ctx) { + const { uid } = ctx.req.param(); + + const userInfo = await getUserInfoFromUID(uid); + const response = await ofetch(`${baseUrl}/api/article/find`, { + query: { + user: uid, + page: 1, + ascending: false, + }, + }); + + const posts = response.articles.result.map((item) => ({ + title: item.title, + link: `${baseUrl}/article/${item.lid}`, + author: item.author.name, + pubDate: parseDate(item.time, 'X'), + description: item.content, + })); + + const item = await Promise.all( + posts.map((item) => + cache.tryGet(item.link, async () => { + const response = await ofetch(item.link); + const $ = cheerio.load(response); + item.description = $('div#rendered-preview').html(); + + return item; + }) + ) + ); + + return { + title: `${userInfo.name} 的个人中心 - 洛谷 | 计算机科学教育新生态`, + description: userInfo.description, + link: `${baseUrl}/user/${uid}#article`, + image: userInfo.avatar, + item, + }; +} diff --git a/lib/routes/luogu/user-blog.ts b/lib/routes/luogu/user-blog.ts index 6d91e5ce8215a0..51538cb4535410 100644 --- a/lib/routes/luogu/user-blog.ts +++ b/lib/routes/luogu/user-blog.ts @@ -17,12 +17,15 @@ export const route: Route = { supportScihub: false, }, radar: [ + { + source: ['luogu.com/blog/:name'], + }, { source: ['luogu.com.cn/blog/:name'], }, ], name: '用户博客', - maintainers: [], + maintainers: ['ftiasch'], handler, }; diff --git a/lib/routes/luogu/user-feed.ts b/lib/routes/luogu/user-feed.ts index 34c50ce04afbb4..bde1cd462776c5 100644 --- a/lib/routes/luogu/user-feed.ts +++ b/lib/routes/luogu/user-feed.ts @@ -1,8 +1,8 @@ import { Route } from '@/types'; -import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; import MarkdownIt from 'markdown-it'; +import { getUserInfoFromUID } from './utils'; const md = MarkdownIt(); export const route: Route = { @@ -19,6 +19,9 @@ export const route: Route = { supportScihub: false, }, radar: [ + { + source: ['luogu.com/user/:uid'], + }, { source: ['luogu.com.cn/user/:uid'], }, @@ -29,27 +32,23 @@ export const route: Route = { }; async function handler(ctx) { - const getUsernameFromUID = (uid) => - cache.tryGet('luogu:username:' + uid, async () => { - const { data } = await got(`https://www.luogu.com.cn/user/${uid}?_contentOnly=1`); - return data.currentData.user.name; - }); - const uid = ctx.req.param('uid'); - const name = await getUsernameFromUID(uid); + const userInfo = await getUserInfoFromUID(uid); const { data: response } = await got(`https://www.luogu.com.cn/api/feed/list?user=${uid}`); const data = response.feeds.result; return { - title: `${name} 的洛谷动态`, + title: `${userInfo.name} 的洛谷动态`, + description: userInfo.description, + image: userInfo.avatar, link: `https://www.luogu.com.cn/user/${uid}#activity`, allowEmpty: true, item: data.map((item) => ({ title: item.content, description: md.render(item.content), pubDate: parseDate(item.time, 'X'), - author: name, + author: userInfo.name, link: `https://www.luogu.com.cn/user/${uid}#activity`, guid: item.id, })), diff --git a/lib/routes/luogu/utils.ts b/lib/routes/luogu/utils.ts new file mode 100644 index 00000000000000..bf28c669f4758a --- /dev/null +++ b/lib/routes/luogu/utils.ts @@ -0,0 +1,17 @@ +import cache from '@/utils/cache'; +import ofetch from '@/utils/got'; + +export const getUserInfoFromUID = (uid) => + cache.tryGet('luogu:username:' + uid, async () => { + const data = await ofetch(`https://www.luogu.com/user/${uid}`, { + query: { + _contentOnly: 1, + }, + }); + + return { + name: data.data.currentData.user.name, + description: data.data.currentData.user.slogan, + avatar: data.data.currentData.user.avatar, + }; + }) as Promise<{ name: string; description: string; avatar: string }>;