yz-yuki-plugin 2.0.7-8 → 2.0.8-0

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.
@@ -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)) {
@@ -71,44 +72,50 @@ class BiliTask {
71
72
  for (let chatId in biliPushData[chatType]) {
72
73
  const subUpsOfChat = Array.prototype.slice.call(biliPushData[chatType][chatId] || []);
73
74
  for (let subInfoOfup of subUpsOfChat) {
75
+ const { uid, bot_id, name, type } = subInfoOfup;
74
76
  let resp;
75
77
  // 检查是否已经请求过该 uid
76
- if (requestedDataOfUids.has(subInfoOfup.uid)) {
77
- resp = requestedDataOfUids.get(subInfoOfup.uid); // 从已请求的映射中获取响应数据
78
- const dynamicData = resp.data?.items || [];
79
- dynamicList[subInfoOfup.uid] = dynamicData;
80
- }
81
- else {
82
- resp = await this.hendleEventDynamicData(subInfoOfup.uid);
78
+ if (!requestedDataOfUids.has(uid)) {
79
+ if (!printedList.has(uid)) {
80
+ logger.info(`正在检测B站动态 [ ${name} : ${uid} ]`);
81
+ printedList.add(uid);
82
+ }
83
+ resp = await this.hendleEventDynamicData(uid);
83
84
  if (resp) {
84
85
  if (resp.code === 0) {
85
- requestedDataOfUids.set(subInfoOfup.uid, resp); // 将响应数据存储到映射中
86
+ requestedDataOfUids.set(uid, resp); // 将响应数据存储到映射中
86
87
  const dynamicData = resp.data?.items || [];
87
- dynamicList[subInfoOfup.uid] = dynamicData;
88
+ dynamicList[uid] = dynamicData;
88
89
  }
89
90
  else if (resp.code === -352) {
90
- logger.error(`获取 ${subInfoOfup.uid} 动态失败,resCode:-352,请待下次任务自动重试`);
91
+ logger.error(`获取 ${uid} 动态失败,resCode:-352,请待下次任务自动重试`);
91
92
  return;
92
93
  }
93
94
  else if (resp.code !== 0) {
94
- logger.error(`获取 ${subInfoOfup.uid} 动态失败,resCode:${resp.code},请待下次任务自动重试`);
95
+ logger.error(`获取 ${uid} 动态失败,resCode:${resp.code},请待下次任务自动重试`);
95
96
  return;
96
97
  }
97
98
  }
98
99
  else {
99
- logger.error(`获取 ${subInfoOfup.uid} 动态失败,无响应数据,请待下次任务自动重试`);
100
+ logger.error(`获取 ${uid} 动态失败,无响应数据,请待下次任务自动重试`);
100
101
  return;
101
102
  }
102
103
  }
103
- const chatIds = Array.from(new Set([...Object((chatTypeMap.get(subInfoOfup.uid) && chatTypeMap.get(subInfoOfup.uid).chatIds) || []), chatId]));
104
- const bot_id = subInfoOfup.bot_id || [];
105
- const { name, type } = subInfoOfup;
106
- chatTypeMap.set(subInfoOfup.uid, { chatIds, bot_id, upName: name, type });
104
+ if (!chatTypeMap.has(uid)) {
105
+ chatTypeMap.set(uid, new Map());
106
+ }
107
+ const botChatMap = chatTypeMap.get(uid);
108
+ if (!botChatMap?.has(bot_id)) {
109
+ botChatMap?.set(bot_id, new Map());
110
+ }
111
+ const chatMap = botChatMap?.get(bot_id);
112
+ chatMap?.set(chatId, { upName: name, types: type });
107
113
  await this.randomDelay(2000, getDataRandomDelay); // 随机延时
108
114
  }
109
115
  }
110
116
  }
111
117
  requestedDataOfUids.clear(); // 清空已请求的 uid 映射
118
+ printedList.clear(); // 清空已打印的动态列表
112
119
  }
113
120
  /**
114
121
  * 构建uid对应动态数据映射
@@ -120,35 +127,30 @@ class BiliTask {
120
127
  */
121
128
  async makeUidDynamicDataMap(uidMap, dynamicList, now, dynamicTimeRange, biliConfigData, messageMap) {
122
129
  for (let [chatType, chatTypeMap] of uidMap) {
123
- for (let [key, value] of chatTypeMap) {
124
- const tempDynamicList = dynamicList[key] || [];
130
+ for (let [upUid, bot_idMap] of chatTypeMap) {
131
+ const tempDynamicList = dynamicList[upUid] || [];
125
132
  const willPushDynamicList = [];
126
- const printedList = new Set(); // 已打印的动态列表
127
133
  for (let dynamicItem of tempDynamicList) {
128
134
  let author = dynamicItem?.modules?.module_author || {};
129
- if (!printedList.has(author?.mid)) {
130
- logger.info(`正在检测B站动态 [ ${author?.name} : ${author?.mid} ]`);
131
- printedList.add(author?.mid);
132
- }
133
135
  if (!author?.pub_ts)
134
136
  continue; // 如果动态没有发布时间,跳过当前循环
135
137
  if (Number(now - author.pub_ts) > dynamicTimeRange) {
136
138
  logger.debug(`超过间隔,跳过 [ ${author?.name} : ${author?.mid} ] ${author?.pub_time} 的动态`);
137
139
  continue;
138
140
  } // 如果超过推送时间间隔,跳过当前循环
139
- if (dynamicItem.type === 'DYNAMIC_TYPE_FORWARD' && !biliConfigData.pushTransmit)
140
- continue; // 如果关闭了转发动态的推送,跳过当前循环
141
+ if (dynamicItem?.type === 'DYNAMIC_TYPE_FORWARD' && !biliConfigData.pushTransmit) {
142
+ continue;
143
+ } // 如果关闭了转发动态的推送,跳过当前循环
141
144
  willPushDynamicList.push(dynamicItem);
142
145
  }
143
- printedList.clear();
144
- const pushMapInfo = value || {}; // 获取当前 uid 对应的推送信息
145
- const { chatIds, bot_id, upName, type } = pushMapInfo;
146
146
  // 遍历待推送的动态数组,发送动态消息
147
- for (let pushDynamicData of willPushDynamicList) {
148
- if (chatIds && chatIds.length) {
149
- for (let chatId of chatIds) {
150
- if (type && type.length && !type.includes(pushDynamicData.type))
151
- continue; // 如果禁用了某类型的动态推送,跳过当前循环
147
+ for (let [bot_id, chatIdMap] of bot_idMap) {
148
+ for (let [chatId, subUpInfo] of chatIdMap) {
149
+ const { upName, types } = subUpInfo;
150
+ for (let pushDynamicData of willPushDynamicList) {
151
+ if (types && types.length > 0 && !types.includes(pushDynamicData.type)) {
152
+ continue;
153
+ } // 如果禁用了某类型的动态推送,跳过当前循环
152
154
  await this.makeDynamicMessageMap(chatId, bot_id, upName, pushDynamicData, biliConfigData, chatType, messageMap); // 发送动态消息
153
155
  await this.randomDelay(1000, 2000); // 随机延时1-2秒
154
156
  }
@@ -378,65 +380,119 @@ class BiliTask {
378
380
  async sendDynamicMessage(messageMap, biliConfigData) {
379
381
  let liveAtAll = !!biliConfigData.liveAtAll === true ? true : false; // 直播动态是否@全体成员,默认false
380
382
  let liveAtAllCD = biliConfigData.liveAtAllCD || 1800; // 直播动态@全体成员 冷却时间CD,默认 30 分钟
383
+ let forwardSendDynamic = biliConfigData.forwardSendDynamic === 0 || biliConfigData.forwardSendDynamic === false ? false : true; // 转发动态是否合并发送,默认 true
381
384
  // 直播动态@全体成员的群组/好友列表,默认空数组,为空则不进行@全体成员操作
382
385
  let liveAtAllGroupList = new Set(Array.isArray(biliConfigData?.liveAtAllGroupList) ? Array.from(biliConfigData.liveAtAllGroupList).map(item => String(item)) : []);
383
386
  const LogMark = new Set(); // 日志mark
384
387
  for (const [chatType, botMap] of messageMap) {
385
388
  for (const [bot_id, chatMap] of botMap) {
386
389
  for (const [chatId, messageCombinationList] of chatMap) {
387
- // 遍历组合消息
388
- for (const messageCombination of messageCombinationList) {
389
- const { sendMode, dynamicUUid_str, dynamicType, messages } = messageCombination;
390
- let sended = null;
391
- let markKey = '';
392
- if (chatType === 'group') {
393
- markKey = this.groupKey;
394
- sended = await Redis.get(`${markKey}${chatId}:${dynamicUUid_str}`);
395
- }
396
- else if (chatType === 'private') {
397
- markKey = this.privateKey;
398
- sended = await Redis.get(`${markKey}${chatId}:${dynamicUUid_str}`);
390
+ // 区分群聊和私聊
391
+ let markKey = chatType === 'group' ? this.groupKey : this.privateKey;
392
+ if (!LogMark.has('1')) {
393
+ global?.logger?.mark('优纪插件: B站动态执行推送');
394
+ LogMark.add('1');
395
+ }
396
+ let liveAtAllMark = await Redis.get(`${markKey}${chatId}:liveAtAllMark`); // 直播动态@全体成员标记,默认 0
397
+ const hasLiveDynamic = messageCombinationList.some(m => m.dynamicType === 'DYNAMIC_TYPE_LIVE_RCMD');
398
+ // 如果开启了直播动态@全体成员
399
+ if (liveAtAll && !liveAtAllMark && hasLiveDynamic && liveAtAllGroupList.has(String(chatId))) {
400
+ try {
401
+ await this.sendMsgApi(chatId, bot_id, chatType, [Segment.at('all')]);
402
+ await Redis.set(`${markKey}${chatId}:liveAtAllMark`, 1, { EX: liveAtAllCD }); // 设置直播动态@全体成员标记为 1
399
403
  }
400
- const sendMarkKey = `${markKey}${chatId}:${dynamicUUid_str}`;
401
- if (sended) {
402
- continue; // 如果已经发送过,则直接跳过
404
+ catch (error) {
405
+ logger.error(`直播动态发送@全体成员失败,请检查 <机器人> 是否有 [管理员权限] 或 [聊天平台是否支持] :${error}`);
406
+ let liveAtAllErrMsg = !!biliConfigData.liveAtAllErrMsg === false ? false : true; // 直播动态@全体成员失败是否发送错误提示消息,默认 false
407
+ if (liveAtAllErrMsg) {
408
+ await this.sendMsgApi(chatId, bot_id, chatType, ['直播动态发送@全体成员失败,请检查权限或平台是否支持']);
409
+ }
403
410
  }
404
- if (!LogMark.has('1')) {
405
- global?.logger?.mark('优纪插件: B站动态执行推送');
406
- LogMark.add('1');
411
+ }
412
+ // 统计图片数量和文字长度
413
+ let imageCount = 0;
414
+ let textLength = 0;
415
+ for (const messageCombination of messageCombinationList) {
416
+ const { messages } = messageCombination;
417
+ for (const msg of messages) {
418
+ if (typeof msg === 'object' && msg.type === 'image') {
419
+ imageCount++;
420
+ }
421
+ else if (typeof msg === 'string') {
422
+ textLength += msg.length;
423
+ }
407
424
  }
408
- let liveAtAllMark = await Redis.get(`${markKey}${chatId}:liveAtAllMark`); // 直播动态@全体成员标记,默认 0
409
- // 如果开启了直播动态@全体成员
410
- if (liveAtAll && !liveAtAllMark && dynamicType === 'DYNAMIC_TYPE_LIVE_RCMD' && liveAtAllGroupList.has(String(chatId))) {
411
- try {
412
- await this.sendMessageApi(chatId, bot_id, chatType, [Segment.at('all')]);
413
- await Redis.set(`${markKey}${chatId}:liveAtAllMark`, 1, { EX: liveAtAllCD }); // 设置直播动态@全体成员标记为 1
425
+ }
426
+ // 满足条件才使用合并转发
427
+ const useForward = imageCount > (biliConfigData?.maxPicsForSingleMsg ?? 2) || textLength > (biliConfigData?.maxTextLengthForSingleMsg ?? 300);
428
+ if (forwardSendDynamic && useForward) {
429
+ const forwardNodes = [];
430
+ // 合并所有消息
431
+ const forwardSendMardKeyList = [];
432
+ forwardNodes.push({
433
+ nickname: '优纪酱',
434
+ user_id: String(80000000),
435
+ message: ['有新的B站动态了~'],
436
+ time: Date.now()
437
+ });
438
+ for (const messageCombination of messageCombinationList) {
439
+ const { sendMode, dynamicUUid_str, dynamicType, messages } = messageCombination;
440
+ const sendMarkKey = `${markKey}${chatId}:${dynamicUUid_str}`;
441
+ // 原子性设置标记,防止并发重复
442
+ const setResult = await Redis.set(sendMarkKey, '1', { NX: true, EX: 3600 * 72 });
443
+ if (!setResult) {
444
+ continue; // 已有标记,跳过
414
445
  }
415
- catch (error) {
416
- logger.error(`直播动态发送@全体成员失败,请检查 <机器人> 是否有 [管理员权限] 或 [聊天平台是否支持] :${error}`);
417
- let liveAtAllErrMsg = !!biliConfigData.liveAtAllErrMsg === false ? false : true; // 直播动态@全体成员失败是否发送错误提示消息,默认 false
418
- if (liveAtAllErrMsg) {
419
- await this.sendMessageApi(chatId, bot_id, chatType, ['直播动态发送@全体成员失败,请检查权限或平台是否支持']);
420
- }
446
+ forwardSendMardKeyList.push(sendMarkKey); // 收集合并转发的标记键
447
+ // 每条动态一个 node
448
+ forwardNodes.push({
449
+ nickname: '匿名消息',
450
+ user_id: String(80000000),
451
+ message: messages,
452
+ time: Date.now()
453
+ });
454
+ }
455
+ // 尝试合并转发动态
456
+ if ((await this.sendMsgApi(chatId, bot_id, chatType, '优纪酱B站动态通知~')) &&
457
+ (await this.sendForwardMsgApi(chatId, bot_id, chatType, forwardNodes))) {
458
+ await this.randomDelay(1000, 2000);
459
+ continue; // 合并转发成功,跳过后续单条发送逻辑
460
+ }
461
+ else {
462
+ for (const sendMarkKey of forwardSendMardKeyList) {
463
+ await Redis.del(sendMarkKey); // 发送消息失败,删除合并转发成功标记
421
464
  }
422
465
  }
466
+ }
467
+ // 合并转发失败,回退为原有方式
468
+ for (const messageCombination of messageCombinationList) {
469
+ const { sendMode, dynamicUUid_str, dynamicType, messages } = messageCombination;
470
+ const sendMarkKey = `${markKey}${chatId}:${dynamicUUid_str}`;
471
+ // 原子性设置标记,防止并发重复
472
+ const setResult = await Redis.set(sendMarkKey, '1', { NX: true, EX: 3600 * 72 });
473
+ if (!setResult) {
474
+ continue; // 已有标记,跳过
475
+ }
476
+ let sendSuccess = true;
423
477
  if (sendMode === 'SINGLE') {
424
- let allSent = true;
425
478
  for (let i = 0; i < messages.length; i++) {
426
- if (!(await this.sendMessageApi(chatId, bot_id, chatType, messages[i]))) {
427
- allSent = false;
428
- break; // 如果有任何一条消息发送失败,停止发送后续消息
479
+ if (!(await this.sendMsgApi(chatId, bot_id, chatType, messages[i]))) {
480
+ sendSuccess = false;
481
+ break;
429
482
  }
430
483
  }
431
- if (allSent) {
432
- await Redis.set(sendMarkKey, '1', { EX: 3600 * 72 }); // 发送成功后设置标记
433
- await this.randomDelay(1000, 2000); // 随机延时1-2秒
484
+ if (!sendSuccess) {
485
+ await Redis.del(sendMarkKey); // 失败删除标记
486
+ }
487
+ else {
488
+ await this.randomDelay(1000, 2000);
434
489
  }
435
490
  }
436
491
  else if (sendMode === 'MERGE') {
437
- if (await this.sendMessageApi(chatId, bot_id, chatType, messages)) {
438
- await Redis.set(sendMarkKey, '1', { EX: 3600 * 72 }); // 发送成功后设置标记
492
+ if (!(await this.sendMsgApi(chatId, bot_id, chatType, messages))) {
493
+ await Redis.del(sendMarkKey); // 失败删除标记
439
494
  }
495
+ await this.randomDelay(1000, 2000);
440
496
  }
441
497
  }
442
498
  }
@@ -451,7 +507,7 @@ class BiliTask {
451
507
  * @param chatType 聊天类型
452
508
  * @param message 消息内容
453
509
  */
454
- async sendMessageApi(chatId, bot_id, chatType, message) {
510
+ async sendMsgApi(chatId, bot_id, chatType, message) {
455
511
  try {
456
512
  if (chatType === 'group') {
457
513
  await (Bot[bot_id] ?? Bot)?.pickGroup(String(chatId)).sendMsg(message); // 发送群聊
@@ -466,6 +522,30 @@ class BiliTask {
466
522
  return false; // 发送失败
467
523
  }
468
524
  }
525
+ /**
526
+ * 发送合并转发消息
527
+ * @param chatId 聊天 ID
528
+ * @param bot_id 机器人 ID
529
+ * @param chatType 聊天类型
530
+ * @param message 消息内容
531
+ * @returns 是否发送成功
532
+ */
533
+ async sendForwardMsgApi(chatId, bot_id, chatType, forwardNodes) {
534
+ const forwardMsg = await Bot.makeForwardMsg(forwardNodes);
535
+ try {
536
+ if (chatType === 'group') {
537
+ await (Bot[bot_id] ?? Bot)?.pickGroup(String(chatId)).sendMsg(forwardMsg); // 发送群聊合并转发
538
+ }
539
+ else if (chatType === 'private') {
540
+ await (Bot[bot_id] ?? Bot)?.pickFriend(String(chatId)).sendMsg(forwardMsg); // 发送好友私聊合并转发
541
+ }
542
+ return true; // 发送成功
543
+ }
544
+ catch (error) {
545
+ global?.logger?.error(`${chatType === 'group' ? '群聊' : '私聊'} ${chatId} 合并转发消息发送失败:${JSON.stringify(error)}`);
546
+ return false; // 发送失败
547
+ }
548
+ }
469
549
  /**
470
550
  * 随机延时
471
551
  * @param min 最小延时时间
@@ -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 = info?.page_info?.page_pic?.url ? [{ url: info.page_info.page_pic.url }] : [];
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,42 @@ 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 title = `微博【${upName}】动态推送:\n`;
209
- const dynamicPicCountLimit = setData.pushPicCountLimit || 3;
213
+ let msg_meta = `微博【${upName}】动态推送:`;
214
+ const dynamicPicCountLimit = setData.pushPicCountLimit || 9;
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
- let cover_img_url = info?.page_info?.page_pic?.url;
215
- let cover_img = Segment.image(cover_img_url, false, 15000, { referer: 'https://weibo.com' });
216
- title = `微博【${upName}】视频动态推送:\n`;
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}】视频动态推送:`;
217
232
  msg = [
218
- title,
219
- `-----------------------------\n`,
220
- `标题:${info?.page_info?.title || ''}\n`,
221
- `${this.filterText(info?.text)}\n`,
222
- `链接:${detail_url}\n`,
223
- `时间:${created_time ? moment(created_time).format('YYYY年MM月DD日 HH:mm:ss') : ''}`
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
+ ...(info?.comments_count != null
243
+ ? [
244
+ `\n${formatNumber(info?.attitudes_count)}点赞 • ${formatNumber(info?.comments_count)}评论 • ${formatNumber(info?.reposts_count)}转发\n--------------------`
245
+ ]
246
+ : []),
247
+ `\n链接:${detail_url}`
224
248
  ];
225
- pics = [cover_img];
226
249
  return { msg, pics, dynamicType };
227
250
  case 'DYNAMIC_TYPE_DRAW':
228
251
  raw_pics_list = retweeted ? info?.retweeted_status?.pics || [] : info?.pics || [];
@@ -235,13 +258,21 @@ class WeiboQuery {
235
258
  const temp = Segment.image(pic_url, false, 15000, { referer: 'https://weibo.com' });
236
259
  pics.push(temp);
237
260
  }
238
- title = `微博【${upName}】图文动态推送:\n`;
261
+ msg_meta = `微博【${upName}】图文动态推送:`;
239
262
  msg = [
240
- title,
241
- `-----------------------------\n`,
242
- `${this.dynamicContentLimit(this.filterText(info?.text), setData)}\n`,
243
- `链接:${detail_url}\n`,
244
- `时间:${created_time ? moment(created_time).format('YYYY年MM月DD日 HH:mm:ss') : ''}`
263
+ msg_meta,
264
+ `\n--------------------`,
265
+ `\n正文:`,
266
+ `\n${this.dynamicContentLimit(this.filterText(info?.text), setData)}`,
267
+ `\n--------------------`,
268
+ `\n投稿:${created_time ? moment(created_time).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
269
+ `\n--------------------`,
270
+ ...(info?.comments_count != null
271
+ ? [
272
+ `\n${formatNumber(info?.attitudes_count)}点赞 • ${formatNumber(info?.comments_count)}评论 • ${formatNumber(info?.reposts_count)}转发\n--------------------`
273
+ ]
274
+ : []),
275
+ `\n链接:${detail_url}`
245
276
  ];
246
277
  return { msg, pics, dynamicType };
247
278
  case 'DYNAMIC_TYPE_ARTICLE':
@@ -255,13 +286,21 @@ class WeiboQuery {
255
286
  const temp = Segment.image(pic_url, false, 15000, { referer: 'https://weibo.com' });
256
287
  pics.push(temp);
257
288
  }
258
- title = `微博【${upName}】文章动态推送:\n`;
289
+ msg_meta = `微博【${upName}】文章动态推送:`;
259
290
  msg = [
260
- title,
261
- `-----------------------------\n`,
262
- `正文:${this.dynamicContentLimit(this.filterText(info?.text), setData)}\n`,
263
- `链接:${detail_url}\n`,
264
- `时间:${created_time ? moment(created_time).format('YYYY年MM月DD日 HH:mm:ss') : ''}`
291
+ msg_meta,
292
+ `\n--------------------`,
293
+ `\n正文:`,
294
+ `\n${this.dynamicContentLimit(this.filterText(info?.text), setData)}`,
295
+ `\n--------------------`,
296
+ `\n投稿:${created_time ? moment(created_time).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
297
+ `\n--------------------`,
298
+ ...(info?.comments_count != null
299
+ ? [
300
+ `\n${formatNumber(info?.attitudes_count)}点赞 • ${formatNumber(info?.comments_count)}评论 • ${formatNumber(info?.reposts_count)}转发\n--------------------`
301
+ ]
302
+ : []),
303
+ `\n链接:${detail_url}`
265
304
  ];
266
305
  return { msg, pics, dynamicType };
267
306
  case 'DYNAMIC_TYPE_FORWARD':
@@ -280,14 +319,22 @@ class WeiboQuery {
280
319
  else {
281
320
  return 'continue';
282
321
  }
283
- title = `微博【${upName}】转发动态推送:\n`;
322
+ msg_meta = `微博【${upName}】转发动态推送:`;
284
323
  msg = [
285
- title,
286
- `-----------------------------\n`,
287
- `${this.dynamicContentLimit(this.filterText(info?.text), setData)}\n`,
288
- `链接:${detail_url}\n`,
289
- `时间:${created_time ? moment(created_time).format('YYYY年MM月DD日 HH:mm:ss') : ''}\n`,
290
- '\n---以下为转发内容---\n',
324
+ msg_meta,
325
+ `\n--------------------`,
326
+ `\n正文:`,
327
+ `\n${this.dynamicContentLimit(this.filterText(info?.text), setData)}`,
328
+ `\n--------------------`,
329
+ `\n投稿:${created_time ? moment(created_time).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
330
+ `\n--------------------`,
331
+ ...(info?.comments_count != null
332
+ ? [
333
+ `\n${formatNumber(info?.attitudes_count)}点赞 • ${formatNumber(info?.comments_count)}评论 • ${formatNumber(info?.reposts_count)}转发\n--------------------`
334
+ ]
335
+ : []),
336
+ `\n链接:${detail_url}\n`,
337
+ '\n>>>>以下为转发内容<<<<\n',
291
338
  ...origContent
292
339
  ];
293
340
  return { msg, pics, dynamicType };
@@ -298,9 +345,9 @@ class WeiboQuery {
298
345
  }
299
346
  // 限制文字模式下动态内容的字数和行数
300
347
  static dynamicContentLimit(content, setData) {
301
- const lines = content.split('\n');
302
- const lengthLimit = setData.pushContentLenLimit || 100;
303
- const lineLimit = setData.pushContentLineLimit || 5;
348
+ const lines = String(content).split('\n');
349
+ const lengthLimit = setData.pushContentLenLimit || 1000;
350
+ const lineLimit = setData.pushContentLineLimit || 100;
304
351
  // 限制行数
305
352
  if (lines.length > lineLimit) {
306
353
  lines.length = lineLimit;