mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-10-16 21:02:57 +08:00
fix(route/weibo/*): sinaimg anti-hotlinking (#11320)
* fix(route/weibo/*): sinaimg anti-hotlinking Signed-off-by: Rongrong <i@rong.moe> * refactor: migrate to v2 * Fix CodeQL warning Signed-off-by: Rongrong <i@rong.moe> * Fix CodeQL warning again Signed-off-by: Rongrong <i@rong.moe> * Narrow sinaimg URL regex Signed-off-by: Rongrong <i@rong.moe> * Fix CodeQL warning again and again Signed-off-by: Rongrong <i@rong.moe> * Fix CodeQL warning again, again and again Signed-off-by: Rongrong <i@rong.moe> * More accurate regex, dismiss CodeQL plz Signed-off-by: Rongrong <i@rong.moe> Signed-off-by: Rongrong <i@rong.moe>
This commit is contained in:
@@ -13,27 +13,6 @@
|
||||
},
|
||||
'https://www.icac.org.hk': { _name: '廉政公署', '.': [{ title: '新闻公布', docs: 'https://docs.rsshub.app/government.html#xiang-gang-lian-zheng-gong-shu', source: ['/:lang/press/index.html'], target: '/icac/news/:lang' }] },
|
||||
'trow.cc': { _name: 'The Ring of Wonder', '.': [{ title: '首页更新', docs: 'https://docs.rsshub.app/bbs.html#the-ring-of-wonder', source: ['/'], target: '/portal' }] },
|
||||
'weibo.com': {
|
||||
_name: '微博',
|
||||
'.': [
|
||||
{
|
||||
title: '博主',
|
||||
docs: 'https://docs.rsshub.app/social-media.html#wei-bo',
|
||||
source: ['/u/:id', '/:id'],
|
||||
target: (params, url, document) => {
|
||||
let uid = document?.documentElement.innerHTML.match(/\$CONFIG\['oid']='(\d+)'/)?.[1];
|
||||
if (!uid && !isNaN(params.id)) {
|
||||
uid = params.id;
|
||||
}
|
||||
return uid ? `/weibo/user/${uid}` : '';
|
||||
},
|
||||
},
|
||||
{ title: '关键词', docs: 'https://docs.rsshub.app/social-media.html#wei-bo' },
|
||||
{ title: '超话', docs: 'https://docs.rsshub.app/social-media.html#wei-bo', source: '/p/:id/super_index', target: '/weibo/super_index/:id' },
|
||||
],
|
||||
s: [{ title: '热搜榜', docs: 'https://docs.rsshub.app/social-media.html#wei-bo', source: '/top/summary', target: '/weibo/search/hot' }],
|
||||
},
|
||||
'weibo.cn': { _name: '微博', m: [{ title: '博主', docs: 'https://docs.rsshub.app/social-media.html#wei-bo', source: ['/u/:uid', '/profile/:uid'], target: '/weibo/user/:uid' }] },
|
||||
'github.com': {
|
||||
_name: 'GitHub',
|
||||
'.': [
|
||||
|
||||
@@ -1,50 +1,4 @@
|
||||
module.exports = {
|
||||
'weibo.com': {
|
||||
_name: '微博',
|
||||
'.': [
|
||||
{
|
||||
title: '博主',
|
||||
docs: 'https://docs.rsshub.app/social-media.html#wei-bo',
|
||||
source: ['/u/:id', '/:id'],
|
||||
target: (params, url, document) => {
|
||||
let uid = document?.documentElement.innerHTML.match(/\$CONFIG\['oid']='(\d+)'/)?.[1];
|
||||
if (!uid && !isNaN(params.id)) {
|
||||
uid = params.id;
|
||||
}
|
||||
return uid ? `/weibo/user/${uid}` : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '关键词',
|
||||
docs: 'https://docs.rsshub.app/social-media.html#wei-bo',
|
||||
},
|
||||
{
|
||||
title: '超话',
|
||||
docs: 'https://docs.rsshub.app/social-media.html#wei-bo',
|
||||
source: '/p/:id/super_index',
|
||||
target: '/weibo/super_index/:id',
|
||||
},
|
||||
],
|
||||
s: [
|
||||
{
|
||||
title: '热搜榜',
|
||||
docs: 'https://docs.rsshub.app/social-media.html#wei-bo',
|
||||
source: '/top/summary',
|
||||
target: '/weibo/search/hot',
|
||||
},
|
||||
],
|
||||
},
|
||||
'weibo.cn': {
|
||||
_name: '微博',
|
||||
m: [
|
||||
{
|
||||
title: '博主',
|
||||
docs: 'https://docs.rsshub.app/social-media.html#wei-bo',
|
||||
source: ['/u/:uid', '/profile/:uid'],
|
||||
target: '/weibo/user/:uid',
|
||||
},
|
||||
],
|
||||
},
|
||||
'ximalaya.com': {
|
||||
_name: '喜马拉雅',
|
||||
'.': [
|
||||
|
||||
+7
-7
@@ -47,12 +47,12 @@ router.get('/benedictevans', lazyloadRouteHandler('./routes/benedictevans/recent
|
||||
// router.get('/twreporter/photography', lazyloadRouteHandler('./routes/twreporter/photography'));
|
||||
// router.get('/twreporter/category/:cid', lazyloadRouteHandler('./routes/twreporter/category'));
|
||||
|
||||
// 微博
|
||||
router.get('/weibo/user/:uid/:routeParams?', lazyloadRouteHandler('./routes/weibo/user'));
|
||||
router.get('/weibo/keyword/:keyword/:routeParams?', lazyloadRouteHandler('./routes/weibo/keyword'));
|
||||
router.get('/weibo/search/hot', lazyloadRouteHandler('./routes/weibo/search/hot'));
|
||||
router.get('/weibo/super_index/:id/:type?/:routeParams?', lazyloadRouteHandler('./routes/weibo/super_index'));
|
||||
router.get('/weibo/oasis/user/:userid', lazyloadRouteHandler('./routes/weibo/oasis/user'));
|
||||
// 微博 migrated to v2
|
||||
// router.get('/weibo/user/:uid/:routeParams?', lazyloadRouteHandler('./routes/weibo/user'));
|
||||
// router.get('/weibo/keyword/:keyword/:routeParams?', lazyloadRouteHandler('./routes/weibo/keyword'));
|
||||
// router.get('/weibo/search/hot', lazyloadRouteHandler('./routes/weibo/search/hot'));
|
||||
// router.get('/weibo/super_index/:id/:type?/:routeParams?', lazyloadRouteHandler('./routes/weibo/super_index'));
|
||||
// router.get('/weibo/oasis/user/:userid', lazyloadRouteHandler('./routes/weibo/oasis/user'));
|
||||
|
||||
// 贴吧 migrated to v2
|
||||
// router.get('/tieba/forum/:kw', lazyloadRouteHandler('./routes/tieba/forum'));
|
||||
@@ -2086,7 +2086,7 @@ router.get('/haimaoba/:id?', lazyloadRouteHandler('./routes/haimaoba/comics'));
|
||||
router.get('/pgyer/:app?', lazyloadRouteHandler('./routes/pgyer/app'));
|
||||
|
||||
// 微博个人时间线
|
||||
router.get('/weibo/timeline/:uid/:feature?/:routeParams?', lazyloadRouteHandler('./routes/weibo/timeline'));
|
||||
// router.get('/weibo/timeline/:uid/:feature?/:routeParams?', lazyloadRouteHandler('./routes/weibo/timeline'));
|
||||
|
||||
// TAPTAP migrated to v2
|
||||
// router.get('/taptap/topic/:id/:label?', lazyloadRouteHandler('./routes/taptap/topic'));
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
const buildData = require('@/utils/common-config');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const userid = ctx.params.userid;
|
||||
const link = `https://oasis.weibo.cn/v1/h5/share?uid=${userid}`;
|
||||
ctx.state.data = await buildData({
|
||||
link,
|
||||
url: link,
|
||||
title: `$('.name-main').text().trim() + ' - 用户 - 绿洲'`,
|
||||
description: `$('.desc').text().trim()`,
|
||||
item: {
|
||||
item: '.container .item',
|
||||
title: `$('.status-desc').text()`,
|
||||
description: `$('.status-desc').text() + '<br>' + $('.media-wrapper').html()`,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -28,7 +28,7 @@ module.exports = async (ctx) => {
|
||||
);
|
||||
|
||||
const routeParams = querystring.parse(ctx.params.routeParams);
|
||||
ctx.state.data = {
|
||||
ctx.state.data = weiboUtils.sinaimgTvax({
|
||||
title: `又有人在微博提到${keyword}了`,
|
||||
link: `http://s.weibo.com/weibo/${encodeURIComponent(keyword)}&b=1&nodup=1`,
|
||||
description: `又有人在微博提到${keyword}了`,
|
||||
@@ -51,5 +51,5 @@ module.exports = async (ctx) => {
|
||||
link: `https://weibo.com/${item.mblog.user.id}/${item.mblog.bid}`,
|
||||
};
|
||||
}),
|
||||
};
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
'/keyword/:keyword/:routeParams?': ['DIYgod'],
|
||||
'/oasis/user/:userid': ['kt286'],
|
||||
'/search/hot': ['xyqfer'],
|
||||
'/super_index/:id/:type?/:routeParams?': ['zengxs'],
|
||||
'/timeline/:uid/:feature?/:routeParams?': ['zytomorrow', 'DIYgod ', 'Rongronggg9'],
|
||||
'/user/:uid/:routeParams?': ['DIYgod', 'iplusx', 'Rongronggg9'],
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
const buildData = require('@/utils/common-config');
|
||||
const weiboUtils = require('../utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const userid = ctx.params.userid;
|
||||
const link = `https://oasis.weibo.cn/v1/h5/share?uid=${userid}`;
|
||||
ctx.state.data = weiboUtils.sinaimgTvax(
|
||||
await buildData({
|
||||
link,
|
||||
url: link,
|
||||
title: `$('.name-main').text().trim() + ' - 用户 - 绿洲'`,
|
||||
description: `$('.desc').text().trim()`,
|
||||
item: {
|
||||
item: '.container .item',
|
||||
title: `$('.status-desc').text()`,
|
||||
description: `$('.status-desc').text() + '<br>' + $('.media-wrapper').html()`,
|
||||
},
|
||||
})
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
module.exports = {
|
||||
'weibo.com': {
|
||||
_name: '微博',
|
||||
'.': [
|
||||
{
|
||||
title: '博主',
|
||||
docs: 'https://docs.rsshub.app/social-media.html#wei-bo',
|
||||
source: ['/u/:id', '/:id'],
|
||||
target: (params, url, document) => {
|
||||
let uid = document?.documentElement.innerHTML.match(/\$CONFIG\['oid']='(\d+)'/)?.[1];
|
||||
if (!uid && !isNaN(params.id)) {
|
||||
uid = params.id;
|
||||
}
|
||||
return uid ? `/weibo/user/${uid}` : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '关键词',
|
||||
docs: 'https://docs.rsshub.app/social-media.html#wei-bo',
|
||||
},
|
||||
{
|
||||
title: '超话',
|
||||
docs: 'https://docs.rsshub.app/social-media.html#wei-bo',
|
||||
source: '/p/:id/super_index',
|
||||
target: '/weibo/super_index/:id',
|
||||
},
|
||||
],
|
||||
s: [
|
||||
{
|
||||
title: '热搜榜',
|
||||
docs: 'https://docs.rsshub.app/social-media.html#wei-bo',
|
||||
source: '/top/summary',
|
||||
target: '/weibo/search/hot',
|
||||
},
|
||||
],
|
||||
},
|
||||
'weibo.cn': {
|
||||
_name: '微博',
|
||||
m: [
|
||||
{
|
||||
title: '博主',
|
||||
docs: 'https://docs.rsshub.app/social-media.html#wei-bo',
|
||||
source: ['/u/:uid', '/profile/:uid'],
|
||||
target: '/weibo/user/:uid',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
module.exports = (router) => {
|
||||
router.get('/keyword/:keyword/:routeParams?', require('./keyword'));
|
||||
router.get('/oasis/user/:userid', require('./oasis/user'));
|
||||
router.get('/search/hot', require('./search/hot'));
|
||||
router.get('/super_index/:id/:type?/:routeParams?', require('./super_index'));
|
||||
router.get('/timeline/:uid/:feature?/:routeParams?', require('./timeline'));
|
||||
router.get('/user/:uid/:routeParams?', require('./user'));
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
const got = require('@/utils/got');
|
||||
// const weiboUtils = require('../utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const {
|
||||
@@ -30,4 +31,5 @@ module.exports = async (ctx) => {
|
||||
};
|
||||
}),
|
||||
};
|
||||
// ctx.state.data = weiboUtils.sinaimgTvax(ctx.state.data); // no image in the route
|
||||
};
|
||||
@@ -53,10 +53,10 @@ module.exports = async (ctx) => {
|
||||
}
|
||||
}
|
||||
|
||||
ctx.state.data = {
|
||||
ctx.state.data = weiboUtils.sinaimgTvax({
|
||||
title: `微博超话 - ${containerData.pageInfo.page_title}`,
|
||||
link: `https://weibo.com/p/${id}/super_index`,
|
||||
description: `#${containerData.pageInfo.page_title}# 的超话`,
|
||||
item: resultItems,
|
||||
};
|
||||
});
|
||||
};
|
||||
@@ -125,13 +125,13 @@ module.exports = async (ctx) => {
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
ctx.state.data = weiboUtils.sinaimgTvax({
|
||||
title: `个人微博时间线--${name}`,
|
||||
link: `http://weibo.com/${uid}/`,
|
||||
description,
|
||||
image: profileImageUrl,
|
||||
item: resultItem,
|
||||
};
|
||||
});
|
||||
} else if (uid === '0' || ctx.querystring) {
|
||||
const { app_key = '', redirect_url = ctx.request.origin + '/weibo/timeline/0', app_secret = '' } = config.weibo;
|
||||
|
||||
@@ -145,11 +145,11 @@ module.exports = async (ctx) => {
|
||||
resultItems = ordinaryItems;
|
||||
}
|
||||
|
||||
ctx.state.data = {
|
||||
ctx.state.data = weiboUtils.sinaimgTvax({
|
||||
title: `${name}的微博`,
|
||||
link: `https://weibo.com/${uid}/`,
|
||||
description,
|
||||
image: profileImageUrl,
|
||||
item: resultItems,
|
||||
};
|
||||
});
|
||||
};
|
||||
@@ -4,6 +4,16 @@ const cheerio = require('cheerio');
|
||||
const { fallback, queryToBoolean, queryToInteger } = require('@/utils/readable-social');
|
||||
|
||||
const weiboUtils = {
|
||||
formatTitle: (html) =>
|
||||
html
|
||||
.replace(/<span class=["']url-icon["']><img\s[^>]*?alt=["']?([^>]+?)["']?\s[^>]*?\/?><\/span>/g, '$1') // 表情转换
|
||||
.replace(/<span class=["']url-icon["']>(<img\s[^>]*>)<\/span>/g, '') // 去掉所有图标
|
||||
.replace(/<img\s[^<]*>/g, '[图片]')
|
||||
// impossible to have inline script in weibo posts, but CodeQL complains about it
|
||||
// Dismiss it through the UI: https://github.com/github/codeql/issues/11427
|
||||
.replace(/<[^<]*>/g, '')
|
||||
.replace(/\n/g, ' ')
|
||||
.trim(),
|
||||
formatExtended: (ctx, status, params = {}, picsPrefixes = []) => {
|
||||
// undefined and strings like "1" is also safely parsed, so no if branch is needed
|
||||
const routeParams = querystring.parse(ctx.params.routeParams);
|
||||
@@ -200,23 +210,11 @@ const weiboUtils = {
|
||||
title += status.user.screen_name + ': ';
|
||||
}
|
||||
if (!status.retweeted_status || showRetweetTextInTitle) {
|
||||
title += htmlNewLineUnreplaced
|
||||
.replace(/<span class=["']url-icon["']><img\s[^>]*?alt=["']?([^>]+?)["']?\s[^>]*?\/><\/span>/g, '$1') // 表情转换
|
||||
.replace(/<span class=["']url-icon["']>(<img\s[^>]*?>)<\/span>/g, '') // 去掉所有图标
|
||||
.replace(/<img[\s\S]*?>/g, '[图片]')
|
||||
.replace(/<.*?>/g, '')
|
||||
.replace('\n', '')
|
||||
.trim();
|
||||
title += weiboUtils.formatTitle(htmlNewLineUnreplaced);
|
||||
}
|
||||
if (status.retweeted_status) {
|
||||
title += showEmojiForRetweet ? '🔁 ' : ' - 转发 ';
|
||||
title += retweeted
|
||||
.replace(/<span class=["']url-icon["']><img\s[^>]*?alt=["']?([^>]+?)["']?\s[^>]*?\/><\/span>/g, '$1') // 表情转换
|
||||
.replace(/<span class=["']url-icon["']>(<img\s[^>]*?>)<\/span>/g, '') // 去掉所有图标
|
||||
.replace(/<img[\s\S]*?>/g, '[图片]')
|
||||
.replace(/<.*?>/g, '')
|
||||
.replace('\n', '')
|
||||
.trim();
|
||||
title += weiboUtils.formatTitle(retweeted);
|
||||
}
|
||||
if (livePhotoCount > 0) {
|
||||
title += ' ';
|
||||
@@ -417,6 +415,36 @@ const weiboUtils = {
|
||||
}
|
||||
return itemDesc;
|
||||
},
|
||||
sinaimgTvax: (() => {
|
||||
// https://datatracker.ietf.org/doc/html/rfc1808#section-2.4.3
|
||||
const regex = /(?<=\/\/)wx(?=[1-4]\.sinaimg\.cn\/)/gi;
|
||||
const prefixes = ['tva', 'tvax'];
|
||||
let cnt = 0;
|
||||
const replace = (html) => {
|
||||
cnt = (cnt + 1) % 2;
|
||||
return html.replace(regex, prefixes[cnt]);
|
||||
};
|
||||
const replaceKV = (obj, keys) => {
|
||||
keys.forEach((key) => {
|
||||
if (obj[key]) {
|
||||
obj[key] = replace(obj[key]);
|
||||
}
|
||||
});
|
||||
};
|
||||
const dataKeys = ['description', 'image'];
|
||||
const itemKeys = ['description'];
|
||||
return (data) => {
|
||||
if (data) {
|
||||
replaceKV(data, dataKeys);
|
||||
if (data.item) {
|
||||
data.item.forEach((item) => {
|
||||
replaceKV(item, itemKeys);
|
||||
});
|
||||
}
|
||||
}
|
||||
return data;
|
||||
};
|
||||
})(),
|
||||
};
|
||||
|
||||
module.exports = weiboUtils;
|
||||
Reference in New Issue
Block a user