feat(weibo): apply description render params to comments (#21389)

This commit is contained in:
LinxHex 2026-03-16 21:09:59 +08:00 committed by GitHub
parent 85b5444d07
commit c97a5a286f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 18 deletions

View File

@ -31,8 +31,8 @@ export const namespace: Namespace = {
| displayVideo | Live Photo线 RSS | 0/1/true/false | true |
| displayArticle | 线 RSS | 0/1/true/false | false |
| displayComments | 线 RSS | 0/1/true/false | false |
| showEmojiInDescription | \`[表情名]\` | 0/1/true/false | true |
| showLinkIconInDescription | | 0/1/true/false | true |
| showEmojiInDescription | \`[表情名]\` | 0/1/true/false | true |
| showLinkIconInDescription | | 0/1/true/false | true |
| preferMobileLink | 使使 PC | 0/1/true/false | false |
| showRetweeted | | 0/1/true/false | true |
| showBloggerIcons | | 0/1/true/false | false |

View File

@ -17,6 +17,25 @@ class RenewWeiboCookiesError extends Error {
}
}
const getDescriptionRenderParams = (routeParams, params = {}) => ({
showEmojiInDescription: fallback(params.showEmojiInDescription, queryToInteger(routeParams.showEmojiInDescription), false),
showLinkIconInDescription: fallback(params.showLinkIconInDescription, queryToInteger(routeParams.showLinkIconInDescription), true),
});
const formatDescriptionText = (html, { showEmojiInDescription, showLinkIconInDescription }) => {
let formattedHtml = html;
if (!showEmojiInDescription) {
formattedHtml = formattedHtml.replaceAll(/<span class=["']?url-icon["']?><img\s[^>]*?alt=["']?([^>]+?)["']?\s[^>]*?\/><\/span>/g, '$1');
}
if (!showLinkIconInDescription) {
formattedHtml = formattedHtml.replaceAll(/(<a\s[^>]*>)<span class=["']?url-icon["']?><img\s[^>]*><\/span>[^<>]*?<span class=["']?surl-text["']?>([^<>]*?)<\/span><\/a>/g, '$1$2</a>');
}
return formattedHtml;
};
const weiboUtils = {
apiHeaders: {
'MWeibo-Pwa': 1,
@ -135,6 +154,7 @@ const weiboUtils = {
// undefined and strings like "1" is also safely parsed, so no if branch is needed
const routeParams = querystring.parse(ctx.req.param('routeParams'));
const descriptionRenderParams = getDescriptionRenderParams(routeParams, params);
const mergedParams = {
readable: fallback(params.readable, queryToBoolean(routeParams.readable), false),
@ -151,8 +171,8 @@ const weiboUtils = {
widthOfPics: fallback(params.widthOfPics, queryToInteger(routeParams.widthOfPics), -1),
heightOfPics: fallback(params.heightOfPics, queryToInteger(routeParams.heightOfPics), -1),
sizeOfAuthorAvatar: fallback(params.sizeOfAuthorAvatar, queryToInteger(routeParams.sizeOfAuthorAvatar), 48),
showEmojiInDescription: fallback(params.showEmojiInDescription, queryToInteger(routeParams.showEmojiInDescription), false),
showLinkIconInDescription: fallback(params.showLinkIconInDescription, queryToInteger(routeParams.showLinkIconInDescription), true),
showEmojiInDescription: descriptionRenderParams.showEmojiInDescription,
showLinkIconInDescription: descriptionRenderParams.showLinkIconInDescription,
preferMobileLink: fallback(params.preferMobileLink, queryToBoolean(routeParams.preferMobileLink), false),
};
@ -173,22 +193,13 @@ const weiboUtils = {
widthOfPics,
heightOfPics,
sizeOfAuthorAvatar,
showEmojiInDescription,
showLinkIconInDescription,
preferMobileLink,
} = params;
let retweeted = '';
// 长文章的处理
let htmlNewLineUnreplaced = (status.longText && status.longText.longTextContent) || status.text || '';
// 表情图标转换为文字
if (!showEmojiInDescription) {
htmlNewLineUnreplaced = htmlNewLineUnreplaced.replaceAll(/<span class=["']?url-icon["']?><img\s[^>]*?alt=["']?([^>]+?)["']?\s[^>]*?\/><\/span>/g, '$1');
}
// 去掉链接的图标,保留 a 标签链接
if (!showLinkIconInDescription) {
htmlNewLineUnreplaced = htmlNewLineUnreplaced.replaceAll(/(<a\s[^>]*>)<span class=["']?url-icon["']?><img\s[^>]*><\/span>[^<>]*?<span class=["']?surl-text["']?>([^<>]*?)<\/span><\/a>/g, '$1$2</a>');
}
htmlNewLineUnreplaced = formatDescriptionText(htmlNewLineUnreplaced, descriptionRenderParams);
// 提取 话题作为 category
const category: string[] = htmlNewLineUnreplaced.match(/<span class=["']?surl-text["']?>#([^<>]*?)#<\/span>/g)?.map((e) => e?.match(/#([^#]+)#/)?.[1]);
@ -519,6 +530,9 @@ const weiboUtils = {
return itemDesc;
},
formatComments: async (ctx, itemDesc, status, showBloggerIcons) => {
const routeParams = querystring.parse(ctx.req.param('routeParams'));
const descriptionRenderParams = getDescriptionRenderParams(routeParams);
if (status && status.comments_count && status.id && status.mid) {
const id = status.id;
const mid = status.mid;
@ -542,7 +556,8 @@ const weiboUtils = {
if (showBloggerIcons === '1' && comment.blogger_icons) {
name += comment.blogger_icons[0].name;
}
itemDesc += `<a href="https://weibo.com/${comment.user.id}" target="_blank">${name}</a>: ${comment.text}`;
const commentText = formatDescriptionText(comment.text, descriptionRenderParams);
itemDesc += `<a href="https://weibo.com/${comment.user.id}" target="_blank">${name}</a>: ${commentText}`;
// 带有图片的评论直接输出图片
if ('pic' in comment) {
itemDesc += `<br><img src="${comment.pic.url}">`;
@ -552,7 +567,8 @@ const weiboUtils = {
for (const com of comment.comments) {
// 评论的带有图片的评论直接输出图片
const pattern = /<a\s+href="https:\/\/weibo\.cn\/sinaurl\?u=([^"]+)"[^>]*><span class='url-icon'><img[^>]*><\/span><span class="surl-text">(查看图片|评论配图|查看动图)<\/span><\/a>/g;
const matches = com.text.match(pattern);
let replyText = com.text;
const matches = replyText.match(pattern);
if (matches) {
for (const match of matches) {
const hrefMatch = match.match(/href="https:\/\/weibo\.cn\/sinaurl\?u=([^"]+)"/);
@ -561,16 +577,17 @@ const weiboUtils = {
const imgSrc = decodeURIComponent(hrefMatch[1]);
const imgTag = `<img src="${imgSrc}" style="width: 1rem; height: 1rem;">`;
// 用替换后的 img 标签替换原来的 <a> 标签部分
com.text = com.text.replaceAll(match, imgTag);
replyText = replyText.replaceAll(match, imgTag);
}
}
}
replyText = formatDescriptionText(replyText, descriptionRenderParams);
itemDesc += '<div style="font-size: 0.9em">';
let name = com.user.screen_name;
if (showBloggerIcons === '1' && com.blogger_icons) {
name += com.blogger_icons[0].name;
}
itemDesc += `<a href="https://weibo.com/${com.user.id}" target="_blank">${name}</a>: ${com.text}`;
itemDesc += `<a href="https://weibo.com/${com.user.id}" target="_blank">${name}</a>: ${replyText}`;
itemDesc += '</div>';
}
itemDesc += '</blockquote>';