yz-yuki-plugin 2.0.8-0 → 2.0.8-10

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 CHANGED
@@ -1,4 +1,7 @@
1
1
  # 2.0.8
2
+ * 优化屏蔽关键词日志
3
+ * 添加微博登录功能(待续)
4
+ * 更新B站动态标题获取
2
5
  * 合并分支dev与dev3,减少维护成本
3
6
 
4
7
  # 2.0.7
package/README.md CHANGED
@@ -6,8 +6,7 @@
6
6
 
7
7
  - 支持 群聊/私聊 订阅B站动态和微博动态,支持定时推送,支持手动触发推送,支持简单查询B站/微博用户信息。
8
8
 
9
- [![访问量](https://profile-counter.glitch.me/yuki-plugin/count.svg)](https://github.com/snowtafir/yuki-plugin)
10
-
9
+ ![访问统计](https://visitor-badge.laobi.icu/badge?page_id=snowtafir/yuki-plugin)
11
10
 
12
11
  # 🚩运行环境:
13
12
  1. 系统:
@@ -187,7 +186,7 @@ https://m.weibo.cn/u/7643376782 # 7643376782 为崩坏星穹铁道博主uid
187
186
  | 扫码B站登录 | app扫码获取登录ck | `#扫码B站登录` |
188
187
  | 取消B站登录 | 删除扫码获取的B站CK | `#取消B站登陆` |
189
188
  | 查看B站登录信息 | 查看app扫码登录的信息和状态 | `#我的B站登录` |
190
- | 绑定B站ck | 配置手动本地获取的B站CK,仅限私聊/私信,权限:Master | `#绑定B本地站ck: xxx` |
189
+ | 绑定B站ck | 配置手动本地获取的B站CK,仅限私聊/私信,权限:Master | `#绑定B站本地ck: xxx` |
191
190
  | 删除B站ck | 删除手动获取的B站cookie,权限:Master | `#删除B站本地ck` |
192
191
  | 查看B站ck | 查看当前启用的B站ck,仅限私聊 | `#我的B站ck` |
193
192
  | 刷新B站临时ck | 重新获取并刷新redis缓存的未绑定自己的B站ck而自动获取的 临时B站cookie | `#刷新B站临时ck` |
@@ -201,6 +200,12 @@ https://m.weibo.cn/u/7643376782 # 7643376782 为崩坏星穹铁道博主uid
201
200
  | 手动推送微博订阅 | 手动触发定时推送任务,权限:Bot的Master | `#执行微博任务` |
202
201
  | 查看博主信息 | 通过uid查看博主信息 | `#微博博主 uid` |
203
202
  | 搜索微博博主 | 根据关键词在微博搜索大V博主的信息 | `#搜索微博博主 xxx` |
203
+ | 扫码微博登录(待完成) | app扫码获取登录ck | `#扫码微博登录` |
204
+ | 取消微博登录 | 删除扫码获取的微博CK | `#取消微博登陆` |
205
+ | 查看微博登录信息 | 查看app扫码登录的信息和状态 | `#我的微博登录` |
206
+ | 绑定微博ck | 配置手动本地获取的微博CK,仅限私聊/私信,权限:Master | `#绑定微博本地ck: xxx` |
207
+ | 删除微博ck | 删除手动获取的微博cookie,权限:Master | `#删除微博本地ck` |
208
+ | 查看微博ck | 查看当前启用的微博ck,仅限私聊 | `#我的微博ck` |
204
209
  ||||
205
210
  | **其他指令** | | |
206
211
  | 查看版本信息 | 查看版本信息 | `#优纪版本` |
@@ -83,6 +83,9 @@ noSplitHeight: 7500
83
83
  # 动态卡片分页截图高度,默认8000px(仅填数字,无需填入单位),请勿设置过大或过小。启用分片截图时生效。
84
84
  splitHeight: 8000
85
85
 
86
+ # 渲染动态内容是否暂停 GIF 动图,默认 0 否,1 是。
87
+ isPauseGif: 0
88
+
86
89
  # 直播动态是否@全体成员,默认 0 关闭,1 开启。
87
90
  # 开启前请检查 <机器人> 是否有 [管理员权限] 或 [聊天平台是否支持],某些聊天平台或类型不支持@全体成员,如qq官方机器人等。
88
91
  liveAtAll: 0
@@ -50,6 +50,9 @@
50
50
  - icon: wondrous_lovely_flower
51
51
  title: '#刷新B站临时ck'
52
52
  desc: '刷新自动获取的临时B站cookie'
53
+ - icon: romaritime_flower
54
+ title: 'B站视频链接解析'
55
+ desc: '直接发送B站视频链接即可'
53
56
  - group: 微博功能
54
57
  list:
55
58
  - icon: diagram
@@ -73,6 +76,24 @@
73
76
  - icon: shell
74
77
  title: '#搜索微博博主原神'
75
78
  desc: '根据关键词在微博搜索大V博主的信息'
79
+ - icon: 雷神瞳共鸣石
80
+ title: '#扫码微博登录'
81
+ desc: 'app扫码获取登录ck(待完成)'
82
+ - icon: everamber
83
+ title: '#取消微博登陆'
84
+ desc: '删除扫码获取的微博CK'
85
+ - icon: condessence_crystal
86
+ title: '#我的微博登录'
87
+ desc: '查看app扫码登录的信息和状态'
88
+ - icon: romaritime_flower
89
+ title: '#绑定微博本地ck: ***'
90
+ desc: '配置本地获取的微博CK'
91
+ - icon: unfading_silky_grace
92
+ title: '#删除微博本地ck'
93
+ desc: '删除手动获取的微博ck'
94
+ - icon: delightful_encounter
95
+ title: '#我的微博ck'
96
+ desc: '查看当前启用的微博ck,仅限私聊'
76
97
  - group: 其他指令
77
98
  list:
78
99
  - icon: 风车
@@ -77,3 +77,6 @@ noSplitHeight: 7500
77
77
 
78
78
  # 动态卡片分页截图高度,默认8000px(仅填数字,无需填入单位),请勿设置过大或过小。启用分片截图时生效。
79
79
  splitHeight: 8000
80
+
81
+ # 渲染动态内容是否暂停 GIF 动图,默认 0 否,1 是。
82
+ isPauseGif: 0
@@ -297,7 +297,7 @@ message.use(async (e) => {
297
297
  e.reply('未取得bot主人身份,无权限删除B站登录ck');
298
298
  }
299
299
  }, [/^(#|\/)(yuki|优纪)?(取消|删除|del|DEL)(b站|B站|bili|bilibili|哔哩|哔哩哔哩)本地(ck|CK|cookie|COOKIE)$/]);
300
- /** 当前正在使用的B站ck */
300
+ /** 当前正在使用的本地B站ck */
301
301
  message.use(async (e) => {
302
302
  if (e.isGroup) {
303
303
  await e.reply('注意账号安全,请私聊查看叭');
@@ -325,7 +325,7 @@ message.use(async (e) => {
325
325
  e.reply('未取得bot主人身份,无权限查看当前使用的B站cookie');
326
326
  }
327
327
  }
328
- }, [/^(#|\/)(yuki|优纪)?(取消|删除|del|DEL)(b站|B站|bili|bilibili|哔哩|哔哩哔哩)本地(ck|CK|cookie|COOKIE)$/]);
328
+ }, [/^(#|\/)(yuki|优纪)?我的(b站|B站|bili|bilibili|哔哩|哔哩哔哩)(ck|CK|cookie|COOKIE)$/]);
329
329
  /** 删除并刷新redis缓存的临时B站ck */
330
330
  message.use(async (e) => {
331
331
  try {
package/lib/apps/weibo.js CHANGED
@@ -1,8 +1,10 @@
1
- import { Messages } from 'yunzaijs';
1
+ import { WeiboWebDataFetcher } from '../models/weibo/weibo.main.get.web.data.js';
2
+ import { WeiboMainModels } from '../models/weibo/weibo.main.models.js';
2
3
  import { WeiboQuery } from '../models/weibo/weibo.main.query.js';
3
4
  import { WeiboTask } from '../models/weibo/weibo.main.task.js';
4
5
  import Config from '../utils/config.js';
5
- import { WeiboWebDataFetcher } from '../models/weibo/weibo.main.get.web.data.js';
6
+ import lodash from 'lodash';
7
+ import { Messages, Redis } from 'yunzaijs';
6
8
 
7
9
  const message = new Messages('message');
8
10
  let weiboPushData = Config.getConfigData('config', 'weibo', 'push');
@@ -124,6 +126,119 @@ message.use(async (e) => {
124
126
  e.reply(`${isDel ? '删除' : '修改'}微博推送成功~\n${uid}`);
125
127
  }
126
128
  }, [/^(#|\/)(yuki|优纪)?(取消|删除|del|DEL)(微博|weibo|WEIBO)推送\s*(视频\s*|图文\s*|文章\s*|转发\s*)*.*$/]);
129
+ /** 扫码登录微博 */
130
+ message.use(async (e) => {
131
+ if (!e.isMaster) {
132
+ e.reply('未取得bot主人身份,无权限配置微博登录ck');
133
+ }
134
+ else {
135
+ const LoginCk = await WeiboMainModels.readLoginCookie();
136
+ if (LoginCk) {
137
+ e.reply(`当前已有微博登录ck,请勿重复扫码!\n如需更换,请先删除当前登录再扫码:\n#yuki删除微博登录`);
138
+ }
139
+ else {
140
+ try {
141
+ const tokenKey = await WeiboMainModels.applyLoginQRCode(e);
142
+ if (tokenKey && tokenKey.rid) {
143
+ let weiboLoginCk = await WeiboMainModels.pollLoginQRCode(e, tokenKey.qrid, tokenKey.rid, tokenKey.X_CSRF_TOKEN);
144
+ if (weiboLoginCk) {
145
+ if (lodash.trim(weiboLoginCk).length != 0) {
146
+ await WeiboMainModels.saveLoginCookie(e, weiboLoginCk);
147
+ e.reply(`get weibo LoginCk:成功!`);
148
+ }
149
+ else {
150
+ e.reply(`get weibo LoginCk:失败X﹏X`);
151
+ }
152
+ }
153
+ }
154
+ }
155
+ catch (Error) {
156
+ global?.logger?.info(`yuki-plugin Login weibo Failed:${Error}`);
157
+ }
158
+ }
159
+ }
160
+ }, [/^(#|\/)(yuki|优纪)?(扫码|添加|ADD|add)(微博|weibo|WEIBO)登录$/]);
161
+ /** 删除登陆的微博ck */
162
+ message.use(async (e) => {
163
+ if (e.isMaster) {
164
+ await Redis.set('Yz:yuki:weibo:loginCookie', '', { EX: 3600 * 24 * 180 });
165
+ e.reply(`扫码登陆的微博cookie已删除~`);
166
+ }
167
+ else {
168
+ e.reply('未取得bot主人身份,无权限删除微博登录ck');
169
+ }
170
+ }, [/^(#|\/)(yuki|优纪)?(取消|删除|del|DEL)(微博|weibo|WEIBO)登录$/]);
171
+ /** 显示我的微博登录信息 */
172
+ message.use(async (e) => {
173
+ if (e.isMaster) {
174
+ await WeiboMainModels.checkWeiboLogin(e);
175
+ }
176
+ else {
177
+ e.reply('未取得bot主人身份,无权限查看微博登录状态');
178
+ }
179
+ }, [/^(#|\/)(yuki|优纪)?我的(微博|weibo|WEIBO)登录$/]);
180
+ /** 手动绑定本地获取的微博cookie */
181
+ message.use(async (e) => {
182
+ if (e.isMaster) {
183
+ if (e.isPrivate) {
184
+ await e.reply('请注意账号安全,请手动撤回发送的cookie,并私聊进行添加绑定!');
185
+ }
186
+ else {
187
+ let localWeiboCookie = e.msg.replace(/^(#|\/)(yuki|优纪)?(绑定|添加|ADD|add)(微博|weibo|WEIBO)(ck|CK|cookie|COOKIE)(:|:)?/g, '').trim();
188
+ const XSRF_TOKEN = await WeiboMainModels.readSavedCookieItems(localWeiboCookie, ['XSRF-TOKEN'], false);
189
+ if (XSRF_TOKEN) {
190
+ //筛选ck
191
+ localWeiboCookie = await WeiboMainModels.readSavedCookieItems(localWeiboCookie, ['XSRF-TOKEN', 'SUB', 'SUBP', 'SRF', 'SCF', 'SRT', ' _T_WM', 'M_WEIBOCN_PARAMS', 'SSOLoginState', 'ALF'], false);
192
+ await WeiboMainModels.saveLocalBiliCk(localWeiboCookie);
193
+ logger.mark(`${e.logFnc} 保存微博cookie成功 [XSRF_TOKEN: ${XSRF_TOKEN}]`);
194
+ let uidMsg = [`好耶~绑定微博cookie成功:\nXSRF_TOKEN: ${XSRF_TOKEN}`];
195
+ await e.reply(uidMsg);
196
+ }
197
+ else {
198
+ e.reply('绑定的微博cookie无效,请检查后重新添加!');
199
+ return false;
200
+ }
201
+ }
202
+ }
203
+ else {
204
+ e.reply('未取得bot主人身份,无权限配置B站登录ck');
205
+ }
206
+ }, [/^^(#|\/)(yuki|优纪)?(绑定|添加|ADD|add)(微博|weibo|WEIBO)本地(ck|CK|cookie|COOKIE)(:|:)?.*$/]);
207
+ /** 删除绑定的本地微博ck */
208
+ message.use(async (e) => {
209
+ if (e.isMaster) {
210
+ await WeiboMainModels.saveLocalBiliCk('');
211
+ await e.reply(`手动绑定的微博ck已删除~`);
212
+ }
213
+ else {
214
+ e.reply('未取得bot主人身份,无权限删除B站登录ck');
215
+ }
216
+ }, [/^(#|\/)(yuki|优纪)?(取消|删除|del|DEL)(微博|weibo|WEIBO)本地(ck|CK|cookie|COOKIE)$/]);
217
+ /** 查看当前正在使用的本地微博ck */
218
+ message.use(async (e) => {
219
+ if (e.isGroup) {
220
+ await e.reply('注意账号安全,请私聊查看叭');
221
+ }
222
+ else {
223
+ if (e.isMaster) {
224
+ let { cookie, mark } = await WeiboMainModels.readSyncCookie();
225
+ if (mark === 'localCk') {
226
+ e.reply(`当前使用本地获取的微博cookie:`);
227
+ e.reply(`${cookie}`);
228
+ }
229
+ else if (mark === 'loginCk') {
230
+ e.reply(`当前使用扫码登录的微博cookie:`);
231
+ e.reply(`${cookie}`);
232
+ }
233
+ else if (mark == 'ckIsEmpty') {
234
+ e.reply(`当前无可使用的微博cookie。`);
235
+ }
236
+ }
237
+ else {
238
+ e.reply('未取得bot主人身份,无权限查看当前使用的B站cookie');
239
+ }
240
+ }
241
+ }, [/^(#|\/)(yuki|优纪)?我的(微博|weibo|WEIBO)(ck|CK|cookie|COOKIE)$/]);
127
242
  /** 订阅的全部微博推送列表 */
128
243
  message.use(async (e) => {
129
244
  if (!e.isMaster) {
@@ -155,17 +270,19 @@ message.use(async (e) => {
155
270
  messages.push('\n>>>>>>群组微博订阅<<<<<<');
156
271
  Object.keys(subData.group).forEach(groupId => {
157
272
  messages.push(`\n<群组${groupId}>:`);
158
- subData.group[groupId].forEach((item) => {
159
- const types = new Set();
160
- if (item.type && item.type.length) {
161
- item.type.forEach((typeItem) => {
162
- if (typeMap[typeItem]) {
163
- types.add(typeMap[typeItem]);
164
- }
165
- });
166
- }
167
- messages.push(`${item.uid}:${item.name} ${types.size ? `[${Array.from(types).join('、')}]` : ' [全部动态]'}`);
168
- });
273
+ if (subData.group) {
274
+ subData.group[groupId].forEach((item) => {
275
+ const types = new Set();
276
+ if (item.type && item.type.length) {
277
+ item.type.forEach((typeItem) => {
278
+ if (typeMap[typeItem]) {
279
+ types.add(typeMap[typeItem]);
280
+ }
281
+ });
282
+ }
283
+ messages.push(`${item.uid}:${item.name} ${types.size ? `[${Array.from(types).join('、')}]` : ' [全部动态]'}`);
284
+ });
285
+ }
169
286
  });
170
287
  }
171
288
  else {
@@ -176,17 +293,19 @@ message.use(async (e) => {
176
293
  messages.push('\n>>>>>>私聊微博订阅<<<<<<');
177
294
  Object.keys(subData.private).forEach(userId => {
178
295
  messages.push(`\n<用户${userId}>:`);
179
- subData.private[userId].forEach((item) => {
180
- const types = new Set();
181
- if (item.type && item.type.length) {
182
- item.type.forEach((typeItem) => {
183
- if (typeMap[typeItem]) {
184
- types.add(typeMap[typeItem]);
185
- }
186
- });
187
- }
188
- messages.push(`${item.uid}:${item.name} ${types.size ? `[${Array.from(types).join('、')}]` : ' [全部动态]'}`);
189
- });
296
+ if (subData.private) {
297
+ subData.private[userId].forEach((item) => {
298
+ const types = new Set();
299
+ if (item.type && item.type.length) {
300
+ item.type.forEach((typeItem) => {
301
+ if (typeMap[typeItem]) {
302
+ types.add(typeMap[typeItem]);
303
+ }
304
+ });
305
+ }
306
+ messages.push(`${item.uid}:${item.name} ${types.size ? `[${Array.from(types).join('、')}]` : ' [全部动态]'}`);
307
+ });
308
+ }
190
309
  });
191
310
  }
192
311
  else {
@@ -11,7 +11,9 @@ function App({ data }) {
11
11
  React.createElement("div", { className: "txt-0 text-center mt-3 mb-3 p-1 text-blue-500" },
12
12
  "Created By yuki-plugin",
13
13
  React.createElement("br", null),
14
- "\u626B\u7801\u767B\u5F55B\u7AD9\u83B7\u53D6CK"),
14
+ "\u626B\u7801\u767B\u5F55",
15
+ data.name,
16
+ "\u83B7\u53D6CK"),
15
17
  React.createElement("div", { className: "QrCode m-auto" },
16
18
  React.createElement("img", { className: "qr-code w-72 h-72 ml-7", src: data.url, alt: "\u4E8C\u7EF4\u7801" })),
17
19
  React.createElement("div", { className: "txt-1 text-center mt-3 mb-3 p-1 text-red-600" },
@@ -1,3 +1,8 @@
1
+ import BiliApi from './bilibili.main.api.js';
2
+ import { gen_buvid_fp } from './bilibili.risk.buid.fp.js';
3
+ import { getBiliTicket } from './bilibili.risk.ticket.js';
4
+ import { renderPage } from '../../utils/image.js';
5
+ import { _paths } from '../../utils/paths.js';
1
6
  import axios from 'axios';
2
7
  import fs__default from 'fs';
3
8
  import lodash from 'lodash';
@@ -7,11 +12,6 @@ import path from 'path';
7
12
  import QRCode from 'qrcode';
8
13
  import YAML from 'yaml';
9
14
  import { Redis, Segment } from 'yunzaijs';
10
- import { renderPage } from '../../utils/image.js';
11
- import { _paths } from '../../utils/paths.js';
12
- import BiliApi from './bilibili.main.api.js';
13
- import { gen_buvid_fp } from './bilibili.risk.buid.fp.js';
14
- import { getBiliTicket } from './bilibili.risk.ticket.js';
15
15
 
16
16
  /**
17
17
  * *******************************************************************
@@ -35,7 +35,7 @@ async function applyLoginQRCode(e) {
35
35
  const qrcodeUrl = res?.data?.url;
36
36
  let loginUrlQrcodeData = await QRCode.toDataURL(`${qrcodeUrl}`);
37
37
  const LoginPropsData = {
38
- data: { url: loginUrlQrcodeData }
38
+ data: { name: 'B站', url: loginUrlQrcodeData }
39
39
  };
40
40
  const ScreenshotOptionsData = {
41
41
  saveHtmlfile: false,
@@ -251,7 +251,7 @@ async function readLocalBiliCk() {
251
251
  if (!fs__default.existsSync(dir)) {
252
252
  fs__default.mkdirSync(dir, { recursive: true }); // 创建目录,包括父目录
253
253
  }
254
- const files = fs__default.readdirSync(dir).filter((file) => file.endsWith('.yaml'));
254
+ const files = fs__default.readdirSync(dir).filter((file) => file.endsWith('biliCookie.yaml'));
255
255
  const readFile = promisify(fs__default.readFile);
256
256
  const promises = files.map((file) => readFile(path.join(dir, file), 'utf8'));
257
257
  const contents = await Promise.all(promises);
@@ -42,15 +42,16 @@ class BiliQuery {
42
42
  return { url: item?.url, width: item?.width, height: item?.height };
43
43
  }) || [];
44
44
  additional = data?.modules?.module_dynamic?.additional;
45
+ formatData.data.title = desc?.title || '';
45
46
  formatData.data.content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text, additional) || '';
46
47
  }
47
48
  else {
48
49
  desc = data?.modules?.module_dynamic?.desc || {};
49
50
  pics = data?.modules?.module_dynamic?.major?.draw?.items;
50
51
  pics = [];
52
+ formatData.data.title = desc?.title || '';
51
53
  formatData.data.content = this.parseRichTextNodes(desc?.text);
52
54
  }
53
- formatData.data.title = '';
54
55
  formatData.data.url = `${BiliDrawDynamicLinkUrl}${data.id_str}`;
55
56
  formatData.data.pubTime = author.pub_time;
56
57
  formatData.data.pubTs = moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss');
@@ -65,6 +66,7 @@ class BiliQuery {
65
66
  return { url: item?.url, width: item?.width, height: item?.height };
66
67
  });
67
68
  additional = data?.modules?.module_dynamic?.additional;
69
+ formatData.data.title = desc?.title || '';
68
70
  formatData.data.content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text, additional) || '';
69
71
  }
70
72
  else if (majorType === 'MAJOR_TYPE_DRAW') {
@@ -73,6 +75,7 @@ class BiliQuery {
73
75
  pics = pics.map((item) => {
74
76
  return { url: item?.url, width: item?.width, height: item?.height };
75
77
  });
78
+ formatData.data.title = desc?.title || '';
76
79
  formatData.data.content = this.parseRichTextNodes(desc?.rich_text_nodes || desc?.text) || '';
77
80
  }
78
81
  else {
@@ -81,9 +84,9 @@ class BiliQuery {
81
84
  pics = pics.map((item) => {
82
85
  return { url: item?.src };
83
86
  });
87
+ formatData.data.title = desc?.title || '';
84
88
  formatData.data.content = this.parseRichTextNodes(desc?.text);
85
89
  }
86
- formatData.data.title = '';
87
90
  formatData.data.url = `${BiliDrawDynamicLinkUrl}${data.id_str}`;
88
91
  formatData.data.pubTime = author.pub_time;
89
92
  formatData.data.pubTs = moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss');
@@ -453,6 +456,7 @@ class BiliQuery {
453
456
  msg_meta = `B站【${upName}】图文动态推送:`;
454
457
  msg = [
455
458
  msg_meta,
459
+ ...(desc?.title ? [`\n--------------------`, `\n${desc.title}`] : []),
456
460
  `\n--------------------`,
457
461
  `\n正文:`,
458
462
  `\n${this.dynamicContentLimit(content, setData)}`,
@@ -508,6 +512,7 @@ class BiliQuery {
508
512
  msg_meta = `B站【${upName}】图文动态推送:`;
509
513
  msg = [
510
514
  msg_meta,
515
+ ...(desc?.title ? [`\n--------------------`, `\n${desc.title}`] : []),
511
516
  `\n--------------------`,
512
517
  `\n正文:`,
513
518
  `\n${this.dynamicContentLimit(content, setData)}`,
@@ -191,7 +191,9 @@ class BiliTask {
191
191
  if (getWhiteWords && Array.isArray(getWhiteWords) && getWhiteWords.length > 0) {
192
192
  // 构建白名单关键字正则表达式,转义特殊字符
193
193
  const whiteWords = new RegExp(getWhiteWords.map(word => word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|'), 'g');
194
- if (!whiteWords.test(`${extentData?.title}${extentData?.content}`)) {
194
+ const content = `${extentData?.title}${extentData?.content}`;
195
+ if (!whiteWords.test(content)) {
196
+ logger.info(`UP主 "${upName}" B站动态:白名单关键词已开启,但动态消息未匹配,已跳过推送`);
195
197
  return; // 如果动态消息不在白名单中,则直接返回
196
198
  }
197
199
  }
@@ -201,7 +203,10 @@ class BiliTask {
201
203
  if (getBanWords && Array.isArray(getBanWords) && getBanWords.length > 0) {
202
204
  // 构建屏蔽关键字正则表达式,转义特殊字符
203
205
  const banWords = new RegExp(getBanWords.map(word => word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|'), 'g');
204
- if (banWords.test(`${extentData?.title}${extentData?.content}`)) {
206
+ const content = `${extentData?.title}${extentData?.content}`;
207
+ const matched = content.match(banWords);
208
+ if (matched) {
209
+ logger.info(`UP主 "${upName}" B站动态:触发屏蔽关键词 "${matched.join(', ')}" ,已跳过推送`);
205
210
  return; // 如果动态消息包含屏蔽关键字,则直接返回
206
211
  }
207
212
  }
@@ -212,6 +217,7 @@ class BiliTask {
212
217
  let isSplit = !!biliConfigData.isSplit === false ? false : true; // 是否启用分片截图,默认为 true
213
218
  let style = isSplit ? '' : `.unfold { max-height: ${biliConfigData?.noSplitHeight ?? 7500}px; }`; // 不启用分片截图模式的样式
214
219
  let splitHeight = biliConfigData?.splitHeight || 8000; // 分片截图高度,默认 8000, 单位 px,启用分片截图时生效
220
+ let isPauseGif = !!biliConfigData?.isPauseGif === true ? true : false; // 是否暂停 GIF 动图,默认为 false
215
221
  const urlQrcodeData = await QRCode.toDataURL(extentData?.url);
216
222
  let renderData = this.buildRenderData(extentData, urlQrcodeData, boxGrid);
217
223
  const ScreenshotOptionsData = {
@@ -224,7 +230,8 @@ class BiliTask {
224
230
  quality: 98
225
231
  },
226
232
  saveHtmlfile: false,
227
- pageSplitHeight: splitHeight
233
+ pageSplitHeight: splitHeight,
234
+ isPauseGif: isPauseGif
228
235
  };
229
236
  let imgs = await this.renderDynamicCard(uid, renderData, ScreenshotOptionsData);
230
237
  if (!imgs)
@@ -242,6 +249,7 @@ class BiliTask {
242
249
  // 构建白名单关键字正则表达式,转义特殊字符
243
250
  const whiteWords = new RegExp(getWhiteWords.map(word => word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|'), 'g');
244
251
  if (!whiteWords.test(dynamicMsg.msg.join(''))) {
252
+ logger.info(`UP主 "${upName}" B站动态:白名单关键词已开启,但动态消息未匹配,已跳过推送`);
245
253
  return; // 如果动态消息不在白名单中,则直接返回
246
254
  }
247
255
  }
@@ -251,8 +259,11 @@ class BiliTask {
251
259
  if (getBanWords && Array.isArray(getBanWords) && getBanWords.length > 0) {
252
260
  // 构建屏蔽关键字正则表达式,转义特殊字符
253
261
  const banWords = new RegExp(getBanWords.map(word => word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|'), 'g');
254
- if (banWords.test(dynamicMsg.msg.join(''))) {
255
- return 'return'; // 如果动态消息包含屏蔽关键字,则直接返回
262
+ const content = dynamicMsg.msg.join('');
263
+ const matched = content.match(banWords);
264
+ if (matched) {
265
+ logger.info(`UP主 "${upName}" B站动态:触发屏蔽关键词 "${matched.join(', ')}" ,已跳过推送`);
266
+ return; // 如果动态消息包含屏蔽关键字,则直接返回
256
267
  }
257
268
  }
258
269
  else if (getBanWords && !Array.isArray(getBanWords)) {
@@ -279,22 +290,25 @@ class BiliTask {
279
290
  * @returns 渲染数据
280
291
  */
281
292
  buildRenderData(extentData, urlQrcodeData, boxGrid) {
293
+ const baseData = {
294
+ appName: 'bilibili',
295
+ boxGrid: boxGrid,
296
+ type: extentData?.type,
297
+ face: extentData?.face,
298
+ pendant: extentData?.pendant,
299
+ name: extentData?.name,
300
+ pubTs: extentData?.pubTs,
301
+ title: extentData?.title,
302
+ content: extentData?.content,
303
+ urlImgData: urlQrcodeData,
304
+ created: extentData?.created,
305
+ pics: extentData?.pics,
306
+ category: extentData?.category
307
+ };
282
308
  if (extentData.orig && extentData.orig.length !== 0) {
283
309
  return {
284
310
  data: {
285
- appName: 'bilibili',
286
- boxGrid: boxGrid,
287
- type: extentData?.type,
288
- face: extentData?.face,
289
- pendant: extentData?.pendant,
290
- name: extentData?.name,
291
- pubTs: extentData?.pubTs,
292
- title: extentData?.title,
293
- content: extentData?.content,
294
- urlImgData: urlQrcodeData,
295
- created: extentData?.created,
296
- pics: extentData?.pics,
297
- category: extentData?.category,
311
+ ...baseData,
298
312
  orig: {
299
313
  data: {
300
314
  type: extentData?.orig?.data?.type,
@@ -312,23 +326,7 @@ class BiliTask {
312
326
  };
313
327
  }
314
328
  else {
315
- return {
316
- data: {
317
- appName: 'bilibili',
318
- boxGrid: boxGrid,
319
- type: extentData?.type,
320
- face: extentData?.face,
321
- pendant: extentData?.pendant,
322
- name: extentData?.name,
323
- pubTs: extentData?.pubTs,
324
- title: extentData?.title,
325
- content: extentData?.content,
326
- urlImgData: urlQrcodeData,
327
- created: extentData?.created,
328
- pics: extentData?.pics,
329
- category: extentData?.category
330
- }
331
- };
329
+ return { data: baseData };
332
330
  }
333
331
  }
334
332
  /**