koishi-plugin-video-parser-all 0.6.6 → 0.6.7
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.js +75 -46
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -42,7 +42,8 @@ IP属地:${'${IP属地}'}
|
|
|
42
42
|
直播间ID:${'${直播间ID}'}
|
|
43
43
|
直播间状态:${'${直播间状态}'}
|
|
44
44
|
图片数量:${'${图片数量}'}
|
|
45
|
-
作者ID:${'${作者ID}'}
|
|
45
|
+
作者ID:${'${作者ID}'}
|
|
46
|
+
视频备用链接:${'${视频备用链接}'}`).description('统一消息格式'),
|
|
46
47
|
}).description('统一消息格式'),
|
|
47
48
|
koishi_1.Schema.object({
|
|
48
49
|
showImageText: koishi_1.Schema.boolean().default(true).description('显示图文内容'),
|
|
@@ -145,18 +146,18 @@ const API_CONFIG = {
|
|
|
145
146
|
zuiyou: 'https://api.bugpk.com/api/zuiyou'
|
|
146
147
|
};
|
|
147
148
|
const VARIABLE_MAPPING = {
|
|
148
|
-
'标题': ['title', '
|
|
149
|
-
'作者': ['author
|
|
150
|
-
'简介': ['desc', 'description', '
|
|
151
|
-
'视频时长': ['duration', '
|
|
152
|
-
'点赞数': ['like', '
|
|
153
|
-
'投币数': ['coin', '
|
|
154
|
-
'收藏数': ['collect', '
|
|
155
|
-
'转发数': ['share', '
|
|
156
|
-
'播放数': ['view', '
|
|
157
|
-
'评论数': ['comment', '
|
|
149
|
+
'标题': ['title', 'note_title', 'content_title', 'item.title', 'data.title', 'video.title', 'live.title', 'data.item.title', 'data.live.title'],
|
|
150
|
+
'作者': ['author', 'author.name', 'name', 'nickname', 'user_name', 'owner.name', 'data.author', 'item.author', 'user.name', 'live.author', 'data.user.name', 'data.author.name'],
|
|
151
|
+
'简介': ['desc', 'description', 'content', 'note_desc', 'text', 'data.desc', 'item.description', 'live.desc', 'data.item.description'],
|
|
152
|
+
'视频时长': ['duration', 'time', 'video_duration', 'item.duration', 'stat.duration', 'data.item.duration'],
|
|
153
|
+
'点赞数': ['like', 'attitudes_count', 'digg_count', 'praise', 'stat.like', 'liked_count', 'data.like', 'data.attitudes_count', 'item.attitudes_count', 'data.item.attitudes_count'],
|
|
154
|
+
'投币数': ['coin', 'bi', 'stat.coin', 'stast.coin'],
|
|
155
|
+
'收藏数': ['collect', 'favorite', 'star', 'stat.collect', 'collected_count', 'stast.favorite', 'data.favorite'],
|
|
156
|
+
'转发数': ['share', 'forward', 'repost', 'stat.share', 'reposts_count', 'shared_count', 'stast.share', 'data.reposts_count', 'data.item.reposts_count'],
|
|
157
|
+
'播放数': ['view', 'play_count', 'play', 'stat.view', 'play_times', 'stast.view', 'data.play_count', 'item.play_count', 'data.item.play_count'],
|
|
158
|
+
'评论数': ['comment', 'comments_count', 'comment_count', 'discuss', 'stat.comment', 'stast.reply', 'data.comments_count', 'item.comments_count', 'data.item.comments_count', 'stat.reply'],
|
|
158
159
|
'IP属地': ['ip_info_str', 'data.ip_info_str', 'item.ip_info', 'data.item.ip_info_str'],
|
|
159
|
-
'发布时间': ['date', 'time', 'publish_time', 'data.date', 'item.publish_time', 'live.time', 'stast.publish_time', 'stat.time', 'data.time.publish_time', 'data.live.time'],
|
|
160
|
+
'发布时间': ['date', 'time', 'publish_time', 'data.date', 'item.publish_time', 'live.time', 'stast.publish_time', 'stat.time', 'data.time.publish_time', 'data.live.time', 'stat.ctime'],
|
|
160
161
|
'粉丝数': ['followers_count', 'data.followers_count', 'item.followers', 'author.fans', 'data.item.followers_count'],
|
|
161
162
|
'在线人数': ['online', 'data.online', 'live.online', 'room.online', 'data.live.online'],
|
|
162
163
|
'关注数': ['attention', 'data.attention', 'live.attention', 'stast.attention', 'data.live.attention'],
|
|
@@ -165,7 +166,8 @@ const VARIABLE_MAPPING = {
|
|
|
165
166
|
'直播间ID': ['room_id', 'live.room_id', 'data.room_id', 'live.room_id', 'data.live.room_id'],
|
|
166
167
|
'直播间状态': ['status', 'live.status', 'data.status', 'room.status', 'data.live.status'],
|
|
167
168
|
'图片数量': ['count', 'data.count', 'item.count', 'images.length', 'data.images.length', 'data.item.count'],
|
|
168
|
-
'作者ID': ['userId', 'userID', 'author_id', 'data.userId', 'item.userID', 'author.mid', 'user.mid', 'data.item.userID', 'data.author_id', 'data.user.mid'],
|
|
169
|
+
'作者ID': ['userId', 'userID', 'author_id', 'data.userId', 'item.userID', 'author.mid', 'user.mid', 'data.item.userID', 'data.author_id', 'data.user.mid', 'author.id', 'uid', 'short_id', 'data.author.id'],
|
|
170
|
+
'视频备用链接': ['data.video_backup', 'video_backup']
|
|
169
171
|
};
|
|
170
172
|
function getErrorInfo(code, detail) {
|
|
171
173
|
const baseMsg = exports.ErrorMessageMap[code] || exports.ErrorMessageMap[ErrorCode.UNKNOWN_ERROR];
|
|
@@ -389,15 +391,21 @@ function formatPublishTime(value) {
|
|
|
389
391
|
if (!value)
|
|
390
392
|
return '';
|
|
391
393
|
const str = String(value).trim();
|
|
394
|
+
// 适配B站的 ctime 时间戳字段名(避免直接传入字符串"ctime")
|
|
395
|
+
if (value === 'ctime')
|
|
396
|
+
return '';
|
|
397
|
+
if (/^\d{10}$/.test(str)) {
|
|
398
|
+
value = Number(str) * 1000;
|
|
399
|
+
}
|
|
392
400
|
if (/^\d{10,}$/.test(str) && Number(str) > 1e12) {
|
|
393
401
|
if (Number(str) > 1e15) {
|
|
394
402
|
value = Number(str) / 1000;
|
|
395
403
|
}
|
|
396
404
|
}
|
|
397
405
|
try {
|
|
398
|
-
const d = new Date(/^\d+$/.test(str) ? Number(str)
|
|
406
|
+
const d = new Date(/^\d+$/.test(str) ? Number(str) : str);
|
|
399
407
|
if (isNaN(d.getTime()))
|
|
400
|
-
return
|
|
408
|
+
return str;
|
|
401
409
|
const y = d.getFullYear();
|
|
402
410
|
const m = (d.getMonth() + 1).toString().padStart(2, '0');
|
|
403
411
|
const d_ = d.getDate().toString().padStart(2, '0');
|
|
@@ -455,18 +463,19 @@ function findValueInObject(obj, keys) {
|
|
|
455
463
|
return undefined;
|
|
456
464
|
}
|
|
457
465
|
function parseData(rawResponse, maxDescLength) {
|
|
458
|
-
const
|
|
459
|
-
const data =
|
|
466
|
+
const root = rawResponse || {};
|
|
467
|
+
const data = root.data || root.result || root || {};
|
|
460
468
|
const stat = {};
|
|
461
469
|
Object.entries(VARIABLE_MAPPING).forEach(([varName, keys]) => {
|
|
462
|
-
let value = findValueInObject(data, keys) || findValueInObject(
|
|
470
|
+
let value = findValueInObject(data, keys) || findValueInObject(root, keys);
|
|
463
471
|
if (varName === '图片数量' && value === undefined) {
|
|
464
472
|
value = Array.isArray(data.images) ? data.images.length :
|
|
465
|
-
Array.isArray(
|
|
473
|
+
Array.isArray(root.images) ? root.images.length :
|
|
466
474
|
Array.isArray(data.imgurl) ? data.imgurl.length :
|
|
467
|
-
Array.isArray(
|
|
475
|
+
Array.isArray(root.imgurl) ? root.imgurl.length :
|
|
476
|
+
data.count || root.count || undefined;
|
|
468
477
|
}
|
|
469
|
-
if (value !== undefined && value !== null && value !== '') {
|
|
478
|
+
if (value !== undefined && value !== null && value !== '' && value !== 0) {
|
|
470
479
|
stat[varName] = value;
|
|
471
480
|
}
|
|
472
481
|
});
|
|
@@ -475,28 +484,32 @@ function parseData(rawResponse, maxDescLength) {
|
|
|
475
484
|
type = data.jx.type;
|
|
476
485
|
else if (data.type)
|
|
477
486
|
type = data.type;
|
|
478
|
-
else if (
|
|
487
|
+
else if (root.msg === 'cv')
|
|
479
488
|
type = 'cv';
|
|
480
|
-
else if (
|
|
489
|
+
else if (root.msg === 'live')
|
|
481
490
|
type = 'live';
|
|
482
|
-
else if ((data.images && data.images.length > 1) || (
|
|
483
|
-
(data.imgurl && data.imgurl.length > 1) || (
|
|
491
|
+
else if ((data.images && data.images.length > 1) || (root.images && root.images.length > 1) ||
|
|
492
|
+
(data.imgurl && data.imgurl.length > 1) || (root.imgurl && root.imgurl.length > 1))
|
|
484
493
|
type = '图集';
|
|
485
|
-
const title = stat['标题'] || data.note_title || data.title || data.content_title || data.
|
|
486
|
-
|
|
487
|
-
|
|
494
|
+
const title = stat['标题'] || data.note_title || data.title || data.content_title || data.video?.title ||
|
|
495
|
+
data.item?.title || root.title || data.live?.title || '无标题';
|
|
496
|
+
let author = stat['作者'] || data.author?.name || data.nickname || data.user_name || data.owner?.name ||
|
|
497
|
+
data.item?.author || root.author || data.user?.name || data.live?.author || '未知作者';
|
|
488
498
|
if (typeof author === 'object' && author.name)
|
|
489
499
|
author = author.name;
|
|
490
500
|
const rawDesc = stat['简介'] || data.note_desc || data.content || data.text || data.description ||
|
|
491
|
-
data.item?.description ||
|
|
492
|
-
|
|
493
|
-
const
|
|
494
|
-
|
|
495
|
-
|
|
501
|
+
data.video?.desc || data.item?.description || root.desc || root.description ||
|
|
502
|
+
data.live?.desc || (title !== '无标题' ? title : '') || '暂无简介';
|
|
503
|
+
const desc = rawDesc.length > 0 ? rawDesc.slice(0, maxDescLength) : '暂无简介';
|
|
504
|
+
const cover = data.cover || data.video?.fm || data.imgurl || data.pic || data.thumbnail || data.cover_url ||
|
|
505
|
+
data.item?.cover || root.cover || data.live?.cover || data.live?.keyframe ||
|
|
506
|
+
(Array.isArray(data.images) && data.images[0]) ||
|
|
507
|
+
(Array.isArray(root.images) && root.images[0]) ||
|
|
508
|
+
(Array.isArray(data.imgurl) && data.imgurl[0]) || '';
|
|
496
509
|
let images = [];
|
|
497
510
|
const imgSources = [
|
|
498
511
|
data.images, data.pics, data.pic_urls, data.image_list, data.imgurl,
|
|
499
|
-
|
|
512
|
+
root.images, root.pics, root.pic_urls, root.image_list, root.imgurl,
|
|
500
513
|
data.item?.images
|
|
501
514
|
];
|
|
502
515
|
for (const source of imgSources) {
|
|
@@ -505,8 +518,9 @@ function parseData(rawResponse, maxDescLength) {
|
|
|
505
518
|
break;
|
|
506
519
|
}
|
|
507
520
|
}
|
|
508
|
-
let video = data.video?.url || data.
|
|
509
|
-
data.video_url ||
|
|
521
|
+
let video = data.video?.url || data.url || data.download_url || data.playUrl ||
|
|
522
|
+
data.video_url || root.url || data.item?.url || data.live?.url ||
|
|
523
|
+
(data.live?.url && Array.isArray(data.live.url) ? data.live.url[0] : '') || '';
|
|
510
524
|
const durationValue = stat['视频时长'] || data.item?.duration || data.duration || 0;
|
|
511
525
|
const duration = typeof durationValue === 'number' ? durationValue : parseInt(durationValue) || 0;
|
|
512
526
|
const durationFormatted = formatDuration(durationValue);
|
|
@@ -526,15 +540,29 @@ function parseData(rawResponse, maxDescLength) {
|
|
|
526
540
|
if (!isNaN(num) && num > 0)
|
|
527
541
|
stat['文件大小'] = `${num.toFixed(2)} MB`;
|
|
528
542
|
}
|
|
529
|
-
const live_photo = data.live_photo ||
|
|
530
|
-
const h_w = data.item?.h_w ||
|
|
531
|
-
const quality_urls = data.quality_urls ||
|
|
532
|
-
const default_quality = data.default_quality ||
|
|
543
|
+
const live_photo = data.live_photo || root.live_photo || [];
|
|
544
|
+
const h_w = data.item?.h_w || root.h_w || [];
|
|
545
|
+
const quality_urls = data.quality_urls || root.quality_urls || {};
|
|
546
|
+
const default_quality = data.default_quality || root.default_quality || '';
|
|
533
547
|
const download_url = data.download_url || video;
|
|
534
|
-
const play_count = stat['播放数'] || '';
|
|
535
|
-
const reposts_count = Number(stat['转发数']) || data.reposts_count ||
|
|
536
|
-
const attitudes_count = Number(stat['点赞数']) || data.attitudes_count ||
|
|
537
|
-
const comments_count = Number(stat['评论数']) || data.comments_count ||
|
|
548
|
+
const play_count = stat['播放数'] || data.play_count || root.play_count || '';
|
|
549
|
+
const reposts_count = Number(stat['转发数']) || data.reposts_count || root.reposts_count || 0;
|
|
550
|
+
const attitudes_count = Number(stat['点赞数']) || data.attitudes_count || root.attitudes_count || data.like || root.like || 0;
|
|
551
|
+
const comments_count = Number(stat['评论数']) || data.comments_count || root.comments_count || 0;
|
|
552
|
+
if (data.live) {
|
|
553
|
+
stat['直播间地址'] = data.live.room_url || '';
|
|
554
|
+
stat['直播间ID'] = data.live.room_id || '';
|
|
555
|
+
stat['直播间状态'] = data.live.status === 1 ? '直播中' : (data.live.status === 0 ? '未开播' : data.live.status || '未知');
|
|
556
|
+
stat['在线人数'] = data.live.online || '';
|
|
557
|
+
stat['关注数'] = data.live.attention || '';
|
|
558
|
+
}
|
|
559
|
+
if (data.followers_count)
|
|
560
|
+
stat['粉丝数'] = data.followers_count;
|
|
561
|
+
if (data.ip_info_str)
|
|
562
|
+
stat['IP属地'] = data.ip_info_str;
|
|
563
|
+
// 处理小红书视频备用链接
|
|
564
|
+
if (data.video_backup)
|
|
565
|
+
stat['视频备用链接'] = data.video_backup;
|
|
538
566
|
return {
|
|
539
567
|
type: type,
|
|
540
568
|
rawData: rawResponse,
|
|
@@ -571,7 +599,8 @@ function generateFormattedText(parseData, config) {
|
|
|
571
599
|
收藏:${'${收藏数}'}
|
|
572
600
|
转发:${'${转发数}'}
|
|
573
601
|
播放:${'${播放数}'}
|
|
574
|
-
评论:${'${评论数}'}
|
|
602
|
+
评论:${'${评论数}'}
|
|
603
|
+
视频备用链接:${'${视频备用链接}'}`;
|
|
575
604
|
}
|
|
576
605
|
let result = format;
|
|
577
606
|
const varMatches = result.match(/\$\{([^}]+)\}/g) || [];
|
|
@@ -682,7 +711,7 @@ function apply(ctx, config) {
|
|
|
682
711
|
return { data: null, code, msg };
|
|
683
712
|
}
|
|
684
713
|
const isSuccess = resData.code === 0 || resData.code === 200 || resData.code === 1 ||
|
|
685
|
-
(resData.msg && (resData.msg.includes('解析成功') || resData.msg.includes('success') || resData.msg.includes('请求成功'))) ||
|
|
714
|
+
(resData.msg && (resData.msg.includes('解析成功') || resData.msg.includes('success') || resData.msg.includes('请求成功') || resData.msg === 'video' || resData.msg === 'cv' || resData.msg === 'live')) ||
|
|
686
715
|
!!resData.data || !!resData.result || !!resData.video || !!resData.images || !!resData.imgurl;
|
|
687
716
|
if (!isSuccess) {
|
|
688
717
|
const apiErrorMsg = resData.msg || resData.error || '解析失败';
|
package/package.json
CHANGED