yz-yuki-plugin 2.0.7-2 → 2.0.7-20

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,18 @@ 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;">`;
231
220
  case 'RICH_TEXT_NODE_TYPE_GOODS':
232
221
  // 处理商品推广类型,使用官方的HTML标签写法
233
222
  const goods_url = node?.jump_url;
234
223
  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>`;
224
+ case 'RICH_TEXT_NODE_TYPE_VOTE':
225
+ // 处理投票类型,使用官方的HTML标签写法
226
+ 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
227
  default:
236
228
  return node;
237
229
  }
@@ -245,7 +237,7 @@ class BiliQuery {
245
237
  };
246
238
  /**获取完整B站文章内容
247
239
  * @param postUrl - 文章链接: https://www.bilibili.com/read/cvxxxx 或者 https://www.bilibili.com/opus/xxxx
248
- * @returns {JSON} 完整的B站文章内容json数据
240
+ * @returns 完整的B站文章内容json数据
249
241
  */
250
242
  static async getFullArticleContent(postUrl) {
251
243
  let { cookie } = await readSyncCookie();
@@ -256,24 +248,22 @@ class BiliQuery {
256
248
  responseType: 'text'
257
249
  });
258
250
  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
- }
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 };
268
260
  }
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
- }
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 };
277
267
  }
278
268
  }
279
269
  catch (err) {
@@ -346,7 +336,7 @@ class BiliQuery {
346
336
  case 'RICH_TEXT_NODE_TYPE_EMOJI':
347
337
  // 处理表情类型,使用 img 标签显示表情
348
338
  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;">`;
339
+ 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;">`;
350
340
  case 'RICH_TEXT_NODE_TYPE_GOODS':
351
341
  // 处理商品推广类型,使用官方的HTML标签写法
352
342
  const goods_url = node?.rich?.jump_url;
@@ -393,9 +383,15 @@ class BiliQuery {
393
383
  */
394
384
  static async formatTextDynamicData(upName, data, isForward, setData) {
395
385
  const BiliDrawDynamicLinkUrl = 'https://m.bilibili.com/dynamic/';
396
- let desc, msg = [], pics = [], author, majorType, content, dynamicTitle;
397
- let title = `B站【${upName}】动态推送:\n`;
386
+ let desc, msg = [], pics = [], author, majorType, content, dynamicTitle, module_stat;
387
+ let msg_meta = `B站【${upName}】动态推送:`;
398
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
+ }
399
395
  switch (dynamicType) {
400
396
  case 'DYNAMIC_TYPE_AV':
401
397
  // 处理视频动态
@@ -403,14 +399,26 @@ class BiliQuery {
403
399
  author = data?.modules?.module_author;
404
400
  if (!desc && !author)
405
401
  return;
406
- title = `B站【${upName}】视频动态推送:\n`;
402
+ module_stat = data?.modules?.module_stat;
403
+ msg_meta = `B站【${upName}】视频动态推送:`;
407
404
  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') : ''}`
405
+ msg_meta,
406
+ `\n--------------------`,
407
+ `\n${desc.title}`, // 标题
408
+ `\n--------------------`,
409
+ `\n视频简介:`,
410
+ `\n${desc.desc}`,
411
+ `\n--------------------`,
412
+ `\n投稿:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
413
+ `\n--------------------`,
414
+ `\n${desc?.stat?.danmaku}弹幕 • ${desc?.stat?.play}播放`,
415
+ ...(module_stat
416
+ ? [
417
+ `\n${formatNumber(module_stat.like?.count)}点赞 • ${formatNumber(module_stat.comment?.count)}评论 • ${formatNumber(module_stat.forward?.count)}转发`
418
+ ]
419
+ : []),
420
+ `\n--------------------`,
421
+ `\n链接:${this.formatUrl(desc.jump_url)}`
414
422
  ];
415
423
  pics = [Segment.image(desc?.cover)];
416
424
  return { msg, pics, dynamicType };
@@ -435,13 +443,22 @@ class BiliQuery {
435
443
  }
436
444
  if (!desc && !author)
437
445
  return;
438
- title = `B站【${upName}】动态推送:\n`;
446
+ module_stat = data?.modules?.module_stat;
447
+ msg_meta = `B站【${upName}】图文动态推送:`;
439
448
  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') : ''}`
449
+ msg_meta,
450
+ `\n--------------------`,
451
+ `\n正文:`,
452
+ `\n${this.dynamicContentLimit(content, setData)}`,
453
+ `\n--------------------`,
454
+ `\n投稿:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
455
+ `\n--------------------`,
456
+ ...(module_stat
457
+ ? [
458
+ `\n${formatNumber(module_stat.like?.count)}点赞 • ${formatNumber(module_stat.comment?.count)}评论 • ${formatNumber(module_stat.forward?.count)}转发\n--------------------`
459
+ ]
460
+ : []),
461
+ `\n链接:${BiliDrawDynamicLinkUrl}${data.id_str}`
445
462
  ];
446
463
  return { msg, pics, dynamicType };
447
464
  case 'DYNAMIC_TYPE_DRAW':
@@ -474,6 +491,7 @@ class BiliQuery {
474
491
  }
475
492
  if (!desc && !pics && !author)
476
493
  return;
494
+ module_stat = data?.modules?.module_stat;
477
495
  const dynamicPicCountLimit = setData.pushPicCountLimit || 3;
478
496
  if (pics.length > dynamicPicCountLimit) {
479
497
  pics.length = dynamicPicCountLimit;
@@ -481,13 +499,21 @@ class BiliQuery {
481
499
  pics = pics.map((item) => {
482
500
  return Segment.image(item);
483
501
  });
484
- title = `B站【${upName}】图文动态推送:\n`;
502
+ msg_meta = `B站【${upName}】图文动态推送:`;
485
503
  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') : ''}`
504
+ msg_meta,
505
+ `\n--------------------`,
506
+ `\n正文:`,
507
+ `\n${this.dynamicContentLimit(content, setData)}`,
508
+ `\n--------------------`,
509
+ `\n投稿:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
510
+ `\n--------------------`,
511
+ ...(module_stat
512
+ ? [
513
+ `\n${formatNumber(module_stat.like?.count)}点赞 • ${formatNumber(module_stat.comment?.count)}评论 • ${formatNumber(module_stat.forward?.count)}转发\n--------------------`
514
+ ]
515
+ : []),
516
+ `\n链接:${BiliDrawDynamicLinkUrl}${data.id_str}`
491
517
  ];
492
518
  return { msg, pics, dynamicType };
493
519
  case 'DYNAMIC_TYPE_ARTICLE':
@@ -521,16 +547,27 @@ class BiliQuery {
521
547
  }
522
548
  if (!desc && !author)
523
549
  return;
550
+ module_stat = data?.modules?.module_stat;
524
551
  pics = pics.map((item) => {
525
552
  return Segment.image(item);
526
553
  });
527
- title = `B站【${upName}】文章动态推送:\n`;
554
+ msg_meta = `B站【${upName}】文章动态推送:`;
528
555
  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') : ''}`
556
+ msg_meta,
557
+ `\n--------------------`,
558
+ `\n${dynamicTitle}`,
559
+ `\n--------------------`,
560
+ `\n正文:`,
561
+ `\n${this.dynamicContentLimit(content, setData)}`,
562
+ `\n--------------------`,
563
+ `\n投稿:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
564
+ `\n--------------------`,
565
+ ...(module_stat
566
+ ? [
567
+ `\n${formatNumber(module_stat.like?.count)}点赞 • ${formatNumber(module_stat.comment?.count)}评论 • ${formatNumber(module_stat.forward?.count)}转发\n--------------------`
568
+ ]
569
+ : []),
570
+ `\n链接:${this.formatUrl(desc.jump_url)}`
534
571
  ];
535
572
  return { msg, pics, dynamicType };
536
573
  case 'DYNAMIC_TYPE_FORWARD':
@@ -542,6 +579,7 @@ class BiliQuery {
542
579
  return;
543
580
  if (!data.orig)
544
581
  return;
582
+ module_stat = data?.modules?.module_stat;
545
583
  isForward = true;
546
584
  let orig = await this.formatTextDynamicData(upName, data.orig, isForward, setData);
547
585
  let origContent = [];
@@ -552,14 +590,22 @@ class BiliQuery {
552
590
  else {
553
591
  return 'continue';
554
592
  }
555
- title = `B站【${upName}】转发动态推送:\n`;
593
+ msg_meta = `B站【${upName}】转发动态推送:`;
556
594
  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',
595
+ msg_meta,
596
+ `\n--------------------`,
597
+ `\n正文:`,
598
+ `\n${this.dynamicContentLimit(content, setData)}`,
599
+ `\n--------------------`,
600
+ `\n投稿:${author ? moment(author.pub_ts * 1000).format('YYYY年MM月DD日 HH:mm:ss') : ''}`,
601
+ `\n--------------------`,
602
+ ...(module_stat
603
+ ? [
604
+ `\n${formatNumber(module_stat.like?.count)}点赞 • ${formatNumber(module_stat.comment?.count)}评论 • ${formatNumber(module_stat.forward?.count)}转发\n--------------------`
605
+ ]
606
+ : []),
607
+ `\n链接:${BiliDrawDynamicLinkUrl}${data.id_str}\n`,
608
+ '\n>>>>以下为转发内容<<<<\n',
563
609
  ...origContent
564
610
  ];
565
611
  return { msg, pics, dynamicType };
@@ -572,8 +618,18 @@ class BiliQuery {
572
618
  desc = desc?.live_play_info;
573
619
  if (!desc)
574
620
  return;
575
- title = `B站【${upName}】直播动态推送:\n`;
576
- msg = [title, `-----------------------------\n`, `标题:${desc.title}\n`, `链接:https:${desc.link}`];
621
+ msg_meta = `B站【${upName}】直播动态推送:`;
622
+ msg = [
623
+ msg_meta,
624
+ `\n--------------------`,
625
+ `\n${desc.title}`,
626
+ `\n--------------------`,
627
+ `\n分区:${desc?.parent_area_name} (${desc?.area_name})`,
628
+ `\n开播:${moment(desc.live_start_time * 1000).format('YYYY年MM月DD日 HH:mm:ss')}`,
629
+ `\n--------------------`,
630
+ `\n${formatNumber(desc?.watched_show?.num)}人看过`,
631
+ `\n链接:https:${desc.link}`
632
+ ];
577
633
  pics = [Segment.image(desc.cover)];
578
634
  return { msg, pics, dynamicType };
579
635
  default: