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.
@@ -13,7 +13,7 @@ class BiliQuery {
13
13
  */
14
14
  static async formatDynamicData(data) {
15
15
  const BiliDrawDynamicLinkUrl = 'https://m.bilibili.com/dynamic/';
16
- let desc, pics = [], majorType;
16
+ let desc, pics = [], majorType, additional;
17
17
  let formatData = { data: {} };
18
18
  const author = data?.modules?.module_author || {};
19
19
  formatData.data.face = author.face; // 作者头像
@@ -41,7 +41,8 @@ class BiliQuery {
41
41
  pics.map((item) => {
42
42
  return { url: item?.url, width: item?.width, height: item?.height };
43
43
  }) || [];
44
- formatData.data.content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text) || '';
44
+ additional = data?.modules?.module_dynamic?.additional;
45
+ formatData.data.content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text, additional) || '';
45
46
  }
46
47
  else {
47
48
  desc = data?.modules?.module_dynamic?.desc || {};
@@ -63,7 +64,8 @@ class BiliQuery {
63
64
  pics = pics.map((item) => {
64
65
  return { url: item?.url, width: item?.width, height: item?.height };
65
66
  });
66
- formatData.data.content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text) || '';
67
+ additional = data?.modules?.module_dynamic?.additional;
68
+ formatData.data.content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text, additional) || '';
67
69
  }
68
70
  else if (majorType === 'MAJOR_TYPE_DRAW') {
69
71
  desc = data?.modules?.module_dynamic?.desc;
@@ -98,43 +100,30 @@ class BiliQuery {
98
100
  return { url: item?.url, width: item?.width, height: item?.height };
99
101
  }) || [];
100
102
  formatData.data.title = desc?.title;
103
+ additional = data?.modules?.module_dynamic?.additional;
101
104
  // 文章内容过长,则尝试获取全文
105
+ let content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text, additional) || '';
102
106
  if (String(desc?.summary?.text).length >= 480) {
103
107
  const fullArticleContent = await this.getFullArticleContent(this.formatUrl(desc?.jump_url));
104
108
  if (fullArticleContent) {
105
109
  const { readInfo, articleType } = fullArticleContent;
106
- // 文章链接类型为 cv(旧类型) 或者 opus(新类型)
107
- if (articleType === 'cv') {
108
- formatData.data.content = this.praseFullOldTypeArticleContent(readInfo?.content);
109
- if (String(formatData.data.content).length < 100) {
110
- formatData.data.content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text) || '';
111
- formatData.data.pics = pics;
112
- }
113
- else {
114
- formatData.data.pics = [];
115
- }
116
- }
117
- else if (articleType === 'opus') {
118
- const FullNewTypeArticleContent = this.praseFullNewTypeArticleContent(readInfo?.paragraphs);
119
- if (FullNewTypeArticleContent) {
120
- const { content, img } = FullNewTypeArticleContent;
121
- formatData.data.content = content;
122
- formatData.data.pics = img && img.length > 0 ? img : pics;
123
- if (content && content.length < 100) {
124
- formatData.data.content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text);
125
- }
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;
126
116
  }
127
117
  }
128
- else {
129
- formatData.data.content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text) || '';
130
- formatData.data.pics = pics;
118
+ else if (articleType === 'cv') {
119
+ const oldTypeContent = this.praseFullOldTypeArticleContent(readInfo?.content);
120
+ content = oldTypeContent || content;
131
121
  }
122
+ content = String(content).length < 100 ? this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text, additional) : content;
132
123
  }
133
124
  }
134
- else {
135
- formatData.data.content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text) || '';
136
- formatData.data.pics = pics;
137
- }
125
+ formatData.data.content = content;
126
+ formatData.data.pics = pics;
138
127
  }
139
128
  else if (majorType === 'MAJOR_TYPE_ARTICLE') {
140
129
  desc = data?.modules?.module_dynamic?.major?.article || {};
@@ -195,7 +184,7 @@ class BiliQuery {
195
184
  * @param nodes - 动态内容富文本节点
196
185
  * @returns 解析后的动态内容富文本
197
186
  */
198
- static parseRichTextNodes = (nodes) => {
187
+ static parseRichTextNodes = (nodes, additional) => {
199
188
  if (typeof nodes === 'string') {
200
189
  // 将\t 替换为&nbsp;实现空格,\n 替换为 <br> 以实现换行
201
190
  nodes = nodes.replace(/\t/g, '&nbsp;');
@@ -223,15 +212,21 @@ class BiliQuery {
223
212
  return `<span data-module="desc" data-type="lottery" data-oid="${node?.rid}" class="bili-rich-text-module lottery">${node?.text}</span>`;
224
213
  case 'RICH_TEXT_NODE_TYPE_WEB':
225
214
  // 处理 RICH_TEXT_NODE_TYPE_WEB 类型,直接拼接 text 属性
226
- return node.text;
215
+ return node.orig_text || node.text;
227
216
  case 'RICH_TEXT_NODE_TYPE_EMOJI':
228
217
  // 处理表情类型,使用 img 标签显示表情
229
218
  const emoji = node.emoji;
230
- return `<img src="${emoji?.icon_url}" alt="${emoji?.text}" title="${emoji?.text}" style="vertical-align: middle; width: ${emoji?.size ? Number(emoji?.size) * 2 : 2}em; height: ${emoji?.size ? Number(emoji?.size) * 2 : 2}em;">`;
219
+ return `<img src="${emoji?.icon_url}" alt="${emoji?.text}" title="${emoji?.text}" style="vertical-align: middle; width: ${emoji?.size ? Number(emoji?.size) * 1.5 : 1.5}em; height: ${emoji?.size ? Number(emoji?.size) * 1.5 : 1.5}em;">`;
220
+ case 'RICH_TEXT_NODE_TYPE_BV':
221
+ // 处理视频类型,使用官方的HTML标签写法
222
+ return `<span class="bili-rich-text-link video">${node?.text}</span>`;
231
223
  case 'RICH_TEXT_NODE_TYPE_GOODS':
232
224
  // 处理商品推广类型,使用官方的HTML标签写法
233
225
  const goods_url = node?.jump_url;
234
226
  return `<span data-module="desc" data-type="goods" data-url="${goods_url}" data-oid="${node?.rid}" class="bili-rich-text-module goods ${node?.icon_name}">&ZeroWidthSpace;${node?.text}</span>`;
227
+ case 'RICH_TEXT_NODE_TYPE_VOTE':
228
+ // 处理投票类型,使用官方的HTML标签写法
229
+ return `<div data-module="additional" data-orig="0" class="bili-dyn-content__orig__additional"><div class="bili-dyn-card-vote"><div class="bili-dyn-card-vote__header"><div class="bili-dyn-card-vote__cover"></div></div> <div class="bili-dyn-card-vote__body"><div class="bili-dyn-card-vote__detail"><div class="bili-dyn-card-vote__detail__title">${node?.text}</div> <div class="bili-dyn-card-vote__detail__desc">${additional && additional?.type === 'ADDITIONAL_TYPE_VOTE' ? additional?.vote?.desc : ''}</div></div> <div class="bili-dyn-card-vote__action"><button class="bili-dyn-card-vote__action__btn_normal">${additional && additional.type === 'ADDITIONAL_TYPE_VOTE' ? additional?.vote?.button?.jump_style?.text : ''}</button></div></div></div></div>`;
235
230
  default:
236
231
  return node;
237
232
  }
@@ -245,7 +240,7 @@ class BiliQuery {
245
240
  };
246
241
  /**获取完整B站文章内容
247
242
  * @param postUrl - 文章链接: https://www.bilibili.com/read/cvxxxx 或者 https://www.bilibili.com/opus/xxxx
248
- * @returns {JSON} 完整的B站文章内容json数据
243
+ * @returns 完整的B站文章内容json数据
249
244
  */
250
245
  static async getFullArticleContent(postUrl) {
251
246
  let { cookie } = await readSyncCookie();
@@ -256,24 +251,22 @@ class BiliQuery {
256
251
  responseType: 'text'
257
252
  });
258
253
  const text = response.data;
259
- let match, readInfo, articleType;
260
- if (/^https:\/\/www.bilibili.com\/read\/cv/.test(postUrl)) {
261
- match = String(text).match(/"readInfo":([\s\S]+?),"readViewInfo":/);
262
- if (match) {
263
- const full_json_text = match[1];
264
- readInfo = JSON.parse(full_json_text);
265
- articleType = 'cv';
266
- return { readInfo, articleType };
267
- }
254
+ let matchCV, matchOPUS, readInfo, articleType;
255
+ matchCV = String(text).match(/"readInfo":([\s\S]+?),"readViewInfo":/);
256
+ matchOPUS = String(text).match(/"module_content"\s*:\s*([\s\S]+?)\s*,\s*"module_type"\s*:\s*"MODULE_TYPE_CONTENT"/);
257
+ if (matchOPUS) {
258
+ logger.info(`文章内容新`);
259
+ const full_json_text = matchOPUS[1];
260
+ readInfo = JSON.parse(full_json_text);
261
+ articleType = 'opus';
262
+ return { readInfo, articleType };
268
263
  }
269
- else if (/^https:\/\/www.bilibili.com\/opus\//.test(postUrl)) {
270
- match = String(text).match(/"module_content":([\s\S]+?),\s*"module_type":"MODULE_TYPE_CONTENT"/);
271
- if (match) {
272
- const full_json_text = match[1];
273
- readInfo = JSON.parse(full_json_text);
274
- articleType = 'opus';
275
- return { readInfo, articleType };
276
- }
264
+ else if (matchCV) {
265
+ logger.info(`文章内容旧`);
266
+ const full_json_text = matchCV[1];
267
+ readInfo = JSON.parse(full_json_text);
268
+ articleType = 'cv';
269
+ return { readInfo, articleType };
277
270
  }
278
271
  }
279
272
  catch (err) {
@@ -346,7 +339,10 @@ class BiliQuery {
346
339
  case 'RICH_TEXT_NODE_TYPE_EMOJI':
347
340
  // 处理表情类型,使用 img 标签显示表情
348
341
  const emoji = node?.rich?.emoji;
349
- return `<img src="${emoji?.icon_url}" alt="${emoji?.text}" title="${emoji?.text}" style="vertical-align: middle; width: ${emoji?.size ? Number(emoji?.size) * 2 : 2}em; height: ${emoji?.size ? Number(emoji?.size) * 2 : 2}em;">`;
342
+ return `<img src="${emoji?.icon_url}" alt="${emoji?.text}" title="${emoji?.text}" style="vertical-align: middle; width: ${emoji?.size ? Number(emoji?.size) * 1.5 : 1.5}em; height: ${emoji?.size ? Number(emoji?.size) * 1.5 : 1.5}em;">`;
343
+ case 'RICH_TEXT_NODE_TYPE_BV':
344
+ // 处理视频类型,使用官方的HTML标签写法
345
+ return `<span class="bili-rich-text-link video">${node?.rich?.text}</span>`;
350
346
  case 'RICH_TEXT_NODE_TYPE_GOODS':
351
347
  // 处理商品推广类型,使用官方的HTML标签写法
352
348
  const goods_url = node?.rich?.jump_url;
@@ -393,9 +389,15 @@ class BiliQuery {
393
389
  */
394
390
  static async formatTextDynamicData(upName, data, isForward, setData) {
395
391
  const BiliDrawDynamicLinkUrl = 'https://m.bilibili.com/dynamic/';
396
- let desc, msg = [], pics = [], author, majorType, content, dynamicTitle;
397
- let title = `B站【${upName}】动态推送:\n`;
392
+ let desc, msg = [], pics = [], author, majorType, content, dynamicTitle, module_stat;
393
+ let msg_meta = `B站【${upName}】动态推送:`;
398
394
  let dynamicType = data.type;
395
+ function formatNumber(num) {
396
+ if (num >= 10000) {
397
+ return `${(num / 10000).toFixed(1)}万`;
398
+ }
399
+ return num.toString();
400
+ }
399
401
  switch (dynamicType) {
400
402
  case 'DYNAMIC_TYPE_AV':
401
403
  // 处理视频动态
@@ -403,14 +405,26 @@ class BiliQuery {
403
405
  author = data?.modules?.module_author;
404
406
  if (!desc && !author)
405
407
  return;
406
- title = `B站【${upName}】视频动态推送:\n`;
408
+ module_stat = data?.modules?.module_stat;
409
+ msg_meta = `B站【${upName}】视频动态推送:`;
407
410
  msg = [
408
- title,
409
- `-----------------------------\n`,
410
- `标题:${desc.title}\n`,
411
- `${desc.desc}\n`,
412
- `链接:${this.formatUrl(desc.jump_url)}\n`,
413
- `时间:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`
411
+ msg_meta,
412
+ `\n--------------------`,
413
+ `\n${desc.title}`, // 标题
414
+ `\n--------------------`,
415
+ `\n视频简介:`,
416
+ `\n${desc.desc}`,
417
+ `\n--------------------`,
418
+ `\n投稿:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
419
+ `\n--------------------`,
420
+ `\n${desc?.stat?.danmaku}弹幕 • ${desc?.stat?.play}播放`,
421
+ ...(module_stat
422
+ ? [
423
+ `\n${formatNumber(module_stat.like?.count)}点赞 • ${formatNumber(module_stat.comment?.count)}评论 • ${formatNumber(module_stat.forward?.count)}转发`
424
+ ]
425
+ : []),
426
+ `\n--------------------`,
427
+ `\n链接:${this.formatUrl(desc.jump_url)}`
414
428
  ];
415
429
  pics = [Segment.image(desc?.cover)];
416
430
  return { msg, pics, dynamicType };
@@ -435,13 +449,22 @@ class BiliQuery {
435
449
  }
436
450
  if (!desc && !author)
437
451
  return;
438
- title = `B站【${upName}】动态推送:\n`;
452
+ module_stat = data?.modules?.module_stat;
453
+ msg_meta = `B站【${upName}】图文动态推送:`;
439
454
  msg = [
440
- title,
441
- `-----------------------------\n`,
442
- `内容:${this.dynamicContentLimit(content, setData)}\n`,
443
- `链接:${BiliDrawDynamicLinkUrl}${data.id_str}\n`,
444
- `时间:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`
455
+ msg_meta,
456
+ `\n--------------------`,
457
+ `\n正文:`,
458
+ `\n${this.dynamicContentLimit(content, setData)}`,
459
+ `\n--------------------`,
460
+ `\n投稿:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
461
+ `\n--------------------`,
462
+ ...(module_stat
463
+ ? [
464
+ `\n${formatNumber(module_stat.like?.count)}点赞 • ${formatNumber(module_stat.comment?.count)}评论 • ${formatNumber(module_stat.forward?.count)}转发\n--------------------`
465
+ ]
466
+ : []),
467
+ `\n链接:${BiliDrawDynamicLinkUrl}${data.id_str}`
445
468
  ];
446
469
  return { msg, pics, dynamicType };
447
470
  case 'DYNAMIC_TYPE_DRAW':
@@ -474,20 +497,29 @@ class BiliQuery {
474
497
  }
475
498
  if (!desc && !pics && !author)
476
499
  return;
477
- const dynamicPicCountLimit = setData.pushPicCountLimit || 3;
500
+ module_stat = data?.modules?.module_stat;
501
+ const dynamicPicCountLimit = setData.pushPicCountLimit || 9;
478
502
  if (pics.length > dynamicPicCountLimit) {
479
503
  pics.length = dynamicPicCountLimit;
480
504
  }
481
505
  pics = pics.map((item) => {
482
506
  return Segment.image(item);
483
507
  });
484
- title = `B站【${upName}】图文动态推送:\n`;
508
+ msg_meta = `B站【${upName}】图文动态推送:`;
485
509
  msg = [
486
- title,
487
- `-----------------------------\n`,
488
- `${this.dynamicContentLimit(content, setData)}\n`,
489
- `链接:${BiliDrawDynamicLinkUrl}${data.id_str}\n`,
490
- `时间:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`
510
+ msg_meta,
511
+ `\n--------------------`,
512
+ `\n正文:`,
513
+ `\n${this.dynamicContentLimit(content, setData)}`,
514
+ `\n--------------------`,
515
+ `\n投稿:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
516
+ `\n--------------------`,
517
+ ...(module_stat
518
+ ? [
519
+ `\n${formatNumber(module_stat.like?.count)}点赞 • ${formatNumber(module_stat.comment?.count)}评论 • ${formatNumber(module_stat.forward?.count)}转发\n--------------------`
520
+ ]
521
+ : []),
522
+ `\n链接:${BiliDrawDynamicLinkUrl}${data.id_str}`
491
523
  ];
492
524
  return { msg, pics, dynamicType };
493
525
  case 'DYNAMIC_TYPE_ARTICLE':
@@ -521,16 +553,27 @@ class BiliQuery {
521
553
  }
522
554
  if (!desc && !author)
523
555
  return;
556
+ module_stat = data?.modules?.module_stat;
524
557
  pics = pics.map((item) => {
525
558
  return Segment.image(item);
526
559
  });
527
- title = `B站【${upName}】文章动态推送:\n`;
560
+ msg_meta = `B站【${upName}】文章动态推送:`;
528
561
  msg = [
529
- title,
530
- `-----------------------------\n`,
531
- `标题:${dynamicTitle}\n`,
532
- `链接:${this.formatUrl(desc.jump_url)}\n`,
533
- `时间:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`
562
+ msg_meta,
563
+ `\n--------------------`,
564
+ `\n${dynamicTitle}`,
565
+ `\n--------------------`,
566
+ `\n正文:`,
567
+ `\n${this.dynamicContentLimit(content, setData)}`,
568
+ `\n--------------------`,
569
+ `\n投稿:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
570
+ `\n--------------------`,
571
+ ...(module_stat
572
+ ? [
573
+ `\n${formatNumber(module_stat.like?.count)}点赞 • ${formatNumber(module_stat.comment?.count)}评论 • ${formatNumber(module_stat.forward?.count)}转发\n--------------------`
574
+ ]
575
+ : []),
576
+ `\n链接:${this.formatUrl(desc.jump_url)}`
534
577
  ];
535
578
  return { msg, pics, dynamicType };
536
579
  case 'DYNAMIC_TYPE_FORWARD':
@@ -542,6 +585,7 @@ class BiliQuery {
542
585
  return;
543
586
  if (!data.orig)
544
587
  return;
588
+ module_stat = data?.modules?.module_stat;
545
589
  isForward = true;
546
590
  let orig = await this.formatTextDynamicData(upName, data.orig, isForward, setData);
547
591
  let origContent = [];
@@ -552,14 +596,22 @@ class BiliQuery {
552
596
  else {
553
597
  return 'continue';
554
598
  }
555
- title = `B站【${upName}】转发动态推送:\n`;
599
+ msg_meta = `B站【${upName}】转发动态推送:`;
556
600
  msg = [
557
- title,
558
- `-----------------------------\n`,
559
- `${this.dynamicContentLimit(content, setData)}\n`,
560
- `链接:${BiliDrawDynamicLinkUrl}${data.id_str}\n`,
561
- `时间:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}\n`,
562
- '\n---以下为转发内容---\n',
601
+ msg_meta,
602
+ `\n--------------------`,
603
+ `\n正文:`,
604
+ `\n${this.dynamicContentLimit(content, setData)}`,
605
+ `\n--------------------`,
606
+ `\n投稿:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
607
+ `\n--------------------`,
608
+ ...(module_stat
609
+ ? [
610
+ `\n${formatNumber(module_stat.like?.count)}点赞 • ${formatNumber(module_stat.comment?.count)}评论 • ${formatNumber(module_stat.forward?.count)}转发\n--------------------`
611
+ ]
612
+ : []),
613
+ `\n链接:${BiliDrawDynamicLinkUrl}${data.id_str}\n`,
614
+ '\n>>>>以下为转发内容<<<<\n',
563
615
  ...origContent
564
616
  ];
565
617
  return { msg, pics, dynamicType };
@@ -572,8 +624,18 @@ class BiliQuery {
572
624
  desc = desc?.live_play_info;
573
625
  if (!desc)
574
626
  return;
575
- title = `B站【${upName}】直播动态推送:\n`;
576
- msg = [title, `-----------------------------\n`, `标题:${desc.title}\n`, `链接:https:${desc.link}`];
627
+ msg_meta = `B站【${upName}】直播动态推送:`;
628
+ msg = [
629
+ msg_meta,
630
+ `\n--------------------`,
631
+ `\n${desc.title}`,
632
+ `\n--------------------`,
633
+ `\n分区:${desc?.parent_area_name} (${desc?.area_name})`,
634
+ `\n开播:${moment(desc.live_start_time * 1000).format('YYYY年MM月DD日 HH:mm:ss')}`,
635
+ `\n--------------------`,
636
+ `\n${formatNumber(desc?.watched_show?.num)}人看过`,
637
+ `\n链接:https:${desc.link}`
638
+ ];
577
639
  pics = [Segment.image(desc.cover)];
578
640
  return { msg, pics, dynamicType };
579
641
  default:
@@ -584,9 +646,9 @@ class BiliQuery {
584
646
  }
585
647
  // 限制文字模式下动态内容的字数和行数
586
648
  static dynamicContentLimit(content, setData) {
587
- const lines = content.split('\n');
588
- const lengthLimit = setData.pushContentLenLimit || 100;
589
- const lineLimit = setData.pushContentLineLimit || 5;
649
+ const lines = String(content).split('\n');
650
+ const lengthLimit = setData.pushContentLenLimit || 1000;
651
+ const lineLimit = setData.pushContentLineLimit || 100;
590
652
  // 限制行数
591
653
  if (lines.length > lineLimit) {
592
654
  lines.length = lineLimit;