koishi-plugin-video-parser-all 0.7.3 → 0.7.4

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 +75 -49
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -415,16 +415,19 @@ function findValueInObject(obj, keys) {
415
415
  function parseData(rawResponse, maxDescLength) {
416
416
  const root = rawResponse || {};
417
417
  const data = root.data || root.result || root || {};
418
+ // 小红书特殊处理:API返回数据在 root 根节点而非 data 子节点
419
+ const isXiaohongshu = root.note_title || root.note_desc || root.author_name || root.cover;
420
+ const parseRoot = isXiaohongshu ? root : data;
418
421
  const stat = {};
419
422
  let totalImageCount = 0;
420
423
  Object.entries(VARIABLE_MAPPING).forEach(([varName, keys]) => {
421
- let value = findValueInObject(data, keys) || findValueInObject(root, keys);
424
+ let value = findValueInObject(parseRoot, keys) || findValueInObject(root, keys);
422
425
  if (varName === '图片数量' && value === undefined) {
423
426
  let imgCount = 0;
424
427
  const imgSources = [
425
- data.images, data.pics, data.pic_urls, data.image_list, data.imgurl,
428
+ parseRoot.images, parseRoot.pics, parseRoot.pic_urls, parseRoot.image_list, parseRoot.imgurl,
426
429
  root.images, root.pics, root.pic_urls, root.image_list, root.imgurl,
427
- data.item?.images
430
+ parseRoot.item?.images
428
431
  ];
429
432
  for (const source of imgSources) {
430
433
  if (Array.isArray(source) && source.length > 0) {
@@ -433,8 +436,8 @@ function parseData(rawResponse, maxDescLength) {
433
436
  }
434
437
  }
435
438
  totalImageCount = imgCount;
436
- const cover = data.cover || data.video?.fm || data.imgurl || data.pic || data.thumbnail || data.cover_url ||
437
- data.item?.cover || root.cover || data.live?.cover || data.live?.keyframe || '';
439
+ const cover = parseRoot.cover || parseRoot.video?.fm || parseRoot.imgurl || parseRoot.pic || parseRoot.thumbnail || parseRoot.cover_url ||
440
+ parseRoot.item?.cover || root.cover || parseRoot.live?.cover || parseRoot.live?.keyframe || '';
438
441
  if (cover && imgCount > 0) {
439
442
  imgCount = imgSources.find(source => Array.isArray(source))?.filter(i => i && typeof i === 'string' && i !== cover).length || 0;
440
443
  }
@@ -444,42 +447,65 @@ function parseData(rawResponse, maxDescLength) {
444
447
  stat[varName] = value;
445
448
  }
446
449
  });
450
+ // 小红书字段兜底
451
+ if (isXiaohongshu) {
452
+ if (!stat['标题'])
453
+ stat['标题'] = root.note_title || root.title || '';
454
+ if (!stat['作者'])
455
+ stat['作者'] = root.author_name || root.nickname || root.author || '';
456
+ if (!stat['简介'])
457
+ stat['简介'] = root.note_desc || root.desc || root.content || '';
458
+ if (!stat['播放数'])
459
+ stat['播放数'] = root.play_count || root.view_count || '';
460
+ if (!stat['点赞数'])
461
+ stat['点赞数'] = root.like_count || root.attitudes_count || '';
462
+ if (!stat['评论数'])
463
+ stat['评论数'] = root.comment_count || root.comments_count || '';
464
+ if (!stat['收藏数'])
465
+ stat['收藏数'] = root.collect_count || root.favorite_count || '';
466
+ if (!stat['转发数'])
467
+ stat['转发数'] = root.share_count || root.repost_count || '';
468
+ if (!stat['发布时间'])
469
+ stat['发布时间'] = root.create_time || root.publish_time || '';
470
+ if (!stat['IP属地'])
471
+ stat['IP属地'] = root.ip_location || root.ip_info_str || '';
472
+ }
447
473
  let type = 'video';
448
- if (data.jx?.type)
449
- type = data.jx.type;
450
- else if (data.type)
451
- type = data.type;
474
+ if (parseRoot.jx?.type)
475
+ type = parseRoot.jx.type;
476
+ else if (parseRoot.type)
477
+ type = parseRoot.type;
452
478
  else if (root.msg === 'cv')
453
479
  type = 'cv';
454
480
  else if (root.msg === 'live')
455
481
  type = 'live';
456
- else if ((data.images && data.images.length > 1) || (root.images && root.images.length > 1) ||
457
- (data.imgurl && data.imgurl.length > 1) || (root.imgurl && root.imgurl.length > 1))
482
+ else if ((parseRoot.images && parseRoot.images.length > 1) || (root.images && root.images.length > 1) ||
483
+ (parseRoot.imgurl && parseRoot.imgurl.length > 1) || (root.imgurl && root.imgurl.length > 1))
458
484
  type = '图集';
459
- const title = stat['标题'] || data.note_title || data.title || data.content_title || data.video?.title ||
460
- data.item?.title || root.title || data.live?.title || '无标题';
461
- let author = stat['作者'] || data.author?.name || data.nickname || data.user_name || data.owner?.name ||
462
- data.item?.author || root.author || data.user?.name || data.live?.author || '';
485
+ const title = stat['标题'] || parseRoot.note_title || parseRoot.title || parseRoot.content_title || parseRoot.video?.title ||
486
+ parseRoot.item?.title || root.title || parseRoot.live?.title || '无标题';
487
+ let author = stat['作者'] || parseRoot.author?.name || parseRoot.nickname || parseRoot.user_name || parseRoot.owner?.name ||
488
+ parseRoot.item?.author || root.author || parseRoot.user?.name || parseRoot.live?.author || '';
463
489
  if (typeof author === 'object') {
464
490
  author = '';
465
491
  }
466
492
  else {
467
493
  author = author || '未知作者';
468
494
  }
469
- const rawDesc = stat['简介'] || data.note_desc || data.content || data.text || data.description ||
470
- data.video?.desc || data.item?.description || root.desc || root.description ||
471
- data.live?.desc || (title !== '无标题' ? title : '') || '暂无简介';
495
+ const rawDesc = stat['简介'] || parseRoot.note_desc || parseRoot.content || parseRoot.text || parseRoot.description ||
496
+ parseRoot.video?.desc || parseRoot.item?.description || root.desc || root.description ||
497
+ parseRoot.live?.desc || (title !== '无标题' ? title : '') || '暂无简介';
472
498
  const desc = rawDesc.length > 0 ? rawDesc.slice(0, maxDescLength) : '暂无简介';
473
- const cover = data.cover || data.video?.fm || data.imgurl || data.pic || data.thumbnail || data.cover_url ||
474
- data.item?.cover || root.cover || data.live?.cover || data.live?.keyframe ||
475
- (Array.isArray(data.images) && data.images[0]) ||
499
+ const cover = parseRoot.cover || parseRoot.video?.fm || parseRoot.imgurl || parseRoot.pic || parseRoot.thumbnail || parseRoot.cover_url ||
500
+ parseRoot.item?.cover || root.cover || parseRoot.live?.cover || parseRoot.live?.keyframe ||
501
+ (Array.isArray(parseRoot.images) && parseRoot.images[0]) ||
476
502
  (Array.isArray(root.images) && root.images[0]) ||
477
- (Array.isArray(data.imgurl) && data.imgurl[0]) || '';
503
+ (Array.isArray(parseRoot.imgurl) && parseRoot.imgurl[0]) || '';
478
504
  let images = [];
479
505
  const imgSources = [
480
- data.images, data.pics, data.pic_urls, data.image_list, data.imgurl,
506
+ parseRoot.images, parseRoot.pics, parseRoot.pic_urls, parseRoot.image_list, parseRoot.imgurl,
481
507
  root.images, root.pics, root.pic_urls, root.image_list, root.imgurl,
482
- data.item?.images
508
+ parseRoot.item?.images
483
509
  ];
484
510
  for (const source of imgSources) {
485
511
  if (Array.isArray(source) && source.length > 0) {
@@ -487,10 +513,10 @@ function parseData(rawResponse, maxDescLength) {
487
513
  break;
488
514
  }
489
515
  }
490
- let video = data.video?.url || data.url || data.download_url || data.playUrl ||
491
- data.video_url || root.url || data.item?.url || data.live?.url ||
492
- (data.live?.url && Array.isArray(data.live.url) ? data.live.url[0] : '') || '';
493
- const durationValue = stat['视频时长'] || data.item?.duration || data.duration || 0;
516
+ let video = parseRoot.video?.url || parseRoot.url || parseRoot.download_url || parseRoot.playUrl ||
517
+ parseRoot.video_url || root.url || parseRoot.item?.url || parseRoot.live?.url ||
518
+ (parseRoot.live?.url && Array.isArray(parseRoot.live.url) ? parseRoot.live.url[0] : '') || '';
519
+ const durationValue = stat['视频时长'] || parseRoot.item?.duration || parseRoot.duration || 0;
494
520
  const duration = typeof durationValue === 'number' ? durationValue : parseInt(durationValue) || 0;
495
521
  const durationFormatted = formatDuration(durationValue);
496
522
  const pubTime = formatPublishTime(stat['发布时间']);
@@ -513,26 +539,26 @@ function parseData(rawResponse, maxDescLength) {
513
539
  if (!isNaN(num) && num > 0)
514
540
  stat['文件大小'] = `${num.toFixed(2)} MB`;
515
541
  }
516
- const live_photo = data.live_photo || root.live_photo || [];
517
- const h_w = data.item?.h_w || root.h_w || [];
518
- const quality_urls = data.quality_urls || root.quality_urls || {};
519
- const default_quality = data.default_quality || root.default_quality || '';
520
- const download_url = data.download_url || video;
521
- const play_count = stat['播放数'] || data.play_count || root.play_count || '';
522
- const reposts_count = Number(stat['转发数']) || data.reposts_count || root.reposts_count || 0;
523
- const attitudes_count = Number(stat['点赞数']) || data.attitudes_count || root.attitudes_count || data.like || root.like || 0;
524
- const comments_count = Number(stat['评论数']) || data.comments_count || root.comments_count || 0;
525
- if (data.live) {
526
- stat['直播间地址'] = data.live.room_url || '';
527
- stat['直播间ID'] = data.live.room_id || '';
528
- stat['直播间状态'] = data.live.status === 1 ? '直播中' : (data.live.status === 0 ? '未开播' : data.live.status || '未知');
529
- stat['在线人数'] = data.live.online || '';
530
- stat['关注数'] = data.live.attention || '';
531
- }
532
- if (data.followers_count)
533
- stat['粉丝数'] = data.followers_count;
534
- if (data.ip_info_str)
535
- stat['IP属地'] = data.ip_info_str;
542
+ const live_photo = parseRoot.live_photo || root.live_photo || [];
543
+ const h_w = parseRoot.item?.h_w || root.h_w || [];
544
+ const quality_urls = parseRoot.quality_urls || root.quality_urls || {};
545
+ const default_quality = parseRoot.default_quality || root.default_quality || '';
546
+ const download_url = parseRoot.download_url || video;
547
+ const play_count = stat['播放数'] || parseRoot.play_count || root.play_count || '';
548
+ const reposts_count = Number(stat['转发数']) || parseRoot.reposts_count || root.reposts_count || 0;
549
+ const attitudes_count = Number(stat['点赞数']) || parseRoot.attitudes_count || root.attitudes_count || parseRoot.like || root.like || 0;
550
+ const comments_count = Number(stat['评论数']) || parseRoot.comments_count || root.comments_count || 0;
551
+ if (parseRoot.live) {
552
+ stat['直播间地址'] = parseRoot.live.room_url || '';
553
+ stat['直播间ID'] = parseRoot.live.room_id || '';
554
+ stat['直播间状态'] = parseRoot.live.status === 1 ? '直播中' : (parseRoot.live.status === 0 ? '未开播' : parseRoot.live.status || '未知');
555
+ stat['在线人数'] = parseRoot.live.online || '';
556
+ stat['关注数'] = parseRoot.live.attention || '';
557
+ }
558
+ if (parseRoot.followers_count)
559
+ stat['粉丝数'] = parseRoot.followers_count;
560
+ if (parseRoot.ip_info_str)
561
+ stat['IP属地'] = parseRoot.ip_info_str;
536
562
  return {
537
563
  type: type,
538
564
  rawData: rawResponse,
@@ -548,7 +574,7 @@ function parseData(rawResponse, maxDescLength) {
548
574
  totalImageCount,
549
575
  live_photo,
550
576
  h_w,
551
- jx: data.jx || null,
577
+ jx: parseRoot.jx || null,
552
578
  quality_urls,
553
579
  default_quality,
554
580
  download_url,
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.7.3",
4
+ "version": "0.7.4",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [