diff --git a/lib/v2/mihoyo/bbs/cache.js b/lib/v2/mihoyo/bbs/cache.js new file mode 100644 index 00000000000000..1d400008478748 --- /dev/null +++ b/lib/v2/mihoyo/bbs/cache.js @@ -0,0 +1,33 @@ +const got = require('@/utils/got'); + +module.exports = { + getUserFullInfo: (ctx, uid) => { + const key = 'mihoyo:user-full-info-uid-' + uid; + return ctx.cache.tryGet(key, async () => { + const query = new URLSearchParams({ + uid, + gids: 2, + }).toString(); + const url = `https://bbs-api.miyoushe.com/user/wapi/getUserFullInfo?${query}`; + const response = await got({ + method: 'get', + url, + headers: { + Referer: `https://www.miyoushe.com/ys/accountCenter/postList?id=${uid}`, + }, + }); + const userInfo = response?.data?.data?.user_info; + if (!userInfo) { + throw new Error('未获取到数据!'); + } + const { nickname, introduce, gender, certification, avatar_url } = userInfo; + return { + nickname, + introduce, + gender, + certification, + avatar_url, + }; + }); + }, +}; diff --git a/lib/v2/mihoyo/bbs/follow-list.js b/lib/v2/mihoyo/bbs/follow-list.js new file mode 100644 index 00000000000000..8acbf2588cfa2a --- /dev/null +++ b/lib/v2/mihoyo/bbs/follow-list.js @@ -0,0 +1,50 @@ +const got = require('@/utils/got'); +const { art } = require('@/utils/render'); +const path = require('path'); +const cache = require('./cache'); + +const renderDescription = (description, images) => art(path.join(__dirname, '../templates/description.art'), { description, images }); + +module.exports = async (ctx) => { + const { uid } = ctx.params; + const page_size = ctx.query.limit || '20'; + const searchParams = { + gids: 2, + uid, + page_size, + }; + const link = `https://www.miyoushe.com/ys/accountCenter/followList?id=${uid}`; + const url = `https://bbs-api.miyoushe.com/user/wapi/following`; + const response = await got({ + method: 'get', + url, + searchParams, + headers: { + Origin: 'https://www.miyoushe.com', + Referer: link, + }, + }); + const list = response?.data?.data?.result; + if (!list) { + throw new Error('未获取到数据!'); + } + const { nickname: username } = await cache.getUserFullInfo(ctx, uid); + const title = `米游社 - ${username} 的关注`; + const items = list.map((e) => { + const title = e.user.nickname; + const link = `https://www.miyoushe.com/ys/accountCenter/postList?id=${e.user.uid}`; + const description = renderDescription(`${e.user.certification.label || ''}\n${e.user.introduce || ''}`.trim(), [e.user.avatar_url]); + return { + title, + link, + description, + }; + }); + + const data = { + title, + link, + item: items, + }; + ctx.state.data = data; +}; diff --git a/lib/v2/mihoyo/bbs/img-ranking.js b/lib/v2/mihoyo/bbs/img-ranking.js index 92d11c8477f166..6d988b7f98e24f 100644 --- a/lib/v2/mihoyo/bbs/img-ranking.js +++ b/lib/v2/mihoyo/bbs/img-ranking.js @@ -78,7 +78,7 @@ module.exports = async (ctx) => { const items = list.map((e) => { const author = e.user.nickname; const title = e.post.subject; - const link = `https://bbs.mihoyo.com/ys/article/${e.post.post_id}`; + const link = `https://www.miyoushe.com/ys/article/${e.post.post_id}`; let describe = e.post.content || ''; try { describe = JSON.parse(e.post.content).describe; @@ -87,14 +87,18 @@ module.exports = async (ctx) => { throw error; } } - const description = renderDescription(describe || '', [e.post.cover, ...e.post.images]); + const description = renderDescription(describe || '', [...new Set([e.post.cover, ...e.post.images])].filter(Boolean)); const pubDate = parseDate(e.post.created_at * 1000); + const upvotes = e.stat.like_num; + const comments = e.stat.reply_num; return { author, title, link, description, pubDate, + upvotes, + comments, }; }); const data = { diff --git a/lib/v2/mihoyo/bbs/official.js b/lib/v2/mihoyo/bbs/official.js index 385263fc6edb60..00639fd6f3f8c1 100644 --- a/lib/v2/mihoyo/bbs/official.js +++ b/lib/v2/mihoyo/bbs/official.js @@ -29,7 +29,7 @@ module.exports = async (ctx) => { page_size, last_id, }).toString(); - const url = `https://bbs-api.mihoyo.com/post/wapi/getNewsList?${query}`; + const url = `https://bbs-api.miyoushe.com/post/wapi/getNewsList?${query}`; const response = await got({ method: 'get', url, @@ -42,7 +42,7 @@ module.exports = async (ctx) => { const items = list.map((e) => { const author = e.user.nickname; const title = e.post.subject; - const link = `https://bbs.mihoyo.com/ys/article/${e.post.post_id}`; + const link = `https://www.miyoushe.com/ys/article/${e.post.post_id}`; const description = renderDescription(e.post.content, e.post.images); const pubDate = parseDate(e.post.created_at * 1000); return { diff --git a/lib/v2/mihoyo/bbs/user-post.js b/lib/v2/mihoyo/bbs/user-post.js new file mode 100644 index 00000000000000..c68302ae352245 --- /dev/null +++ b/lib/v2/mihoyo/bbs/user-post.js @@ -0,0 +1,61 @@ +const got = require('@/utils/got'); +const { art } = require('@/utils/render'); +const path = require('path'); +const { parseDate } = require('@/utils/parse-date'); + +const renderDescription = (description, images) => art(path.join(__dirname, '../templates/description.art'), { description, images }); + +module.exports = async (ctx) => { + const { uid } = ctx.params; + const size = ctx.query.limit || '20'; + const searchParams = { + uid, + size, + }; + const link = `https://www.miyoushe.com/ys/accountCenter/postList?id=${uid}`; + const url = `https://bbs-api.miyoushe.com/post/wapi/userPost`; + const response = await got({ + method: 'get', + url, + searchParams, + }); + const list = response?.data?.data?.list; + if (!list) { + throw new Error('未获取到数据!'); + } + const username = list[0]?.user.nickname; + const title = `米游社 - ${username} 的发帖`; + const items = list.map((e) => { + const author = e.user.nickname; + const title = e.post.subject; + const link = `https://www.miyoushe.com/ys/article/${e.post.post_id}`; + let describe = e.post.content || ''; + try { + describe = JSON.parse(e.post.content).describe; + } catch (error) { + if (!(error instanceof SyntaxError)) { + throw error; + } + } + const description = renderDescription(describe || '', [...new Set([e.post.cover, ...e.post.images])].filter(Boolean)); + const pubDate = parseDate(e.post.created_at * 1000); + const upvotes = e.stat.like_num; + const comments = e.stat.reply_num; + return { + author, + title, + link, + description, + pubDate, + upvotes, + comments, + }; + }); + + const data = { + title, + link, + item: items, + }; + ctx.state.data = data; +}; diff --git a/lib/v2/mihoyo/maintainer.js b/lib/v2/mihoyo/maintainer.js index d7e5821f3c438f..7eb64e1a81e80a 100644 --- a/lib/v2/mihoyo/maintainer.js +++ b/lib/v2/mihoyo/maintainer.js @@ -1,6 +1,8 @@ module.exports = { + '/bbs/follow-list/:uid': ['CaoMeiYouRen'], '/bbs/img-ranking/:game/:routeParams?': ['CaoMeiYouRen'], '/bbs/official/:gids/:type?/:page_size?/:last_id?': ['CaoMeiYouRen'], + '/bbs/user-post/:uid': ['CaoMeiYouRen'], '/sr/:location?/:category?': ['shinanory'], '/ys/:location?/:category?': ['nczitzk'], }; diff --git a/lib/v2/mihoyo/radar.js b/lib/v2/mihoyo/radar.js index e7a61d00aa725d..e49873a683d399 100644 --- a/lib/v2/mihoyo/radar.js +++ b/lib/v2/mihoyo/radar.js @@ -1,3 +1,53 @@ +const bbs = [ + { + title: '米游社 - 用户关注', + docs: 'https://docs.rsshub.app/routes/game#mi-ha-you', + source: '/:game/accountCenter/postList', + target: (params, url) => { + const uid = new URL(url).searchParams.get('id'); + return `/mihoyo/bbs/follow-list/${uid}`; + }, + }, + { + title: '米游社 - 同人榜', + docs: 'https://docs.rsshub.app/routes/game#mi-ha-you', + source: '/:game/imgRanking/:forum_id/:ranking_id/:cate_id', + target: `/mihoyo/bbs/img-ranking/:game`, + }, + { + title: '米游社 - 官方公告', + docs: 'https://docs.rsshub.app/routes/game#mi-ha-you', + source: ['/:game/home/28', '/:game/home/6', '/:game/home/31', '/:game/home/33', '/:game/home/53', '/:game/home/58'], + target: (params, url) => { + const GITS_MAP = { + bh3: 1, // '崩坏三', + ys: 2, // '原神', + bh2: 3, // '崩坏二', + wd: 4, // '未定事件簿', + sr: 6, // '崩坏:星穹铁道', + zzz: 8, // '绝区零' + }; + const { game } = params; + const gids = GITS_MAP[game]; + if (!gids) { + return ''; + } + const type = new URL(url).searchParams.get('type') || '1'; + const page_size = '20'; + const last_id = ''; + return `/mihoyo/bbs/official/${gids}/${type}/${page_size}/${last_id}`; + }, + }, + { + title: '米游社 - 用户帖子', + docs: 'https://docs.rsshub.app/routes/game#mi-ha-you', + source: '/:game/accountCenter/postList', + target: (params, url) => { + const uid = new URL(url).searchParams.get('id'); + return `/mihoyo/bbs/user-post/${uid}`; + }, + }, +]; module.exports = { 'hoyoverse.com': { _name: '米哈游', @@ -20,38 +70,7 @@ module.exports = { }, 'mihoyo.com': { _name: '米哈游', - bbs: [ - { - title: '米游社 - 同人榜', - docs: 'https://docs.rsshub.app/routes/game#mi-ha-you', - source: '/:game/imgRanking/:forum_id/:ranking_id/:cate_id', - target: `/mihoyo/bbs/img-ranking/:game`, - }, - { - title: '米游社 - 官方公告', - docs: 'https://docs.rsshub.app/routes/game#mi-ha-you', - source: ['/:game/home/28', '/:game/home/6', '/:game/home/31', '/:game/home/33', '/:game/home/53', '/:game/home/58'], - target: (params, url) => { - const GITS_MAP = { - bh3: 1, // '崩坏三', - ys: 2, // '原神', - bh2: 3, // '崩坏二', - wd: 4, // '未定事件簿', - sr: 6, // '崩坏:星穹铁道', - zzz: 8, // '绝区零' - }; - const { game } = params; - const gids = GITS_MAP[game]; - if (!gids) { - return ''; - } - const type = new URL(url).searchParams.get('type') || '1'; - const page_size = '20'; - const last_id = ''; - return `/mihoyo/bbs/official/${gids}/${type}/${page_size}/${last_id}`; - }, - }, - ], + bbs, sr: [ { title: '崩坏:星穹铁道 - 新闻', @@ -69,4 +88,8 @@ module.exports = { }, ], }, + 'miyoushe.com': { + _name: '米游社', + '.': bbs, + }, }; diff --git a/lib/v2/mihoyo/router.js b/lib/v2/mihoyo/router.js index d9cdb704ad3ec5..c45443e727a6db 100644 --- a/lib/v2/mihoyo/router.js +++ b/lib/v2/mihoyo/router.js @@ -1,6 +1,8 @@ module.exports = function (router) { + router.get('/bbs/follow-list/:uid', require('./bbs/follow-list')); router.get('/bbs/img-ranking/:game/:routeParams?', require('./bbs/img-ranking')); router.get('/bbs/official/:gids/:type?/:page_size?/:last_id?', require('./bbs/official')); + router.get('/bbs/user-post/:uid', require('./bbs/user-post')); router.get('/sr/:location?/:category?', require('./sr/news')); router.get('/ys/:location?/:category?', require('./ys/news')); }; diff --git a/website/docs/routes/game.mdx b/website/docs/routes/game.mdx index 17192d6eab76b7..236aa5cdcd2254 100644 --- a/website/docs/routes/game.mdx +++ b/website/docs/routes/game.mdx @@ -658,7 +658,7 @@ Example:`https://www.iyingdi.com/tz/people/55547` ,id 是 `55547` ### 米游社 - 同人榜 {#mi-ha-you-mi-you-she-tong-ren-bang} - + | 键 | 含义 | 接受的值 | 默认值 | | ----------- | ------------------------------------- | -------------------------------------------------------------------- | ------------ | | forumType | 主榜类型(仅原神、大别野有 cos 主榜) | tongren/cos | tongren | @@ -701,7 +701,7 @@ Example:`https://www.iyingdi.com/tz/people/55547` ,id 是 `55547` ### 米游社 - 官方公告 {#mi-ha-you-mi-you-she-guan-fang-gong-gao} - + 游戏 id | 崩坏三 | 原神 | 崩坏二 | 未定事件簿 | 星穹铁道 | 绝区零 | @@ -715,6 +715,14 @@ Example:`https://www.iyingdi.com/tz/people/55547` ,id 是 `55547` | 1 | 2 | 3 | +### 米游社 - 用户关注 {#mi-ha-you-mi-you-she-yong-hu-guan-zhu} + + + +### 米游社 - 用户帖子 {#mi-ha-you-mi-you-she-yong-hu-tie-zi} + + + ### 原神 {#mi-ha-you-yuan-shen} #### 新闻 {#mi-ha-you-yuan-shen-xin-wen}