koishi-plugin-video-parser-all 0.5.4 → 0.5.5

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 (2) hide show
  1. package/lib/index.js +133 -34
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -123,9 +123,10 @@ const PLATFORM_KEYWORDS = {
123
123
  douyin: ['douyin', '抖音', 'v.douyin.com', 'douyinpic.com', 'douyinvod.com', 'douyin.com/video', 'douyin.com/note', 'www.douyin.com', 'tiktok.com'],
124
124
  zuiyou: ['zuiyou', '最右', 'xiaochuankeji.cn', 'izuiyou.com', 'izuiyou.com/topic']
125
125
  };
126
+ // 更新API配置:B站和抖音使用新的api.xingzhige.com,其他平台保持不变
126
127
  const API_CONFIG = {
127
- bilibili: 'https://api.bugpk.com/api/bilibili',
128
- douyin: 'https://api.bugpk.com/api/dyjx',
128
+ bilibili: 'https://api.xingzhige.com/API/b_parse',
129
+ douyin: 'https://api.xingzhige.com/API/douyin/',
129
130
  kuaishou: 'https://api.bugpk.com/api/ksjx',
130
131
  xiaohongshu: 'https://api.bugpk.com/api/xhsjx',
131
132
  weibo: 'https://api.bugpk.com/api/weibo',
@@ -147,16 +148,16 @@ const PLATFORM_ERROR_CODE_MAP = {
147
148
  };
148
149
  const VARIABLE_MAPPING = {
149
150
  '标题': ['title', 'Title', 'TITLE'],
150
- '作者': ['author.name', 'author', 'name', 'Author', 'Name'],
151
+ '作者': ['author.name', 'author', 'name', 'Author', 'Name', 'owner.name'],
151
152
  '简介': ['desc', 'description', 'Desc', 'Description', 'content', 'Content'],
152
153
  '视频时长': ['duration', 'Duration', 'time', 'Time'],
153
- '点赞数': ['like', 'Like', 'attitudes_count', 'digg_count', 'praise'],
154
+ '点赞数': ['like', 'Like', 'attitudes_count', 'digg_count', 'praise', 'stat.like'],
154
155
  '投币数': ['coin', 'Coin', 'bi', 'Bi'],
155
- '收藏数': ['collect', 'Collect', 'favorite', 'Favorite', 'star', 'Star'],
156
- '转发数': ['share', 'Share', 'forward', 'Forward', 'repost'],
156
+ '收藏数': ['collect', 'Collect', 'favorite', 'Favorite', 'star', 'Star', 'stat.collect'],
157
+ '转发数': ['share', 'Share', 'forward', 'Forward', 'repost', 'stat.share'],
157
158
  '播放数': ['view', 'View', 'play_count', 'PlayCount', 'play'],
158
- '评论数': ['comment', 'Comment', 'comments_count', 'comment_count', 'discuss'],
159
- '音乐名': ['music.title', 'music_name', 'audio_name', 'sound_name']
159
+ '评论数': ['comment', 'Comment', 'comments_count', 'comment_count', 'discuss', 'stat.comment'],
160
+ '音乐名': ['music.title', 'music_name', 'audio_name', 'sound_name', 'muisic']
160
161
  };
161
162
  function getErrorInfo(code, detail) {
162
163
  const baseMsg = exports.ErrorMessageMap[code] || exports.ErrorMessageMap[ErrorCode.UNKNOWN_ERROR];
@@ -408,48 +409,126 @@ function findValueInObject(obj, keys) {
408
409
  }
409
410
  return undefined;
410
411
  }
412
+ // 适配新的API返回格式
411
413
  function parseData(rawResponse, maxDescLength, platform) {
412
414
  let data = rawResponse;
413
- if (data.data) {
415
+ // 处理不同平台的返回结构差异
416
+ if (platform === 'bilibili' && rawResponse.data) {
417
+ // 适配api.xingzhige.com的B站返回格式
418
+ data = rawResponse.data;
419
+ }
420
+ else if (platform === 'douyin' && rawResponse.data) {
421
+ // 适配api.xingzhige.com的抖音返回格式
422
+ data = rawResponse.data;
423
+ }
424
+ else if (data.data) {
425
+ // 其他平台保持原有逻辑
414
426
  data = data.data;
415
427
  }
416
428
  const stat = {};
429
+ // 适配新的字段映射
417
430
  Object.entries(VARIABLE_MAPPING).forEach(([varName, keys]) => {
418
431
  const value = findValueInObject(data, keys);
419
432
  if (value !== undefined) {
420
433
  stat[varName] = value;
421
434
  }
422
435
  });
423
- let type = data.type || 'video';
424
- const title = findValueInObject(data, ['title']) || '无标题';
425
- const author = findValueInObject(data, ['author.name', 'author']) || '未知作者';
426
- const desc = (findValueInObject(data, ['desc', 'description', 'content']) || title).toString().slice(0, maxDescLength);
427
- const cover = findValueInObject(data, ['cover', 'imgurl', 'pic', 'thumbnail']) || '';
428
- let images = findValueInObject(data, ['imgurl', 'images', 'pics']) || [];
436
+ // 处理不同平台的类型字段
437
+ let type = 'video';
438
+ if (platform === 'douyin' && data.jx && data.jx.type) {
439
+ type = data.jx.type; // 抖音的图集类型
440
+ }
441
+ else if (data.type) {
442
+ type = data.type;
443
+ }
444
+ // 适配不同平台的标题字段
445
+ let title = '无标题';
446
+ if (platform === 'bilibili' && data.video && data.video.title) {
447
+ title = data.video.title;
448
+ }
449
+ else if (platform === 'douyin' && data.item && data.item.title) {
450
+ title = data.item.title;
451
+ }
452
+ else {
453
+ title = findValueInObject(data, ['title']) || '无标题';
454
+ }
455
+ // 适配不同平台的作者字段
456
+ let author = '未知作者';
457
+ if (platform === 'bilibili' && data.owner && data.owner.name) {
458
+ author = data.owner.name;
459
+ }
460
+ else if (platform === 'douyin' && data.author && data.author.name) {
461
+ author = data.author.name;
462
+ }
463
+ else {
464
+ author = findValueInObject(data, ['author.name', 'author', 'name', 'auther']) || '未知作者';
465
+ }
466
+ // 适配不同平台的描述字段
467
+ let desc = title;
468
+ if (platform === 'bilibili' && data.video && data.video.desc) {
469
+ desc = data.video.desc;
470
+ }
471
+ else if (platform === 'douyin') {
472
+ desc = title; // 抖音没有单独的描述字段
473
+ }
474
+ else {
475
+ desc = findValueInObject(data, ['desc', 'description', 'content']) || title;
476
+ }
477
+ desc = desc.toString().slice(0, maxDescLength);
478
+ // 适配不同平台的封面字段
479
+ let cover = '';
480
+ if (platform === 'bilibili' && data.video && data.video.fm) {
481
+ cover = data.video.fm;
482
+ }
483
+ else if (platform === 'douyin' && data.item && data.item.cover) {
484
+ cover = data.item.cover;
485
+ }
486
+ else {
487
+ cover = findValueInObject(data, ['cover', 'imgurl', 'pic', 'thumbnail']) || '';
488
+ }
489
+ // 适配不同平台的图片字段
490
+ let images = [];
491
+ if (platform === 'douyin' && data.item && data.item.images) {
492
+ images = data.item.images;
493
+ }
494
+ else {
495
+ images = findValueInObject(data, ['imgurl', 'images', 'pics']) || [];
496
+ }
429
497
  if (!Array.isArray(images))
430
498
  images = [images];
431
- const videoUrls = [
432
- findValueInObject(data, ['url']),
433
- findValueInObject(data, ['download_url']),
434
- findValueInObject(data, ['video_backup']),
435
- findValueInObject(data, ['playUrl']),
436
- findValueInObject(data, ['video_url'])
437
- ];
499
+ // 适配不同平台的视频链接字段
438
500
  let video = '';
439
- if (Array.isArray(videoUrls[2])) {
440
- video = videoUrls[2][0]?.url || '';
501
+ if (platform === 'bilibili' && data.video && data.video.url) {
502
+ video = data.video.url;
503
+ }
504
+ else if (platform === 'douyin') {
505
+ video = ''; // 抖音图集没有视频链接
441
506
  }
442
507
  else {
443
- for (const url of videoUrls) {
444
- if (url && typeof url === 'string' && url.trim() !== '') {
445
- video = url;
446
- break;
508
+ const videoUrls = [
509
+ findValueInObject(data, ['url']),
510
+ findValueInObject(data, ['download_url']),
511
+ findValueInObject(data, ['video_backup']),
512
+ findValueInObject(data, ['playUrl']),
513
+ findValueInObject(data, ['video_url'])
514
+ ];
515
+ if (Array.isArray(videoUrls[2])) {
516
+ video = videoUrls[2][0]?.url || '';
517
+ }
518
+ else {
519
+ for (const url of videoUrls) {
520
+ if (url && typeof url === 'string' && url.trim() !== '') {
521
+ video = url;
522
+ break;
523
+ }
447
524
  }
448
525
  }
449
526
  }
527
+ // 适配不同平台的时长字段
450
528
  const durationValue = findValueInObject(data, ['duration']);
451
529
  const duration = typeof durationValue === 'number' ? durationValue : parseInt(durationValue) || 0;
452
530
  const durationFormatted = formatDuration(durationValue || 0);
531
+ // 处理live_photo字段
453
532
  const live_photo = data.live_photo || [];
454
533
  return {
455
534
  type: type,
@@ -576,9 +655,17 @@ function apply(ctx, config) {
576
655
  }
577
656
  try {
578
657
  const resData = await parseWithRetry(realUrl, platform, config.retryTimes);
579
- // 正确的成功判断逻辑:code为200或0,或者msg包含"解析成功"
580
- const isSuccess = resData.code === 200 || resData.code === 0 ||
581
- (resData.msg && resData.msg.includes('解析成功'));
658
+ // 适配不同平台的成功判断逻辑
659
+ let isSuccess = false;
660
+ // B站和抖音使用新的判断逻辑(code=0表示成功)
661
+ if (platform === 'bilibili' || platform === 'douyin') {
662
+ isSuccess = resData.code === 0 || (resData.msg && (resData.msg.includes('解析成功') || resData.msg === 'video'));
663
+ }
664
+ else {
665
+ // 其他平台保持原有逻辑
666
+ isSuccess = resData.code === 200 || resData.code === 0 ||
667
+ (resData.msg && resData.msg.includes('解析成功'));
668
+ }
582
669
  if (!isSuccess) {
583
670
  const apiErrorMsg = resData.msg || '解析失败';
584
671
  const platformCode = PLATFORM_ERROR_CODE_MAP[platform] || ErrorCode.API_RETURN_ERROR;
@@ -593,11 +680,12 @@ function apply(ctx, config) {
593
680
  }
594
681
  try {
595
682
  const parseResult = parseData(resData, config.maxDescLength, platform);
596
- // 修正内容判断逻辑:支持live类型和live_photo
683
+ // 修正内容判断逻辑:支持抖音图集、live类型和live_photo
597
684
  const hasValidContent = parseResult.video ||
598
685
  (parseResult.images && parseResult.images.length > 0) ||
599
686
  (parseResult.live_photo && parseResult.live_photo.length > 0) ||
600
- parseResult.type === 'live';
687
+ parseResult.type === 'live' ||
688
+ parseResult.type === '图集';
601
689
  if (!hasValidContent) {
602
690
  const code = ErrorCode.NO_VIDEO_FOUND;
603
691
  const msg = getErrorInfo(code, '链接有效但未找到视频/图片内容(可能是直播、私密内容或已删除)');
@@ -728,6 +816,12 @@ function apply(ctx, config) {
728
816
  forwardMessages.push(buildForwardNode(session, item.text, botName));
729
817
  if (item.cover && forwardMessages.length < 100)
730
818
  forwardMessages.push(buildForwardNode(session, koishi_1.h.image(item.cover), botName));
819
+ // 处理抖音图集
820
+ if (item.type === '图集' && item.images?.length) {
821
+ for (let i = 0; i < item.images.length && forwardMessages.length < 100; i++) {
822
+ forwardMessages.push(buildForwardNode(session, koishi_1.h.image(item.images[i]), botName));
823
+ }
824
+ }
731
825
  if (item.type === 'image' && item.images?.length) {
732
826
  for (let i = 0; i < item.images.length && forwardMessages.length < 100; i++) {
733
827
  forwardMessages.push(buildForwardNode(session, koishi_1.h.image(item.images[i]), botName));
@@ -795,7 +889,12 @@ function apply(ctx, config) {
795
889
  await sendTimeout(session, item.text);
796
890
  await delay(300);
797
891
  }
798
- if (item.type === 'live' || item.type === 'live_photo') {
892
+ // 处理抖音图集
893
+ if (item.type === '图集' && item.images?.length) {
894
+ const imgMsg = (0, koishi_1.h)('message', ...item.images.map((url) => koishi_1.h.image(url)));
895
+ await sendTimeout(session, imgMsg);
896
+ }
897
+ else if (item.type === 'live' || item.type === 'live_photo') {
799
898
  if (item.live_photo?.length) {
800
899
  for (const liveItem of item.live_photo) {
801
900
  await sendTimeout(session, koishi_1.h.image(liveItem.image));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-video-parser-all",
3
3
  "description": "Koishi 全平台视频解析插件,支持抖音/快手/B站/小红书/微博/今日头条/皮皮搞笑/皮皮虾/最右视频链接解析",
4
- "version": "0.5.4",
4
+ "version": "0.5.5",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [