From b126e7bc571009888f27571b281aa138bdefc232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=99=8E=E6=95=85=E6=B4=9E?= <55782476+TigerWolfDen@users.noreply.github.com> Date: Sun, 1 Nov 2020 23:39:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20=E5=93=94=E5=93=A9?= =?UTF-8?q?=E5=93=94=E5=93=A9-=E7=94=A8=E6=88=B7=E5=85=B3=E6=B3=A8?= =?UTF-8?q?=E5=8A=A8=E6=80=81=20=E8=B7=AF=E7=94=B1=20(#6014)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/social-media.md | 10 ++ lib/router.js | 1 + lib/routes/bilibili/followings_dynamic.js | 127 ++++++++++++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 lib/routes/bilibili/followings_dynamic.js diff --git a/docs/social-media.md b/docs/social-media.md index 9ffdadd889..893885f2ef 100644 --- a/docs/social-media.md +++ b/docs/social-media.md @@ -206,6 +206,16 @@ Tiny Tiny RSS 会给所有 iframe 元素添加 `sandbox="allow-scripts"` 属性 +### 用户关注动态 + + +::: warning 注意 + +用户动态需要 b 站登录后的 Cookie 值,所以只能自建,详情见部署页面的配置模块。 + +::: + + ### 用户关注视频动态 diff --git a/lib/router.js b/lib/router.js index b5a7edba52..8c6ef2c56b 100644 --- a/lib/router.js +++ b/lib/router.js @@ -85,6 +85,7 @@ router.get('/bilibili/followings/article/:uid', require('./routes/bilibili/follo router.get('/bilibili/readlist/:listid', require('./routes/bilibili/readlist')); router.get('/bilibili/weekly', require('./routes/bilibili/weekly_recommend')); router.get('/bilibili/manga/update/:comicid', require('./routes/bilibili/manga_update')); +router.get('/bilibili/followings/dynamic/:uid/:disableEmbed?', require('./routes/bilibili/followings_dynamic')); // bangumi router.get('/bangumi/calendar/today', require('./routes/bangumi/calendar/today')); diff --git a/lib/routes/bilibili/followings_dynamic.js b/lib/routes/bilibili/followings_dynamic.js new file mode 100644 index 0000000000..af83923b97 --- /dev/null +++ b/lib/routes/bilibili/followings_dynamic.js @@ -0,0 +1,127 @@ +const got = require('@/utils/got'); +const cache = require('./cache'); +const config = require('@/config').value; +const utils = require('./utils'); +const JSONbig = require('json-bigint'); + +module.exports = async (ctx) => { + const uid = String(ctx.params.uid); + const disableEmbed = ctx.params.disableEmbed; + const name = await cache.getUsernameFromUID(ctx, uid); + + const cookie = config.bilibili.cookies[uid]; + if (cookie === undefined) { + throw Error('缺少对应 uid 的 Bilibili 用户登录后的 Cookie 值'); + } + + const response = await got({ + method: 'get', + url: `https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_new?uid=${uid}&type_list=268435455`, + headers: { + Referer: `https://space.bilibili.com/${uid}/`, + Cookie: cookie, + }, + }); + if (response.data.code === -6) { + throw Error('对应 uid 的 Bilibili 用户的 Cookie 已过期'); + } + const data = JSONbig.parse(response.body).data.cards; + + ctx.state.data = { + title: `${name} 关注的动态`, + link: `https://t.bilibili.com`, + description: `${name} 关注的动态`, + item: data.map((item) => { + const parsed = JSONbig.parse(item.card); + const data = parsed.item || parsed; + const origin = parsed.origin ? JSONbig.parse(parsed.origin) : null; + + // img + let imgHTML = ''; + const getImgs = (data) => { + let imgs = ''; + // 动态图片 + if (data.pictures) { + for (let i = 0; i < data.pictures.length; i++) { + imgs += ``; + } + } + // 专栏封面 + if (data.image_urls) { + for (let i = 0; i < data.image_urls.length; i++) { + imgs += ``; + } + } + // 视频封面 + if (data.pic) { + imgs += ``; + } + // 音频/番剧/直播间封面/小视频封面 + if (data.cover && data.cover.unclipped) { + imgs += ``; + } else if (data.cover) { + imgs += ``; + } + // 专题页封面 + if (data.sketch && data.sketch.cover_url) { + imgs += ``; + } + return imgs; + }; + + imgHTML += getImgs(data); + + if (origin) { + imgHTML += getImgs(origin.item || origin); + } + // video小视频 + let videoHTML = ''; + if (data.video_playurl) { + videoHTML += ``; + } + // some rss readers disallow http content. + // 部分 RSS 阅读器要求内容必须使用https传输 + // bilibili short video does support https request, but https request may timeout ocassionally. + // to maximize content availability, here add two source tags. + // bilibili的API中返回的视频地址采用http,然而经验证,短视频地址支持https访问,但偶尔会返回超时错误(可能是网络原因)。 + // 因此保险起见加入两个source标签 + // link + let link = ''; + if (data.dynamic_id) { + link = `https://t.bilibili.com/${data.dynamic_id}`; + } else if (item.desc && item.desc.dynamic_id) { + link = `https://t.bilibili.com/${item.desc.dynamic_id}`; + } + + const getTitle = (data) => data.title || data.description || data.content || (data.vest && data.vest.content) || ''; + const getDes = (data) => + data.dynamic || data.desc || data.description || data.content || data.summary || (data.vest && data.vest.content) + (data.sketch && `
${data.sketch.title}
${data.sketch.desc_text}`) || data.intro || ''; + const getOriginDes = (data) => (data && (data.apiSeasonInfo && data.apiSeasonInfo.title && `//转发自: ${data.apiSeasonInfo.title}`) + (data.index_title && `
${data.index_title}`)) || ''; + const getOriginName = (data) => data.uname || (data.author && data.author.name) || data.upper || (data.user && (data.user.uname || data.user.name)) || (data.owner && data.owner.name) || ''; + const getOriginTitle = (data) => (data.title ? `${data.title}
` : ''); + const getIframe = (data) => (!disableEmbed && data && data.aid ? `

${utils.iframe(data.aid)}
` : ''); + + // emoji + let data_content = getDes(data); + if (item.display.emoji_info) { + const emoji = item.display.emoji_info.emoji_details; + emoji.forEach(function (item) { + data_content = data_content.replace( + new RegExp(`\\${item.text}`, 'g'), + `${item.text}` + ); + }); + } + + return { + title: getTitle(data), + author: item.desc.user_profile.info.uname, + description: `${data_content || getDes(data)}${ + origin && getOriginName(origin) ? `

//转发自: @${getOriginName(origin)}: ${getOriginTitle(origin.item || origin)}${getDes(origin.item || origin)}` : `${getOriginDes(origin)}` + }${getIframe(data)}${getIframe(origin)}${imgHTML ? `
${imgHTML}` : ''}${videoHTML ? `
${videoHTML}` : ''}`, + pubDate: new Date(item.desc.timestamp * 1000).toUTCString(), + link: link, + }; + }), + }; +};