Skip to content

Commit

Permalink
feat(core/utils/wechat-mp): major rewrite (DIYgod#15276)
Browse files Browse the repository at this point in the history
* feat(core/utils/wechat-mp): major rewrite

* Support more `item_show_type`: `APP_MSG_PAGE`, `VIDEO_SHARE_PAGE`,
`AUDIO_SHARE_PAGE`, and `IMG_SHARE_PAGE`. Previously only the first one
could be parsed properly. There are still some other known types waiting
for live examples for further adaptation. If this is the case, a
fallback method will try to generate entries using mostly OpenGraph
metadata. Meanwhile, the administrator of self-hosted instances will see
warnings in the log, asking them to report the URL as a new live
example. Still, `VIDEO_SHARE_PAGE` explicitly uses the fallback method
without any warning, as there is no possible approach to generate a
video/iframe URL from page metadata.

* Show audio and videos in `APP_MSG_PAGE`. However, not all videos
can be shown due to the same reason as `VIDEO_SHARE_PAGE`.

* Show the location where the article is sent.

* Some bugs, mostly due to outdated cheerio selector, are fixed.

* Add a new sub-route `wechat-mp` to `/test` to make things easier.

* All changes are well-tested.

Signed-off-by: Rongrong <i@rong.moe>

* style(core/utils/wechat-mp): fix ESLint & CodeQL errors

Signed-off-by: Rongrong <i@rong.moe>

* style(core/utils/wechat-mp): fix a DeepScan issue

Signed-off-by: Rongrong <i@rong.moe>

* style(core/utils/wechat-mp): fix ESLint error

Another try w/ pre-commit hook disabled.

Signed-off-by: Rongrong <i@rong.moe>

---------

Signed-off-by: Rongrong <i@rong.moe>
  • Loading branch information
Rongronggg9 authored Apr 18, 2024
1 parent 7feab90 commit a99b35f
Show file tree
Hide file tree
Showing 5 changed files with 852 additions and 115 deletions.
4 changes: 2 additions & 2 deletions lib/errors/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ describe('route throws an error', () => {
expect(value).toBe('9');
break;
case 'Hot Routes:':
expect(value).toBe('6 /test/:id<br>');
expect(value).toBe('6 /test/:id/:params?<br>');
break;
case 'Hot Paths:':
expect(value).toBe('2 /test/error<br>2 /test/slow<br>1 /test/httperror<br>1 /test/config-not-found-error<br>1 /test/invalid-parameter-error<br>1 /thisDoesNotExist<br>1 /<br>');
break;
case 'Hot Error Routes:':
expect(value).toBe('5 /test/:id<br>');
expect(value).toBe('5 /test/:id/:params?<br>');
break;
case 'Hot Error Paths:':
expect(value).toBe('2 /test/error<br>1 /test/httperror<br>1 /test/slow<br>1 /test/config-not-found-error<br>1 /test/invalid-parameter-error<br>1 /thisDoesNotExist<br>');
Expand Down
12 changes: 11 additions & 1 deletion lib/routes/test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { config } from '@/config';
import got from '@/utils/got';
import wait from '@/utils/wait';
import cache from '@/utils/cache';
import { fetchArticle } from '@/utils/wechat-mp';
import ConfigNotFoundError from '@/errors/types/config-not-found';
import InvalidParameterError from '@/errors/types/invalid-parameter';

let cacheIndex = 0;

export const route: Route = {
path: '/:id',
path: '/:id/:params?',
name: 'Unknown',
maintainers: ['DIYgod', 'NeverBehave'],
handler,
Expand Down Expand Up @@ -384,6 +385,15 @@ async function handler(ctx) {
];
}

if (ctx.req.param('id') === 'wechat-mp') {
const params = ctx.req.param('params');
if (!params) {
throw new InvalidParameterError('Invalid parameter');
}
const mpUrl = 'https:/mp.weixin.qq.com/s' + (params.includes('&') ? '?' : '/') + params;
item = [await fetchArticle(mpUrl)];
}

return {
title: `Test ${ctx.req.param('id')}`,
itunes_author: ctx.req.param('id') === 'enclosure' ? 'DIYgod' : null,
Expand Down
132 changes: 120 additions & 12 deletions lib/setup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@ import { afterAll, afterEach } from 'vitest';
import { setupServer } from 'msw/node';
import { http, HttpResponse } from 'msw';

const genWeChatMpPage = (rich_media_content: string, scripts: string[] | string) => {
if (!Array.isArray(scripts)) {
scripts = [scripts];
}
let pageHtml = `
<meta name="description" content="summary" />
<meta name="author" content="author" />
<meta property="og:title" content="title" />
<meta property="og:image" content="https://mmbiz.qpic.cn/rsshub_test/og_img_1/0?wx_fmt=jpeg" />
<meta property="twitter:card" content="summary" />
<div class="rich_media_content" id="js_content" style="visibility: hidden;">
${rich_media_content}
</div>
<div class="wx_follow_nickname">mpName</div>`;
for (const script of scripts) {
pageHtml += `
<script type="text/javascript" nonce="000000000">
${script}
</script>`;
}
return pageHtml;
};

const server = setupServer(
http.post(`https://api.openai.mock/v1/chat/completions`, () =>
HttpResponse.json({
Expand Down Expand Up @@ -33,21 +56,106 @@ const server = setupServer(
</ul>
</div>`)
),
http.get(`https://mp.weixin.qq.com/rsshub_test/wechatMp_fetchArticle`, () =>
http.get(`https://mp.weixin.qq.com/rsshub_test/appMsg`, () =>
HttpResponse.text(
genWeChatMpPage(
`
description
<iframe class="video_iframe rich_pages" data-ratio="1.7777777777777777" data-w="864"data-src="https://v.qq.com/rsshub_test/?vid=fake"></iframe>
<mpvoice name="title" voice_encode_fileid="rsshub_test"></mpvoice>
`,
`
var item_show_type = "0";
var real_item_show_type = "0";
var appmsg_type = "9";
var ct = "${1_636_626_300}";
var msg_source_url = "https://mp.weixin.qq.com/rsshub_test/fake";
window.ip_wording = {
countryName: '中国',
countryId: '156',
provinceName: '福建',
provinceId: '',
cityName: '',
cityId: ''
};`
)
)
),
http.get(`https://mp.weixin.qq.com/rsshub_test/img`, () =>
HttpResponse.text(
genWeChatMpPage('fake_description', [
`
var item_show_type = "8";
var real_item_show_type = "8";
var appmsg_type = "9";
var ct = "${1_636_626_300}";
`,
`
window.picture_page_info_list = [
{
cdn_url: 'https://mmbiz.qpic.cn/rsshub_test/fake_img_1/0?wx_fmt=jpeg',
},
{
cdn_url: 'https://mmbiz.qpic.cn/rsshub_test/fake_img_2/0?wx_fmt=jpeg',
},
].slice(0, 20);
`,
])
)
),
http.get(`https://mp.weixin.qq.com/rsshub_test/audio`, () =>
HttpResponse.text(
genWeChatMpPage('fake_description', [
`
var item_show_type = "7";
var real_item_show_type = "7";
var appmsg_type = "9";
var ct = "${1_636_626_300}";
`,
`
reportOpt = {
voiceid: "",
uin: "",
biz: "",
mid: "",
idx: ""
};
window.cgiData = {
voiceid: "rsshub_test_voiceid_1",
duration: "6567" * 1,
};
`,
])
)
),
http.get(`https://mp.weixin.qq.com/rsshub_test/video`, () =>
HttpResponse.text(
genWeChatMpPage(
'fake_description',
`
var item_show_type = "5";
var real_item_show_type = "5";
var appmsg_type = "9";
var ct = "${1_636_626_300}";
`
)
)
),
http.get(`https://mp.weixin.qq.com/rsshub_test/fallback`, () =>
HttpResponse.text(
'\n' +
'<meta name="description" content="summary" />\n' +
'<meta name="author" content="author" />\n' +
'<meta property="og:title" content="title" />\n' +
'<meta property="twitter:card" content="summary" />\n' +
'<div class="rich_media_content" id="js_content" style="visibility: hidden;">description</div>\n' +
'<div class="profile_inner"><strong class="profile_nickname">mpName</strong></div>\n' +
'<script type="text/javascript" nonce="000000000">\n' +
'var appmsg_type = "9";\n' +
`var ct = "${1_636_626_300}";\n` +
'</script>'
genWeChatMpPage(
'fake_description',
`
var item_show_type = "99988877";
var real_item_show_type = "99988877";
var appmsg_type = "9";
var ct = "${1_636_626_300}";
`
)
)
),
http.get(`https://mp.weixin.qq.com/s/rsshub_test`, () => HttpResponse.text(genWeChatMpPage('', ''))),
http.get(`https://mp.weixin.qq.com/s?__biz=rsshub_test&mid=1&idx=1&sn=1`, () => HttpResponse.text(genWeChatMpPage('', ''))),
http.get(`http://rsshub.test/headers`, ({ request }) =>
HttpResponse.json({
...Object.fromEntries(request.headers.entries()),
Expand Down
Loading

0 comments on commit a99b35f

Please sign in to comment.