koishi-plugin-video-parser-all 0.4.7 → 0.4.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.
Files changed (3) hide show
  1. package/lib/index.d.ts +6 -13
  2. package/lib/index.js +177 -212
  3. package/package.json +2 -2
package/lib/index.d.ts CHANGED
@@ -2,7 +2,6 @@ import { Schema } from 'koishi';
2
2
  export declare const name = "video-parser-all";
3
3
  export declare const Config: Schema<{
4
4
  enable?: boolean | null | undefined;
5
- debug?: boolean | null | undefined;
6
5
  autoParse?: boolean | null | undefined;
7
6
  enableBvAvParse?: boolean | null | undefined;
8
7
  botName?: string | null | undefined;
@@ -17,7 +16,6 @@ export declare const Config: Schema<{
17
16
  bilibili?: boolean | null | undefined;
18
17
  douyin?: boolean | null | undefined;
19
18
  kuaishou?: boolean | null | undefined;
20
- xigua?: boolean | null | undefined;
21
19
  xiaohongshu?: boolean | null | undefined;
22
20
  weibo?: boolean | null | undefined;
23
21
  toutiao?: boolean | null | undefined;
@@ -53,10 +51,9 @@ export declare const Config: Schema<{
53
51
  } & import("cosmokit").Dict) | ({
54
52
  enableApiSelection?: true | null | undefined;
55
53
  preferredApi?: ({
56
- bilibili?: "https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/b_parse/" | "https://api.bugpk.com/api/bilibili" | "https://api.xingzhige.com/API/b_video/" | "https://api.bilibili.com/x/web-interface/view" | null | undefined;
54
+ bilibili?: "https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/b_parse/" | "https://api.bugpk.com/api/bilibili" | "https://api.bilibili.com/x/web-interface/view" | null | undefined;
57
55
  douyin?: "https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/douyin/" | "https://api.bugpk.com/api/douyin" | "https://api.bugpk.com/api/dyjx" | "https://api.bugpk.com/api/dylive" | null | undefined;
58
- kuaishou?: "https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/kuaishou/" | "https://api.bugpk.com/api/ksjx" | "https://api.bugpk.com/api/kuaishou" | "https://api.bugpk.com/api/ksimg" | "https://api.suyanw.cn/api/kuaishou.php" | null | undefined;
59
- xigua?: "https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/xigua/" | "https://api.bugpk.com/api/toutiao" | null | undefined;
56
+ kuaishou?: "https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/ksjx" | "https://api.bugpk.com/api/kuaishou" | "https://api.bugpk.com/api/ksimg" | "https://api.suyanw.cn/api/kuaishou.php" | null | undefined;
60
57
  xiaohongshu?: "https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/xhsjx" | "https://api.bugpk.com/api/xhsimg" | "https://api.bugpk.com/api/xhslive" | "https://api.bugpk.com/api/xhs" | null | undefined;
61
58
  weibo?: "https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/weibo" | "https://api.bugpk.com/api/weibo_v" | null | undefined;
62
59
  toutiao?: "https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/toutiao" | null | undefined;
@@ -66,7 +63,6 @@ export declare const Config: Schema<{
66
63
  } & import("cosmokit").Dict) | null | undefined;
67
64
  } & import("cosmokit").Dict))))), {
68
65
  enable: boolean;
69
- debug: boolean;
70
66
  autoParse: boolean;
71
67
  enableBvAvParse: boolean;
72
68
  botName: string;
@@ -81,7 +77,6 @@ export declare const Config: Schema<{
81
77
  bilibili: Schema<boolean, boolean>;
82
78
  douyin: Schema<boolean, boolean>;
83
79
  kuaishou: Schema<boolean, boolean>;
84
- xigua: Schema<boolean, boolean>;
85
80
  xiaohongshu: Schema<boolean, boolean>;
86
81
  weibo: Schema<boolean, boolean>;
87
82
  toutiao: Schema<boolean, boolean>;
@@ -117,10 +112,9 @@ export declare const Config: Schema<{
117
112
  }> | Schemastery.ObjectT<{
118
113
  enableApiSelection: Schema<true, true>;
119
114
  preferredApi: Schema<Schemastery.ObjectS<{
120
- bilibili: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/b_parse/" | "https://api.bugpk.com/api/bilibili" | "https://api.xingzhige.com/API/b_video/" | "https://api.bilibili.com/x/web-interface/view", "https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/b_parse/" | "https://api.bugpk.com/api/bilibili" | "https://api.xingzhige.com/API/b_video/" | "https://api.bilibili.com/x/web-interface/view">;
115
+ bilibili: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/b_parse/" | "https://api.bugpk.com/api/bilibili" | "https://api.bilibili.com/x/web-interface/view", "https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/b_parse/" | "https://api.bugpk.com/api/bilibili" | "https://api.bilibili.com/x/web-interface/view">;
121
116
  douyin: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/douyin/" | "https://api.bugpk.com/api/douyin" | "https://api.bugpk.com/api/dyjx" | "https://api.bugpk.com/api/dylive", "https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/douyin/" | "https://api.bugpk.com/api/douyin" | "https://api.bugpk.com/api/dyjx" | "https://api.bugpk.com/api/dylive">;
122
- kuaishou: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/kuaishou/" | "https://api.bugpk.com/api/ksjx" | "https://api.bugpk.com/api/kuaishou" | "https://api.bugpk.com/api/ksimg" | "https://api.suyanw.cn/api/kuaishou.php", "https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/kuaishou/" | "https://api.bugpk.com/api/ksjx" | "https://api.bugpk.com/api/kuaishou" | "https://api.bugpk.com/api/ksimg" | "https://api.suyanw.cn/api/kuaishou.php">;
123
- xigua: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/xigua/" | "https://api.bugpk.com/api/toutiao", "https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/xigua/" | "https://api.bugpk.com/api/toutiao">;
117
+ kuaishou: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/ksjx" | "https://api.bugpk.com/api/kuaishou" | "https://api.bugpk.com/api/ksimg" | "https://api.suyanw.cn/api/kuaishou.php", "https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/ksjx" | "https://api.bugpk.com/api/kuaishou" | "https://api.bugpk.com/api/ksimg" | "https://api.suyanw.cn/api/kuaishou.php">;
124
118
  xiaohongshu: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/xhsjx" | "https://api.bugpk.com/api/xhsimg" | "https://api.bugpk.com/api/xhslive" | "https://api.bugpk.com/api/xhs", "https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/xhsjx" | "https://api.bugpk.com/api/xhsimg" | "https://api.bugpk.com/api/xhslive" | "https://api.bugpk.com/api/xhs">;
125
119
  weibo: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/weibo" | "https://api.bugpk.com/api/weibo_v", "https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/weibo" | "https://api.bugpk.com/api/weibo_v">;
126
120
  toutiao: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/toutiao", "https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/toutiao">;
@@ -128,10 +122,9 @@ export declare const Config: Schema<{
128
122
  pipixia: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/pipixia", "https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/pipixia">;
129
123
  zuiyou: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/zuiyou" | "https://api.suyanw.cn/api/zuiyou.php", "https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/zuiyou" | "https://api.suyanw.cn/api/zuiyou.php">;
130
124
  }>, Schemastery.ObjectT<{
131
- bilibili: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/b_parse/" | "https://api.bugpk.com/api/bilibili" | "https://api.xingzhige.com/API/b_video/" | "https://api.bilibili.com/x/web-interface/view", "https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/b_parse/" | "https://api.bugpk.com/api/bilibili" | "https://api.xingzhige.com/API/b_video/" | "https://api.bilibili.com/x/web-interface/view">;
125
+ bilibili: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/b_parse/" | "https://api.bugpk.com/api/bilibili" | "https://api.bilibili.com/x/web-interface/view", "https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/b_parse/" | "https://api.bugpk.com/api/bilibili" | "https://api.bilibili.com/x/web-interface/view">;
132
126
  douyin: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/douyin/" | "https://api.bugpk.com/api/douyin" | "https://api.bugpk.com/api/dyjx" | "https://api.bugpk.com/api/dylive", "https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/douyin/" | "https://api.bugpk.com/api/douyin" | "https://api.bugpk.com/api/dyjx" | "https://api.bugpk.com/api/dylive">;
133
- kuaishou: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/kuaishou/" | "https://api.bugpk.com/api/ksjx" | "https://api.bugpk.com/api/kuaishou" | "https://api.bugpk.com/api/ksimg" | "https://api.suyanw.cn/api/kuaishou.php", "https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/kuaishou/" | "https://api.bugpk.com/api/ksjx" | "https://api.bugpk.com/api/kuaishou" | "https://api.bugpk.com/api/ksimg" | "https://api.suyanw.cn/api/kuaishou.php">;
134
- xigua: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/xigua/" | "https://api.bugpk.com/api/toutiao", "https://api.bugpk.com/api/short_videos" | "https://api.xingzhige.com/API/xigua/" | "https://api.bugpk.com/api/toutiao">;
127
+ kuaishou: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/ksjx" | "https://api.bugpk.com/api/kuaishou" | "https://api.bugpk.com/api/ksimg" | "https://api.suyanw.cn/api/kuaishou.php", "https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/ksjx" | "https://api.bugpk.com/api/kuaishou" | "https://api.bugpk.com/api/ksimg" | "https://api.suyanw.cn/api/kuaishou.php">;
135
128
  xiaohongshu: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/xhsjx" | "https://api.bugpk.com/api/xhsimg" | "https://api.bugpk.com/api/xhslive" | "https://api.bugpk.com/api/xhs", "https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/xhsjx" | "https://api.bugpk.com/api/xhsimg" | "https://api.bugpk.com/api/xhslive" | "https://api.bugpk.com/api/xhs">;
136
129
  weibo: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/weibo" | "https://api.bugpk.com/api/weibo_v", "https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/weibo" | "https://api.bugpk.com/api/weibo_v">;
137
130
  toutiao: Schema<"https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/toutiao", "https://api.bugpk.com/api/short_videos" | "https://api.bugpk.com/api/toutiao">;
package/lib/index.js CHANGED
@@ -17,28 +17,24 @@ const API_CONFIG = {
17
17
  universal: 'https://api.bugpk.com/api/short_videos',
18
18
  xingzhige: {
19
19
  bilibili: 'https://api.xingzhige.com/API/b_parse/',
20
- kuaishou: 'https://api.xingzhige.com/API/kuaishou/',
21
- douyin: 'https://api.xingzhige.com/API/douyin/',
22
- xigua: 'https://api.xingzhige.com/API/xigua/'
20
+ douyin: 'https://api.xingzhige.com/API/douyin/'
23
21
  },
24
22
  platform: {
25
- bilibili: ['https://api.bugpk.com/api/bilibili', 'https://api.xingzhige.com/API/b_parse/', 'https://api.xingzhige.com/API/b_video/'],
26
- kuaishou: ['https://api.bugpk.com/api/ksjx', 'https://api.bugpk.com/api/kuaishou', 'https://api.bugpk.com/api/ksimg', 'https://api.suyanw.cn/api/kuaishou.php', 'https://api.xingzhige.com/API/kuaishou/'],
23
+ bilibili: ['https://api.bugpk.com/api/bilibili', 'https://api.xingzhige.com/API/b_parse/'],
24
+ kuaishou: ['https://api.bugpk.com/api/ksjx', 'https://api.bugpk.com/api/kuaishou', 'https://api.bugpk.com/api/ksimg', 'https://api.suyanw.cn/api/kuaishou.php'],
27
25
  xiaohongshu: ['https://api.bugpk.com/api/xhsjx', 'https://api.bugpk.com/api/xhsimg', 'https://api.bugpk.com/api/xhslive', 'https://api.bugpk.com/api/xhs'],
28
26
  weibo: ['https://api.bugpk.com/api/weibo', 'https://api.bugpk.com/api/weibo_v'],
29
27
  toutiao: ['https://api.bugpk.com/api/toutiao'],
30
28
  pipigx: ['https://api.bugpk.com/api/pipigx', 'https://api.suyanw.cn/api/pipigx.php'],
31
29
  pipixia: ['https://api.bugpk.com/api/pipixia'],
32
30
  douyin: ['https://api.bugpk.com/api/douyin', 'https://api.bugpk.com/api/dyjx', 'https://api.bugpk.com/api/dylive', 'https://api.xingzhige.com/API/douyin/'],
33
- zuiyou: ['https://api.bugpk.com/api/zuiyou', 'https://api.suyanw.cn/api/zuiyou.php'],
34
- xigua: ['https://api.bugpk.com/api/toutiao', 'https://api.xingzhige.com/API/xigua/']
31
+ zuiyou: ['https://api.bugpk.com/api/zuiyou', 'https://api.suyanw.cn/api/zuiyou.php']
35
32
  }
36
33
  };
37
34
  exports.name = 'video-parser-all';
38
35
  exports.Config = koishi_1.Schema.intersect([
39
36
  koishi_1.Schema.object({
40
37
  enable: koishi_1.Schema.boolean().default(true).description('是否启用视频解析插件'),
41
- debug: koishi_1.Schema.boolean().default(false).description('开启调试模式,输出详细日志'),
42
38
  autoParse: koishi_1.Schema.boolean().default(true).description('是否自动解析消息中的视频链接'),
43
39
  enableBvAvParse: koishi_1.Schema.boolean().default(true).description('是否解析独立的BV/AV号(如:BV1xx411c7mD)'),
44
40
  botName: koishi_1.Schema.string().default('视频解析机器人').description('机器人显示名称'),
@@ -54,7 +50,6 @@ exports.Config = koishi_1.Schema.intersect([
54
50
  bilibili: koishi_1.Schema.boolean().default(true).description('B站'),
55
51
  douyin: koishi_1.Schema.boolean().default(true).description('抖音'),
56
52
  kuaishou: koishi_1.Schema.boolean().default(true).description('快手'),
57
- xigua: koishi_1.Schema.boolean().default(true).description('西瓜视频'),
58
53
  xiaohongshu: koishi_1.Schema.boolean().default(true).description('小红书'),
59
54
  weibo: koishi_1.Schema.boolean().default(true).description('微博'),
60
55
  toutiao: koishi_1.Schema.boolean().default(true).description('今日头条'),
@@ -64,7 +59,18 @@ exports.Config = koishi_1.Schema.intersect([
64
59
  }).description('平台开关')
65
60
  }).description('平台开关'),
66
61
  koishi_1.Schema.object({
67
- messageFormat: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}\n时长:${视频时长}\n点赞:${点赞数}\n投币:${投币数}\n收藏:${收藏数}\n转发:${转发数}\n播放:${播放数}\n视频大小:${视频大小}MB').description('消息格式,可用变量:${标题}、${作者}、${简介}、${视频时长}、${点赞数}、${投币数}、${收藏数}、${转发数}、${播放数}、${视频大小}'),
62
+ messageFormat: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}\n时长:${视频时长}\n点赞:${点赞数}\n投币:${投币数}\n收藏:${收藏数}\n转发:${转发数}\n播放:${播放数}\n视频大小:${视频大小}MB').description(`消息格式,可用变量:
63
+ ${'${标题}'} - 视频/图文标题
64
+ ${'${作者}'} - 作者名称
65
+ ${'${简介}'} - 作品简介/描述
66
+ ${'${视频时长}'} - 视频时长(格式化)
67
+ ${'${点赞数}'} - 点赞数量
68
+ ${'${投币数}'} - 投币数量(仅B站有效)
69
+ ${'${收藏数}'} - 收藏数量
70
+ ${'${转发数}'} - 转发/分享数量
71
+ ${'${播放数}'} - 播放/浏览数量
72
+ ${'${视频大小}'} - 视频文件大小(MB)
73
+ 注:非B站平台会自动隐藏投币字段`),
68
74
  }).description('消息格式'),
69
75
  koishi_1.Schema.object({
70
76
  showImageText: koishi_1.Schema.boolean().default(true).description('显示图文内容'),
@@ -99,13 +105,12 @@ exports.Config = koishi_1.Schema.intersect([
99
105
  enableApiSelection: koishi_1.Schema.const(false).required(),
100
106
  }).description('关闭API选择设置'),
101
107
  koishi_1.Schema.object({
102
- enableApiSelection: koishi_1.Schema.const(true),
108
+ enableApiSelection: koishi_1.Schema.const(true).required(),
103
109
  preferredApi: koishi_1.Schema.object({
104
110
  bilibili: koishi_1.Schema.union([
105
111
  'https://api.xingzhige.com/API/b_parse/',
106
112
  'https://api.bugpk.com/api/short_videos',
107
113
  'https://api.bugpk.com/api/bilibili',
108
- 'https://api.xingzhige.com/API/b_video/',
109
114
  'https://api.bilibili.com/x/web-interface/view'
110
115
  ]).default('https://api.xingzhige.com/API/b_parse/').description('B站首选解析源'),
111
116
  douyin: koishi_1.Schema.union([
@@ -116,18 +121,12 @@ exports.Config = koishi_1.Schema.intersect([
116
121
  'https://api.bugpk.com/api/dylive'
117
122
  ]).default('https://api.xingzhige.com/API/douyin/').description('抖音首选解析源'),
118
123
  kuaishou: koishi_1.Schema.union([
119
- 'https://api.xingzhige.com/API/kuaishou/',
120
124
  'https://api.bugpk.com/api/short_videos',
121
125
  'https://api.bugpk.com/api/ksjx',
122
126
  'https://api.bugpk.com/api/kuaishou',
123
127
  'https://api.bugpk.com/api/ksimg',
124
128
  'https://api.suyanw.cn/api/kuaishou.php'
125
- ]).default('https://api.xingzhige.com/API/kuaishou/').description('快手首选解析源'),
126
- xigua: koishi_1.Schema.union([
127
- 'https://api.xingzhige.com/API/xigua/',
128
- 'https://api.bugpk.com/api/short_videos',
129
- 'https://api.bugpk.com/api/toutiao'
130
- ]).default('https://api.xingzhige.com/API/xigua/').description('西瓜视频首选解析源'),
129
+ ]).default('https://api.bugpk.com/api/short_videos').description('快手首选解析源'),
131
130
  xiaohongshu: koishi_1.Schema.union([
132
131
  'https://api.bugpk.com/api/short_videos',
133
132
  'https://api.bugpk.com/api/xhsjx',
@@ -171,7 +170,7 @@ if (!worker_threads_1.isMainThread) {
171
170
  (async () => {
172
171
  try {
173
172
  if (url.endsWith('.m4a') || url.endsWith('.mp3')) {
174
- worker_threads_1.parentPort?.postMessage({ success: false, error: '不支持音频' });
173
+ worker_threads_1.parentPort?.postMessage({ success: false, error: '不支持音频', code: 3001 });
175
174
  return;
176
175
  }
177
176
  const maxSizeBytes = maxSize * 1024 * 1024;
@@ -184,8 +183,12 @@ if (!worker_threads_1.isMainThread) {
184
183
  });
185
184
  if (maxSize > 0 && response.headers['content-length']) {
186
185
  const contentLength = parseInt(response.headers['content-length']);
186
+ if (isNaN(contentLength)) {
187
+ worker_threads_1.parentPort?.postMessage({ success: false, error: '无法获取视频大小', code: 3002 });
188
+ return;
189
+ }
187
190
  if (contentLength > maxSizeBytes) {
188
- worker_threads_1.parentPort?.postMessage({ success: false, error: `视频大小超过限制(${maxSize}MB)` });
191
+ worker_threads_1.parentPort?.postMessage({ success: false, error: `视频大小超过限制(${maxSize}MB)`, code: 3003 });
189
192
  return;
190
193
  }
191
194
  }
@@ -196,15 +199,20 @@ if (!worker_threads_1.isMainThread) {
196
199
  if (maxSize > 0 && downloadedSize > maxSizeBytes) {
197
200
  response.data.destroy();
198
201
  writeStream.destroy();
199
- fs_1.default.unlinkSync(filePath);
200
- worker_threads_1.parentPort?.postMessage({ success: false, error: `视频大小超过限制(${maxSize}MB)` });
202
+ try {
203
+ fs_1.default.unlinkSync(filePath);
204
+ }
205
+ catch (err) {
206
+ logger.error(`删除文件失败: ${getErrorMessage(err)}`);
207
+ }
208
+ worker_threads_1.parentPort?.postMessage({ success: false, error: `视频大小超过限制(${maxSize}MB)`, code: 3003 });
201
209
  }
202
210
  });
203
211
  await (0, promises_1.pipeline)(response.data, writeStream);
204
212
  worker_threads_1.parentPort?.postMessage({ success: true, filePath });
205
213
  }
206
214
  catch (error) {
207
- worker_threads_1.parentPort?.postMessage({ success: false, error: getErrorMessage(error) });
215
+ worker_threads_1.parentPort?.postMessage({ success: false, error: getErrorMessage(error), code: 3004 });
208
216
  }
209
217
  })();
210
218
  }
@@ -220,7 +228,6 @@ const PLATFORM_KEYWORDS = {
220
228
  pipixia: ['pipixia', '皮皮虾', 'h5.pipix.com', 'pipix.com'],
221
229
  douyin: ['douyin', '抖音', 'v.douyin.com', 'douyin.com', 'tiktok.com'],
222
230
  zuiyou: ['zuiyou', '最右', 'xiaochuankeji.cn', 'izuiyou.com'],
223
- xigua: ['ixigua', '西瓜视频', 'xigua.com', 'ixigua.com']
224
231
  };
225
232
  function extractUrl(content, enableBvAvParse) {
226
233
  const urls = content.match(/https?:\/\/[^\s"'>]+/gi) || [];
@@ -322,29 +329,49 @@ function formatDuration(seconds) {
322
329
  function parseData(data, maxDescLength, platform) {
323
330
  let type = 'unknown';
324
331
  if (data.type) {
325
- type = data.type;
332
+ type = data.type.toLowerCase();
333
+ }
334
+ else if (data.data?.type) {
335
+ type = data.data.type.toLowerCase();
326
336
  }
327
- else if (data.images?.length && !data.url) {
337
+ else if (data.images?.length && !data.url && !data.data?.url) {
328
338
  type = 'image';
329
339
  }
330
- else if (data.live_photo?.length) {
340
+ else if (data.live_photo?.length || data.data?.live_photo?.length) {
331
341
  type = 'live';
332
342
  }
333
- else if (data.url || data.video) {
343
+ else if (data.url || data.video || data.data?.url || data.data?.video) {
334
344
  type = 'video';
335
345
  }
336
- const title = data.title || data.desc || '无标题';
337
- let author = data.author || data.name || '未知作者';
346
+ let title = data.title || data.data?.title || data.desc || data.data?.desc || '无标题';
347
+ let author = data.author || data.data?.author || data.name || data.data?.name || '未知作者';
338
348
  if (author && typeof author === 'object') {
339
- author = author.name || author.nickname || author.username || '未知作者';
349
+ author = author.name || author.nickname || author.username || author.uid || '未知作者';
350
+ }
351
+ let video = '';
352
+ const videoUrls = [];
353
+ if (data.url)
354
+ videoUrls.push(data.url);
355
+ if (data.video)
356
+ videoUrls.push(data.video);
357
+ if (data.data?.url)
358
+ videoUrls.push(data.data.url);
359
+ if (data.data?.video)
360
+ videoUrls.push(data.data.video);
361
+ if (data.data?.videos && Array.isArray(data.data.videos) && data.data.videos.length > 0) {
362
+ videoUrls.push(data.data.videos[0].url);
363
+ }
364
+ if (data.data?.live_photo && Array.isArray(data.data.live_photo) && data.data.live_photo.length > 0) {
365
+ videoUrls.push(data.data.live_photo[0].video);
340
366
  }
341
- let video = data.url || data.video || '';
367
+ video = videoUrls.find(url => url && typeof url === 'string' && url.startsWith('http')) || '';
368
+ let video_backup;
342
369
  if (data.video_backup) {
343
370
  if (Array.isArray(data.video_backup)) {
344
- video = video || data.video_backup[0]?.url || '';
371
+ video_backup = data.video_backup.map((item) => typeof item === 'object' ? item.url : item).filter(Boolean);
345
372
  }
346
373
  else if (typeof data.video_backup === 'string') {
347
- video = video || data.video_backup;
374
+ video_backup = [data.video_backup];
348
375
  }
349
376
  }
350
377
  let like = 0;
@@ -354,6 +381,10 @@ function parseData(data, maxDescLength, platform) {
354
381
  like = data.like;
355
382
  else if (data.likes !== undefined)
356
383
  like = data.likes;
384
+ else if (data.data?.stat?.like !== undefined)
385
+ like = data.data.stat.like;
386
+ else if (data.data?.like !== undefined)
387
+ like = data.data.like;
357
388
  let view = 0;
358
389
  if (data.stat?.view !== undefined)
359
390
  view = data.stat.view;
@@ -363,6 +394,10 @@ function parseData(data, maxDescLength, platform) {
363
394
  view = data.views;
364
395
  else if (data.play_count !== undefined)
365
396
  view = data.play_count;
397
+ else if (data.data?.stat?.view !== undefined)
398
+ view = data.data.stat.view;
399
+ else if (data.data?.play_count !== undefined)
400
+ view = data.data.play_count;
366
401
  let share = 0;
367
402
  if (data.stat?.share !== undefined)
368
403
  share = data.stat.share;
@@ -370,6 +405,8 @@ function parseData(data, maxDescLength, platform) {
370
405
  share = data.share;
371
406
  else if (data.shares !== undefined)
372
407
  share = data.shares;
408
+ else if (data.data?.stat?.share !== undefined)
409
+ share = data.data.stat.share;
373
410
  let favorite = 0;
374
411
  if (data.stat?.favorite !== undefined)
375
412
  favorite = data.stat.favorite;
@@ -377,23 +414,38 @@ function parseData(data, maxDescLength, platform) {
377
414
  favorite = data.favorite;
378
415
  else if (data.collect !== undefined)
379
416
  favorite = data.collect;
380
- let coin = data.stat?.coin || 0;
381
- let size = data.stat?.size || 0;
382
- if (data.size)
383
- size = data.size;
417
+ else if (data.data?.stat?.favorite !== undefined)
418
+ favorite = data.data.stat.favorite;
419
+ let coin = data.stat?.coin || data.data?.stat?.coin || 0;
420
+ let size = data.stat?.size || data.size || data.data?.stat?.size || data.data?.size || 0;
421
+ if (size && typeof size === 'string' && size.endsWith('MB')) {
422
+ size = parseFloat(size);
423
+ }
424
+ let duration = data.duration || data.data?.duration || 0;
425
+ if (typeof duration === 'string') {
426
+ duration = parseFloat(duration);
427
+ }
428
+ let cover = data.cover || data.imgurl || data.pic || data.data?.cover || data.data?.imgurl || '';
429
+ let images = data.images || data.data?.images || [];
430
+ if (data.imgurl && Array.isArray(data.imgurl)) {
431
+ images = [...images, ...data.imgurl];
432
+ }
433
+ let live_photo = data.live_photo || data.data?.live_photo;
434
+ let desc = (data.desc || data.description || data.data?.desc || data.data?.description || title || '').slice(0, maxDescLength);
435
+ let music = data.music || data.data?.music;
384
436
  return {
385
437
  type,
386
438
  title,
387
439
  author,
388
- desc: (data.desc || data.description || data.title || '').slice(0, maxDescLength),
389
- cover: data.cover || data.imgurl || data.pic || '',
390
- images: data.images || [],
440
+ desc,
441
+ cover,
442
+ images: Array.isArray(images) ? images : [],
391
443
  video,
392
- video_backup: Array.isArray(data.video_backup) ? data.video_backup : (data.video_backup ? [data.video_backup] : undefined),
393
- live_photo: data.live_photo,
394
- duration: data.duration || 0,
395
- durationFormatted: formatDuration(data.duration || 0),
396
- music: data.music,
444
+ video_backup: video_backup?.filter(url => url !== video),
445
+ live_photo: Array.isArray(live_photo) ? live_photo : undefined,
446
+ duration,
447
+ durationFormatted: formatDuration(duration),
448
+ music,
397
449
  stat: {
398
450
  like,
399
451
  coin,
@@ -401,7 +453,7 @@ function parseData(data, maxDescLength, platform) {
401
453
  share,
402
454
  view,
403
455
  size,
404
- duration: formatDuration(data.duration || 0)
456
+ duration: formatDuration(duration)
405
457
  }
406
458
  };
407
459
  }
@@ -478,7 +530,7 @@ function generateFormattedText(platform, parseData, config) {
478
530
  .replace(/\${播放数}/g, String(parseData.stat.view))
479
531
  .replace(/\${视频大小}/g, String(parseData.stat.size));
480
532
  if (platform !== 'bilibili') {
481
- text = text.replace(/\n投币:[0-9]+/g, '');
533
+ text = text.replace(/投币:[0-9]+\n?/g, '');
482
534
  }
483
535
  return text;
484
536
  }
@@ -495,12 +547,12 @@ async function downloadVideoWithThreads(url, filename, maxSize, threads, userAge
495
547
  if (result.success && result.filePath)
496
548
  resolve(result.filePath);
497
549
  else
498
- reject(new Error(result.error || '下载失败'));
550
+ reject(new Error(`${result.error || '下载失败'} (错误码: ${result.code || 3000})`));
499
551
  });
500
552
  worker.on('error', reject);
501
553
  worker.on('exit', (code) => {
502
554
  if (code !== 0)
503
- reject(new Error('视频下载线程异常'));
555
+ reject(new Error(`视频下载线程异常 (错误码: 3005)`));
504
556
  });
505
557
  });
506
558
  }
@@ -512,7 +564,8 @@ function clearAllCache() {
512
564
  if (fs_1.default.existsSync(tempDir)) {
513
565
  fs_1.default.readdirSync(tempDir).forEach(file => {
514
566
  try {
515
- fs_1.default.unlinkSync(path_1.default.join(tempDir, file));
567
+ const filePath = path_1.default.join(tempDir, file);
568
+ fs_1.default.unlinkSync(filePath);
516
569
  }
517
570
  catch { }
518
571
  });
@@ -539,36 +592,24 @@ function apply(ctx, config) {
539
592
  if (!worker_threads_1.isMainThread)
540
593
  return;
541
594
  clearAllCache();
542
- if (config.debug) {
543
- logger.info('视频解析插件已加载,调试模式已开启');
544
- }
595
+ logger.info('视频解析插件已加载');
545
596
  const http = axios_1.default.create({
546
597
  timeout: config.timeout,
547
- headers: { 'User-Agent': config.userAgent }
598
+ headers: { 'User-Agent': config.userAgent },
599
+ maxRedirects: 5,
600
+ validateStatus: (status) => status >= 200 && status < 500
548
601
  });
549
602
  async function tryAPI(apiFunc, apiName) {
550
603
  try {
551
- if (config.debug) {
552
- logger.debug(`尝试调用API: ${apiName}`);
553
- }
554
604
  const result = await apiFunc();
555
- if (config.debug && result) {
556
- logger.debug(`API ${apiName} 调用成功`);
557
- }
558
605
  return result;
559
606
  }
560
607
  catch (error) {
561
- if (config.debug) {
562
- logger.debug(`API ${apiName} 调用失败: ${getErrorMessage(error)}`);
563
- }
564
608
  return null;
565
609
  }
566
610
  }
567
611
  async function requestAPI(apiUrl, params, method = 'GET') {
568
612
  try {
569
- if (config.debug) {
570
- logger.debug(`请求API: ${apiUrl}, 方法: ${method}, 参数:`, params);
571
- }
572
613
  let response;
573
614
  if (method.toUpperCase() === 'GET') {
574
615
  response = await http.get(apiUrl, { params });
@@ -576,22 +617,13 @@ function apply(ctx, config) {
576
617
  else {
577
618
  response = await http.post(apiUrl, params);
578
619
  }
579
- if (config.debug) {
580
- logger.debug(`API响应: ${apiUrl}, 状态码: ${response.status}`);
581
- }
582
620
  return response.data;
583
621
  }
584
622
  catch (error) {
585
- if (config.debug) {
586
- logger.debug(`API请求失败 ${apiUrl}: ${getErrorMessage(error)}`);
587
- }
588
623
  throw error;
589
624
  }
590
625
  }
591
626
  async function parseBilibili(realUrl) {
592
- if (config.debug) {
593
- logger.debug(`开始解析B站链接: ${realUrl}`);
594
- }
595
627
  const preferred = config.enableApiSelection ? config.preferredApi?.bilibili : 'https://api.xingzhige.com/API/b_parse/';
596
628
  const apis = [preferred];
597
629
  if (config.bilibiliAccessKey && preferred.includes('xingzhige')) {
@@ -610,15 +642,14 @@ function apply(ctx, config) {
610
642
  }
611
643
  const otherApis = [
612
644
  { url: 'https://api.xingzhige.com/API/b_parse/', method: 'GET' },
613
- { url: 'https://api.xingzhige.com/API/b_video/', method: 'GET' },
614
- { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' },
615
645
  { url: 'https://api.bugpk.com/api/bilibili', method: 'GET' },
646
+ { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' },
616
647
  { url: 'https://api.bilibili.com/x/web-interface/view', method: 'GET' }
617
648
  ].filter(api => api.url !== preferred);
618
649
  for (const apiInfo of otherApis) {
619
650
  const result = await tryAPI(async () => {
620
651
  const params = { url: realUrl };
621
- if (apiInfo.url.includes('xingzhige.com/API/b_video/')) {
652
+ if (apiInfo.url.includes('bilibili.com/x/web-interface/view')) {
622
653
  const vid = vid_type_parse(realUrl);
623
654
  if (vid.type === 'bv') {
624
655
  params.bvid = vid.id;
@@ -638,7 +669,7 @@ function apply(ctx, config) {
638
669
  }
639
670
  else if (apiInfo.url.includes('bugpk.com')) {
640
671
  if ((data?.code === 200 || data?.code === 0) && data?.data) {
641
- return { data: parseData(data.data, config.maxDescLength, 'bilibili'), msg: 'B站解析成功' };
672
+ return { data: parseData(data, config.maxDescLength, 'bilibili'), msg: 'B站解析成功' };
642
673
  }
643
674
  }
644
675
  else if (apiInfo.url.includes('bilibili.com') && data?.code === 0 && data?.data) {
@@ -657,35 +688,31 @@ function apply(ctx, config) {
657
688
  return result;
658
689
  }
659
690
  logger.error(`B站解析失败 - URL: ${realUrl}, 错误码: 2001`);
660
- return { data: null, msg: 'B站解析失败' };
691
+ return { data: null, msg: 'B站解析失败 (错误码: 2001)' };
661
692
  }
662
693
  async function parseKuaishou(realUrl) {
663
- if (config.debug) {
664
- logger.debug(`开始解析快手链接: ${realUrl}`);
665
- }
666
- const preferred = config.enableApiSelection ? config.preferredApi?.kuaishou : 'https://api.xingzhige.com/API/kuaishou/';
694
+ const preferred = config.enableApiSelection ? config.preferredApi?.kuaishou : 'https://api.bugpk.com/api/short_videos';
667
695
  const apis = [{ url: preferred, method: 'GET' }];
668
696
  const otherApis = [
669
- { url: 'https://api.xingzhige.com/API/kuaishou/', method: 'GET' },
670
- { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' },
671
- { url: 'https://api.bugpk.com/api/ksjx', method: 'GET' },
672
697
  { url: 'https://api.bugpk.com/api/kuaishou', method: 'GET' },
698
+ { url: 'https://api.bugpk.com/api/ksjx', method: 'GET' },
673
699
  { url: 'https://api.bugpk.com/api/ksimg', method: 'GET' },
674
- { url: 'https://api.suyanw.cn/api/kuaishou.php', method: 'GET' }
700
+ { url: 'https://api.suyanw.cn/api/kuaishou.php', method: 'GET' },
701
+ { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' }
675
702
  ].filter(api => api.url !== preferred);
676
703
  apis.push(...otherApis);
677
704
  for (const apiInfo of apis) {
678
705
  const result = await tryAPI(async () => {
679
706
  const data = await requestAPI(apiInfo.url, { url: realUrl }, apiInfo.method);
680
- if (apiInfo.url.includes('xingzhige')) {
681
- if (data?.jx?.length) {
682
- return { data: parseData(parse_xingzhige_data(data, 'kuaishou'), config.maxDescLength, 'kuaishou'), msg: '快手解析成功' };
707
+ if (apiInfo.url.includes('suyanw.cn')) {
708
+ if (data?.code === 200) {
709
+ return { data: parseData(parse_suyanw_data(data), config.maxDescLength, 'kuaishou'), msg: '快手解析成功' };
683
710
  }
684
711
  }
685
712
  else if (apiInfo.url.includes('bugpk.com')) {
686
713
  if ((data?.code === 200 || data?.code === 0)) {
687
714
  if (data.data) {
688
- return { data: parseData(data.data, config.maxDescLength, 'kuaishou'), msg: '快手解析成功' };
715
+ return { data: parseData(data, config.maxDescLength, 'kuaishou'), msg: '快手解析成功' };
689
716
  }
690
717
  else if (data.images) {
691
718
  return {
@@ -700,45 +727,38 @@ function apply(ctx, config) {
700
727
  }
701
728
  }
702
729
  }
703
- else if (apiInfo.url.includes('suyanw.cn')) {
704
- if (data?.code === 200) {
705
- return { data: parseData(parse_suyanw_data(data), config.maxDescLength, 'kuaishou'), msg: '快手解析成功' };
706
- }
707
- }
708
730
  return null;
709
731
  }, apiInfo.url);
710
732
  if (result)
711
733
  return result;
712
734
  }
713
735
  logger.error(`快手解析失败 - URL: ${realUrl}, 错误码: 2002`);
714
- return { data: null, msg: '快手解析失败' };
736
+ return { data: null, msg: '快手解析失败 (错误码: 2002)' };
715
737
  }
716
738
  async function parseDouyin(realUrl) {
717
- if (config.debug) {
718
- logger.debug(`开始解析抖音链接: ${realUrl}`);
719
- }
720
739
  const preferred = config.enableApiSelection ? config.preferredApi?.douyin : 'https://api.xingzhige.com/API/douyin/';
721
740
  const apis = [{ url: preferred, method: 'GET' }];
722
741
  const otherApis = [
723
742
  { url: 'https://api.xingzhige.com/API/douyin/', method: 'GET' },
724
- { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' },
725
743
  { url: 'https://api.bugpk.com/api/douyin', method: 'GET' },
726
744
  { url: 'https://api.bugpk.com/api/dyjx', method: 'GET' },
727
- { url: 'https://api.bugpk.com/api/dylive', method: 'GET' }
745
+ { url: 'https://api.bugpk.com/api/dylive', method: 'GET' },
746
+ { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' }
728
747
  ].filter(api => api.url !== preferred);
729
748
  apis.push(...otherApis);
730
749
  for (const apiInfo of apis) {
731
750
  const result = await tryAPI(async () => {
732
- const data = await requestAPI(apiInfo.url, { url: realUrl }, apiInfo.method);
751
+ const method = apiInfo.url.includes('bugpk.com') ? 'POST' : 'GET';
752
+ const data = await requestAPI(apiInfo.url, { url: realUrl }, method);
733
753
  if (apiInfo.url.includes('xingzhige')) {
734
- if (data?.jx?.length) {
754
+ if (data?.jx?.length || data?.data) {
735
755
  return { data: parseData(parse_xingzhige_data(data, 'douyin'), config.maxDescLength, 'douyin'), msg: '抖音解析成功' };
736
756
  }
737
757
  }
738
758
  else if (apiInfo.url.includes('bugpk.com')) {
739
759
  if ((data?.code === 200 || data?.code === 0)) {
740
760
  if (data.data) {
741
- return { data: parseData(data.data, config.maxDescLength, 'douyin'), msg: '抖音解析成功' };
761
+ return { data: parseData(data, config.maxDescLength, 'douyin'), msg: '抖音解析成功' };
742
762
  }
743
763
  }
744
764
  }
@@ -748,77 +768,41 @@ function apply(ctx, config) {
748
768
  return result;
749
769
  }
750
770
  logger.error(`抖音解析失败 - URL: ${realUrl}, 错误码: 2003`);
751
- return { data: null, msg: '抖音解析失败' };
752
- }
753
- async function parseXigua(realUrl) {
754
- if (config.debug) {
755
- logger.debug(`开始解析西瓜视频链接: ${realUrl}`);
756
- }
757
- const preferred = config.enableApiSelection ? config.preferredApi?.xigua : 'https://api.xingzhige.com/API/xigua/';
758
- const apis = [{ url: preferred, method: 'GET' }];
759
- const otherApis = [
760
- { url: 'https://api.xingzhige.com/API/xigua/', method: 'GET' },
761
- { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' },
762
- { url: 'https://api.bugpk.com/api/toutiao', method: 'GET' }
763
- ].filter(api => api.url !== preferred);
764
- apis.push(...otherApis);
765
- for (const apiInfo of apis) {
766
- const result = await tryAPI(async () => {
767
- const data = await requestAPI(apiInfo.url, { url: realUrl }, apiInfo.method);
768
- if (apiInfo.url.includes('xingzhige')) {
769
- if (data?.jx?.length) {
770
- return { data: parseData(parse_xingzhige_data(data, 'xigua'), config.maxDescLength, 'xigua'), msg: '西瓜视频解析成功' };
771
- }
772
- }
773
- else if (apiInfo.url.includes('bugpk.com')) {
774
- if ((data?.code === 200 || data?.code === 0) && data?.data) {
775
- return { data: parseData(data.data, config.maxDescLength, 'xigua'), msg: '西瓜视频解析成功' };
776
- }
777
- }
778
- return null;
779
- }, apiInfo.url);
780
- if (result)
781
- return result;
782
- }
783
- logger.error(`西瓜视频解析失败 - URL: ${realUrl}, 错误码: 2004`);
784
- return { data: null, msg: '西瓜视频解析失败' };
771
+ return { data: null, msg: '抖音解析失败 (错误码: 2003)' };
785
772
  }
786
773
  async function parseOther(realUrl, platform) {
787
- if (config.debug) {
788
- logger.debug(`开始解析${platform}链接: ${realUrl}`);
789
- }
790
774
  const preferred = config.enableApiSelection ? config.preferredApi?.[platform] : 'https://api.bugpk.com/api/short_videos';
791
775
  const apis = [{ url: preferred, method: 'GET' }];
792
776
  const platformApis = {
793
777
  xiaohongshu: [
794
- { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' },
795
778
  { url: 'https://api.bugpk.com/api/xhsjx', method: 'GET' },
796
779
  { url: 'https://api.bugpk.com/api/xhsimg', method: 'GET' },
797
780
  { url: 'https://api.bugpk.com/api/xhslive', method: 'GET' },
798
- { url: 'https://api.bugpk.com/api/xhs', method: 'GET' }
781
+ { url: 'https://api.bugpk.com/api/xhs', method: 'GET' },
782
+ { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' }
799
783
  ],
800
784
  weibo: [
801
- { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' },
802
785
  { url: 'https://api.bugpk.com/api/weibo', method: 'GET' },
803
- { url: 'https://api.bugpk.com/api/weibo_v', method: 'GET' }
786
+ { url: 'https://api.bugpk.com/api/weibo_v', method: 'GET' },
787
+ { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' }
804
788
  ],
805
789
  toutiao: [
806
- { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' },
807
- { url: 'https://api.bugpk.com/api/toutiao', method: 'GET' }
790
+ { url: 'https://api.bugpk.com/api/toutiao', method: 'GET' },
791
+ { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' }
808
792
  ],
809
793
  pipigx: [
810
- { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' },
811
794
  { url: 'https://api.bugpk.com/api/pipigx', method: 'GET' },
812
- { url: 'https://api.suyanw.cn/api/pipigx.php', method: 'GET' }
795
+ { url: 'https://api.suyanw.cn/api/pipigx.php', method: 'GET' },
796
+ { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' }
813
797
  ],
814
798
  pipixia: [
815
- { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' },
816
- { url: 'https://api.bugpk.com/api/pipixia', method: 'GET' }
799
+ { url: 'https://api.bugpk.com/api/pipixia', method: 'GET' },
800
+ { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' }
817
801
  ],
818
802
  zuiyou: [
819
- { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' },
820
803
  { url: 'https://api.bugpk.com/api/zuiyou', method: 'GET' },
821
- { url: 'https://api.suyanw.cn/api/zuiyou.php', method: 'GET' }
804
+ { url: 'https://api.suyanw.cn/api/zuiyou.php', method: 'GET' },
805
+ { url: 'https://api.bugpk.com/api/short_videos', method: 'GET' }
822
806
  ]
823
807
  };
824
808
  const otherApis = (platformApis[platform] || []).filter(api => api.url !== preferred);
@@ -829,7 +813,7 @@ function apply(ctx, config) {
829
813
  if (apiInfo.url.includes('bugpk.com') || apiInfo.url.includes('suyanw.cn')) {
830
814
  if (data?.code === 200 || data?.code === 0) {
831
815
  if (data.data) {
832
- return { data: parseData(data.data, config.maxDescLength, platform), msg: '解析成功' };
816
+ return { data: parseData(data, config.maxDescLength, platform), msg: '解析成功' };
833
817
  }
834
818
  else if (data.images) {
835
819
  return {
@@ -850,26 +834,20 @@ function apply(ctx, config) {
850
834
  return result;
851
835
  }
852
836
  logger.error(`${platform}解析失败 - URL: ${realUrl}, 错误码: 2005`);
853
- return { data: null, msg: '解析失败,请稍后重试' };
837
+ return { data: null, msg: '解析失败,请稍后重试 (错误码: 2005)' };
854
838
  }
855
839
  async function parse(url) {
856
- if (config.debug) {
857
- logger.debug(`开始解析URL: ${url}`);
858
- }
859
840
  const realUrl = await resolveShortUrl(url);
860
- if (config.debug) {
861
- logger.debug(`解析后URL: ${realUrl}`);
862
- }
863
841
  const platform = getPlatformType(realUrl);
864
842
  if (!platform || !config.platformEnable[platform]) {
865
- logger.error(`解析失败 - 平台: ${platform || '未知'}, URL: ${url}, 错误码: 1001`);
866
- return { data: null, msg: platform ? '该平台解析已关闭' : '不支持该平台链接' };
843
+ const code = !platform ? 1001 : 1002;
844
+ logger.error(`解析失败 - 平台: ${platform || '未知'}, URL: ${url}, 错误码: ${code}`);
845
+ return { data: null, msg: platform ? `该平台解析已关闭 (错误码: ${code})` : `不支持该平台链接 (错误码: ${code})` };
867
846
  }
868
847
  const parsers = {
869
848
  bilibili: parseBilibili,
870
849
  kuaishou: parseKuaishou,
871
- douyin: parseDouyin,
872
- xigua: parseXigua
850
+ douyin: parseDouyin
873
851
  };
874
852
  if (parsers[platform]) {
875
853
  return parsers[platform](realUrl);
@@ -880,27 +858,15 @@ function apply(ctx, config) {
880
858
  const hash = crypto_1.default.createHash('md5').update(url).digest('hex');
881
859
  const now = Date.now();
882
860
  if (processed.get(hash) && now - processed.get(hash) < config.sameLinkInterval * 1000) {
883
- if (config.debug) {
884
- logger.debug(`重复解析,跳过: ${url}`);
885
- }
886
- return { data: null, msg: '请勿重复解析' };
861
+ return { data: null, msg: '请勿重复解析 (错误码: 1003)' };
887
862
  }
888
863
  processed.set(hash, now);
889
- if (config.debug) {
890
- logger.debug(`开始处理URL: ${url}`);
891
- }
892
864
  const result = await parse(url);
893
865
  if (!result.data) {
894
- if (config.debug) {
895
- logger.debug(`解析失败: ${url}, 原因: ${result.msg}`);
896
- }
897
866
  return { data: null, msg: result.msg };
898
867
  }
899
868
  const platform = getPlatformType(url);
900
869
  const text = generateFormattedText(platform || 'bilibili', result.data, config);
901
- if (config.debug) {
902
- logger.debug(`解析成功: ${url}, 标题: ${result.data.title}`);
903
- }
904
870
  return {
905
871
  data: { text, cover: result.data.cover, images: result.data.images, video: result.data.video, type: result.data.type, live_photo: result.data.live_photo },
906
872
  msg: 'ok'
@@ -910,7 +876,7 @@ function apply(ctx, config) {
910
876
  if (config.videoSendTimeout <= 0) {
911
877
  return session.send(content).catch((err) => {
912
878
  if (!config.ignoreSendError)
913
- logger.error('发送消息失败:', err.message);
879
+ logger.error(`发送消息失败 (错误码: 4001): ${err.message}`);
914
880
  return null;
915
881
  });
916
882
  }
@@ -919,7 +885,7 @@ function apply(ctx, config) {
919
885
  new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), config.videoSendTimeout))
920
886
  ]).catch((err) => {
921
887
  if (!config.ignoreSendError)
922
- logger.error('发送消息超时:', err.message);
888
+ logger.error(`发送消息超时 (错误码: 4002): ${err.message}`);
923
889
  return null;
924
890
  });
925
891
  }
@@ -931,9 +897,6 @@ function apply(ctx, config) {
931
897
  clearTimeout(buffer.timer);
932
898
  linkBuffer.delete(key);
933
899
  }
934
- if (config.debug) {
935
- logger.debug(`开始处理批量URL: ${urls.length}个`);
936
- }
937
900
  const items = [];
938
901
  const errs = [];
939
902
  for (const url of urls) {
@@ -941,7 +904,7 @@ function apply(ctx, config) {
941
904
  if (result.data) {
942
905
  items.push(result.data);
943
906
  }
944
- else if (result.msg !== '请勿重复解析') {
907
+ else if (result.msg !== '请勿重复解析 (错误码: 1003)') {
945
908
  errs.push(`【${url.slice(0, 22)}...】:${result.msg}`);
946
909
  logger.error(`解析失败: ${url}, 原因: ${result.msg}`);
947
910
  }
@@ -969,9 +932,6 @@ function apply(ctx, config) {
969
932
  }
970
933
  return;
971
934
  }
972
- if (config.debug) {
973
- logger.debug(`成功解析: ${items.length}个`);
974
- }
975
935
  for (const item of items) {
976
936
  try {
977
937
  if (enableForward) {
@@ -1002,7 +962,7 @@ function apply(ctx, config) {
1002
962
  videoElem = koishi_1.h.file(filePath);
1003
963
  }
1004
964
  catch (error) {
1005
- logger.error(`视频下载失败: ${getErrorMessage(error)}`);
965
+ logger.error(`视频下载失败 (错误码: 4003): ${getErrorMessage(error)}`);
1006
966
  videoElem = koishi_1.h.video(item.video);
1007
967
  }
1008
968
  }
@@ -1046,7 +1006,7 @@ function apply(ctx, config) {
1046
1006
  videoElem = koishi_1.h.file(filePath);
1047
1007
  }
1048
1008
  catch (error) {
1049
- logger.error(`视频下载失败: ${getErrorMessage(error)}`);
1009
+ logger.error(`视频下载失败 (错误码: 4003): ${getErrorMessage(error)}`);
1050
1010
  videoElem = koishi_1.h.video(item.video);
1051
1011
  }
1052
1012
  }
@@ -1060,8 +1020,8 @@ function apply(ctx, config) {
1060
1020
  }
1061
1021
  }
1062
1022
  catch (error) {
1063
- logger.error(`处理内容失败: ${getErrorMessage(error)}`);
1064
- await sendTimeout(session, `❌ 处理${item.type}内容失败: ${getErrorMessage(error)}`);
1023
+ logger.error(`处理内容失败 (错误码: 4004): ${getErrorMessage(error)}`);
1024
+ await sendTimeout(session, `❌ 处理${item.type}内容失败: ${getErrorMessage(error)} (错误码: 4004)`);
1065
1025
  }
1066
1026
  }
1067
1027
  if (enableForward && forwardMessages.length) {
@@ -1069,7 +1029,7 @@ function apply(ctx, config) {
1069
1029
  await sendTimeout(session, (0, koishi_1.h)('message', { forward: true }, forwardMessages.slice(0, 100)));
1070
1030
  }
1071
1031
  catch (error) {
1072
- logger.error(`合并转发失败: ${getErrorMessage(error)}`);
1032
+ logger.error(`合并转发失败 (错误码: 4005): ${getErrorMessage(error)}`);
1073
1033
  for (const node of forwardMessages) {
1074
1034
  await sendTimeout(session, node.data.content);
1075
1035
  await delay(500);
@@ -1080,12 +1040,22 @@ function apply(ctx, config) {
1080
1040
  ctx.on('message', async (session) => {
1081
1041
  if (!config.enable || !config.autoParse)
1082
1042
  return;
1083
- const urls = extractUrl(session.content.trim(), config.enableBvAvParse);
1043
+ let textContent = '';
1044
+ if (Array.isArray(session.elements)) {
1045
+ session.elements.forEach((element) => {
1046
+ if (element.type === 'text') {
1047
+ textContent += element.content;
1048
+ }
1049
+ });
1050
+ }
1051
+ else {
1052
+ textContent = session.content || '';
1053
+ }
1054
+ if (!textContent.trim())
1055
+ return;
1056
+ const urls = extractUrl(textContent.trim(), config.enableBvAvParse);
1084
1057
  if (!urls.length)
1085
1058
  return;
1086
- if (config.debug) {
1087
- logger.debug(`收到消息,提取到URL: ${urls.length}个`);
1088
- }
1089
1059
  const key = `${session.platform}:${session.userId}:${session.channelId}`;
1090
1060
  const uniqueUrls = [...new Set(urls)];
1091
1061
  if (linkBuffer.has(key)) {
@@ -1095,9 +1065,6 @@ function apply(ctx, config) {
1095
1065
  buffer.urls.push(...newUrls);
1096
1066
  clearTimeout(buffer.timer);
1097
1067
  buffer.timer = setTimeout(() => flush(session), config.messageBufferDelay * 1000);
1098
- if (config.debug) {
1099
- logger.debug(`缓冲中添加新URL: ${newUrls.length}个`);
1100
- }
1101
1068
  }
1102
1069
  return;
1103
1070
  }
@@ -1111,17 +1078,14 @@ function apply(ctx, config) {
1111
1078
  timer: setTimeout(() => flush(session), config.messageBufferDelay * 1000),
1112
1079
  tipMsgId
1113
1080
  });
1114
- if (config.debug) {
1115
- logger.debug(`创建新缓冲,等待处理: ${uniqueUrls.length}个`);
1116
- }
1117
1081
  });
1118
1082
  ctx.command('parse <url>', '手动解析视频链接')
1119
1083
  .action(async ({ session }, url) => {
1120
1084
  if (!url)
1121
- return '请输入视频链接';
1085
+ return '请输入视频链接 (错误码: 5001)';
1122
1086
  const urls = extractUrl(url, config.enableBvAvParse);
1123
1087
  if (!urls.length)
1124
- return '不支持该链接';
1088
+ return '不支持该链接 (错误码: 1001)';
1125
1089
  await flush(session, [...new Set(urls)]);
1126
1090
  });
1127
1091
  ctx.command('clear-cache', '清空解析缓存与临时文件')
@@ -1143,12 +1107,13 @@ function apply(ctx, config) {
1143
1107
  const now = Date.now();
1144
1108
  fs_1.default.readdirSync(tempDir).forEach(file => {
1145
1109
  try {
1146
- const stat = fs_1.default.statSync(path_1.default.join(tempDir, file));
1110
+ const filePath = path_1.default.join(tempDir, file);
1111
+ const stat = fs_1.default.statSync(filePath);
1147
1112
  if (now - stat.mtimeMs > 3600000)
1148
- fs_1.default.unlinkSync(path_1.default.join(tempDir, file));
1113
+ fs_1.default.unlinkSync(filePath);
1149
1114
  }
1150
1115
  catch (error) {
1151
- logger.error(`清理临时文件失败: ${file}, ${getErrorMessage(error)}`);
1116
+ logger.error(`清理临时文件失败 (错误码: 4006): ${file}, ${getErrorMessage(error)}`);
1152
1117
  }
1153
1118
  });
1154
1119
  }, 1800000);
@@ -1156,7 +1121,7 @@ function apply(ctx, config) {
1156
1121
  setInterval(clearAllCache, config.autoClearCacheInterval * 60000);
1157
1122
  }
1158
1123
  process.on('exit', clearAllCache);
1159
- logger.info('视频解析插件已加载');
1124
+ logger.info('视频解析插件已加载完成');
1160
1125
  }
1161
1126
  module.exports = {
1162
1127
  name: exports.name,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-video-parser-all",
3
- "description": "Koishi 全平台视频解析插件,支持抖音/快手/B站/小红书/微博/今日头条/皮皮搞笑/皮皮虾/西瓜视频/最右视频链接解析",
4
- "version": "0.4.7",
3
+ "description": "Koishi 全平台视频解析插件,支持抖音/快手/B站/小红书/微博/今日头条/皮皮搞笑/皮皮虾/右视频链接解析",
4
+ "version": "0.4.8",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [