koishi-plugin-video-parser-all 0.4.0 → 0.4.2
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 +2 -0
- package/lib/index.js +463 -142
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare const Config: Schema<{
|
|
|
8
8
|
sameLinkInterval?: number | null | undefined;
|
|
9
9
|
maxVideoSize?: number | null | undefined;
|
|
10
10
|
downloadThreads?: number | null | undefined;
|
|
11
|
+
debug?: boolean | null | undefined;
|
|
11
12
|
} & Dict & {
|
|
12
13
|
platformEnable?: ({
|
|
13
14
|
bilibili?: boolean | null | undefined;
|
|
@@ -64,6 +65,7 @@ export declare const Config: Schema<{
|
|
|
64
65
|
sameLinkInterval: number;
|
|
65
66
|
maxVideoSize: number;
|
|
66
67
|
downloadThreads: number;
|
|
68
|
+
debug: boolean;
|
|
67
69
|
} & Dict & {
|
|
68
70
|
platformEnable: Schemastery.ObjectT<{
|
|
69
71
|
bilibili: Schema<boolean, boolean>;
|
package/lib/index.js
CHANGED
|
@@ -15,72 +15,79 @@ const worker_threads_1 = require("worker_threads");
|
|
|
15
15
|
exports.name = 'video-parser-all';
|
|
16
16
|
exports.Config = koishi_1.Schema.intersect([
|
|
17
17
|
koishi_1.Schema.object({
|
|
18
|
-
enable: koishi_1.Schema.boolean().default(true),
|
|
19
|
-
botName: koishi_1.Schema.string().default('视频解析机器人'),
|
|
20
|
-
showWaitingTip: koishi_1.Schema.boolean().default(true),
|
|
21
|
-
waitingTipText: koishi_1.Schema.string().default('正在解析视频,请稍候...'),
|
|
22
|
-
sameLinkInterval: koishi_1.Schema.number().min(0).default(180),
|
|
23
|
-
maxVideoSize: koishi_1.Schema.number().min(0).default(50),
|
|
24
|
-
downloadThreads: koishi_1.Schema.number().min(0).default(4),
|
|
25
|
-
|
|
18
|
+
enable: koishi_1.Schema.boolean().default(true).description('是否启用视频解析插件'),
|
|
19
|
+
botName: koishi_1.Schema.string().default('视频解析机器人').description('机器人显示名称'),
|
|
20
|
+
showWaitingTip: koishi_1.Schema.boolean().default(true).description('解析时显示等待提示'),
|
|
21
|
+
waitingTipText: koishi_1.Schema.string().default('正在解析视频,请稍候...').description('等待提示文本内容'),
|
|
22
|
+
sameLinkInterval: koishi_1.Schema.number().min(0).default(180).description('相同链接重复解析间隔(秒)'),
|
|
23
|
+
maxVideoSize: koishi_1.Schema.number().min(0).default(50).description('允许发送的最大视频大小(MB)'),
|
|
24
|
+
downloadThreads: koishi_1.Schema.number().min(0).default(4).description('视频下载线程数'),
|
|
25
|
+
debug: koishi_1.Schema.boolean().default(false).description('调试模式,输出详细日志'),
|
|
26
|
+
}).description('基础设置'),
|
|
26
27
|
koishi_1.Schema.object({
|
|
27
28
|
platformEnable: koishi_1.Schema.object({
|
|
28
|
-
bilibili: koishi_1.Schema.boolean().default(true),
|
|
29
|
-
douyin: koishi_1.Schema.boolean().default(true),
|
|
30
|
-
kuaishou: koishi_1.Schema.boolean().default(true),
|
|
31
|
-
xigua: koishi_1.Schema.boolean().default(true),
|
|
32
|
-
xiaohongshu: koishi_1.Schema.boolean().default(true),
|
|
33
|
-
weibo: koishi_1.Schema.boolean().default(true),
|
|
34
|
-
toutiao: koishi_1.Schema.boolean().default(true),
|
|
35
|
-
pipigx: koishi_1.Schema.boolean().default(true),
|
|
36
|
-
pipixia: koishi_1.Schema.boolean().default(true),
|
|
37
|
-
zuiyou: koishi_1.Schema.boolean().default(true),
|
|
38
|
-
})
|
|
39
|
-
}),
|
|
29
|
+
bilibili: koishi_1.Schema.boolean().default(true).description('B站'),
|
|
30
|
+
douyin: koishi_1.Schema.boolean().default(true).description('抖音'),
|
|
31
|
+
kuaishou: koishi_1.Schema.boolean().default(true).description('快手'),
|
|
32
|
+
xigua: koishi_1.Schema.boolean().default(true).description('西瓜视频'),
|
|
33
|
+
xiaohongshu: koishi_1.Schema.boolean().default(true).description('小红书'),
|
|
34
|
+
weibo: koishi_1.Schema.boolean().default(true).description('微博'),
|
|
35
|
+
toutiao: koishi_1.Schema.boolean().default(true).description('今日头条'),
|
|
36
|
+
pipigx: koishi_1.Schema.boolean().default(true).description('皮皮搞笑'),
|
|
37
|
+
pipixia: koishi_1.Schema.boolean().default(true).description('皮皮虾'),
|
|
38
|
+
zuiyou: koishi_1.Schema.boolean().default(true).description('最右'),
|
|
39
|
+
}).description('启用平台(勾选即开启对应平台解析)')
|
|
40
|
+
}).description('平台开关'),
|
|
40
41
|
koishi_1.Schema.object({
|
|
41
42
|
platformFormat: koishi_1.Schema.object({
|
|
42
|
-
bilibili: koishi_1.Schema.string().role('textarea').default('标题:${标题}\nUP主:${作者}\n简介:${简介}\n时长:${视频时长}\n点赞:${点赞数}\n投币:${投币数}\n收藏:${收藏数}\n转发:${转发数}'),
|
|
43
|
-
douyin: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n点赞:${点赞数}\n收藏:${收藏数}\n转发:${转发数}'),
|
|
44
|
-
kuaishou: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n点赞:${点赞数}\n播放:${播放数}\n转发:${转发数}'),
|
|
45
|
-
xigua: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n播放:${播放数}\n点赞:${点赞数}\n视频大小:${视频大小}MB'),
|
|
46
|
-
xiaohongshu: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
47
|
-
weibo: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
48
|
-
toutiao: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
49
|
-
pipigx: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
50
|
-
pipixia: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
51
|
-
zuiyou: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
52
|
-
})
|
|
53
|
-
}),
|
|
43
|
+
bilibili: koishi_1.Schema.string().role('textarea').default('标题:${标题}\nUP主:${作者}\n简介:${简介}\n时长:${视频时长}\n点赞:${点赞数}\n投币:${投币数}\n收藏:${收藏数}\n转发:${转发数}').description('B站消息格式'),
|
|
44
|
+
douyin: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n点赞:${点赞数}\n收藏:${收藏数}\n转发:${转发数}').description('抖音消息格式'),
|
|
45
|
+
kuaishou: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n点赞:${点赞数}\n播放:${播放数}\n转发:${转发数}').description('快手消息格式'),
|
|
46
|
+
xigua: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n播放:${播放数}\n点赞:${点赞数}\n视频大小:${视频大小}MB').description('西瓜视频消息格式'),
|
|
47
|
+
xiaohongshu: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}').description('小红书消息格式'),
|
|
48
|
+
weibo: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}').description('微博消息格式'),
|
|
49
|
+
toutiao: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}').description('今日头条消息格式'),
|
|
50
|
+
pipigx: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}').description('皮皮搞笑消息格式'),
|
|
51
|
+
pipixia: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}').description('皮皮虾消息格式'),
|
|
52
|
+
zuiyou: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}').description('最右消息格式'),
|
|
53
|
+
}).description('各平台消息输出格式(支持${变量}占位符)')
|
|
54
|
+
}).description('消息格式'),
|
|
54
55
|
koishi_1.Schema.object({
|
|
55
|
-
showImageText: koishi_1.Schema.boolean().default(true),
|
|
56
|
-
showVideoUrl: koishi_1.Schema.boolean().default(false),
|
|
57
|
-
showVideoFile: koishi_1.Schema.boolean().default(true),
|
|
58
|
-
}),
|
|
56
|
+
showImageText: koishi_1.Schema.boolean().default(true).description('显示图文内容'),
|
|
57
|
+
showVideoUrl: koishi_1.Schema.boolean().default(false).description('显示视频无水印链接'),
|
|
58
|
+
showVideoFile: koishi_1.Schema.boolean().default(true).description('发送视频文件(关闭则只发链接)'),
|
|
59
|
+
}).description('内容显示设置'),
|
|
59
60
|
koishi_1.Schema.object({
|
|
60
|
-
maxDescLength: koishi_1.Schema.number().default(200),
|
|
61
|
-
}),
|
|
61
|
+
maxDescLength: koishi_1.Schema.number().default(200).description('简介内容最大长度(字符)'),
|
|
62
|
+
}).description('内容长度限制'),
|
|
62
63
|
koishi_1.Schema.object({
|
|
63
|
-
timeout: koishi_1.Schema.number().min(0).default(180000),
|
|
64
|
-
videoSendTimeout: koishi_1.Schema.number().min(0).default(0),
|
|
65
|
-
userAgent: koishi_1.Schema.string().default('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'),
|
|
66
|
-
bilibiliAccessKey: koishi_1.Schema.string().default(''),
|
|
67
|
-
}),
|
|
64
|
+
timeout: koishi_1.Schema.number().min(0).default(180000).description('API请求超时时间(毫秒)'),
|
|
65
|
+
videoSendTimeout: koishi_1.Schema.number().min(0).default(0).description('视频发送超时时间(毫秒,0为不限制)'),
|
|
66
|
+
userAgent: koishi_1.Schema.string().default('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36').description('请求UA标识'),
|
|
67
|
+
bilibiliAccessKey: koishi_1.Schema.string().default('').description('B站AccessKey(可选,用于高级解析)'),
|
|
68
|
+
}).description('网络与API设置'),
|
|
68
69
|
koishi_1.Schema.object({
|
|
69
|
-
ignoreSendError: koishi_1.Schema.boolean().default(true),
|
|
70
|
-
retryTimes: koishi_1.Schema.number().min(0).default(0),
|
|
71
|
-
retryInterval: koishi_1.Schema.number().min(0).default(0),
|
|
72
|
-
}),
|
|
70
|
+
ignoreSendError: koishi_1.Schema.boolean().default(true).description('忽略发送失败错误'),
|
|
71
|
+
retryTimes: koishi_1.Schema.number().min(0).default(0).description('API请求重试次数'),
|
|
72
|
+
retryInterval: koishi_1.Schema.number().min(0).default(0).description('重试间隔时间(毫秒)'),
|
|
73
|
+
}).description('错误与重试设置'),
|
|
73
74
|
koishi_1.Schema.object({
|
|
74
|
-
enableForward: koishi_1.Schema.boolean().default(false),
|
|
75
|
-
downloadVideoBeforeSend: koishi_1.Schema.boolean().default(false),
|
|
76
|
-
}),
|
|
75
|
+
enableForward: koishi_1.Schema.boolean().default(false).description('启用合并转发(仅OneBot平台)'),
|
|
76
|
+
downloadVideoBeforeSend: koishi_1.Schema.boolean().default(false).description('发送前先下载视频(避免链接失效)'),
|
|
77
|
+
}).description('发送方式设置'),
|
|
77
78
|
koishi_1.Schema.object({
|
|
78
|
-
messageBufferDelay: koishi_1.Schema.number().min(0).default(0),
|
|
79
|
-
}),
|
|
79
|
+
messageBufferDelay: koishi_1.Schema.number().min(0).default(0).description('消息缓冲延迟(毫秒,批量处理链接)'),
|
|
80
|
+
}).description('消息处理设置'),
|
|
80
81
|
koishi_1.Schema.object({
|
|
81
|
-
autoClearCacheInterval: koishi_1.Schema.number().min(0).default(0),
|
|
82
|
-
}),
|
|
82
|
+
autoClearCacheInterval: koishi_1.Schema.number().min(0).default(0).description('自动清理缓存间隔(分钟,0为关闭)'),
|
|
83
|
+
}).description('缓存清理设置'),
|
|
83
84
|
]);
|
|
85
|
+
// 辅助函数:安全获取错误消息
|
|
86
|
+
function getErrorMessage(error) {
|
|
87
|
+
if (error instanceof Error)
|
|
88
|
+
return error.message;
|
|
89
|
+
return String(error);
|
|
90
|
+
}
|
|
84
91
|
if (!worker_threads_1.isMainThread) {
|
|
85
92
|
const workerDataTyped = worker_threads_1.workerData;
|
|
86
93
|
const { url, filePath, maxSize } = workerDataTyped;
|
|
@@ -596,6 +603,9 @@ function apply(ctx, config) {
|
|
|
596
603
|
const realUrl = await resolveShortUrl(url);
|
|
597
604
|
const platform = getPlatformType(realUrl);
|
|
598
605
|
if (!platform || !config.platformEnable[platform]) {
|
|
606
|
+
if (!config.debug) {
|
|
607
|
+
ctx.logger.error(`不支持该平台或未启用: ${platform || '未知'}, URL: ${url}`);
|
|
608
|
+
}
|
|
599
609
|
return { data: null, msg: platform ? '该平台解析已关闭' : '不支持该平台链接' };
|
|
600
610
|
}
|
|
601
611
|
if (platform === 'bilibili') {
|
|
@@ -609,193 +619,444 @@ function apply(ctx, config) {
|
|
|
609
619
|
params.ep_id = bangumiIds.ep_id;
|
|
610
620
|
if (config.bilibiliAccessKey)
|
|
611
621
|
params.access_key = config.bilibiliAccessKey;
|
|
622
|
+
if (config.debug)
|
|
623
|
+
ctx.logger.debug(`请求B站番剧API: ${API_CONFIG.xingzhige.bilibili.bangumiUrl}, 参数: ${JSON.stringify(params)}`);
|
|
612
624
|
const res = await http({
|
|
613
625
|
method: 'GET',
|
|
614
626
|
url: API_CONFIG.xingzhige.bilibili.bangumiUrl,
|
|
615
627
|
params
|
|
616
628
|
});
|
|
629
|
+
if (config.debug)
|
|
630
|
+
ctx.logger.debug(`B站番剧API响应状态: ${res.status}`);
|
|
617
631
|
if (res.data && (res.data.season || res.data.bangumi)) {
|
|
618
632
|
const xgData = parse_xingzhige_data(res.data, 'bilibili_bangumi');
|
|
619
633
|
const parseResult = parseData(xgData, config.maxDescLength, 'bilibili_bangumi');
|
|
634
|
+
if (config.debug)
|
|
635
|
+
ctx.logger.debug('B站番剧解析成功');
|
|
620
636
|
return { data: parseResult, msg: 'B站解析成功' };
|
|
621
637
|
}
|
|
638
|
+
else {
|
|
639
|
+
if (config.debug)
|
|
640
|
+
ctx.logger.debug('B站番剧API返回数据无效');
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
catch (error) {
|
|
644
|
+
if (config.debug) {
|
|
645
|
+
ctx.logger.debug(`B站番剧API请求失败: ${getErrorMessage(error)}`);
|
|
646
|
+
}
|
|
647
|
+
else {
|
|
648
|
+
ctx.logger.error(`B站番剧解析失败: ${getErrorMessage(error)}`);
|
|
649
|
+
}
|
|
622
650
|
}
|
|
623
|
-
catch (error) { }
|
|
624
651
|
}
|
|
625
652
|
try {
|
|
653
|
+
const apiUrl = API_CONFIG.xingzhige.bilibili.vidUrl;
|
|
654
|
+
const params = (() => {
|
|
655
|
+
const biliId = realUrl.startsWith('BV') || realUrl.startsWith('av') || realUrl.startsWith('AV') ? realUrl : extract_bilibili_id(realUrl);
|
|
656
|
+
if (!biliId)
|
|
657
|
+
return { url: realUrl };
|
|
658
|
+
const vid = vid_type_parse(biliId);
|
|
659
|
+
return vid.type === 'bv' ? { bvid: vid.id } : { aid: vid.id };
|
|
660
|
+
})();
|
|
661
|
+
if (config.debug)
|
|
662
|
+
ctx.logger.debug(`请求B站VID API: ${apiUrl}, 参数: ${JSON.stringify(params)}`);
|
|
626
663
|
const res = await http({
|
|
627
664
|
method: 'GET',
|
|
628
|
-
url:
|
|
629
|
-
params
|
|
630
|
-
const biliId = realUrl.startsWith('BV') || realUrl.startsWith('av') || realUrl.startsWith('AV') ? realUrl : extract_bilibili_id(realUrl);
|
|
631
|
-
if (!biliId)
|
|
632
|
-
return { url: realUrl };
|
|
633
|
-
const vid = vid_type_parse(biliId);
|
|
634
|
-
return vid.type === 'bv' ? { bvid: vid.id } : { aid: vid.id };
|
|
635
|
-
})()
|
|
665
|
+
url: apiUrl,
|
|
666
|
+
params
|
|
636
667
|
});
|
|
668
|
+
if (config.debug)
|
|
669
|
+
ctx.logger.debug(`B站VID API响应状态: ${res.status}`);
|
|
637
670
|
if (res.data && (res.data.url || res.data.title)) {
|
|
638
671
|
const xgData = parse_xingzhige_data(res.data, platform);
|
|
639
672
|
const parseResult = parseData(xgData, config.maxDescLength, platform);
|
|
673
|
+
if (config.debug)
|
|
674
|
+
ctx.logger.debug('B站VID解析成功');
|
|
675
|
+
return { data: parseResult, msg: 'B站解析成功' };
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
if (config.debug)
|
|
679
|
+
ctx.logger.debug('B站VID API返回数据无效');
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
catch (error) {
|
|
683
|
+
if (config.debug) {
|
|
684
|
+
ctx.logger.debug(`B站VID API请求失败: ${getErrorMessage(error)}`);
|
|
685
|
+
}
|
|
686
|
+
else {
|
|
687
|
+
ctx.logger.error(`B站VID解析失败: ${getErrorMessage(error)}`);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
try {
|
|
691
|
+
const universalUrl = API_CONFIG.universal;
|
|
692
|
+
if (config.debug)
|
|
693
|
+
ctx.logger.debug(`请求通用API: ${universalUrl}, 参数: { url: ${realUrl} }`);
|
|
694
|
+
const res = await http.get(universalUrl, { params: { url: realUrl } });
|
|
695
|
+
if (config.debug)
|
|
696
|
+
ctx.logger.debug(`通用API响应状态: ${res.status}`);
|
|
697
|
+
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
698
|
+
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
699
|
+
if (config.debug)
|
|
700
|
+
ctx.logger.debug('通用API解析成功');
|
|
640
701
|
return { data: parseResult, msg: 'B站解析成功' };
|
|
641
702
|
}
|
|
703
|
+
else {
|
|
704
|
+
if (config.debug)
|
|
705
|
+
ctx.logger.debug('通用API返回数据无效');
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
catch (error) {
|
|
709
|
+
if (config.debug) {
|
|
710
|
+
ctx.logger.debug(`通用API请求失败: ${getErrorMessage(error)}`);
|
|
711
|
+
}
|
|
712
|
+
else {
|
|
713
|
+
ctx.logger.error(`通用API解析失败: ${getErrorMessage(error)}`);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
try {
|
|
717
|
+
const biliId = realUrl.startsWith('BV') || realUrl.startsWith('av') || realUrl.startsWith('AV') ? realUrl : extract_bilibili_id(realUrl);
|
|
718
|
+
if (biliId) {
|
|
719
|
+
if (config.debug)
|
|
720
|
+
ctx.logger.debug(`请求B站官方API: 获取信息 ${biliId}`);
|
|
721
|
+
const officialInfo = await fetch_bilibili_official_info(biliId, config.userAgent);
|
|
722
|
+
if (officialInfo && officialInfo.code === 0 && officialInfo.data) {
|
|
723
|
+
const { bvid, cid } = officialInfo.data;
|
|
724
|
+
if (config.debug)
|
|
725
|
+
ctx.logger.debug(`请求B站官方播放地址: bvid=${bvid}, cid=${cid}`);
|
|
726
|
+
const playInfo = await get_bilibili_play_url(bvid, cid, config.userAgent);
|
|
727
|
+
if (playInfo) {
|
|
728
|
+
const parseResult = parseData({
|
|
729
|
+
...officialInfo,
|
|
730
|
+
playUrl: playInfo.url,
|
|
731
|
+
duration: playInfo.duration
|
|
732
|
+
}, config.maxDescLength, platform);
|
|
733
|
+
if (config.debug)
|
|
734
|
+
ctx.logger.debug('B站官方API解析成功');
|
|
735
|
+
return { data: parseResult, msg: 'B站解析成功' };
|
|
736
|
+
}
|
|
737
|
+
else {
|
|
738
|
+
if (config.debug)
|
|
739
|
+
ctx.logger.debug('B站官方播放地址获取失败');
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
else {
|
|
743
|
+
if (config.debug)
|
|
744
|
+
ctx.logger.debug('B站官方信息获取失败');
|
|
745
|
+
}
|
|
746
|
+
}
|
|
642
747
|
}
|
|
643
748
|
catch (error) {
|
|
749
|
+
if (config.debug) {
|
|
750
|
+
ctx.logger.debug(`B站官方API请求失败: ${getErrorMessage(error)}`);
|
|
751
|
+
}
|
|
752
|
+
else {
|
|
753
|
+
ctx.logger.error(`B站官方API解析失败: ${getErrorMessage(error)}`);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
const platformApis = API_CONFIG.platform.bilibili || [];
|
|
757
|
+
for (const apiUrl of platformApis) {
|
|
644
758
|
try {
|
|
645
|
-
|
|
646
|
-
|
|
759
|
+
if (config.debug)
|
|
760
|
+
ctx.logger.debug(`请求B站平台API: ${apiUrl}, 参数: { url: ${realUrl} }`);
|
|
761
|
+
const res = await http.get(apiUrl, { params: { url: realUrl } });
|
|
762
|
+
if (config.debug)
|
|
763
|
+
ctx.logger.debug(`B站平台API响应状态: ${res.status}`);
|
|
764
|
+
if ((res.data.code === 0 || res.data.code === 200) && res.data.data) {
|
|
647
765
|
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
766
|
+
if (config.debug)
|
|
767
|
+
ctx.logger.debug('B站平台API解析成功');
|
|
648
768
|
return { data: parseResult, msg: 'B站解析成功' };
|
|
649
769
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
const biliId = realUrl.startsWith('BV') || realUrl.startsWith('av') || realUrl.startsWith('AV') ? realUrl : extract_bilibili_id(realUrl);
|
|
654
|
-
if (biliId) {
|
|
655
|
-
const officialInfo = await fetch_bilibili_official_info(biliId, config.userAgent);
|
|
656
|
-
if (officialInfo && officialInfo.code === 0 && officialInfo.data) {
|
|
657
|
-
const { bvid, cid } = officialInfo.data;
|
|
658
|
-
const playInfo = await get_bilibili_play_url(bvid, cid, config.userAgent);
|
|
659
|
-
if (playInfo) {
|
|
660
|
-
const parseResult = parseData({
|
|
661
|
-
...officialInfo,
|
|
662
|
-
playUrl: playInfo.url,
|
|
663
|
-
duration: playInfo.duration
|
|
664
|
-
}, config.maxDescLength, platform);
|
|
665
|
-
return { data: parseResult, msg: 'B站解析成功' };
|
|
666
|
-
}
|
|
667
|
-
}
|
|
770
|
+
else {
|
|
771
|
+
if (config.debug)
|
|
772
|
+
ctx.logger.debug('B站平台API返回数据无效');
|
|
668
773
|
}
|
|
669
774
|
}
|
|
670
|
-
catch (
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
try {
|
|
674
|
-
const res = await http.get(apiUrl, { params: { url: realUrl } });
|
|
675
|
-
if ((res.data.code === 0 || res.data.code === 200) && res.data.data) {
|
|
676
|
-
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
677
|
-
return { data: parseResult, msg: 'B站解析成功' };
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
catch (error) {
|
|
681
|
-
continue;
|
|
775
|
+
catch (error) {
|
|
776
|
+
if (config.debug) {
|
|
777
|
+
ctx.logger.debug(`B站平台API请求失败: ${apiUrl}, 错误: ${getErrorMessage(error)}`);
|
|
682
778
|
}
|
|
683
779
|
}
|
|
684
780
|
}
|
|
781
|
+
if (config.debug) {
|
|
782
|
+
ctx.logger.debug(`所有B站API尝试失败, URL: ${realUrl}`);
|
|
783
|
+
}
|
|
784
|
+
else {
|
|
785
|
+
ctx.logger.error(`B站解析失败: ${realUrl}`);
|
|
786
|
+
}
|
|
685
787
|
return { data: null, msg: 'B站解析失败' };
|
|
686
788
|
}
|
|
687
789
|
if (platform === 'kuaishou') {
|
|
688
790
|
try {
|
|
791
|
+
const apiUrl = API_CONFIG.xingzhige.kuaishou.url;
|
|
792
|
+
if (config.debug)
|
|
793
|
+
ctx.logger.debug(`请求快手xingzhige API: ${apiUrl}, 参数: { url: ${realUrl} }`);
|
|
689
794
|
const res = await http({
|
|
690
795
|
method: 'GET',
|
|
691
|
-
url:
|
|
796
|
+
url: apiUrl,
|
|
692
797
|
params: { url: realUrl }
|
|
693
798
|
});
|
|
799
|
+
if (config.debug)
|
|
800
|
+
ctx.logger.debug(`快手xingzhige API响应状态: ${res.status}`);
|
|
694
801
|
if (res.data && res.data.jx && res.data.jx.length > 0) {
|
|
695
802
|
const xgData = parse_xingzhige_data(res.data, platform);
|
|
696
803
|
const parseResult = parseData(xgData, config.maxDescLength, platform);
|
|
804
|
+
if (config.debug)
|
|
805
|
+
ctx.logger.debug('快手xingzhige解析成功');
|
|
697
806
|
return { data: parseResult, msg: '快手解析成功' };
|
|
698
807
|
}
|
|
808
|
+
else {
|
|
809
|
+
if (config.debug)
|
|
810
|
+
ctx.logger.debug('快手xingzhige API返回数据无效');
|
|
811
|
+
}
|
|
699
812
|
}
|
|
700
813
|
catch (error) {
|
|
814
|
+
if (config.debug) {
|
|
815
|
+
ctx.logger.debug(`快手xingzhige API请求失败: ${getErrorMessage(error)}`);
|
|
816
|
+
}
|
|
817
|
+
else {
|
|
818
|
+
ctx.logger.error(`快手xingzhige解析失败: ${getErrorMessage(error)}`);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
try {
|
|
822
|
+
const universalUrl = API_CONFIG.universal;
|
|
823
|
+
if (config.debug)
|
|
824
|
+
ctx.logger.debug(`请求通用API: ${universalUrl}, 参数: { url: ${realUrl} }`);
|
|
825
|
+
const res = await http.get(universalUrl, { params: { url: realUrl } });
|
|
826
|
+
if (config.debug)
|
|
827
|
+
ctx.logger.debug(`通用API响应状态: ${res.status}`);
|
|
828
|
+
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
829
|
+
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
830
|
+
if (config.debug)
|
|
831
|
+
ctx.logger.debug('通用API解析成功');
|
|
832
|
+
return { data: parseResult, msg: '快手解析成功' };
|
|
833
|
+
}
|
|
834
|
+
else {
|
|
835
|
+
if (config.debug)
|
|
836
|
+
ctx.logger.debug('通用API返回数据无效');
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
catch (error) {
|
|
840
|
+
if (config.debug) {
|
|
841
|
+
ctx.logger.debug(`通用API请求失败: ${getErrorMessage(error)}`);
|
|
842
|
+
}
|
|
843
|
+
else {
|
|
844
|
+
ctx.logger.error(`通用API解析失败: ${getErrorMessage(error)}`);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
const platformApis = API_CONFIG.platform.kuaishou || [];
|
|
848
|
+
for (const apiUrl of platformApis) {
|
|
701
849
|
try {
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
850
|
+
if (config.debug)
|
|
851
|
+
ctx.logger.debug(`请求快手平台API: ${apiUrl}, 参数: { url: ${realUrl} }`);
|
|
852
|
+
const res = await http.get(apiUrl, { params: { url: realUrl } });
|
|
853
|
+
if (config.debug)
|
|
854
|
+
ctx.logger.debug(`快手平台API响应状态: ${res.status}`);
|
|
855
|
+
if ((res.data.code === 200 || res.data.code === 0) && (res.data.data || res.data.image)) {
|
|
856
|
+
const parseResult = parseData(res.data.data || res.data, config.maxDescLength, platform);
|
|
857
|
+
if (config.debug)
|
|
858
|
+
ctx.logger.debug('快手平台API解析成功');
|
|
705
859
|
return { data: parseResult, msg: '快手解析成功' };
|
|
706
860
|
}
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
for (const apiUrl of platformApis) {
|
|
711
|
-
try {
|
|
712
|
-
const res = await http.get(apiUrl, { params: { url: realUrl } });
|
|
713
|
-
if ((res.data.code === 200 || res.data.code === 0) && (res.data.data || res.data.image)) {
|
|
714
|
-
const parseResult = parseData(res.data.data || res.data, config.maxDescLength, platform);
|
|
715
|
-
return { data: parseResult, msg: '快手解析成功' };
|
|
716
|
-
}
|
|
861
|
+
else {
|
|
862
|
+
if (config.debug)
|
|
863
|
+
ctx.logger.debug('快手平台API返回数据无效');
|
|
717
864
|
}
|
|
718
|
-
|
|
719
|
-
|
|
865
|
+
}
|
|
866
|
+
catch (error) {
|
|
867
|
+
if (config.debug) {
|
|
868
|
+
ctx.logger.debug(`快手平台API请求失败: ${apiUrl}, 错误: ${getErrorMessage(error)}`);
|
|
720
869
|
}
|
|
721
870
|
}
|
|
722
871
|
}
|
|
872
|
+
if (config.debug) {
|
|
873
|
+
ctx.logger.debug(`所有快手API尝试失败, URL: ${realUrl}`);
|
|
874
|
+
}
|
|
875
|
+
else {
|
|
876
|
+
ctx.logger.error(`快手解析失败: ${realUrl}`);
|
|
877
|
+
}
|
|
723
878
|
return { data: null, msg: '快手解析失败' };
|
|
724
879
|
}
|
|
725
880
|
if (platform === 'douyin') {
|
|
726
881
|
try {
|
|
882
|
+
const apiUrl = API_CONFIG.xingzhige.douyin.url;
|
|
883
|
+
if (config.debug)
|
|
884
|
+
ctx.logger.debug(`请求抖音xingzhige API: ${apiUrl}, 参数: { url: ${realUrl} }`);
|
|
727
885
|
const res = await http({
|
|
728
886
|
method: 'GET',
|
|
729
|
-
url:
|
|
887
|
+
url: apiUrl,
|
|
730
888
|
params: { url: realUrl }
|
|
731
889
|
});
|
|
890
|
+
if (config.debug)
|
|
891
|
+
ctx.logger.debug(`抖音xingzhige API响应状态: ${res.status}`);
|
|
732
892
|
if (res.data && res.data.jx && res.data.jx.length > 0) {
|
|
733
893
|
const xgData = parse_xingzhige_data(res.data, platform);
|
|
734
894
|
const parseResult = parseData(xgData, config.maxDescLength, platform);
|
|
895
|
+
if (config.debug)
|
|
896
|
+
ctx.logger.debug('抖音xingzhige解析成功');
|
|
735
897
|
return { data: parseResult, msg: '抖音解析成功' };
|
|
736
898
|
}
|
|
899
|
+
else {
|
|
900
|
+
if (config.debug)
|
|
901
|
+
ctx.logger.debug('抖音xingzhige API返回数据无效');
|
|
902
|
+
}
|
|
737
903
|
}
|
|
738
904
|
catch (error) {
|
|
905
|
+
if (config.debug) {
|
|
906
|
+
ctx.logger.debug(`抖音xingzhige API请求失败: ${getErrorMessage(error)}`);
|
|
907
|
+
}
|
|
908
|
+
else {
|
|
909
|
+
ctx.logger.error(`抖音xingzhige解析失败: ${getErrorMessage(error)}`);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
try {
|
|
913
|
+
const universalUrl = API_CONFIG.universal;
|
|
914
|
+
if (config.debug)
|
|
915
|
+
ctx.logger.debug(`请求通用API: ${universalUrl}, 参数: { url: ${realUrl} }`);
|
|
916
|
+
const res = await http.get(universalUrl, { params: { url: realUrl } });
|
|
917
|
+
if (config.debug)
|
|
918
|
+
ctx.logger.debug(`通用API响应状态: ${res.status}`);
|
|
919
|
+
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
920
|
+
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
921
|
+
if (config.debug)
|
|
922
|
+
ctx.logger.debug('通用API解析成功');
|
|
923
|
+
return { data: parseResult, msg: '抖音解析成功' };
|
|
924
|
+
}
|
|
925
|
+
else {
|
|
926
|
+
if (config.debug)
|
|
927
|
+
ctx.logger.debug('通用API返回数据无效');
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
catch (error) {
|
|
931
|
+
if (config.debug) {
|
|
932
|
+
ctx.logger.debug(`通用API请求失败: ${getErrorMessage(error)}`);
|
|
933
|
+
}
|
|
934
|
+
else {
|
|
935
|
+
ctx.logger.error(`通用API解析失败: ${getErrorMessage(error)}`);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
const platformApis = API_CONFIG.platform.douyin || [];
|
|
939
|
+
for (const apiUrl of platformApis) {
|
|
739
940
|
try {
|
|
740
|
-
|
|
941
|
+
if (config.debug)
|
|
942
|
+
ctx.logger.debug(`请求抖音平台API: ${apiUrl}, 参数: { url: ${realUrl} }`);
|
|
943
|
+
const res = await http.get(apiUrl, { params: { url: realUrl } });
|
|
944
|
+
if (config.debug)
|
|
945
|
+
ctx.logger.debug(`抖音平台API响应状态: ${res.status}`);
|
|
741
946
|
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
742
947
|
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
948
|
+
if (config.debug)
|
|
949
|
+
ctx.logger.debug('抖音平台API解析成功');
|
|
743
950
|
return { data: parseResult, msg: '抖音解析成功' };
|
|
744
951
|
}
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
for (const apiUrl of platformApis) {
|
|
749
|
-
try {
|
|
750
|
-
const res = await http.get(apiUrl, { params: { url: realUrl } });
|
|
751
|
-
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
752
|
-
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
753
|
-
return { data: parseResult, msg: '抖音解析成功' };
|
|
754
|
-
}
|
|
952
|
+
else {
|
|
953
|
+
if (config.debug)
|
|
954
|
+
ctx.logger.debug('抖音平台API返回数据无效');
|
|
755
955
|
}
|
|
756
|
-
|
|
757
|
-
|
|
956
|
+
}
|
|
957
|
+
catch (error) {
|
|
958
|
+
if (config.debug) {
|
|
959
|
+
ctx.logger.debug(`抖音平台API请求失败: ${apiUrl}, 错误: ${getErrorMessage(error)}`);
|
|
758
960
|
}
|
|
759
961
|
}
|
|
760
962
|
}
|
|
963
|
+
if (config.debug) {
|
|
964
|
+
ctx.logger.debug(`所有抖音API尝试失败, URL: ${realUrl}`);
|
|
965
|
+
}
|
|
966
|
+
else {
|
|
967
|
+
ctx.logger.error(`抖音解析失败: ${realUrl}`);
|
|
968
|
+
}
|
|
761
969
|
return { data: null, msg: '抖音解析失败' };
|
|
762
970
|
}
|
|
763
971
|
if (platform === 'xigua') {
|
|
764
972
|
try {
|
|
973
|
+
const apiUrl = API_CONFIG.xingzhige.xigua.url;
|
|
974
|
+
if (config.debug)
|
|
975
|
+
ctx.logger.debug(`请求西瓜xingzhige API: ${apiUrl}, 参数: { url: ${realUrl} }`);
|
|
765
976
|
const res = await http({
|
|
766
977
|
method: 'GET',
|
|
767
|
-
url:
|
|
978
|
+
url: apiUrl,
|
|
768
979
|
params: { url: realUrl }
|
|
769
980
|
});
|
|
981
|
+
if (config.debug)
|
|
982
|
+
ctx.logger.debug(`西瓜xingzhige API响应状态: ${res.status}`);
|
|
770
983
|
if (res.data && res.data.jx && res.data.jx.length > 0) {
|
|
771
984
|
const xgData = parse_xingzhige_data(res.data, platform);
|
|
772
985
|
const parseResult = parseData(xgData, config.maxDescLength, platform);
|
|
986
|
+
if (config.debug)
|
|
987
|
+
ctx.logger.debug('西瓜xingzhige解析成功');
|
|
988
|
+
return { data: parseResult, msg: '西瓜视频解析成功' };
|
|
989
|
+
}
|
|
990
|
+
else {
|
|
991
|
+
if (config.debug)
|
|
992
|
+
ctx.logger.debug('西瓜xingzhige API返回数据无效');
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
catch (error) {
|
|
996
|
+
if (config.debug) {
|
|
997
|
+
ctx.logger.debug(`西瓜xingzhige API请求失败: ${getErrorMessage(error)}`);
|
|
998
|
+
}
|
|
999
|
+
else {
|
|
1000
|
+
ctx.logger.error(`西瓜xingzhige解析失败: ${getErrorMessage(error)}`);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
try {
|
|
1004
|
+
const universalUrl = API_CONFIG.universal;
|
|
1005
|
+
if (config.debug)
|
|
1006
|
+
ctx.logger.debug(`请求通用API: ${universalUrl}, 参数: { url: ${realUrl} }`);
|
|
1007
|
+
const res = await http.get(universalUrl, { params: { url: realUrl } });
|
|
1008
|
+
if (config.debug)
|
|
1009
|
+
ctx.logger.debug(`通用API响应状态: ${res.status}`);
|
|
1010
|
+
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
1011
|
+
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
1012
|
+
if (config.debug)
|
|
1013
|
+
ctx.logger.debug('通用API解析成功');
|
|
773
1014
|
return { data: parseResult, msg: '西瓜视频解析成功' };
|
|
774
1015
|
}
|
|
1016
|
+
else {
|
|
1017
|
+
if (config.debug)
|
|
1018
|
+
ctx.logger.debug('通用API返回数据无效');
|
|
1019
|
+
}
|
|
775
1020
|
}
|
|
776
1021
|
catch (error) {
|
|
1022
|
+
if (config.debug) {
|
|
1023
|
+
ctx.logger.debug(`通用API请求失败: ${getErrorMessage(error)}`);
|
|
1024
|
+
}
|
|
1025
|
+
else {
|
|
1026
|
+
ctx.logger.error(`通用API解析失败: ${getErrorMessage(error)}`);
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
const platformApis = API_CONFIG.platform.xigua || [];
|
|
1030
|
+
for (const apiUrl of platformApis) {
|
|
777
1031
|
try {
|
|
778
|
-
|
|
1032
|
+
if (config.debug)
|
|
1033
|
+
ctx.logger.debug(`请求西瓜平台API: ${apiUrl}, 参数: { url: ${realUrl} }`);
|
|
1034
|
+
const res = await http.get(apiUrl, { params: { url: realUrl } });
|
|
1035
|
+
if (config.debug)
|
|
1036
|
+
ctx.logger.debug(`西瓜平台API响应状态: ${res.status}`);
|
|
779
1037
|
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
780
1038
|
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
1039
|
+
if (config.debug)
|
|
1040
|
+
ctx.logger.debug('西瓜平台API解析成功');
|
|
781
1041
|
return { data: parseResult, msg: '西瓜视频解析成功' };
|
|
782
1042
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
for (const apiUrl of platformApis) {
|
|
787
|
-
try {
|
|
788
|
-
const res = await http.get(apiUrl, { params: { url: realUrl } });
|
|
789
|
-
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
790
|
-
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
791
|
-
return { data: parseResult, msg: '西瓜视频解析成功' };
|
|
792
|
-
}
|
|
1043
|
+
else {
|
|
1044
|
+
if (config.debug)
|
|
1045
|
+
ctx.logger.debug('西瓜平台API返回数据无效');
|
|
793
1046
|
}
|
|
794
|
-
|
|
795
|
-
|
|
1047
|
+
}
|
|
1048
|
+
catch (error) {
|
|
1049
|
+
if (config.debug) {
|
|
1050
|
+
ctx.logger.debug(`西瓜平台API请求失败: ${apiUrl}, 错误: ${getErrorMessage(error)}`);
|
|
796
1051
|
}
|
|
797
1052
|
}
|
|
798
1053
|
}
|
|
1054
|
+
if (config.debug) {
|
|
1055
|
+
ctx.logger.debug(`所有西瓜API尝试失败, URL: ${realUrl}`);
|
|
1056
|
+
}
|
|
1057
|
+
else {
|
|
1058
|
+
ctx.logger.error(`西瓜解析失败: ${realUrl}`);
|
|
1059
|
+
}
|
|
799
1060
|
return { data: null, msg: '西瓜视频解析失败' };
|
|
800
1061
|
}
|
|
801
1062
|
const currentPlatform = platform;
|
|
@@ -803,16 +1064,32 @@ function apply(ctx, config) {
|
|
|
803
1064
|
if (nonKuaishouPlatforms.includes(currentPlatform)) {
|
|
804
1065
|
for (let retry = 0; retry <= config.retryTimes; retry++) {
|
|
805
1066
|
try {
|
|
806
|
-
const
|
|
1067
|
+
const universalUrl = API_CONFIG.universal;
|
|
1068
|
+
if (config.debug)
|
|
1069
|
+
ctx.logger.debug(`请求通用API: ${universalUrl}, 参数: { url: ${realUrl} }`);
|
|
1070
|
+
const res = await http.get(universalUrl, { params: { url: realUrl } });
|
|
1071
|
+
if (config.debug)
|
|
1072
|
+
ctx.logger.debug(`通用API响应状态: ${res.status}`);
|
|
807
1073
|
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
808
1074
|
const parseResult = parseData(res.data.data, config.maxDescLength, currentPlatform);
|
|
1075
|
+
if (config.debug)
|
|
1076
|
+
ctx.logger.debug('通用API解析成功');
|
|
809
1077
|
return { data: parseResult, msg: '解析成功' };
|
|
810
1078
|
}
|
|
811
1079
|
else if (res.data.code === 201) {
|
|
1080
|
+
if (config.debug)
|
|
1081
|
+
ctx.logger.debug('通用API返回code 201');
|
|
812
1082
|
break;
|
|
813
1083
|
}
|
|
1084
|
+
else {
|
|
1085
|
+
if (config.debug)
|
|
1086
|
+
ctx.logger.debug('通用API返回数据无效');
|
|
1087
|
+
}
|
|
814
1088
|
}
|
|
815
1089
|
catch (error) {
|
|
1090
|
+
if (config.debug) {
|
|
1091
|
+
ctx.logger.debug(`通用API请求失败: ${getErrorMessage(error)}`);
|
|
1092
|
+
}
|
|
816
1093
|
if (retry === config.retryTimes)
|
|
817
1094
|
break;
|
|
818
1095
|
await delay(config.retryInterval);
|
|
@@ -824,7 +1101,11 @@ function apply(ctx, config) {
|
|
|
824
1101
|
const apiUrl = platformApis[apiIndex];
|
|
825
1102
|
for (let retry = 0; retry <= config.retryTimes; retry++) {
|
|
826
1103
|
try {
|
|
1104
|
+
if (config.debug)
|
|
1105
|
+
ctx.logger.debug(`请求平台API: ${apiUrl}, 参数: { url: ${realUrl} }`);
|
|
827
1106
|
const res = await http.get(apiUrl, { params: { url: realUrl } });
|
|
1107
|
+
if (config.debug)
|
|
1108
|
+
ctx.logger.debug(`平台API响应状态: ${res.status}`);
|
|
828
1109
|
let shouldContinue = false;
|
|
829
1110
|
if ((res.data.code === 200 || res.data.code === 0)) {
|
|
830
1111
|
let parseResult = null;
|
|
@@ -853,24 +1134,39 @@ function apply(ctx, config) {
|
|
|
853
1134
|
}
|
|
854
1135
|
}
|
|
855
1136
|
if (parseResult) {
|
|
1137
|
+
if (config.debug)
|
|
1138
|
+
ctx.logger.debug('平台API解析成功');
|
|
856
1139
|
return { data: parseResult, msg: '解析成功' };
|
|
857
1140
|
}
|
|
858
1141
|
}
|
|
859
1142
|
if (shouldContinue && retry < config.retryTimes) {
|
|
1143
|
+
if (config.debug)
|
|
1144
|
+
ctx.logger.debug('平台API返回数据无效,准备重试');
|
|
860
1145
|
await delay(config.retryInterval);
|
|
861
1146
|
continue;
|
|
862
1147
|
}
|
|
863
1148
|
else {
|
|
1149
|
+
if (config.debug)
|
|
1150
|
+
ctx.logger.debug('平台API返回数据无效,放弃');
|
|
864
1151
|
break;
|
|
865
1152
|
}
|
|
866
1153
|
}
|
|
867
1154
|
catch (error) {
|
|
1155
|
+
if (config.debug) {
|
|
1156
|
+
ctx.logger.debug(`平台API请求失败: ${apiUrl}, 错误: ${getErrorMessage(error)}`);
|
|
1157
|
+
}
|
|
868
1158
|
if (retry === config.retryTimes)
|
|
869
1159
|
break;
|
|
870
1160
|
await delay(config.retryInterval);
|
|
871
1161
|
}
|
|
872
1162
|
}
|
|
873
1163
|
}
|
|
1164
|
+
if (config.debug) {
|
|
1165
|
+
ctx.logger.debug(`所有API尝试失败,平台: ${platform}, URL: ${realUrl}`);
|
|
1166
|
+
}
|
|
1167
|
+
else {
|
|
1168
|
+
ctx.logger.error(`解析失败: ${platform} ${realUrl}`);
|
|
1169
|
+
}
|
|
874
1170
|
return { data: null, msg: '解析失败,请稍后重试' };
|
|
875
1171
|
}
|
|
876
1172
|
async function processSingleUrl(session, url) {
|
|
@@ -925,8 +1221,17 @@ function apply(ctx, config) {
|
|
|
925
1221
|
}
|
|
926
1222
|
else {
|
|
927
1223
|
errs.push(`【${url.slice(0, 22)}...】:${result.msg}`);
|
|
1224
|
+
if (config.debug) {
|
|
1225
|
+
ctx.logger.debug(`解析失败: ${url}, 原因: ${result.msg}`);
|
|
1226
|
+
}
|
|
1227
|
+
else {
|
|
1228
|
+
ctx.logger.error(`解析失败: ${url}, 原因: ${result.msg}`);
|
|
1229
|
+
}
|
|
928
1230
|
}
|
|
929
1231
|
}
|
|
1232
|
+
if (errs.length) {
|
|
1233
|
+
ctx.logger.error(`解析失败数量: ${errs.length}, 示例: ${errs[0]}`);
|
|
1234
|
+
}
|
|
930
1235
|
const enableForward = config.enableForward && session.platform === 'onebot';
|
|
931
1236
|
const forwardMessages = [];
|
|
932
1237
|
const botName = config.botName || '视频解析机器人';
|
|
@@ -973,6 +1278,12 @@ function apply(ctx, config) {
|
|
|
973
1278
|
videoElem = koishi_1.h.file(filePath);
|
|
974
1279
|
}
|
|
975
1280
|
catch (error) {
|
|
1281
|
+
if (config.debug) {
|
|
1282
|
+
ctx.logger.debug(`视频下载失败: ${getErrorMessage(error)}`);
|
|
1283
|
+
}
|
|
1284
|
+
else {
|
|
1285
|
+
ctx.logger.error(`视频下载失败: ${getErrorMessage(error)}`);
|
|
1286
|
+
}
|
|
976
1287
|
videoElem = koishi_1.h.video(item.video);
|
|
977
1288
|
}
|
|
978
1289
|
}
|
|
@@ -1009,6 +1320,12 @@ function apply(ctx, config) {
|
|
|
1009
1320
|
videoElem = koishi_1.h.file(filePath);
|
|
1010
1321
|
}
|
|
1011
1322
|
catch (error) {
|
|
1323
|
+
if (config.debug) {
|
|
1324
|
+
ctx.logger.debug(`视频下载失败: ${getErrorMessage(error)}`);
|
|
1325
|
+
}
|
|
1326
|
+
else {
|
|
1327
|
+
ctx.logger.error(`视频下载失败: ${getErrorMessage(error)}`);
|
|
1328
|
+
}
|
|
1012
1329
|
videoElem = koishi_1.h.video(item.video);
|
|
1013
1330
|
}
|
|
1014
1331
|
}
|
|
@@ -1027,7 +1344,8 @@ function apply(ctx, config) {
|
|
|
1027
1344
|
}
|
|
1028
1345
|
}
|
|
1029
1346
|
catch (error) {
|
|
1030
|
-
|
|
1347
|
+
ctx.logger.error(`处理内容失败: ${getErrorMessage(error)}`);
|
|
1348
|
+
await sendTimeout(session, `❌ 处理${item.type}内容失败: ${getErrorMessage(error)}`);
|
|
1031
1349
|
}
|
|
1032
1350
|
}
|
|
1033
1351
|
if (enableForward && forwardMessages.length) {
|
|
@@ -1037,6 +1355,7 @@ function apply(ctx, config) {
|
|
|
1037
1355
|
await sendTimeout(session, forwardMsg);
|
|
1038
1356
|
}
|
|
1039
1357
|
catch (error) {
|
|
1358
|
+
ctx.logger.error(`合并转发失败: ${getErrorMessage(error)}`);
|
|
1040
1359
|
for (const node of forwardMessages) {
|
|
1041
1360
|
await sendTimeout(session, node.data.content);
|
|
1042
1361
|
await delay(500);
|
|
@@ -1114,7 +1433,9 @@ function apply(ctx, config) {
|
|
|
1114
1433
|
fs_1.default.unlinkSync(path_1.default.join(tempDir, file));
|
|
1115
1434
|
}
|
|
1116
1435
|
}
|
|
1117
|
-
catch (error) {
|
|
1436
|
+
catch (error) {
|
|
1437
|
+
ctx.logger.error(`清理临时文件失败: ${file}, ${getErrorMessage(error)}`);
|
|
1438
|
+
}
|
|
1118
1439
|
});
|
|
1119
1440
|
}, 1800000);
|
|
1120
1441
|
if (config.autoClearCacheInterval > 0) {
|
package/package.json
CHANGED