koishi-plugin-video-parser-all 0.5.7 → 0.5.8

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.
package/lib/index.d.ts CHANGED
@@ -81,12 +81,7 @@ export declare enum ErrorCode {
81
81
  NO_IMAGE_FOUND = 3004,
82
82
  MESSAGE_SEND_FAILED = 4000,
83
83
  MESSAGE_SEND_TIMEOUT = 4001,
84
- FORWARD_MESSAGE_FAILED = 4002,
85
- DOUYIN_PARSE_FAILED = 5001,
86
- XIAOHONGSHU_PARSE_FAILED = 5002,
87
- BILIBILI_PARSE_FAILED = 5003,
88
- KUAISHOU_PARSE_FAILED = 5004,
89
- WEIBO_PARSE_FAILED = 5005
84
+ FORWARD_MESSAGE_FAILED = 4002
90
85
  }
91
86
  export declare const ErrorMessageMap: Record<ErrorCode, string>;
92
87
  export declare function apply(ctx: Context, config: any): void;
package/lib/index.js CHANGED
@@ -76,11 +76,6 @@ var ErrorCode;
76
76
  ErrorCode[ErrorCode["MESSAGE_SEND_FAILED"] = 4000] = "MESSAGE_SEND_FAILED";
77
77
  ErrorCode[ErrorCode["MESSAGE_SEND_TIMEOUT"] = 4001] = "MESSAGE_SEND_TIMEOUT";
78
78
  ErrorCode[ErrorCode["FORWARD_MESSAGE_FAILED"] = 4002] = "FORWARD_MESSAGE_FAILED";
79
- ErrorCode[ErrorCode["DOUYIN_PARSE_FAILED"] = 5001] = "DOUYIN_PARSE_FAILED";
80
- ErrorCode[ErrorCode["XIAOHONGSHU_PARSE_FAILED"] = 5002] = "XIAOHONGSHU_PARSE_FAILED";
81
- ErrorCode[ErrorCode["BILIBILI_PARSE_FAILED"] = 5003] = "BILIBILI_PARSE_FAILED";
82
- ErrorCode[ErrorCode["KUAISHOU_PARSE_FAILED"] = 5004] = "KUAISHOU_PARSE_FAILED";
83
- ErrorCode[ErrorCode["WEIBO_PARSE_FAILED"] = 5005] = "WEIBO_PARSE_FAILED";
84
79
  })(ErrorCode || (exports.ErrorCode = ErrorCode = {}));
85
80
  exports.ErrorMessageMap = {
86
81
  [ErrorCode.SUCCESS]: '操作成功',
@@ -103,11 +98,6 @@ exports.ErrorMessageMap = {
103
98
  [ErrorCode.MESSAGE_SEND_FAILED]: '消息发送失败',
104
99
  [ErrorCode.MESSAGE_SEND_TIMEOUT]: '消息发送超时',
105
100
  [ErrorCode.FORWARD_MESSAGE_FAILED]: '合并转发失败',
106
- [ErrorCode.DOUYIN_PARSE_FAILED]: '抖音链接解析失败',
107
- [ErrorCode.XIAOHONGSHU_PARSE_FAILED]: '小红书链接解析失败',
108
- [ErrorCode.BILIBILI_PARSE_FAILED]: 'B站链接解析失败',
109
- [ErrorCode.KUAISHOU_PARSE_FAILED]: '快手链接解析失败',
110
- [ErrorCode.WEIBO_PARSE_FAILED]: '微博链接解析失败',
111
101
  };
112
102
  const processed = new Map();
113
103
  const linkBuffer = new Map();
@@ -134,17 +124,6 @@ const API_CONFIG = {
134
124
  pipixia: 'https://api.bugpk.com/api/ppx',
135
125
  zuiyou: 'https://api.bugpk.com/api/zuiyou'
136
126
  };
137
- const PLATFORM_ERROR_CODE_MAP = {
138
- douyin: ErrorCode.DOUYIN_PARSE_FAILED,
139
- xiaohongshu: ErrorCode.XIAOHONGSHU_PARSE_FAILED,
140
- bilibili: ErrorCode.BILIBILI_PARSE_FAILED,
141
- kuaishou: ErrorCode.KUAISHOU_PARSE_FAILED,
142
- weibo: ErrorCode.WEIBO_PARSE_FAILED,
143
- toutiao: ErrorCode.API_RETURN_ERROR,
144
- pipigx: ErrorCode.API_RETURN_ERROR,
145
- pipixia: ErrorCode.API_RETURN_ERROR,
146
- zuiyou: ErrorCode.API_RETURN_ERROR
147
- };
148
127
  const VARIABLE_MAPPING = {
149
128
  '标题': ['title', 'Title', 'TITLE'],
150
129
  '作者': ['author.name', 'author', 'name', 'Author', 'Name', 'owner.name'],
@@ -406,117 +385,55 @@ function findValueInObject(obj, keys) {
406
385
  }
407
386
  return undefined;
408
387
  }
409
- function parseData(rawResponse, maxDescLength, platform) {
410
- let data = rawResponse;
411
- if (platform === 'bilibili' && rawResponse.data) {
412
- data = rawResponse.data;
413
- }
414
- else if (platform === 'douyin' && rawResponse.data) {
415
- data = rawResponse.data;
416
- }
417
- else if (data.data) {
418
- data = data.data;
419
- }
388
+ function parseData(rawResponse, maxDescLength) {
389
+ const data = rawResponse.data || rawResponse;
420
390
  const stat = {};
421
391
  Object.entries(VARIABLE_MAPPING).forEach(([varName, keys]) => {
422
- const value = findValueInObject(data, keys);
423
- if (value !== undefined) {
392
+ let value = undefined;
393
+ value = value || getNestedValue(data, 'title');
394
+ value = value || getNestedValue(data, 'author.name');
395
+ value = value || getNestedValue(data, 'desc');
396
+ value = value || getNestedValue(data, 'duration');
397
+ value = value || getNestedValue(data, 'like');
398
+ value = value || getNestedValue(data, 'coin');
399
+ value = value || getNestedValue(data, 'collect');
400
+ value = value || getNestedValue(data, 'share');
401
+ value = value || getNestedValue(data, 'view');
402
+ value = value || getNestedValue(data, 'comment');
403
+ value = value || getNestedValue(data, 'music.title');
404
+ value = value || findValueInObject(data, keys);
405
+ if (value !== undefined)
424
406
  stat[varName] = value;
425
- }
426
407
  });
427
408
  let type = 'video';
428
- if (platform === 'douyin' && data.jx && data.jx.type) {
409
+ if (data.jx?.type)
429
410
  type = data.jx.type;
430
- }
431
- else if (data.type) {
411
+ else if (data.type)
432
412
  type = data.type;
433
- }
434
413
  let title = '无标题';
435
- if (platform === 'bilibili' && data.video && data.video.title) {
436
- title = data.video.title;
437
- }
438
- else if (platform === 'douyin' && data.item && data.item.title) {
439
- title = data.item.title;
440
- }
441
- else {
442
- title = findValueInObject(data, ['title']) || '无标题';
443
- }
414
+ title = data.video?.title || data.item?.title || data.title || findValueInObject(data, VARIABLE_MAPPING['标题']) || '无标题';
444
415
  let author = '未知作者';
445
- if (platform === 'bilibili' && data.owner && data.owner.name) {
446
- author = data.owner.name;
447
- }
448
- else if (platform === 'douyin' && data.author && data.author.name) {
449
- author = data.author.name;
450
- }
451
- else {
452
- author = findValueInObject(data, ['author.name', 'author', 'name', 'auther']) || '未知作者';
453
- }
416
+ author = data.owner?.name || data.author?.name || findValueInObject(data, VARIABLE_MAPPING['作者']) || '未知作者';
454
417
  let desc = title;
455
- if (platform === 'bilibili' && data.video && data.video.desc) {
456
- desc = data.video.desc;
457
- }
458
- else if (platform === 'douyin') {
459
- desc = title;
460
- }
461
- else {
462
- desc = findValueInObject(data, ['desc', 'description', 'content']) || title;
463
- }
418
+ desc = data.video?.desc || data.desc || data.content || findValueInObject(data, VARIABLE_MAPPING['简介']) || title;
464
419
  desc = desc.toString().slice(0, maxDescLength);
465
420
  let cover = '';
466
- if (platform === 'bilibili' && data.video && data.video.fm) {
467
- cover = data.video.fm;
468
- }
469
- else if (platform === 'douyin' && data.item && data.item.cover) {
470
- cover = data.item.cover;
471
- }
472
- else {
473
- cover = findValueInObject(data, ['cover', 'imgurl', 'pic', 'thumbnail']) || '';
474
- }
421
+ cover = data.video?.fm || data.item?.cover || data.cover || data.imgurl || data.pic || findValueInObject(data, ['cover', 'imgurl', 'pic']) || '';
475
422
  let images = [];
476
- if (platform === 'douyin' && data.item && data.item.images) {
477
- images = data.item.images;
478
- }
479
- else {
480
- images = findValueInObject(data, ['imgurl', 'images', 'pics']) || [];
481
- }
423
+ images = data.item?.images || data.images || data.pics || findValueInObject(data, ['images', 'pics', 'imgurl']) || [];
482
424
  if (!Array.isArray(images))
483
425
  images = [images];
484
426
  let video = '';
485
- if (platform === 'bilibili' && data.video && data.video.url) {
486
- video = data.video.url;
487
- }
488
- else if (platform === 'douyin' && data.item && data.item.url) {
489
- video = data.item.url;
490
- }
491
- else {
492
- const videoUrls = [
493
- findValueInObject(data, ['url']),
494
- findValueInObject(data, ['download_url']),
495
- findValueInObject(data, ['video_backup']),
496
- findValueInObject(data, ['playUrl']),
497
- findValueInObject(data, ['video_url'])
498
- ];
499
- if (Array.isArray(videoUrls[2])) {
500
- video = videoUrls[2][0]?.url || '';
501
- }
502
- else {
503
- for (const url of videoUrls) {
504
- if (url && typeof url === 'string' && url.trim() !== '') {
505
- video = url;
506
- break;
507
- }
508
- }
509
- }
510
- }
511
- const durationValue = findValueInObject(data, ['duration']);
427
+ video = data.video?.url || data.item?.url || data.url || data.download_url || data.playUrl || data.video_url || findValueInObject(data, ['url', 'download_url', 'playUrl', 'video_url']) || '';
428
+ const durationValue = data.duration || findValueInObject(data, VARIABLE_MAPPING['视频时长']);
512
429
  const duration = typeof durationValue === 'number' ? durationValue : parseInt(durationValue) || 0;
513
430
  const durationFormatted = formatDuration(durationValue || 0);
514
431
  const live_photo = data.live_photo || [];
515
- const music = findValueInObject(data, ['music', 'muisic']) || '';
516
- const h_w = platform === 'douyin' && data.item && data.item.h_w ? data.item.h_w : [];
432
+ const music = data.music?.title || data.music || findValueInObject(data, VARIABLE_MAPPING['音乐名']) || '';
433
+ const h_w = data.item?.h_w || [];
517
434
  const quality_urls = data.quality_urls || {};
518
435
  const default_quality = data.default_quality || '';
519
- const download_url = data.download_url || '';
436
+ const download_url = data.download_url || video;
520
437
  const play_count = data.play_count || '';
521
438
  const reposts_count = data.reposts_count || 0;
522
439
  const attitudes_count = data.attitudes_count || 0;
@@ -546,11 +463,8 @@ function parseData(rawResponse, maxDescLength, platform) {
546
463
  comments_count
547
464
  };
548
465
  }
549
- function generateFormattedText(platform, parseData, config) {
466
+ function generateFormattedText(parseData, config) {
550
467
  let format = config.unifiedMessageFormat;
551
- if (platform !== 'bilibili') {
552
- format = format.replace(/投币:\$\{投币数\}\n?/g, '');
553
- }
554
468
  let result = format;
555
469
  const formatLines = result.split('\n');
556
470
  const validLines = [];
@@ -616,7 +530,7 @@ function apply(ctx, config) {
616
530
  clearAllCache();
617
531
  const http = axios_1.default.create({
618
532
  timeout: config.timeout,
619
- headers: { 'User-Agent': config.userAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' }
533
+ headers: { 'User-Agent': config.userAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' }
620
534
  });
621
535
  async function parseWithRetry(url, platform, retryTimes) {
622
536
  let lastError = null;
@@ -657,28 +571,16 @@ function apply(ctx, config) {
657
571
  }
658
572
  try {
659
573
  const resData = await parseWithRetry(realUrl, platform, config.retryTimes);
660
- let isSuccess = false;
661
- if (platform === 'bilibili' || platform === 'douyin') {
662
- isSuccess = resData.code === 0 || (resData.msg && (resData.msg.includes('解析成功') || resData.msg === 'video'));
663
- }
664
- else {
665
- isSuccess = resData.code === 200 || resData.code === 0 ||
666
- (resData.msg && resData.msg.includes('解析成功'));
667
- }
574
+ const isSuccess = resData.code === 0 || resData.code === 200 || (resData.msg && resData.msg.includes('解析成功')) || !!resData.data;
668
575
  if (!isSuccess) {
669
576
  const apiErrorMsg = resData.msg || '解析失败';
670
- const platformCode = PLATFORM_ERROR_CODE_MAP[platform] || ErrorCode.API_RETURN_ERROR;
671
- let detailedMsg = apiErrorMsg;
672
- if (apiErrorMsg.includes('无法识别解析类型') || apiErrorMsg.includes('未找到有效内容')) {
673
- detailedMsg = `链接格式不支持或内容已失效:${apiErrorMsg}`;
674
- }
675
- const code = platformCode;
676
- const msg = getErrorInfo(code, detailedMsg);
677
- logger.error(`[${code}] API返回错误: ${platform}, URL: ${url}, 错误: ${apiErrorMsg}`);
577
+ const code = ErrorCode.API_RETURN_ERROR;
578
+ const msg = getErrorInfo(code, apiErrorMsg);
579
+ logger.error(`[${code}] API返回错误: ${url}, 错误: ${apiErrorMsg}`);
678
580
  return { data: null, code, msg };
679
581
  }
680
582
  try {
681
- const parseResult = parseData(resData, config.maxDescLength, platform);
583
+ const parseResult = parseData(resData, config.maxDescLength);
682
584
  const hasValidContent = parseResult.video ||
683
585
  (parseResult.images && parseResult.images.length > 0) ||
684
586
  (parseResult.live_photo && parseResult.live_photo.length > 0) ||
@@ -686,11 +588,11 @@ function apply(ctx, config) {
686
588
  parseResult.type === '图集';
687
589
  if (!hasValidContent) {
688
590
  const code = ErrorCode.NO_VIDEO_FOUND;
689
- const msg = getErrorInfo(code, '链接有效但未找到视频/图片内容(可能是直播、私密内容或已删除)');
690
- logger.warn(`[${code}] 解析成功但无有效内容: ${platform}, URL: ${url}`);
591
+ const msg = getErrorInfo(code, '链接有效但未找到视频/图片内容');
592
+ logger.warn(`[${code}] 解析成功但无有效内容: ${url}`);
691
593
  return { data: null, code, msg };
692
594
  }
693
- logger.info(`[${ErrorCode.SUCCESS}] ${platform}解析成功: ${url}`);
595
+ logger.info(`[${ErrorCode.SUCCESS}] 解析成功: ${url}`);
694
596
  return {
695
597
  data: parseResult,
696
598
  code: ErrorCode.SUCCESS,
@@ -701,7 +603,7 @@ function apply(ctx, config) {
701
603
  const errorMsg = getErrorMessage(parseError);
702
604
  const code = ErrorCode.API_DATA_PARSE_FAILED;
703
605
  const msg = getErrorInfo(code, errorMsg);
704
- logger.error(`[${code}] 解析数据失败: ${platform}, URL: ${url}, 错误: ${errorMsg}`);
606
+ logger.error(`[${code}] 解析数据失败: ${url}, 错误: ${errorMsg}`);
705
607
  return { data: null, code, msg };
706
608
  }
707
609
  }
@@ -718,7 +620,7 @@ function apply(ctx, config) {
718
620
  code = ErrorCode.NETWORK_ERROR;
719
621
  }
720
622
  const msg = getErrorInfo(code, errorMsg);
721
- logger.error(`[${code}] 解析请求失败: ${platform}, URL: ${url}, 错误: ${errorMsg}`);
623
+ logger.error(`[${code}] 解析请求失败: ${url}, 错误: ${errorMsg}`);
722
624
  return { data: null, code, msg };
723
625
  }
724
626
  }
@@ -735,8 +637,7 @@ function apply(ctx, config) {
735
637
  if (!result.data)
736
638
  return { data: null, code: result.code, msg: result.msg };
737
639
  const parseData = result.data;
738
- const platform = getPlatformType(url);
739
- const text = generateFormattedText(platform, parseData, config);
640
+ const text = generateFormattedText(parseData, config);
740
641
  return {
741
642
  data: {
742
643
  text,
@@ -932,8 +833,7 @@ function apply(ctx, config) {
932
833
  const filename = crypto_1.default.createHash('md5').update(item.video).digest('hex');
933
834
  const downloadResult = await downloadVideo(item.video, filename, config.userAgent, config.maxVideoSize, config.downloadThreads);
934
835
  if (downloadResult.code !== ErrorCode.SUCCESS) {
935
- const errorMsg = getErrorInfo(downloadResult.code);
936
- await sendTimeout(session, koishi_1.h.text(`${errorMsg}\n链接:${item.video}`));
836
+ await sendTimeout(session, koishi_1.h.text(`${getErrorInfo(downloadResult.code)}\n链接:${item.video}`));
937
837
  continue;
938
838
  }
939
839
  else {
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.7",
4
+ "version": "0.5.8",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [