diff --git a/lib/v2/weibo/friends.js b/lib/v2/weibo/friends.js
new file mode 100644
index 00000000000000..f49eff5785b348
--- /dev/null
+++ b/lib/v2/weibo/friends.js
@@ -0,0 +1,122 @@
+const querystring = require('querystring');
+const got = require('@/utils/got');
+const config = require('@/config').value;
+const weiboUtils = require('./utils');
+const { fallback, queryToBoolean } = require('@/utils/readable-social');
+
+module.exports = async (ctx) => {
+ if (!config.weibo.cookies) {
+ throw 'Weibo Friends Timeline is not available due to the absense of [Weibo Cookies]. Check relevant config tutorial';
+ }
+
+ let displayVideo = '1';
+ let displayArticle = '0';
+ let displayComments = '0';
+ if (ctx.params.routeParams) {
+ if (ctx.params.routeParams === '1' || ctx.params.routeParams === '0') {
+ displayVideo = ctx.params.routeParams;
+ } else {
+ const routeParams = querystring.parse(ctx.params.routeParams);
+ displayVideo = fallback(undefined, queryToBoolean(routeParams.displayVideo), true) ? '1' : '0';
+ displayArticle = fallback(undefined, queryToBoolean(routeParams.displayArticle), false) ? '1' : '0';
+ displayComments = fallback(undefined, queryToBoolean(routeParams.displayComments), false) ? '1' : '0';
+ }
+ }
+
+ const uid = await ctx.cache.tryGet(
+ `weibo:friends:login-user`,
+ async () => {
+ const _r = await got({
+ method: 'get',
+ url: 'https://m.weibo.cn/api/config',
+ headers: {
+ Referer: `https://m.weibo.cn/`,
+ 'MWeibo-Pwa': 1,
+ 'X-Requested-With': 'XMLHttpRequest',
+ Cookie: config.weibo.cookies,
+ },
+ });
+ return _r.data.data.uid;
+ },
+ config.cache.routeExpire,
+ false
+ );
+
+ const containerData = await ctx.cache.tryGet(
+ `weibo:user:index:${uid}`,
+ async () => {
+ const _r = await got({
+ method: 'get',
+ url: `https://m.weibo.cn/api/container/getIndex?type=uid&value=${uid}`,
+ headers: {
+ Referer: `https://m.weibo.cn/u/${uid}`,
+ 'MWeibo-Pwa': 1,
+ 'X-Requested-With': 'XMLHttpRequest',
+ Cookie: config.weibo.cookies,
+ },
+ });
+ return _r.data;
+ },
+ config.cache.routeExpire,
+ false
+ );
+
+ const name = containerData.data.userInfo.screen_name;
+ const title = `${name} 的 最新关注时间线`;
+
+ const responseData = await ctx.cache.tryGet(
+ `weibo:friends:index:${uid}`,
+ async () => {
+ const _r = await got({
+ method: 'get',
+ url: 'https://m.weibo.cn/feed/friends',
+ headers: {
+ Referer: `https://m.weibo.cn/`,
+ 'MWeibo-Pwa': 1,
+ 'X-Requested-With': 'XMLHttpRequest',
+ Cookie: config.weibo.cookies,
+ },
+ });
+ return _r.data.data;
+ },
+ config.cache.routeExpire,
+ false
+ );
+ const resultItems = await Promise.all(
+ responseData.statuses.map(async (item) => {
+ const retweet = item.retweeted_status;
+ if (retweet && retweet.isLongText) {
+ const retweetData = await ctx.cache.tryGet(`weibo:retweeted:${retweet.user.id}:${retweet.bid}`, () => weiboUtils.getShowData(retweet.user.id, retweet.bid));
+ if (retweetData !== undefined && retweetData.text) {
+ item.retweeted_status.text = retweetData.text;
+ }
+ }
+
+ const formatExtended = weiboUtils.formatExtended(ctx, item);
+ let description = formatExtended.description;
+
+ if (displayVideo === '1') {
+ description = item.retweeted_status ? weiboUtils.formatVideo(description, item.retweeted_status) : weiboUtils.formatVideo(description, item);
+ }
+
+ if (displayComments === '1') {
+ description = await weiboUtils.formatComments(ctx, description, item);
+ }
+
+ if (displayArticle === '1') {
+ description = await (item.retweeted_status ? weiboUtils.formatArticle(ctx, description, item.retweeted_status) : weiboUtils.formatArticle(ctx, description, item));
+ }
+
+ return {
+ ...formatExtended,
+ description,
+ };
+ })
+ );
+
+ ctx.state.data = weiboUtils.sinaimgTvax({
+ title,
+ link: `https://weibo.com`,
+ item: resultItems,
+ });
+};
diff --git a/lib/v2/weibo/maintainer.js b/lib/v2/weibo/maintainer.js
index 0e1231675fd98b..03a42ce6b21caf 100644
--- a/lib/v2/weibo/maintainer.js
+++ b/lib/v2/weibo/maintainer.js
@@ -1,4 +1,5 @@
module.exports = {
+ '/friends/:routeParams?': ['CaoMeiYouRen'],
'/group/:gid/:gname?/:routeParams?': ['monologconnor', 'Rongronggg9'],
'/keyword/:keyword/:routeParams?': ['DIYgod', 'Rongronggg9'],
'/oasis/user/:userid': ['kt286'],
diff --git a/lib/v2/weibo/radar.js b/lib/v2/weibo/radar.js
index 30ad3837fd8421..b0f58ee6277922 100644
--- a/lib/v2/weibo/radar.js
+++ b/lib/v2/weibo/radar.js
@@ -8,7 +8,7 @@ module.exports = {
source: ['/u/:id', '/:id'],
target: (params, url, document) => {
let uid = document?.documentElement.innerHTML.match(/\$CONFIG\['oid']='(\d+)'/)?.[1];
- if (!uid && !isNaN(params.id)) {
+ if (!uid && !Number.isNaN(params.id)) {
uid = params.id;
}
return uid ? `/weibo/user/${uid}` : '';
@@ -24,6 +24,12 @@ module.exports = {
source: '/p/:id/super_index',
target: '/weibo/super_index/:id',
},
+ {
+ title: '最新关注时间线',
+ docs: 'https://docs.rsshub.app/routes/social-media#wei-bo',
+ source: '/',
+ target: '/weibo/friends',
+ },
],
s: [
{
diff --git a/lib/v2/weibo/router.js b/lib/v2/weibo/router.js
index 9a4545aed80567..6f2c6d54b3b9bf 100644
--- a/lib/v2/weibo/router.js
+++ b/lib/v2/weibo/router.js
@@ -1,4 +1,5 @@
module.exports = (router) => {
+ router.get('/friends/:routeParams?', require('./friends'));
router.get('/group/:gid/:gname?/:routeParams?', require('./group'));
router.get('/keyword/:keyword/:routeParams?', require('./keyword'));
router.get('/oasis/user/:userid', require('./oasis/user'));
diff --git a/website/docs/routes/government.mdx b/website/docs/routes/government.mdx
index 71ca7b15e8564f..da920cce827c40 100644
--- a/website/docs/routes/government.mdx
+++ b/website/docs/routes/government.mdx
@@ -12,9 +12,9 @@
-## Constitutional Court of Baden-Württemberg (Germany) {#constitutional-court-of-baden-w%C3%BCrttemberg-germany}
+## Constitutional Court of Baden-Württemberg (Germany) {#constitutional-court-of-baden-wvrttemberg-germany}
-### Press releases {#constitutional-court-of-baden-w%C3%BCrttemberg-germany-press-releases}
+### Press releases {#constitutional-court-of-baden-wvrttemberg-germany-press-releases}
diff --git a/website/docs/routes/other.mdx b/website/docs/routes/other.mdx
index abca26609334ef..c697910947312f 100644
--- a/website/docs/routes/other.mdx
+++ b/website/docs/routes/other.mdx
@@ -121,7 +121,7 @@ See [#app-store-mac-app-store](/routes/program-update#app-store-mac-app-store)
-### Macao Pagina Electrónica Especial Contra Epidemias: What’s New {#corona-virus-disease-2019-macao-pagina-electr%C3%B3nica-especial-contra-epidemias-what-s-new}
+### Macao Pagina Electrónica Especial Contra Epidemias: What’s New {#corona-virus-disease-2019-macao-pagina-electronica-especial-contra-epidemias-what-s-new}
Official Website: [https://www.ssm.gov.mo/apps1/PreventWuhanInfection/en.aspx](https://www.ssm.gov.mo/apps1/PreventWuhanInfection/en.aspx)
diff --git a/website/docs/routes/social-media.mdx b/website/docs/routes/social-media.mdx
index 342034c7298e5b..6170782901c511 100644
--- a/website/docs/routes/social-media.mdx
+++ b/website/docs/routes/social-media.mdx
@@ -1525,6 +1525,18 @@ YouTube provides official RSS feeds for channels, for instance [https://www.yout
:::
+### 最新关注时间线 {#wei-bo-zui-xin-guan-zhu-shi-jian-xian}
+
+
+ :::warning
+ 此方案必须使用用户`Cookie`进行抓取
+
+ 因微博 cookies 的过期与更新方案未经验证,部署一次 Cookie 的有效时长未知
+
+ 微博用户 Cookie 的配置可参照部署文档
+ :::
+
+
### 自定义分组 {#wei-bo-zi-ding-yi-fen-zu}