koishi-plugin-bilibili-videolink-analysis 1.1.10 → 1.1.12

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.
Files changed (3) hide show
  1. package/lib/index.js +104 -58
  2. package/package.json +1 -1
  3. package/readme.md +5 -1
package/lib/index.js CHANGED
@@ -72,7 +72,7 @@ exports.Config = Schema.intersect([
72
72
  Schema.const('4').description('返回视频和视频直链'),
73
73
  Schema.const('5').description('返回视频,仅在日志记录视频直链'),
74
74
  ]).role('radio').default('2').description("是否返回` 视频/视频直链 `"),
75
- BVnumberParsing: Schema.boolean().default(true).description("是否允许根据`独立的BV号`解析视频 `开启后,可以通过视频的BV号解析视频。` <br> [触发说明见README](https://www.npmjs.com/package/koishi-plugin-bilibili-videolink-analysis)"),
75
+ BVnumberParsing: Schema.boolean().default(true).description("是否允许根据`独立的BV、AV号`解析视频 `开启后,可以通过视频的BV、AV号解析视频。` <br> [触发说明见README](https://www.npmjs.com/package/koishi-plugin-bilibili-videolink-analysis)"),
76
76
  Maximumduration: Schema.number().default(25).description("允许解析的视频最大时长(分钟)`超过这个时长 就不会发视频`").min(1),
77
77
  Maximumduration_tip: Schema.union([
78
78
  Schema.const('不返回文字提示').description('不返回文字提示'),
@@ -97,6 +97,7 @@ exports.Config = Schema.intersect([
97
97
  }).description("链接的图文解析设置"),
98
98
 
99
99
  Schema.object({
100
+ isfigure: Schema.boolean().default(false).description("是否开启合并转发 `仅支持 onebot 适配器` 其他平台开启 无效").experimental(),
100
101
  userAgent: Schema.string().description("所有 API 请求所用的 User-Agent").default("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"),
101
102
  middleware: Schema.boolean().default(false).description("前置中间件模式"),
102
103
  loggerinfo: Schema.boolean().default(false).description("日志调试输出 `日常使用无需开启`"),
@@ -105,6 +106,16 @@ exports.Config = Schema.intersect([
105
106
 
106
107
  function apply(ctx, config) {
107
108
 
109
+ function logInfo(message, message2) {
110
+ if (config.loggerinfo) {
111
+ if (message2) {
112
+ ctx.logger.info(message, message2)
113
+ } else {
114
+ ctx.logger.info(message);
115
+ }
116
+ }
117
+ }
118
+
108
119
  ctx.middleware(async (session, next) => {
109
120
  let sessioncontent = session.content;
110
121
  // 如果允许解析 BV 号,则进行解析
@@ -285,13 +296,13 @@ display: none !important;
285
296
  }, config.point) // 传递配置的 point 参数
286
297
 
287
298
  // 如果开启了日志调试模式,打印获取到的视频信息
288
- if (config.loggerinfo) {
289
- ctx.logger.info(options)
290
- ctx.logger.info(`共找到 ${videos.length} 个视频:`)
291
- videos.forEach((video, index) => {
292
- ctx.logger.info(`序号 ${index + 1}: ID - ${video.id}`)
293
- })
294
- }
299
+
300
+ logInfo(options)
301
+ logInfo(`共找到 ${videos.length} 个视频:`)
302
+ videos.forEach((video, index) => {
303
+ logInfo(`序号 ${index + 1}: ID - ${video.id}`)
304
+ })
305
+
295
306
 
296
307
  if (videos.length === 0) {
297
308
  await page.close()
@@ -335,10 +346,9 @@ display: none !important;
335
346
  const chosenVideo = videos[choiceIndex]
336
347
 
337
348
  // 如果开启了日志调试模式,打印用户选择的视频信息
338
- if (config.loggerinfo) {
339
- ctx.logger.info(`渲染序号设置\noverlay.style.top = ${config.point[0]}% \noverlay.style.left = ${config.point[1]}%`)
340
- ctx.logger.info(`用户选择了序号 ${choiceIndex + 1}: ID - ${chosenVideo.id}`)
341
- }
349
+ logInfo(`渲染序号设置\noverlay.style.top = ${config.point[0]}% \noverlay.style.left = ${config.point[1]}%`)
350
+ logInfo(`用户选择了序号 ${choiceIndex + 1}: ID - ${chosenVideo.id}`)
351
+
342
352
 
343
353
  if (config.enable) { // 开启自动解析了
344
354
 
@@ -401,14 +411,13 @@ display: none !important;
401
411
  }).filter(video => video.id);
402
412
  }, config.point);
403
413
 
404
- // 如果开启了日志调试模式,打印获取到的视频信息
405
- if (config.loggerinfo) {
406
- ctx.logger.info(options);
407
- ctx.logger.info(`共找到 ${videos.length} 个视频:`);
408
- videos.forEach((video, index) => {
409
- ctx.logger.info(`序号 ${index + 1}: ID - ${video.id}`);
410
- });
411
- }
414
+ // 如果开启了日志调试模式,打印获取到的视频信息
415
+ logInfo(options);
416
+ logInfo(`共找到 ${videos.length} 个视频:`);
417
+ videos.forEach((video, index) => {
418
+ logInfo(`序号 ${index + 1}: ID - ${video.id}`);
419
+ });
420
+
412
421
  if (videos.length === 0) {
413
422
  await page.close();
414
423
  return '未找到相关视频。';
@@ -442,10 +451,9 @@ display: none !important;
442
451
  // 返回用户选择的视频ID
443
452
  const chosenVideo = videos[choiceIndex];
444
453
  // 如果开启了日志调试模式,打印用户选择的视频信息
445
- if (config.loggerinfo) {
446
- ctx.logger.info(`渲染序号设置\noverlay.style.top = ${config.point[0]}% \noverlay.style.left = ${config.point[1]}%`);
447
- ctx.logger.info(`用户选择了序号 ${choiceIndex + 1}: ID - ${chosenVideo.id}`);
448
- }
454
+ logInfo(`渲染序号设置\noverlay.style.top = ${config.point[0]}% \noverlay.style.left = ${config.point[1]}%`);
455
+ logInfo(`用户选择了序号 ${choiceIndex + 1}: ID - ${chosenVideo.id}`);
456
+
449
457
 
450
458
  if (config.enable) {
451
459
  // 开启自动解析了
@@ -501,9 +509,8 @@ display: none !important;
501
509
  const currentTime = Date.now();
502
510
 
503
511
  if (lastProcessedUrls[lastretUrl] && (currentTime - lastProcessedUrls[lastretUrl] < config.MinimumTimeInterval * 1000)) {
504
- if (config.loggerinfo) {
505
- logger.info(`重复出现,略过处理:\n ${lastretUrl}`);
506
- }
512
+ ctx.logger.info(`重复出现,略过处理:\n ${lastretUrl}`);
513
+
507
514
  return true; // 已经处理过
508
515
  }
509
516
 
@@ -512,16 +519,18 @@ display: none !important;
512
519
  return false; // 没有处理过
513
520
  }
514
521
 
515
- //解析视频并返回
522
+ //解析视频并返回
516
523
  async function processVideoFromLink(session, config, ctx, lastProcessedUrls, logger, ret, options = { video: true }) {
517
524
  const lastretUrl = extractLastUrl(ret);
518
525
 
526
+ // 等待提示语单独发送
519
527
  if (config.waitTip_Switch) {
520
- // 等候的提示文字
521
528
  await session.send(config.waitTip_Switch);
522
529
  }
523
530
 
524
- let textParts = []; // 用于存储分割后的文本部分
531
+ let responseElements = []; // 用于存储所有要发送的元素
532
+
533
+ // 图文解析
525
534
  if (config.linktextParsing) {
526
535
  let fullText;
527
536
  if (config.bVideoShowLink) {
@@ -532,16 +541,32 @@ display: none !important;
532
541
  }
533
542
 
534
543
  // 分割文本
535
- textParts = fullText.split('${~~~}');
536
- }
537
- // 发送分割后的文本部分
538
- for (const part of textParts) {
539
- const trimmedPart = part.trim(); // 去除首尾空格
540
- if (trimmedPart) { // 确保不是空字符串
541
- await session.send(trimmedPart);
544
+ const textParts = fullText.split('${~~~}');
545
+
546
+ // 创建 message 元素的内容数组
547
+ let messageContent = [];
548
+
549
+ // 将分割后的文本部分解析为消息元素,并添加到 messageContent
550
+ for (const part of textParts) {
551
+ const trimmedPart = part.trim(); // 去除首尾空格
552
+ if (trimmedPart) { // 确保不是空字符串
553
+ // 使用 h.parse 解析文本为消息元素
554
+ const parsedElements = h.parse(trimmedPart);
555
+ messageContent.push(...parsedElements);
556
+ }
542
557
  }
558
+
559
+ // 创建 message 元素
560
+ const messageElement = h('message', {
561
+ userId: session.userId,
562
+ nickname: session.author?.nickname || session.username,
563
+ }, messageContent);
564
+
565
+ // 添加 message 元素到 responseElements
566
+ responseElements.push(messageElement);
543
567
  }
544
568
 
569
+ // 视频/链接解析
545
570
  if (config.VideoParsing_ToLink) {
546
571
  const fullAPIurl = `https://api.xingzhige.com/API/b_parse/?url=${encodeURIComponent(lastretUrl)}`;
547
572
 
@@ -552,9 +577,7 @@ display: none !important;
552
577
  const { bvid, cid, video } = responseData.data;
553
578
  const bilibiliUrl = `https://api.bilibili.com/x/player/playurl?fnval=80&cid=${cid}&bvid=${bvid}`;
554
579
  const playData = await ctx.http.get(bilibiliUrl);
555
- if (config.loggerinfo) {
556
- ctx.logger.info(bilibiliUrl);
557
- }
580
+ logInfo(bilibiliUrl);
558
581
  if (playData.code === 0 && playData.data && playData.data.dash.duration) {
559
582
  const videoDurationSeconds = playData.data.dash.duration;
560
583
  const videoDurationMinutes = videoDurationSeconds / 60;
@@ -569,33 +592,30 @@ display: none !important;
569
592
  }
570
593
 
571
594
  const videoUrl = video.url;
572
- if (config.loggerinfo) {
573
- ctx.logger.info(videoUrl);
574
- }
595
+ logInfo(videoUrl);
596
+
575
597
  if (videoUrl) {
576
598
  if (options.link) {
577
- await session.send(h.text(videoUrl));
578
- return;
599
+ responseElements.push(h.text(videoUrl));
579
600
  } else if (options.audio) {
580
- await session.send(h.audio(videoUrl));
581
- return;
601
+ responseElements.push(h.audio(videoUrl));
582
602
  } else {
583
603
  switch (config.VideoParsing_ToLink) {
584
604
  case '1':
585
605
  break;
586
606
  case '2':
587
- await session.send(h.video(videoUrl));
607
+ responseElements.push(h.video(videoUrl));
588
608
  break;
589
609
  case '3':
590
- await session.send(h.text(videoUrl));
610
+ responseElements.push(h.text(videoUrl));
591
611
  break;
592
612
  case '4':
593
- await session.send(h.text(videoUrl));
594
- await session.send(h.video(videoUrl));
613
+ responseElements.push(h.text(videoUrl));
614
+ responseElements.push(h.video(videoUrl));
595
615
  break;
596
616
  case '5':
597
617
  logger.info(videoUrl);
598
- await session.send(h.video(videoUrl));
618
+ responseElements.push(h.video(videoUrl));
599
619
  break;
600
620
  default:
601
621
  break;
@@ -615,9 +635,26 @@ display: none !important;
615
635
  }
616
636
  }
617
637
 
618
- if (config.loggerinfo) {
619
- logger.info(`机器人发送完整消息为:\n ${ret}`);
638
+ // 合并转发处理
639
+ if (config.isfigure && (session.platform === "onebot" || session.platform === "red")) {
640
+ logInfo(`使用合并转发,正在合并消息。`);
641
+
642
+ // 创建 figure 元素
643
+ const figureContent = h('figure', {
644
+ children: responseElements // 直接使用 responseElements
645
+ });
646
+ logInfo(JSON.stringify(figureContent, null, 2));
647
+
648
+ // 发送合并转发消息
649
+ await session.send(figureContent);
650
+ } else {
651
+ // 没有启用合并转发,按顺序发送所有元素
652
+ for (const element of responseElements) {
653
+ await session.send(element);
654
+ }
620
655
  }
656
+
657
+ logInfo(`机器人发送完整消息。`);
621
658
  return;
622
659
  }
623
660
 
@@ -630,15 +667,24 @@ display: none !important;
630
667
  return urls ? urls.pop() : null;
631
668
  }
632
669
 
633
- // 检测BV号并转换为URL
670
+ // 检测BV / AV 号并转换为URL
634
671
  function convertBVToUrl(text) {
635
672
  const bvPattern = /(?:^|\s)(BV\w{10})(?:\s|$)/g;
636
- const bvMatches = [];
673
+ const avPattern = /(?:^|\s)(av\d+)(?:\s|$)/g; // 新增 AV 号的正则表达式
674
+ const matches = [];
637
675
  let match;
676
+
677
+ // 查找 BV 号
638
678
  while ((match = bvPattern.exec(text)) !== null) {
639
- bvMatches.push(match[1]);
679
+ matches.push(`https://www.bilibili.com/video/${match[1]}`);
640
680
  }
641
- return bvMatches.length ? bvMatches.map(bv => `https://www.bilibili.com/video/${bv}`) : [];
681
+
682
+ // 查找 AV 号
683
+ while ((match = avPattern.exec(text)) !== null) {
684
+ matches.push(`https://www.bilibili.com/video/${match[1]}`);
685
+ }
686
+
687
+ return matches;
642
688
  }
643
689
 
644
690
  // 记录上次处理链接的时间
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "koishi-plugin-bilibili-videolink-analysis",
3
3
  "description": "[<ruby>Bilibili视频解析<rp>(</rp><rt>点我查看食用方法</rt><rp>)</rp></ruby>](https://www.npmjs.com/package/koishi-plugin-bilibili-videolink-analysis)解析B站链接(支持小程序卡片)支持搜索点播功能!灵感来自完美的 [bili-parser](/market?keyword=bili-parser) !",
4
4
  "license": "MIT",
5
- "version": "1.1.10",
5
+ "version": "1.1.12",
6
6
  "main": "lib/index.js",
7
7
  "typings": "lib/index.d.ts",
8
8
  "files": [
package/readme.md CHANGED
@@ -178,7 +178,11 @@ https://www.bilibili.com/video/BV1ii421Q7oj
178
178
  <details>
179
179
  <summary>点击此处 可查看更新日志</summary>
180
180
 
181
- - **1.1.10**
181
+ - **1.1.12**
182
+ - 支持合并转发
183
+ - 支持独立的AV号
184
+
185
+ - **1.1.11**
182
186
  - 又想写了(指readme)
183
187
  - 新增解析格式的的变量分割线
184
188
  - 期间还写了什么,忘了