koishi-plugin-bilibili-videolink-analysis 0.6.3 → 1.0.1

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 +273 -265
  2. package/package.json +4 -6
  3. package/readme.md +3 -0
package/lib/index.js CHANGED
@@ -7,7 +7,7 @@ const logger = new Logger('bilibili-videolink-analysis');
7
7
  exports.name = 'bilibili-videolink-analysis';
8
8
  exports.inject = {
9
9
  optional: ['puppeteer'],
10
- required: ['BiliBiliVideo']
10
+ //required: ['BiliBiliVideo']
11
11
  }
12
12
  exports.usage = `
13
13
 
@@ -24,7 +24,6 @@ exports.usage = `
24
24
  #### ⚠️ **如果你使用不了本项目,请优先检查:** ⚠️
25
25
  #### 若无注册的指令,请关开一下[command插件](/market?keyword=commands+email:shigma10826@gmail.com)(没有指令也不影响解析别人的链接)
26
26
  #### 视频内容是否为B站的大会员专属视频/付费视频/充电专属视频
27
- #### 是否正确配置并启动了[bilibili-login插件](/market?keyword=bilibili-login) (启动即可,不是必须登录)
28
27
  #### 接入方法是否支持获取网址链接/小程序卡片消息
29
28
  #### 接入方法是否支持视频元素的发送
30
29
  #### 发送视频超时/其他网络问题
@@ -48,7 +47,6 @@ exports.usage = `
48
47
  特别鸣谢以下项目的支持:
49
48
 
50
49
  - [@summonhim/koishi-plugin-bili-parser](/market?keyword=bili-parser)
51
- - [koishi-plugin-iirose-media-request](/market?keyword=iirose-media-request)
52
50
 
53
51
  ---
54
52
 
@@ -74,16 +72,16 @@ exports.Config = Schema.intersect([
74
72
  Schema.const('4').description('返回视频和视频直链'),
75
73
  Schema.const('5').description('返回视频,仅在日志记录视频直链'),
76
74
  ]).role('radio').default('2').description("是否返回` 视频/视频直链 `"),
77
- Video_ClarityPriority: Schema.union([
78
- Schema.const('1').description('低清晰度优先(低清晰度的视频发得快一点)'),
79
- Schema.const('2').description('高清晰度优先(清晰的还是去B站看吧)'),
80
- ]).role('radio').default('1').description("发送的视频清晰度优先策略"),
75
+ //Video_ClarityPriority: Schema.union([
76
+ // Schema.const('1').description('低清晰度优先(低清晰度的视频发得快一点)'),
77
+ // Schema.const('2').description('高清晰度优先(清晰的还是去B站看吧)'),
78
+ //]).role('radio').default('1').description("发送的视频清晰度优先策略"),
81
79
  BVnumberParsing: Schema.boolean().default(true).description("是否允许根据`独立的BV号`解析视频 `开启后,可以通过视频的BV号解析视频。` <br> [触发说明见README](https://www.npmjs.com/package/koishi-plugin-bilibili-videolink-analysis)"),
82
- Maximumduration: Schema.number().default(25).description("允许解析的视频最大时长(分钟)`超过这个时长 就不会发视频`").min(1),
83
- Maximumduration_tip: Schema.union([
84
- Schema.const('不返回文字提示').description('不返回文字提示'),
85
- Schema.string().description('返回文字提示(请在右侧填写文字内容)').default('视频太长啦!还是去B站看吧~'),
86
- ]).description("对过长视频的文字提示内容").default('视频太长啦!还是去B站看吧~'),
80
+ //Maximumduration: Schema.number().default(25).description("允许解析的视频最大时长(分钟)`超过这个时长 就不会发视频`").min(1),
81
+ //Maximumduration_tip: Schema.union([
82
+ // Schema.const('不返回文字提示').description('不返回文字提示'),
83
+ // Schema.string().description('返回文字提示(请在右侧填写文字内容)').default('视频太长啦!还是去B站看吧~'),
84
+ //]).description("对过长视频的文字提示内容").default('视频太长啦!还是去B站看吧~'),
87
85
  MinimumTimeInterval: Schema.number().default(180).description("若干`秒`内 不再处理相同链接 `防止多bot互相触发 导致的刷屏/性能浪费`").min(1),
88
86
  }).description("基础设置"),
89
87
 
@@ -110,7 +108,7 @@ exports.Config = Schema.intersect([
110
108
  ]);
111
109
 
112
110
  function apply(ctx, config) {
113
- const bilibiliVideo = ctx.BiliBiliVideo;
111
+
114
112
  ctx.middleware(async (session, next) => {
115
113
  // 如果允许解析 BV 号,则进行解析
116
114
  if (config.BVnumberParsing) {
@@ -129,7 +127,202 @@ function apply(ctx, config) {
129
127
  return next();
130
128
  });
131
129
 
132
- ctx.command('点播 [keyword]', '点播B站视频')
130
+ ctx.command('B站点播')
131
+ ctx.command('B站点播/退出登录', '退出B站账号')
132
+ .action(async ({ session }) => {
133
+ const page = await ctx.puppeteer.page();
134
+ await page.goto('https://www.bilibili.com/', { waitUntil: 'networkidle2' });
135
+
136
+ const loginButtonSelector = '.right-entry__outside.go-login-btn';
137
+ const isLoggedIn = await page.$(loginButtonSelector) === null;
138
+
139
+ if (!isLoggedIn) {
140
+ await page.close();
141
+ await session.send(h.text('您尚未登录。'))
142
+ return;
143
+ }
144
+
145
+ const avatarLinkSelector = '.header-entry-mini';
146
+ const logoutButtonSelector = '.logout-item';
147
+
148
+ try {
149
+ const avatarElement = await page.$(avatarLinkSelector);
150
+ if (avatarElement) {
151
+ await avatarElement.hover();
152
+ await page.waitForSelector(logoutButtonSelector, { visible: true });
153
+
154
+ await page.click(logoutButtonSelector);
155
+
156
+ await new Promise(resolve => setTimeout(resolve, 1000));
157
+
158
+ await page.close();
159
+ await session.send(h.text('已成功退出登录。'))
160
+ return;
161
+ } else {
162
+ await page.close();
163
+ await session.send(h.text('找不到用户头像,无法退出登录。'))
164
+ return;
165
+ }
166
+ } catch (error) {
167
+ await page.close();
168
+ logger.error('Error during logout:', error);
169
+ await session.send(h.text('退出登录时出错。'))
170
+ return;
171
+ }
172
+ });
173
+
174
+ ctx.command('B站点播/登录', '登录B站账号')
175
+ .alias("登陆")
176
+ .action(async ({ session }) => {
177
+ const page = await ctx.puppeteer.page();
178
+ await page.goto('https://www.bilibili.com/', { waitUntil: 'networkidle2' });
179
+
180
+ const loginButtonSelector = '.right-entry__outside.go-login-btn';
181
+ const isLoggedIn = await page.$(loginButtonSelector) === null;
182
+
183
+ if (isLoggedIn) {
184
+ await page.close();
185
+ await session.send(h.text('您已经登录了。'))
186
+ return;
187
+ }
188
+
189
+ await page.click(loginButtonSelector);
190
+
191
+ const qrCodeSelector = '.login-scan-box img';
192
+ await page.waitForSelector(qrCodeSelector);
193
+ const qrCodeUrl = await page.$eval(qrCodeSelector, img => img.src);
194
+
195
+ await session.send(h.image(qrCodeUrl, 'image/png'));
196
+ await session.send('请扫描二维码进行登录。');
197
+
198
+ let attempts = 0;
199
+ let loginSuccessful = false;
200
+
201
+ while (attempts < 6) {
202
+ await new Promise(resolve => setTimeout(resolve, 5000)); // Wait
203
+ const isStillLoggedIn = await page.$(loginButtonSelector) === null;
204
+
205
+ if (isStillLoggedIn) {
206
+ loginSuccessful = true;
207
+ break;
208
+ }
209
+
210
+ attempts++;
211
+ }
212
+
213
+ await page.close();
214
+ await session.send(h.text(loginSuccessful ? '登录成功!' : '登录失败,请重试。'))
215
+ return;
216
+ });
217
+
218
+ if (config.loggerinfo) {
219
+ ctx.command('B站点播/调试点播 [keyword]', '调试时点播B站视频')
220
+ .option('video', '-v 解析返回视频')
221
+ .option('audio', '-a 解析返回语音')
222
+ .option('link', '-l 解析返回链接')
223
+ .option('page', '-p <page:number> 指定页数', { fallback: '1' })
224
+ .example('调试点播 遠い空へ -v')
225
+ .action(async ({ options, session }, keyword) => {
226
+ if (!keyword) {
227
+ await session.execute('调试点播 -h');
228
+ return '没输入keyword';
229
+ }
230
+ const url = `https://search.bilibili.com/video?keyword=${encodeURIComponent(keyword)}&page=${options.page}&o=30`;
231
+ const page = await ctx.puppeteer.page();
232
+ await page.goto(url, {
233
+ waitUntil: 'networkidle2',
234
+ });
235
+
236
+ // 获取视频列表并为每个视频元素添加序号
237
+ const videos = await page.evaluate((point) => {
238
+ const items = Array.from(document.querySelectorAll('.video-list-item:not([style*="display: none"])'));
239
+ return items.map((item, index) => {
240
+ const link = item.querySelector('a');
241
+ const href = link?.getAttribute('href') || '';
242
+ const idMatch = href.match(/\/video\/(BV\w+)\//);
243
+ const id = idMatch ? idMatch[1] : '';
244
+ if (!id) {
245
+ const htmlElement = item;
246
+ htmlElement.style.display = 'none';
247
+ } else {
248
+ const overlay = document.createElement('div');
249
+ overlay.style.position = 'absolute';
250
+ overlay.style.top = `${point[0]}%`;
251
+ overlay.style.left = `${point[1]}%`;
252
+ overlay.style.transform = 'translate(-50%, -50%)';
253
+ overlay.style.fontSize = '48px';
254
+ overlay.style.fontWeight = 'bold';
255
+ overlay.style.color = 'black';
256
+ overlay.style.zIndex = '10';
257
+ overlay.style.backgroundColor = 'rgba(255, 255, 255, 0.7)';
258
+ overlay.style.padding = '10px';
259
+ overlay.style.borderRadius = '8px';
260
+ overlay.textContent = `${index + 1}`;
261
+ const videoElement = item;
262
+ videoElement.style.position = 'relative';
263
+ videoElement.appendChild(overlay);
264
+ }
265
+ return { id };
266
+ }).filter(video => video.id);
267
+ }, config.point);
268
+
269
+ // 如果开启了日志调试模式,打印获取到的视频信息
270
+ if (config.loggerinfo) {
271
+ ctx.logger.info(options);
272
+ ctx.logger.info(`共找到 ${videos.length} 个视频:`);
273
+ videos.forEach((video, index) => {
274
+ ctx.logger.info(`序号 ${index + 1}: ID - ${video.id}`);
275
+ });
276
+ }
277
+ if (videos.length === 0) {
278
+ await page.close();
279
+ return '未找到相关视频。';
280
+ }
281
+
282
+ // 动态调整窗口大小以适应视频数量
283
+ const viewportHeight = 200 + videos.length * 100;
284
+ await page.setViewport({
285
+ width: 1440,
286
+ height: viewportHeight,
287
+ });
288
+
289
+ let msg;
290
+ // 截取整个页面
291
+ const imgBuf = await page.screenshot({ fullPage: true });
292
+ msg = h.image(imgBuf, 'image/png');
293
+
294
+ await page.close();
295
+
296
+ // 发送截图
297
+ await session.send(msg);
298
+ // 提示用户输入
299
+ await session.send(`请选择视频的序号:`);
300
+ // 等待用户输入
301
+ const userChoice = await session.prompt(config.timeout * 1000);
302
+ const choiceIndex = parseInt(userChoice) - 1;
303
+ if (isNaN(choiceIndex) || choiceIndex < 0 || choiceIndex >= videos.length) {
304
+ return '输入无效,请输入正确的序号。';
305
+ }
306
+
307
+ // 返回用户选择的视频ID
308
+ const chosenVideo = videos[choiceIndex];
309
+ // 如果开启了日志调试模式,打印用户选择的视频信息
310
+ if (config.loggerinfo) {
311
+ ctx.logger.info(`渲染序号设置\noverlay.style.top = ${config.point[0]}% \noverlay.style.left = ${config.point[1]}%`);
312
+ ctx.logger.info(`用户选择了序号 ${choiceIndex + 1}: ID - ${chosenVideo.id}`);
313
+ }
314
+
315
+ if (config.enable) {
316
+ // 开启自动解析了
317
+ session.content = `https://www.bilibili.com/video/${chosenVideo.id}`;
318
+ const ret = await extractLinks(session, config, ctx, lastProcessedUrls, logger);
319
+ if (ret && !isLinkProcessedRecently(ret, lastProcessedUrls, config, logger)) {
320
+ await processVideoFromLink(session, config, ctx, lastProcessedUrls, logger, ret, options);
321
+ }
322
+ }
323
+ });
324
+ }
325
+ ctx.command('B站点播/点播 [keyword]', '点播B站视频')
133
326
  .option('video', '-v 解析返回视频')
134
327
  .option('audio', '-a 解析返回语音')
135
328
  .option('link', '-l 解析返回链接')
@@ -138,7 +331,8 @@ function apply(ctx, config) {
138
331
  .action(async ({ options, session }, keyword) => {
139
332
  if (!keyword) {
140
333
  await session.execute('点播 -h')
141
- return '没输入keyword'
334
+ await session.send(h.text('没输入点播内容'))
335
+ return
142
336
  }
143
337
 
144
338
 
@@ -151,13 +345,13 @@ function apply(ctx, config) {
151
345
 
152
346
  await page.addStyleTag({
153
347
  content: `
154
- div.bili-header,
155
- div.login-tip,
156
- div.v-popover,
157
- div.right-entry__outside {
158
- display: none !important;
159
- }
160
- `
348
+ div.bili-header,
349
+ div.login-tip,
350
+ div.v-popover,
351
+ div.right-entry__outside {
352
+ display: none !important;
353
+ }
354
+ `
161
355
  })
162
356
  // 获取视频列表并为每个视频元素添加序号
163
357
  const videos = await page.evaluate((point) => {
@@ -211,7 +405,8 @@ function apply(ctx, config) {
211
405
 
212
406
  if (videos.length === 0) {
213
407
  await page.close()
214
- return '未找到相关视频。'
408
+ await session.send(h.text('未找到相关视频。'))
409
+ return
215
410
  }
216
411
 
217
412
  // 动态调整窗口大小以适应视频数量
@@ -242,7 +437,8 @@ function apply(ctx, config) {
242
437
  const userChoice = await session.prompt(config.timeout * 1000)
243
438
  const choiceIndex = parseInt(userChoice) - 1
244
439
  if (isNaN(choiceIndex) || choiceIndex < 0 || choiceIndex >= videos.length) {
245
- return '输入无效,请输入正确的序号。'
440
+ await session.send(h.text('输入无效,请输入正确的序号。'))
441
+ return
246
442
  }
247
443
 
248
444
  // 返回用户选择的视频ID
@@ -263,6 +459,26 @@ function apply(ctx, config) {
263
459
  }
264
460
  })
265
461
 
462
+ async function handleBilibiliMedia(lastretUrl, config) {
463
+ const fullAPIurl = `https://api.xingzhige.com/API/b_parse/?url=${encodeURIComponent(lastretUrl)}`;
464
+
465
+ try {
466
+ // 发起请求,解析 Bilibili 视频信息
467
+ const data = await ctx.http.get(fullAPIurl);
468
+ // 检查返回的状态码是否为0,表示成功
469
+ if (data.code === 0 && data.msg === "video" && data.data && data.data.video) {
470
+ const videoData = data.data.video;
471
+ const videoUrl = videoData.url; // 视频直链
472
+ // 返回视频直链
473
+ return videoUrl;
474
+ } else {
475
+ throw new Error("解析视频信息失败或非视频类型内容");
476
+ }
477
+ } catch (error) {
478
+ logger.error("请求解析 API 失败或处理出错:", error);
479
+ return null;
480
+ }
481
+ }
266
482
 
267
483
  //判断是否需要解析
268
484
  async function isProcessLinks(session, config, ctx, lastProcessedUrls, logger) {
@@ -324,7 +540,7 @@ function apply(ctx, config) {
324
540
  //解析视频并返回
325
541
  async function processVideoFromLink(session, config, ctx, lastProcessedUrls, logger, ret, options = { video: true }) {
326
542
  const lastretUrl = extractLastUrl(ret);
327
- let bilibilimediaDataURL = '';
543
+
328
544
  let mediaData = '';
329
545
 
330
546
  if (config.waitTip_Switch) {
@@ -343,17 +559,8 @@ function apply(ctx, config) {
343
559
  }
344
560
 
345
561
  if (config.VideoParsing_ToLink) {
346
- const mediaDataString = JSON.stringify(await handleBilibiliMedia(bilibiliVideo, lastretUrl, config));
347
- mediaData = JSON.parse(mediaDataString);
348
- bilibilimediaDataURL = mediaData[0].url;
349
- const videoDuration = mediaData[0].duration; // 提取视频时长,单位为秒
350
-
351
- if (videoDuration > config.Maximumduration * 60) {
352
- if (config.Maximumduration_tip) {
353
- await session.send(config.Maximumduration_tip);
354
- }
355
- return;
356
- }
562
+ const bilibilimediaDataURL = await handleBilibiliMedia(lastretUrl);
563
+
357
564
  if (options.link) { // 发送链接
358
565
  await session.send(h.text(bilibilimediaDataURL));
359
566
  return;
@@ -442,10 +649,10 @@ function apply(ctx, config) {
442
649
  this.config = config;
443
650
  }
444
651
  /**
445
- * 解析 ID 类型
446
- * @param id 视频 ID
447
- * @returns type: ID 类型, id: 视频 ID
448
- */
652
+ * 解析 ID 类型
653
+ * @param id 视频 ID
654
+ * @returns type: ID 类型, id: 视频 ID
655
+ */
449
656
  vid_type_parse(id) {
450
657
  var idRegex = [
451
658
  {
@@ -472,10 +679,10 @@ function apply(ctx, config) {
472
679
  };
473
680
  }
474
681
  /**
475
- * 根据视频 ID 查找视频信息
476
- * @param id 视频 ID
477
- * @returns 视频信息 Json
478
- */
682
+ * 根据视频 ID 查找视频信息
683
+ * @param id 视频 ID
684
+ * @returns 视频信息 Json
685
+ */
479
686
  async fetch_video_info(id) {
480
687
  var ret;
481
688
  const vid = this.vid_type_parse(id);
@@ -501,10 +708,10 @@ function apply(ctx, config) {
501
708
  return ret;
502
709
  }
503
710
  /**
504
- * 生成视频信息
505
- * @param id 视频 ID
506
- * @returns 文字视频信息
507
- */
711
+ * 生成视频信息
712
+ * @param id 视频 ID
713
+ * @returns 文字视频信息
714
+ */
508
715
  async gen_context(id) {
509
716
  const info = await this.fetch_video_info(id);
510
717
  if (!info || !info["data"])
@@ -541,10 +748,10 @@ function apply(ctx, config) {
541
748
  }
542
749
 
543
750
  /**
544
- * 链接类型解析
545
- * @param content 传入消息
546
- * @returns type: "链接类型", id :"内容ID"
547
- */
751
+ * 链接类型解析
752
+ * @param content 传入消息
753
+ * @returns type: "链接类型", id :"内容ID"
754
+ */
548
755
  function link_type_parser(content) {
549
756
  var linkRegex = [
550
757
  {
@@ -610,12 +817,12 @@ function apply(ctx, config) {
610
817
  }
611
818
 
612
819
  /**
613
- * 类型执行器
614
- * @param ctx Context
615
- * @param config Config
616
- * @param element 链接列表
617
- * @returns 解析来的文本
618
- */
820
+ * 类型执行器
821
+ * @param ctx Context
822
+ * @param config Config
823
+ * @param element 链接列表
824
+ * @returns 解析来的文本
825
+ */
619
826
  async function type_processer(ctx, config, element) {
620
827
  var ret = "";
621
828
  switch (element["type"]) {
@@ -648,10 +855,10 @@ function apply(ctx, config) {
648
855
  this.config = config;
649
856
  }
650
857
  /**
651
- * 根据短链接重定向获取正常链接
652
- * @param id 短链接 ID
653
- * @returns 正常链接
654
- */
858
+ * 根据短链接重定向获取正常链接
859
+ * @param id 短链接 ID
860
+ * @returns 正常链接
861
+ */
655
862
  async get_redir_url(id) {
656
863
  var data = await this.ctx.http.get("https://b23.tv/" + id, {
657
864
  redirect: "manual",
@@ -670,10 +877,10 @@ function apply(ctx, config) {
670
877
  /////////////////////////////////////////////////////////////////////////////////////////////////////////
671
878
  /////////////////////////////////////////////////////////////////////////////////////////////////////////
672
879
  /**
673
- * 检查看看一个url是否返回403,或者无法访问,主要用在通过bilibili官方api拿到的视频流
674
- * @param url 链接
675
- * @returns boolean
676
- */
880
+ * 检查看看一个url是否返回403,或者无法访问,主要用在通过bilibili官方api拿到的视频流
881
+ * @param url 链接
882
+ * @returns boolean
883
+ */
677
884
  async function checkResponseStatus(url) {
678
885
  try {
679
886
  const response = await ctx.http(url, {
@@ -701,205 +908,6 @@ function apply(ctx, config) {
701
908
  }
702
909
  }
703
910
 
704
- async function handleBilibiliMedia(bilibiliVideo, originUrl) {
705
- const GetVideoStream = async (h5videoStream, pcvideoStream, cid) => {
706
- if (!h5videoStream.data ||
707
- !pcvideoStream.data ||
708
- !h5videoStream.data.accept_quality ||
709
- !pcvideoStream.data.accept_quality ||
710
- !h5videoStream.data.accept_format ||
711
- !pcvideoStream.data.accept_format)
712
- throw new Error('无法获取清晰度信息, 可能该视频为大会员专享或者该视频为付费视频/充电专属视频!或者账号被风控。');
713
- const h5Quality = h5videoStream.data.accept_quality;
714
- const pcQuality = pcvideoStream.data.accept_quality;
715
- if (config.loggerinfo) {
716
- logger.info(`h5Quality清晰度: ` + h5Quality)
717
- logger.info(`pcQuality清晰度: ` + pcQuality)
718
- }
719
- const CombinedQualityInfo = h5Quality
720
- .filter((item, index) => !(h5videoStream.data?.accept_format?.includes('flv') && h5videoStream.data.accept_format.split(',')[index].includes('flv')))
721
- .map(item => ['html5', item])
722
- .concat(pcQuality
723
- .filter((item, index) => !(pcvideoStream.data?.accept_format?.includes('flv') && pcvideoStream.data.accept_format.split(',')[index].includes('flv')))
724
- .map(item => ['pc', item]));
725
- CombinedQualityInfo.sort((a, b) => {
726
- if (b[1] === a[1]) {
727
- // 如果两者数字相等
728
- if (a[0] === 'html5') {
729
- // html5排在前面
730
- return -1;
731
- }
732
- else if (b[0] === 'html5') {
733
- // pc排在前面
734
- return 1;
735
- }
736
- else {
737
- // 如果都是相同类型,则按照原顺序
738
- return 0;
739
- }
740
- }
741
- else {
742
- // 根据配置决定排序顺序
743
- switch (config.Video_ClarityPriority) {
744
- case '1':
745
- //logger.info(`低清晰度优先排序,a[1]: ${a[1]}, b[1]: ${b[1]}`);
746
- return a[1] - b[1]; // 从低到高排序(低清晰度优先)
747
- case '2':
748
- //logger.info(`高清晰度优先排序,a[1]: ${a[1]}, b[1]: ${b[1]}`);
749
- return b[1] - a[1]; // 从高到低排序(高清晰度优先)
750
- default:
751
- //logger.warn(`未知的视频清晰度优先级配置: ${config.Video_ClarityPriority}`);
752
- return 0; // 默认保持原顺序
753
- }
754
- }
755
- });
756
- outerLoop: for (const [index, item] of CombinedQualityInfo.entries()) {
757
-
758
- videoStream = await bilibiliVideo.getBilibiliVideoStream(avid, bvid, cid, item[1], item[0], 1);
759
-
760
- if (!videoStream || !videoStream.data || !videoStream.data.durl) {
761
- continue;
762
- }
763
- if (await checkResponseStatus(videoStream.data.durl[0].url) === true) {
764
- break outerLoop;
765
- }
766
- const isLastItem = index === CombinedQualityInfo.length - 1;
767
- if (isLastItem) {
768
- throw new Error('在尝试了全部清晰度和平台后,无法获取流媒体');
769
- }
770
- }
771
- return videoStream;
772
- };
773
- const duration = [];
774
- const cids = [];
775
- const cover = [];
776
- const name = [];
777
- const type = [];
778
- const singer = [];
779
- const link = [];
780
- const origin = [];
781
- const bitRate = [];
782
- const url = [];
783
- let bvid;
784
- if (originUrl.includes('http') && originUrl.includes('video')) {
785
- originUrl = originUrl.replace(/\?/g, '/');
786
- bvid = originUrl.split('/video/')[1].split('/')[0];
787
- }
788
- else if (originUrl.includes('BV') || originUrl.includes('bv')) {
789
- bvid = originUrl;
790
- }
791
- else {
792
- const mediaData = returnErrorMediaData(['暂不支持']);
793
- return mediaData;
794
- }
795
- const videoInfo = await bilibiliVideo.getBilibiliVideoDetail(null, bvid);
796
- if (!videoInfo || !videoInfo.data) {
797
- const mediaData = returnErrorMediaData(['这个不是正确的bv号']);
798
- return mediaData;
799
- }
800
- videoInfo.data.pages.forEach((page) => {
801
- if (!videoInfo.data)
802
- return;
803
- cids.push(page.cid);
804
- cover.push(videoInfo.data.pic);
805
- type.push('video');
806
- singer.push(videoInfo.data.owner.name);
807
- link.push(`https://www.bilibili.com/video/${bvid}`);
808
- duration.push(page.duration + 1 || videoInfo.data.duration + 1);
809
- origin.push('bilibili');
810
- if (videoInfo.data.pages.length <= 1) {
811
- name.push(videoInfo.data.title);
812
- }
813
- else {
814
- name.push(`${videoInfo.data.title} - P${page.part}`);
815
- }
816
- });
817
- const avid = videoInfo.data.aid;
818
- let videoStream;
819
-
820
- const h5videoStream = await bilibiliVideo.getBilibiliVideoStream(avid, bvid, cids[0], 112, 'html5', 1);
821
- const pcvideoStream = await bilibiliVideo.getBilibiliVideoStream(avid, bvid, cids[0], 112, 'pc', 1);
822
- if (!h5videoStream || !pcvideoStream)
823
- return returnErrorMediaData(['无法获取B站视频流']);
824
-
825
- const cid = cids[0];
826
- videoStream = await GetVideoStream(h5videoStream, pcvideoStream, cid);
827
- if (!videoStream || !videoStream.data || !videoStream.data.quality || !videoStream.data.durl)
828
- return returnErrorMediaData(['无法获取videoStream信息']);
829
- bitRate.push(videoStream.data.quality);
830
- url.push(videoStream.data.durl[0].url);
831
- /*
832
- for (const cid of cids) {
833
- videoStream = await GetVideoStream(h5videoStream, pcvideoStream, cid);
834
- if (!videoStream || !videoStream.data || !videoStream.data.quality || !videoStream.data.durl)
835
- return returnErrorMediaData(['无法获取videoStream信息']);
836
- bitRate.push(videoStream.data.quality);
837
- url.push(videoStream.data.durl[0].url);
838
- }
839
- */
840
- const mediaData = returnCompleteMediaData(type, name, singer, cover, url, duration, bitRate, [], origin, link);
841
- return mediaData;
842
- }
843
-
844
- /**
845
- * 返回包含错误信息的mediaData
846
- * @param errorMsg 错误信息
847
- * @return mediaData
848
- */
849
- function returnErrorMediaData(errorMsgs) {
850
- const errorMediaDataArray = [];
851
- for (const errorMsg of errorMsgs) {
852
- const mediaData = {
853
- type: 'music',
854
- name: '0',
855
- signer: '0',
856
- cover: '0',
857
- link: '0',
858
- url: '0',
859
- duration: 0,
860
- bitRate: 0,
861
- lyrics: null,
862
- origin: null,
863
- error: errorMsg,
864
- };
865
- errorMediaDataArray.push(mediaData);
866
- }
867
- return errorMediaDataArray;
868
- }
869
-
870
- /**
871
- * 返回完整的mediaData
872
- * @param type 类型
873
- * @param name 标题
874
- * @param signer 创作者
875
- * @param cover 封面图url
876
- * @param url 链接
877
- * @param duration 时长
878
- * @param bitRate 比特率
879
- * @return mediaData
880
- */
881
- function returnCompleteMediaData(typeList, nameList, signerList, coverList, urlList, durationList, bitRateList, lyricsList = [], origin = [], linkList = [], commentList) {
882
- const mediaDataArray = [];
883
- for (let i = 0; i < urlList.length; i++) {
884
- const mediaData = {
885
- type: typeList[i],
886
- name: nameList[i],
887
- signer: signerList[i],
888
- cover: coverList[i],
889
- link: linkList[i] || urlList[i],
890
- url: urlList[i],
891
- duration: durationList[i],
892
- bitRate: bitRateList[i],
893
- lyrics: lyricsList[i] || null,
894
- origin: origin[i] || null,
895
- comment: commentList?.[i] || undefined,
896
- error: null,
897
- };
898
-
899
- mediaDataArray.push(mediaData);
900
- }
901
- return mediaDataArray;
902
- }
903
911
 
904
912
  }
905
913
  exports.apply = apply;
package/package.json CHANGED
@@ -1,15 +1,14 @@
1
1
  {
2
2
  "name": "koishi-plugin-bilibili-videolink-analysis",
3
- "description": "[<ruby>Bilibili视频解析<rp>(</rp><rt>点我查看食用方法</rt><rp>)</rp></ruby>](https://www.npmjs.com/package/koishi-plugin-bilibili-videolink-analysis)解析B站链接(支持小程序卡片)支持搜索点播功能!灵感来自强大的 [iirose-media-request](/market?keyword=iirose-media-request) 以及完美的 [bili-parser](/market?keyword=bili-parser) ,十分感谢这两个优秀的项目!",
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": "0.6.3",
5
+ "version": "1.0.1",
6
6
  "main": "lib/index.js",
7
7
  "typings": "lib/index.d.ts",
8
8
  "files": [
9
9
  "lib",
10
10
  "dist"
11
11
  ],
12
- "scripts": {},
13
12
  "homepage": "https://github.com/shangxueink/koishi-shangxue-apps/tree/main/",
14
13
  "bugs": {
15
14
  "url": "https://github.com/shangxueink/koishi-shangxue-apps/issues"
@@ -23,7 +22,6 @@
23
22
  "bilibili-videolink-analysis"
24
23
  ],
25
24
  "peerDependencies": {
26
- "koishi": "^4.16.8",
27
- "koishi-plugin-bilibili-login": "^0.1.50"
25
+ "koishi": "^4.16.8"
28
26
  }
29
- }
27
+ }
package/readme.md CHANGED
@@ -178,6 +178,9 @@ https://www.bilibili.com/video/BV1ii421Q7oj
178
178
  <details>
179
179
  <summary>点击此处 可查看更新日志</summary>
180
180
 
181
+ - **1.0.0**
182
+ - 不想写了
183
+
181
184
  - **0.6.3**
182
185
  - 修复单独的bv号解析报错
183
186
  - 0.6.2更新了点播,忘写了