yz-yuki-plugin 2.0.7-13 → 2.0.7-15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -0
- package/README.md +23 -22
- package/lib/apps/bilibili.js +28 -24
- package/lib/components/dynamic/Content.js +2 -2
- package/lib/components/dynamic/Footer.js +2 -2
- package/lib/components/help/Help.js +2 -2
- package/lib/components/version/Version.js +2 -2
- package/lib/models/bilibili/bilibili.main.query.js +114 -80
- package/lib/models/bilibili/bilibili.main.task.js +6 -6
- package/lib/models/weibo/weibo.main.query.js +68 -33
- package/lib/models/weibo/weibo.main.task.js +7 -7
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# YUKI-PLUGIN
|
|
4
4
|
|
|
5
|
-
- 一个适用于 `Yunzai 系列机器人框架` 的B
|
|
5
|
+
- 一个适用于 `Yunzai 系列机器人框架` 的B站动态、微博动态订阅推送和B站视频链接解析的插件
|
|
6
6
|
|
|
7
7
|
- 支持 群聊/私聊 订阅B站动态和微博动态,支持定时推送,支持手动触发推送,支持简单查询B站/微博用户信息。
|
|
8
8
|
|
|
@@ -36,7 +36,27 @@ chromium-browser --version
|
|
|
36
36
|
## 选择安装方式
|
|
37
37
|
按照网络情况以及使用的bot框架是`Yunzaijs`还是`Yunzai-V3`,选择对应的安装方式。
|
|
38
38
|
|
|
39
|
-
### ***(一)
|
|
39
|
+
### ***(一)Yunzai-V3***
|
|
40
|
+
|
|
41
|
+
> 仅支持Yunzai-V3(TRSS/Miao)的分支,选择仓库,安装到 `yunzai/plugins`:
|
|
42
|
+
|
|
43
|
+
gitee仓库:
|
|
44
|
+
```
|
|
45
|
+
git clone --branch main3 https://gitee.com/snowtafir/yuki-plugin.git ./plugins/yuki-plugin
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
github仓库:
|
|
49
|
+
```
|
|
50
|
+
git clone --branch main3 https://github.com/snowtafir/yuki-plugin.git ./plugins/yuki-plugin
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
* 安装依赖
|
|
54
|
+
|
|
55
|
+
```shell
|
|
56
|
+
pnpm install --filter=yuki-plugin
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### ***(二)YunzaiJS***
|
|
40
60
|
> 选择其中一种方式安装插件:
|
|
41
61
|
|
|
42
62
|
1. npm包安装到`yunzaijs/node_modules`的方式,仅YunzaiJS支持:
|
|
@@ -86,26 +106,6 @@ git clone --branch main https://github.com/snowtafir/yuki-plugin.git ./plugins/y
|
|
|
86
106
|
yarn install
|
|
87
107
|
```
|
|
88
108
|
|
|
89
|
-
### ***(二)Yunzai-V3***
|
|
90
|
-
|
|
91
|
-
> 仅支持Yunzai-V3(TRSS/Miao)的分支,选择仓库,安装到 `yunzai/plugins`:
|
|
92
|
-
|
|
93
|
-
gitee仓库:
|
|
94
|
-
```
|
|
95
|
-
git clone --branch main3 https://gitee.com/snowtafir/yuki-plugin.git ./plugins/yuki-plugin
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
github仓库:
|
|
99
|
-
```
|
|
100
|
-
git clone --branch main3 https://github.com/snowtafir/yuki-plugin.git ./plugins/yuki-plugin
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
* 安装依赖
|
|
104
|
-
|
|
105
|
-
```shell
|
|
106
|
-
pnpm install --filter=yuki-plugin
|
|
107
|
-
```
|
|
108
|
-
|
|
109
109
|
# 📦二、插件配置
|
|
110
110
|
|
|
111
111
|
> [!IMPORTANT]
|
|
@@ -255,3 +255,4 @@ yarn install
|
|
|
255
255
|
| [TRSS-Yunzai](https://gitee.com/TimeRainStarSky/Yunzai) | 时雨🌌星空的 TRSS-Yunzai |
|
|
256
256
|
| [Miao-Yunzai](https://gitee.com/yoimiya-kokomi/Miao-Yunzai) | 喵喵的 Miao-Yunzai |
|
|
257
257
|
| [Yunzai-Bot](https://gitee.com/Le-niao/Yunzai-Bot) | 乐神的 Yunzai-Bot |
|
|
258
|
+
|[jsxp](https://github.com/lemonade-lab/lvyjs/tree/main/packages/jsxp) | 一个可以在 tsx 环境中,使用 puppeteer 对 tsx 组件进行截图的库 |
|
package/lib/apps/bilibili.js
CHANGED
|
@@ -383,17 +383,19 @@ message.use(async (e) => {
|
|
|
383
383
|
messages.push('\n>>>>>>群组B站订阅<<<<<<');
|
|
384
384
|
Object.keys(subData.group).forEach(groupId => {
|
|
385
385
|
messages.push(`\n<群组${groupId}>:`);
|
|
386
|
-
subData.group
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
item.type.
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
386
|
+
if (subData.group) {
|
|
387
|
+
subData.group[groupId].forEach((item) => {
|
|
388
|
+
const types = new Set();
|
|
389
|
+
if (item.type && item.type.length) {
|
|
390
|
+
item.type.forEach((typeItem) => {
|
|
391
|
+
if (typeMap[typeItem]) {
|
|
392
|
+
types.add(typeMap[typeItem]);
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
messages.push(`${item.uid}:${item.name} ${types.size ? `[${Array.from(types).join('、')}]` : ' [全部动态]'}`);
|
|
397
|
+
});
|
|
398
|
+
}
|
|
397
399
|
});
|
|
398
400
|
}
|
|
399
401
|
else {
|
|
@@ -404,17 +406,19 @@ message.use(async (e) => {
|
|
|
404
406
|
messages.push('\n>>>>>>私聊B站订阅<<<<<<');
|
|
405
407
|
Object.keys(subData.private).forEach(userId => {
|
|
406
408
|
messages.push(`\n<用户${userId}>:`);
|
|
407
|
-
subData.private
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
item.type.
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
409
|
+
if (subData.private) {
|
|
410
|
+
subData.private[userId].forEach((item) => {
|
|
411
|
+
const types = new Set();
|
|
412
|
+
if (item.type && item.type.length) {
|
|
413
|
+
item.type.forEach((typeItem) => {
|
|
414
|
+
if (typeMap[typeItem]) {
|
|
415
|
+
types.add(typeMap[typeItem]);
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
messages.push(`${item.uid}:${item.name} ${types.size ? `[${Array.from(types).join('、')}]` : ' [全部动态]'}`);
|
|
420
|
+
});
|
|
421
|
+
}
|
|
418
422
|
});
|
|
419
423
|
}
|
|
420
424
|
else {
|
|
@@ -486,9 +490,9 @@ message.use(async (e) => {
|
|
|
486
490
|
e.reply('用户不存在,输入的uid无效。');
|
|
487
491
|
return;
|
|
488
492
|
}
|
|
489
|
-
const message = [
|
|
493
|
+
const message = [`--------------------`, `\n昵称:${data?.name}`, `\n性别:${data?.sex}`, `\n等级:${data?.level}`, `\n--------------------`];
|
|
490
494
|
if (data.live_room) {
|
|
491
|
-
message.push(`\n
|
|
495
|
+
message.push(`\n>>>>>直播间信息<<<<<`, `\n标题:${data?.live_room?.title}`, `\n房间:${data?.live_room?.roomid}`, `\n状态:${data?.live_room?.liveStatus ? '直播中' : '未开播'}`, `\n观看人数:${data?.live_room?.watched_show?.num}`);
|
|
492
496
|
e.reply(`直播链接:${data?.live_room?.url}`);
|
|
493
497
|
}
|
|
494
498
|
e.reply(message);
|
|
@@ -83,9 +83,9 @@ const Content = ({ data }) => {
|
|
|
83
83
|
contentCss,
|
|
84
84
|
boxGrid,
|
|
85
85
|
React.createElement("div", { className: "content" },
|
|
86
|
-
picItems,
|
|
87
86
|
React.createElement("div", { className: "content-text-title", style: { marginBottom: '10px' } }, data.title && React.createElement("h1", null, data.title)),
|
|
88
|
-
React.createElement("div", { className: "content-text", dangerouslySetInnerHTML: { __html: data.content || '' } })
|
|
87
|
+
React.createElement("div", { className: "content-text", dangerouslySetInnerHTML: { __html: data.content || '' } }),
|
|
88
|
+
picItems)));
|
|
89
89
|
case 'DYNAMIC_TYPE_WORD':
|
|
90
90
|
return (React.createElement(React.Fragment, null,
|
|
91
91
|
contentCss,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { ConfigController, BOT_NAME } from 'yunzaijs';
|
|
3
3
|
import Config from '../../utils/config.js';
|
|
4
4
|
import path from 'path';
|
|
5
|
-
import {
|
|
5
|
+
import { _paths, createRequire } from '../../utils/paths.js';
|
|
6
6
|
|
|
7
7
|
// Footer.tsx
|
|
8
8
|
const require = createRequire(import.meta.url);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { ConfigController, BOT_NAME } from 'yunzaijs';
|
|
3
3
|
import Config from '../../utils/config.js';
|
|
4
4
|
import path from 'path';
|
|
5
|
-
import {
|
|
5
|
+
import { _paths, createRequire } from '../../utils/paths.js';
|
|
6
6
|
|
|
7
7
|
//help.tsx
|
|
8
8
|
const require = createRequire(import.meta.url);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { ConfigController, BOT_NAME } from 'yunzaijs';
|
|
3
3
|
import Config from '../../utils/config.js';
|
|
4
4
|
import path from 'path';
|
|
5
|
-
import {
|
|
5
|
+
import { _paths, createRequire } from '../../utils/paths.js';
|
|
6
6
|
|
|
7
7
|
const require = createRequire(import.meta.url);
|
|
8
8
|
const botVersion = ConfigController.package?.version;
|
|
@@ -102,42 +102,28 @@ class BiliQuery {
|
|
|
102
102
|
formatData.data.title = desc?.title;
|
|
103
103
|
additional = data?.modules?.module_dynamic?.additional;
|
|
104
104
|
// 文章内容过长,则尝试获取全文
|
|
105
|
+
let content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text, additional) || '';
|
|
105
106
|
if (String(desc?.summary?.text).length >= 480) {
|
|
106
107
|
const fullArticleContent = await this.getFullArticleContent(this.formatUrl(desc?.jump_url));
|
|
107
108
|
if (fullArticleContent) {
|
|
108
109
|
const { readInfo, articleType } = fullArticleContent;
|
|
109
|
-
//
|
|
110
|
-
if (articleType === '
|
|
111
|
-
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
formatData.data.pics = [];
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
else if (articleType === 'opus') {
|
|
121
|
-
const FullNewTypeArticleContent = this.praseFullNewTypeArticleContent(readInfo?.paragraphs);
|
|
122
|
-
if (FullNewTypeArticleContent) {
|
|
123
|
-
const { content, img } = FullNewTypeArticleContent;
|
|
124
|
-
formatData.data.content = content;
|
|
125
|
-
formatData.data.pics = img && img.length > 0 ? img : pics;
|
|
126
|
-
if (content && content.length < 100) {
|
|
127
|
-
formatData.data.content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text, additional);
|
|
128
|
-
}
|
|
110
|
+
// 文章类型为 cv(旧类型) 或者 opus(新类型)
|
|
111
|
+
if (articleType === 'opus') {
|
|
112
|
+
const newTypeContent = this.praseFullNewTypeArticleContent(readInfo?.paragraphs);
|
|
113
|
+
if (newTypeContent) {
|
|
114
|
+
content = newTypeContent.content || content;
|
|
115
|
+
pics = newTypeContent.img && newTypeContent.img.length > 0 ? newTypeContent.img : pics;
|
|
129
116
|
}
|
|
130
117
|
}
|
|
131
|
-
else {
|
|
132
|
-
|
|
133
|
-
|
|
118
|
+
else if (articleType === 'cv') {
|
|
119
|
+
const oldTypeContent = this.praseFullOldTypeArticleContent(readInfo?.content);
|
|
120
|
+
content = oldTypeContent || content;
|
|
134
121
|
}
|
|
122
|
+
content = String(content).length < 100 ? this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text, additional) : content;
|
|
135
123
|
}
|
|
136
124
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
formatData.data.pics = pics;
|
|
140
|
-
}
|
|
125
|
+
formatData.data.content = content;
|
|
126
|
+
formatData.data.pics = pics;
|
|
141
127
|
}
|
|
142
128
|
else if (majorType === 'MAJOR_TYPE_ARTICLE') {
|
|
143
129
|
desc = data?.modules?.module_dynamic?.major?.article || {};
|
|
@@ -251,7 +237,7 @@ class BiliQuery {
|
|
|
251
237
|
};
|
|
252
238
|
/**获取完整B站文章内容
|
|
253
239
|
* @param postUrl - 文章链接: https://www.bilibili.com/read/cvxxxx 或者 https://www.bilibili.com/opus/xxxx
|
|
254
|
-
* @returns
|
|
240
|
+
* @returns 完整的B站文章内容json数据
|
|
255
241
|
*/
|
|
256
242
|
static async getFullArticleContent(postUrl) {
|
|
257
243
|
let { cookie } = await readSyncCookie();
|
|
@@ -262,24 +248,22 @@ class BiliQuery {
|
|
|
262
248
|
responseType: 'text'
|
|
263
249
|
});
|
|
264
250
|
const text = response.data;
|
|
265
|
-
let
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
251
|
+
let matchCV, matchOPUS, readInfo, articleType;
|
|
252
|
+
matchCV = String(text).match(/"readInfo":([\s\S]+?),"readViewInfo":/);
|
|
253
|
+
matchOPUS = String(text).match(/"module_content"\s*:\s*([\s\S]+?)\s*,\s*"module_type"\s*:\s*"MODULE_TYPE_CONTENT"/);
|
|
254
|
+
if (matchOPUS) {
|
|
255
|
+
logger.info(`文章内容新`);
|
|
256
|
+
const full_json_text = matchOPUS[1];
|
|
257
|
+
readInfo = JSON.parse(full_json_text);
|
|
258
|
+
articleType = 'opus';
|
|
259
|
+
return { readInfo, articleType };
|
|
274
260
|
}
|
|
275
|
-
else if (
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
return { readInfo, articleType };
|
|
282
|
-
}
|
|
261
|
+
else if (matchCV) {
|
|
262
|
+
logger.info(`文章内容旧`);
|
|
263
|
+
const full_json_text = matchCV[1];
|
|
264
|
+
readInfo = JSON.parse(full_json_text);
|
|
265
|
+
articleType = 'cv';
|
|
266
|
+
return { readInfo, articleType };
|
|
283
267
|
}
|
|
284
268
|
}
|
|
285
269
|
catch (err) {
|
|
@@ -399,9 +383,15 @@ class BiliQuery {
|
|
|
399
383
|
*/
|
|
400
384
|
static async formatTextDynamicData(upName, data, isForward, setData) {
|
|
401
385
|
const BiliDrawDynamicLinkUrl = 'https://m.bilibili.com/dynamic/';
|
|
402
|
-
let desc, msg = [], pics = [], author, majorType, content, dynamicTitle;
|
|
403
|
-
let
|
|
386
|
+
let desc, msg = [], pics = [], author, majorType, content, dynamicTitle, module_stat;
|
|
387
|
+
let msg_meta = `B站【${upName}】动态推送:\n`;
|
|
404
388
|
let dynamicType = data.type;
|
|
389
|
+
function formatNumber(num) {
|
|
390
|
+
if (num >= 10000) {
|
|
391
|
+
return `${(num / 10000).toFixed(1)}万`;
|
|
392
|
+
}
|
|
393
|
+
return num.toString();
|
|
394
|
+
}
|
|
405
395
|
switch (dynamicType) {
|
|
406
396
|
case 'DYNAMIC_TYPE_AV':
|
|
407
397
|
// 处理视频动态
|
|
@@ -409,14 +399,22 @@ class BiliQuery {
|
|
|
409
399
|
author = data?.modules?.module_author;
|
|
410
400
|
if (!desc && !author)
|
|
411
401
|
return;
|
|
412
|
-
|
|
402
|
+
module_stat = data?.modules?.module_stat;
|
|
403
|
+
msg_meta = `B站【${upName}】视频动态推送:\n`;
|
|
413
404
|
msg = [
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
405
|
+
msg_meta,
|
|
406
|
+
`\n--------------------`,
|
|
407
|
+
`\n${desc.title}`, // 标题
|
|
408
|
+
`\n--------------------`,
|
|
409
|
+
`\n视频简介:`,
|
|
417
410
|
`${desc.desc}\n`,
|
|
418
|
-
|
|
419
|
-
|
|
411
|
+
`\n--------------------`,
|
|
412
|
+
`投稿:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
|
|
413
|
+
`\n--------------------`,
|
|
414
|
+
`\n${desc?.stat?.danmaku}弹幕 • ${desc?.stat?.play}播放`,
|
|
415
|
+
`\n${formatNumber(module_stat?.like?.count)}点赞 • ${formatNumber(module_stat?.comment?.count)}评论 • ${formatNumber(module_stat?.forward?.count)}转发`,
|
|
416
|
+
`\n--------------------`,
|
|
417
|
+
`\n链接:${this.formatUrl(desc.jump_url)}`
|
|
420
418
|
];
|
|
421
419
|
pics = [Segment.image(desc?.cover)];
|
|
422
420
|
return { msg, pics, dynamicType };
|
|
@@ -441,13 +439,19 @@ class BiliQuery {
|
|
|
441
439
|
}
|
|
442
440
|
if (!desc && !author)
|
|
443
441
|
return;
|
|
444
|
-
|
|
442
|
+
module_stat = data?.modules?.module_stat;
|
|
443
|
+
msg_meta = `B站【${upName}】图文动态推送:\n`;
|
|
445
444
|
msg = [
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
445
|
+
msg_meta,
|
|
446
|
+
`\n--------------------`,
|
|
447
|
+
`\n正文:`,
|
|
448
|
+
`\n${this.dynamicContentLimit(content, setData)}`,
|
|
449
|
+
`\n--------------------`,
|
|
450
|
+
`\n投稿:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
|
|
451
|
+
`\n--------------------`,
|
|
452
|
+
`\n${formatNumber(module_stat?.like?.count)}点赞 • ${formatNumber(module_stat?.comment?.count)}评论 • ${formatNumber(module_stat?.forward?.count)}转发`,
|
|
453
|
+
`\n--------------------`,
|
|
454
|
+
`\n链接:${BiliDrawDynamicLinkUrl}${data.id_str}\n`
|
|
451
455
|
];
|
|
452
456
|
return { msg, pics, dynamicType };
|
|
453
457
|
case 'DYNAMIC_TYPE_DRAW':
|
|
@@ -480,6 +484,7 @@ class BiliQuery {
|
|
|
480
484
|
}
|
|
481
485
|
if (!desc && !pics && !author)
|
|
482
486
|
return;
|
|
487
|
+
module_stat = data?.modules?.module_stat;
|
|
483
488
|
const dynamicPicCountLimit = setData.pushPicCountLimit || 3;
|
|
484
489
|
if (pics.length > dynamicPicCountLimit) {
|
|
485
490
|
pics.length = dynamicPicCountLimit;
|
|
@@ -487,13 +492,18 @@ class BiliQuery {
|
|
|
487
492
|
pics = pics.map((item) => {
|
|
488
493
|
return Segment.image(item);
|
|
489
494
|
});
|
|
490
|
-
|
|
495
|
+
msg_meta = `B站【${upName}】图文动态推送:\n`;
|
|
491
496
|
msg = [
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
+
msg_meta,
|
|
498
|
+
`\n--------------------`,
|
|
499
|
+
`\n正文:`,
|
|
500
|
+
`\n${this.dynamicContentLimit(content, setData)}`,
|
|
501
|
+
`\n--------------------`,
|
|
502
|
+
`\n投稿:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
|
|
503
|
+
`\n--------------------`,
|
|
504
|
+
`\n${formatNumber(module_stat?.like?.count)}点赞 • ${formatNumber(module_stat?.comment?.count)}评论 • ${formatNumber(module_stat?.forward?.count)}转发`,
|
|
505
|
+
`\n--------------------`,
|
|
506
|
+
`\n链接:${BiliDrawDynamicLinkUrl}${data.id_str}`
|
|
497
507
|
];
|
|
498
508
|
return { msg, pics, dynamicType };
|
|
499
509
|
case 'DYNAMIC_TYPE_ARTICLE':
|
|
@@ -527,16 +537,24 @@ class BiliQuery {
|
|
|
527
537
|
}
|
|
528
538
|
if (!desc && !author)
|
|
529
539
|
return;
|
|
540
|
+
module_stat = data?.modules?.module_stat;
|
|
530
541
|
pics = pics.map((item) => {
|
|
531
542
|
return Segment.image(item);
|
|
532
543
|
});
|
|
533
|
-
|
|
544
|
+
msg_meta = `B站【${upName}】文章动态推送:\n`;
|
|
534
545
|
msg = [
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
546
|
+
msg_meta,
|
|
547
|
+
`\n--------------------`,
|
|
548
|
+
`\n${dynamicTitle}`,
|
|
549
|
+
`\n--------------------`,
|
|
550
|
+
`\n正文:`,
|
|
551
|
+
`\n${this.dynamicContentLimit(content, setData)}`,
|
|
552
|
+
`\n--------------------`,
|
|
553
|
+
`\n投稿:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
|
|
554
|
+
`\n--------------------`,
|
|
555
|
+
`\n${formatNumber(module_stat?.like?.count)}点赞 • ${formatNumber(module_stat?.comment?.count)}评论 • ${formatNumber(module_stat?.forward?.count)}转发`,
|
|
556
|
+
`\n--------------------`,
|
|
557
|
+
`\n链接:${this.formatUrl(desc.jump_url)}`
|
|
540
558
|
];
|
|
541
559
|
return { msg, pics, dynamicType };
|
|
542
560
|
case 'DYNAMIC_TYPE_FORWARD':
|
|
@@ -548,6 +566,7 @@ class BiliQuery {
|
|
|
548
566
|
return;
|
|
549
567
|
if (!data.orig)
|
|
550
568
|
return;
|
|
569
|
+
module_stat = data?.modules?.module_stat;
|
|
551
570
|
isForward = true;
|
|
552
571
|
let orig = await this.formatTextDynamicData(upName, data.orig, isForward, setData);
|
|
553
572
|
let origContent = [];
|
|
@@ -558,14 +577,19 @@ class BiliQuery {
|
|
|
558
577
|
else {
|
|
559
578
|
return 'continue';
|
|
560
579
|
}
|
|
561
|
-
|
|
580
|
+
msg_meta = `B站【${upName}】转发动态推送:\n`;
|
|
562
581
|
msg = [
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
582
|
+
msg_meta,
|
|
583
|
+
`\n--------------------`,
|
|
584
|
+
`\n正文:`,
|
|
585
|
+
`\n${this.dynamicContentLimit(content, setData)}`,
|
|
586
|
+
`\n--------------------`,
|
|
587
|
+
`\n投稿:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
|
|
588
|
+
`\n--------------------`,
|
|
589
|
+
`\n${formatNumber(module_stat?.like?.count)}点赞 • ${formatNumber(module_stat?.comment?.count)}评论 • ${formatNumber(module_stat?.forward?.count)}转发`,
|
|
590
|
+
`\n--------------------`,
|
|
591
|
+
`\n链接:${BiliDrawDynamicLinkUrl}${data.id_str}\n`,
|
|
592
|
+
'\n>>>>以下为转发内容<<<<\n',
|
|
569
593
|
...origContent
|
|
570
594
|
];
|
|
571
595
|
return { msg, pics, dynamicType };
|
|
@@ -578,8 +602,18 @@ class BiliQuery {
|
|
|
578
602
|
desc = desc?.live_play_info;
|
|
579
603
|
if (!desc)
|
|
580
604
|
return;
|
|
581
|
-
|
|
582
|
-
msg = [
|
|
605
|
+
msg_meta = `B站【${upName}】直播动态推送:\n`;
|
|
606
|
+
msg = [
|
|
607
|
+
msg_meta,
|
|
608
|
+
`\n--------------------`,
|
|
609
|
+
`\n${desc.title}`,
|
|
610
|
+
`\n--------------------`,
|
|
611
|
+
`\n分区:${desc?.parent_area_name} (${desc?.area_name})`,
|
|
612
|
+
`\n开播:${moment(desc.live_start_time * 1000).format('YYYY年MM月DD日 HH:mm:ss')}`,
|
|
613
|
+
`\n--------------------`,
|
|
614
|
+
`\n${formatNumber(desc?.watched_show?.num)}人看过`,
|
|
615
|
+
`\n链接:https:${desc.link}`
|
|
616
|
+
];
|
|
583
617
|
pics = [Segment.image(desc.cover)];
|
|
584
618
|
return { msg, pics, dynamicType };
|
|
585
619
|
default:
|
|
@@ -60,6 +60,7 @@ class BiliTask {
|
|
|
60
60
|
async processBiliData(biliPushData, biliConfigData, uidMap, dynamicList) {
|
|
61
61
|
let getDataRandomDelay = biliConfigData?.getDataRandomDelay || 8000; // 获取相邻up动态数据的随机延时间隔
|
|
62
62
|
const requestedDataOfUids = new Map(); // 存放已请求的 uid 映射
|
|
63
|
+
const printedList = new Set(); // 已打印的动态列表
|
|
63
64
|
for (let chatType in biliPushData) {
|
|
64
65
|
// 遍历 group 和 private
|
|
65
66
|
if (!uidMap.has(chatType)) {
|
|
@@ -75,6 +76,10 @@ class BiliTask {
|
|
|
75
76
|
let resp;
|
|
76
77
|
// 检查是否已经请求过该 uid
|
|
77
78
|
if (!requestedDataOfUids.has(uid)) {
|
|
79
|
+
if (!printedList.has(uid)) {
|
|
80
|
+
logger.info(`正在检测B站动态 [ ${name} : ${uid} ]`);
|
|
81
|
+
printedList.add(uid);
|
|
82
|
+
}
|
|
78
83
|
resp = await this.hendleEventDynamicData(uid);
|
|
79
84
|
if (resp) {
|
|
80
85
|
if (resp.code === 0) {
|
|
@@ -110,6 +115,7 @@ class BiliTask {
|
|
|
110
115
|
}
|
|
111
116
|
}
|
|
112
117
|
requestedDataOfUids.clear(); // 清空已请求的 uid 映射
|
|
118
|
+
printedList.clear(); // 清空已打印的动态列表
|
|
113
119
|
}
|
|
114
120
|
/**
|
|
115
121
|
* 构建uid对应动态数据映射
|
|
@@ -120,17 +126,12 @@ class BiliTask {
|
|
|
120
126
|
* @param biliConfigData Bilibili配置数据
|
|
121
127
|
*/
|
|
122
128
|
async makeUidDynamicDataMap(uidMap, dynamicList, now, dynamicTimeRange, biliConfigData, messageMap) {
|
|
123
|
-
const printedList = new Set(); // 已打印的动态列表
|
|
124
129
|
for (let [chatType, chatTypeMap] of uidMap) {
|
|
125
130
|
for (let [upUid, bot_idMap] of chatTypeMap) {
|
|
126
131
|
const tempDynamicList = dynamicList[upUid] || [];
|
|
127
132
|
const willPushDynamicList = [];
|
|
128
133
|
for (let dynamicItem of tempDynamicList) {
|
|
129
134
|
let author = dynamicItem?.modules?.module_author || {};
|
|
130
|
-
if (!printedList.has(author?.mid)) {
|
|
131
|
-
logger.info(`正在检测B站动态 [ ${author?.name} : ${author?.mid} ]`);
|
|
132
|
-
printedList.add(author?.mid);
|
|
133
|
-
}
|
|
134
135
|
if (!author?.pub_ts)
|
|
135
136
|
continue; // 如果动态没有发布时间,跳过当前循环
|
|
136
137
|
if (Number(now - author.pub_ts) > dynamicTimeRange) {
|
|
@@ -157,7 +158,6 @@ class BiliTask {
|
|
|
157
158
|
}
|
|
158
159
|
}
|
|
159
160
|
}
|
|
160
|
-
printedList.clear(); // 清空已打印的动态列表
|
|
161
161
|
}
|
|
162
162
|
/**
|
|
163
163
|
* 渲染构建待发送的动态消息数据的映射数组
|
|
@@ -72,7 +72,7 @@ class WeiboQuery {
|
|
|
72
72
|
/**动态详情链接 */
|
|
73
73
|
let detail_url = `https://weibo.com/${info?.user?.id}/${info?.bid}`;
|
|
74
74
|
/* 构造动态渲染数据 *************************** */
|
|
75
|
-
let pics = [];
|
|
75
|
+
let pics = [], video_pics_list;
|
|
76
76
|
let formatData = { data: {} };
|
|
77
77
|
/**头像 */
|
|
78
78
|
formatData.data.face = face_url;
|
|
@@ -85,12 +85,17 @@ class WeiboQuery {
|
|
|
85
85
|
formatData.data.type = type;
|
|
86
86
|
switch (type) {
|
|
87
87
|
case 'DYNAMIC_TYPE_AV':
|
|
88
|
+
video_pics_list = info?.pics ? info?.pics : info?.page_info?.page_pic?.url ? [{ large: { url: info.page_info.page_pic.url } }] : [];
|
|
89
|
+
pics =
|
|
90
|
+
video_pics_list.map((img) => {
|
|
91
|
+
return { url: img?.large?.url, width: Number(img?.large?.geo?.width), height: Number(img?.large?.geo?.height) };
|
|
92
|
+
}) || [];
|
|
88
93
|
formatData.data.title = info?.page_info?.title || '';
|
|
89
94
|
formatData.data.content = this.parseRichTextNodes(info?.text);
|
|
90
95
|
formatData.data.url = detail_url;
|
|
91
96
|
formatData.data.pubTs = moment(created_time).format('YYYY年MM月DD日 HH:mm:ss');
|
|
92
97
|
formatData.data.category = '视频动态';
|
|
93
|
-
formatData.data.pics =
|
|
98
|
+
formatData.data.pics = pics;
|
|
94
99
|
break;
|
|
95
100
|
case 'DYNAMIC_TYPE_DRAW':
|
|
96
101
|
let raw_pics_list = retweeted ? info?.retweeted_status?.pics || [] : info?.pics || [];
|
|
@@ -182,7 +187,7 @@ class WeiboQuery {
|
|
|
182
187
|
/**图片高清资源链接*/
|
|
183
188
|
pic_urls = [],
|
|
184
189
|
/**图片*/
|
|
185
|
-
pics = [];
|
|
190
|
+
pics = [], video_pics_list;
|
|
186
191
|
let info = raw_post?.mblog || raw_post;
|
|
187
192
|
let retweeted = info && info.retweeted_status ? true : false; //是否为转发动态
|
|
188
193
|
let pic_num = retweeted ? info?.retweeted_status?.pic_num : info?.pic_num;
|
|
@@ -205,24 +210,39 @@ class WeiboQuery {
|
|
|
205
210
|
/**动态发布时间 */
|
|
206
211
|
let created_time = this.getDynamicCreatetDate(raw_post);
|
|
207
212
|
let detail_url = `https://weibo.com/${info?.user?.id}/${info?.bid}`;
|
|
208
|
-
let
|
|
213
|
+
let msg_meta = `微博【${upName}】动态推送:\n`;
|
|
209
214
|
const dynamicPicCountLimit = setData.pushPicCountLimit || 3;
|
|
215
|
+
function formatNumber(num) {
|
|
216
|
+
if (num >= 10000) {
|
|
217
|
+
return `${(num / 10000).toFixed(1)}万`;
|
|
218
|
+
}
|
|
219
|
+
return num.toString();
|
|
220
|
+
}
|
|
210
221
|
switch (dynamicType) {
|
|
211
222
|
case 'DYNAMIC_TYPE_AV':
|
|
212
223
|
if (!info)
|
|
213
224
|
return;
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
225
|
+
video_pics_list = info?.pics ? info?.pics : info?.page_info?.page_pic?.url ? [{ large: { url: info.page_info.page_pic.url } }] : [];
|
|
226
|
+
pic_urls = video_pics_list.map(img => img?.large?.url);
|
|
227
|
+
for (const pic_url of pic_urls) {
|
|
228
|
+
const temp = Segment.image(pic_url, false, 15000, { referer: 'https://weibo.com' });
|
|
229
|
+
pics.push(temp);
|
|
230
|
+
}
|
|
231
|
+
msg_meta = `微博【${upName}】视频动态推送:\n`;
|
|
217
232
|
msg = [
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
233
|
+
msg_meta,
|
|
234
|
+
`\n--------------------`,
|
|
235
|
+
`\n${info?.page_info?.title || ''}`, //标题
|
|
236
|
+
`\n--------------------`,
|
|
237
|
+
`\n正文:`,
|
|
238
|
+
`\n${this.filterText(info?.text)}`,
|
|
239
|
+
`\n--------------------`,
|
|
240
|
+
`\n投稿:${created_time ? moment(created_time).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
|
|
241
|
+
`\n--------------------`,
|
|
242
|
+
`\n${formatNumber(info?.attitudes_count)}点赞 • ${formatNumber(info?.comments_count)}评论 • ${formatNumber(info?.reposts_count)}转发 `,
|
|
243
|
+
`\n--------------------`,
|
|
244
|
+
`\n链接:${detail_url}`
|
|
224
245
|
];
|
|
225
|
-
pics = [cover_img];
|
|
226
246
|
return { msg, pics, dynamicType };
|
|
227
247
|
case 'DYNAMIC_TYPE_DRAW':
|
|
228
248
|
raw_pics_list = retweeted ? info?.retweeted_status?.pics || [] : info?.pics || [];
|
|
@@ -235,13 +255,18 @@ class WeiboQuery {
|
|
|
235
255
|
const temp = Segment.image(pic_url, false, 15000, { referer: 'https://weibo.com' });
|
|
236
256
|
pics.push(temp);
|
|
237
257
|
}
|
|
238
|
-
|
|
258
|
+
msg_meta = `微博【${upName}】图文动态推送:\n`;
|
|
239
259
|
msg = [
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
260
|
+
msg_meta,
|
|
261
|
+
`\n--------------------`,
|
|
262
|
+
`\n正文:`,
|
|
263
|
+
`\n${this.dynamicContentLimit(this.filterText(info?.text), setData)}`,
|
|
264
|
+
`\n--------------------`,
|
|
265
|
+
`\n投稿:${created_time ? moment(created_time).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
|
|
266
|
+
`\n--------------------`,
|
|
267
|
+
`\n${formatNumber(info?.attitudes_count)}点赞 • ${formatNumber(info?.comments_count)}评论 • ${formatNumber(info?.reposts_count)}转发 `,
|
|
268
|
+
`\n--------------------`,
|
|
269
|
+
`\n链接:${detail_url}`
|
|
245
270
|
];
|
|
246
271
|
return { msg, pics, dynamicType };
|
|
247
272
|
case 'DYNAMIC_TYPE_ARTICLE':
|
|
@@ -255,13 +280,18 @@ class WeiboQuery {
|
|
|
255
280
|
const temp = Segment.image(pic_url, false, 15000, { referer: 'https://weibo.com' });
|
|
256
281
|
pics.push(temp);
|
|
257
282
|
}
|
|
258
|
-
|
|
283
|
+
msg_meta = `微博【${upName}】文章动态推送:\n`;
|
|
259
284
|
msg = [
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
285
|
+
msg_meta,
|
|
286
|
+
`\n--------------------`,
|
|
287
|
+
`\n正文:`,
|
|
288
|
+
`\n${this.dynamicContentLimit(this.filterText(info?.text), setData)}`,
|
|
289
|
+
`\n--------------------`,
|
|
290
|
+
`\n投稿:${created_time ? moment(created_time).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
|
|
291
|
+
`\n--------------------`,
|
|
292
|
+
`\n${formatNumber(info?.attitudes_count)}点赞 • ${formatNumber(info?.comments_count)}评论 • ${formatNumber(info?.reposts_count)}转发 `,
|
|
293
|
+
`\n--------------------`,
|
|
294
|
+
`\n链接:${detail_url}`
|
|
265
295
|
];
|
|
266
296
|
return { msg, pics, dynamicType };
|
|
267
297
|
case 'DYNAMIC_TYPE_FORWARD':
|
|
@@ -280,14 +310,19 @@ class WeiboQuery {
|
|
|
280
310
|
else {
|
|
281
311
|
return 'continue';
|
|
282
312
|
}
|
|
283
|
-
|
|
313
|
+
msg_meta = `微博【${upName}】转发动态推送:\n`;
|
|
284
314
|
msg = [
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
315
|
+
msg_meta,
|
|
316
|
+
`\n--------------------`,
|
|
317
|
+
`\n正文:`,
|
|
318
|
+
`\n${this.dynamicContentLimit(this.filterText(info?.text), setData)}`,
|
|
319
|
+
`\n--------------------`,
|
|
320
|
+
`\n投稿:${created_time ? moment(created_time).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
|
|
321
|
+
`\n--------------------`,
|
|
322
|
+
`\n${formatNumber(info?.attitudes_count)}点赞 • ${formatNumber(info?.comments_count)}评论 • ${formatNumber(info?.reposts_count)}转发 `,
|
|
323
|
+
`\n--------------------`,
|
|
324
|
+
`\n链接:${detail_url}\n`,
|
|
325
|
+
'\n>>>>以下为转发内容<<<<\n',
|
|
291
326
|
...origContent
|
|
292
327
|
];
|
|
293
328
|
return { msg, pics, dynamicType };
|
|
@@ -40,6 +40,7 @@ class WeiboTask {
|
|
|
40
40
|
*/
|
|
41
41
|
async processWeiboData(weiboPushData, uidMap, dynamicList) {
|
|
42
42
|
const requestedDataOfUids = new Map(); // 存放已请求的 uid 映射
|
|
43
|
+
const printedList = new Set(); // 已打印的动态列表
|
|
43
44
|
for (let chatType in weiboPushData) {
|
|
44
45
|
// 遍历 group 和 private
|
|
45
46
|
if (!uidMap.has(chatType)) {
|
|
@@ -55,11 +56,15 @@ class WeiboTask {
|
|
|
55
56
|
let resp;
|
|
56
57
|
// 检查是否已经请求过该 uid
|
|
57
58
|
if (!requestedDataOfUids.has(uid)) {
|
|
59
|
+
if (!printedList.has(uid)) {
|
|
60
|
+
logger.info(`正在检测微博动态 [ ${name} : ${uid} ]`);
|
|
61
|
+
printedList.add(uid);
|
|
62
|
+
}
|
|
58
63
|
resp = await new WeiboWebDataFetcher().getBloggerDynamicList(uid); // 获取指定 uid 的动态列表
|
|
59
64
|
if (resp) {
|
|
60
65
|
requestedDataOfUids.set(uid, resp); // 将响应数据存储到映射中
|
|
61
66
|
const dynamicData = resp || [];
|
|
62
|
-
dynamicList[
|
|
67
|
+
dynamicList[uid] = dynamicData;
|
|
63
68
|
}
|
|
64
69
|
}
|
|
65
70
|
if (!chatTypeMap.has(uid)) {
|
|
@@ -76,6 +81,7 @@ class WeiboTask {
|
|
|
76
81
|
}
|
|
77
82
|
}
|
|
78
83
|
requestedDataOfUids.clear(); // 清空已请求的映射
|
|
84
|
+
printedList.clear(); // 清空已打印的动态列表
|
|
79
85
|
}
|
|
80
86
|
/**
|
|
81
87
|
* 构建uid对应动态数据映射
|
|
@@ -86,7 +92,6 @@ class WeiboTask {
|
|
|
86
92
|
* @param weiboConfigData 微博配置数据
|
|
87
93
|
*/
|
|
88
94
|
async makeUidDynamicDataMap(uidMap, dynamicList, now, dynamicTimeRange, weiboConfigData, messageMap) {
|
|
89
|
-
const printedList = new Set(); // 已打印的动态列表
|
|
90
95
|
for (let [chatType, chatTypeMap] of uidMap) {
|
|
91
96
|
for (let [upUid, bot_idMap] of chatTypeMap) {
|
|
92
97
|
const tempDynamicList = dynamicList[upUid] || [];
|
|
@@ -94,10 +99,6 @@ class WeiboTask {
|
|
|
94
99
|
for (let dynamicItem of tempDynamicList) {
|
|
95
100
|
let raw_post = dynamicItem || {};
|
|
96
101
|
let user = raw_post?.mblog?.user || {};
|
|
97
|
-
if (!printedList.has(user?.id)) {
|
|
98
|
-
logger.info(`正在检测微博动态 [ ${user?.screen_name} : ${user?.id} ]`);
|
|
99
|
-
printedList.add(user?.id);
|
|
100
|
-
}
|
|
101
102
|
if (!raw_post?.mblog?.created_at)
|
|
102
103
|
continue;
|
|
103
104
|
if (Number(now - WeiboQuery.getDynamicCreatetDate(raw_post) / 1000) > dynamicTimeRange) {
|
|
@@ -124,7 +125,6 @@ class WeiboTask {
|
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
|
-
printedList.clear(); // 清空已打印的动态列表
|
|
128
128
|
}
|
|
129
129
|
/**
|
|
130
130
|
* 渲染构建待发送的动态消息数据的映射数组
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yz-yuki-plugin",
|
|
3
|
-
"version": "2.0.7-
|
|
3
|
+
"version": "2.0.7-15",
|
|
4
4
|
"description": "优纪插件,yunzaijs 关于 微博推送、B站推送 等功能的拓展插件",
|
|
5
5
|
"author": "snowtafir",
|
|
6
6
|
"type": "module",
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
"debug": "^4.3.6",
|
|
32
32
|
"jsdom": "^25.0.1",
|
|
33
33
|
"json5": "^2.2.3",
|
|
34
|
-
"jsxp": "^1.1
|
|
34
|
+
"jsxp": "^1.2.1",
|
|
35
35
|
"lodash": "^4.17.21",
|
|
36
36
|
"md5": "^2.3.0",
|
|
37
37
|
"moment": "^2.30.1",
|
|
38
38
|
"node-fetch": "^3.3.2",
|
|
39
|
-
"puppeteer": "^24.
|
|
39
|
+
"puppeteer": "^24.8.2",
|
|
40
40
|
"qrcode": "^1.5.4",
|
|
41
41
|
"react": "^18.3.1",
|
|
42
42
|
"react-dom": "^18.3.1",
|
|
@@ -63,14 +63,14 @@
|
|
|
63
63
|
"icqq": "^0.6.10",
|
|
64
64
|
"jsdom": "^24.1.1",
|
|
65
65
|
"json5": "^2.2.3",
|
|
66
|
-
"jsxp": "^1.1
|
|
66
|
+
"jsxp": "^1.2.1",
|
|
67
67
|
"lodash": "^4.17.21",
|
|
68
|
-
"lvyjs": "^0.2.
|
|
68
|
+
"lvyjs": "^0.2.19",
|
|
69
69
|
"md5": "^2.3.0",
|
|
70
70
|
"node-fetch": "^3.3.2",
|
|
71
71
|
"postcss": "^8.4.47",
|
|
72
72
|
"prettier": "^3.4.2",
|
|
73
|
-
"puppeteer": "^24.
|
|
73
|
+
"puppeteer": "^24.8.2",
|
|
74
74
|
"qrcode": "^1.5.4",
|
|
75
75
|
"react": "^18.3.1",
|
|
76
76
|
"react-dom": "^18.3.1",
|