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 +1 -6
- package/lib/index.js +42 -142
- package/package.json +1 -1
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
|
|
410
|
-
|
|
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
|
-
|
|
423
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
486
|
-
|
|
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, ['
|
|
516
|
-
const 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(
|
|
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/
|
|
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
|
-
|
|
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
|
|
671
|
-
|
|
672
|
-
|
|
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
|
|
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}] 解析成功但无有效内容: ${
|
|
591
|
+
const msg = getErrorInfo(code, '链接有效但未找到视频/图片内容');
|
|
592
|
+
logger.warn(`[${code}] 解析成功但无有效内容: ${url}`);
|
|
691
593
|
return { data: null, code, msg };
|
|
692
594
|
}
|
|
693
|
-
logger.info(`[${ErrorCode.SUCCESS}]
|
|
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}] 解析数据失败: ${
|
|
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}] 解析请求失败: ${
|
|
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
|
|
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
|
-
|
|
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