koishi-plugin-video-parser-all 0.4.3 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/lib/index.d.ts +26 -0
  2. package/lib/index.js +555 -506
  3. package/package.json +1 -1
package/lib/index.d.ts CHANGED
@@ -57,6 +57,19 @@ export declare const Config: Schema<{
57
57
  messageBufferDelay?: number | null | undefined;
58
58
  } & {
59
59
  autoClearCacheInterval?: number | null | undefined;
60
+ } & {
61
+ preferredApi?: ({
62
+ bilibili?: "xingzhige" | "universal" | "platform" | "official" | null | undefined;
63
+ douyin?: "xingzhige" | "universal" | "platform" | null | undefined;
64
+ kuaishou?: "xingzhige" | "universal" | "platform" | null | undefined;
65
+ xigua?: "xingzhige" | "universal" | "platform" | null | undefined;
66
+ xiaohongshu?: "universal" | "platform" | null | undefined;
67
+ weibo?: "universal" | "platform" | null | undefined;
68
+ toutiao?: "universal" | "platform" | null | undefined;
69
+ pipigx?: "universal" | "platform" | null | undefined;
70
+ pipixia?: "universal" | "platform" | null | undefined;
71
+ zuiyou?: "universal" | "platform" | null | undefined;
72
+ } & Dict) | null | undefined;
60
73
  }, {
61
74
  enable: boolean;
62
75
  botName: string;
@@ -114,5 +127,18 @@ export declare const Config: Schema<{
114
127
  messageBufferDelay: number;
115
128
  } & {
116
129
  autoClearCacheInterval: number;
130
+ } & {
131
+ preferredApi: Schemastery.ObjectT<{
132
+ bilibili: Schema<"xingzhige" | "universal" | "platform" | "official", "xingzhige" | "universal" | "platform" | "official">;
133
+ douyin: Schema<"xingzhige" | "universal" | "platform", "xingzhige" | "universal" | "platform">;
134
+ kuaishou: Schema<"xingzhige" | "universal" | "platform", "xingzhige" | "universal" | "platform">;
135
+ xigua: Schema<"xingzhige" | "universal" | "platform", "xingzhige" | "universal" | "platform">;
136
+ xiaohongshu: Schema<"universal" | "platform", "universal" | "platform">;
137
+ weibo: Schema<"universal" | "platform", "universal" | "platform">;
138
+ toutiao: Schema<"universal" | "platform", "universal" | "platform">;
139
+ pipigx: Schema<"universal" | "platform", "universal" | "platform">;
140
+ pipixia: Schema<"universal" | "platform", "universal" | "platform">;
141
+ zuiyou: Schema<"universal" | "platform", "universal" | "platform">;
142
+ }>;
117
143
  }>;
118
144
  export declare function apply(ctx: any, config: any): void;
package/lib/index.js CHANGED
@@ -81,8 +81,21 @@ exports.Config = koishi_1.Schema.intersect([
81
81
  koishi_1.Schema.object({
82
82
  autoClearCacheInterval: koishi_1.Schema.number().min(0).default(0).description('自动清理缓存间隔(分钟,0为关闭)'),
83
83
  }).description('缓存清理设置'),
84
+ koishi_1.Schema.object({
85
+ preferredApi: koishi_1.Schema.object({
86
+ bilibili: koishi_1.Schema.union(['xingzhige', 'universal', 'platform', 'official']).default('xingzhige').description('B站首选解析源'),
87
+ douyin: koishi_1.Schema.union(['xingzhige', 'universal', 'platform']).default('xingzhige').description('抖音首选解析源'),
88
+ kuaishou: koishi_1.Schema.union(['xingzhige', 'universal', 'platform']).default('xingzhige').description('快手首选解析源'),
89
+ xigua: koishi_1.Schema.union(['xingzhige', 'universal', 'platform']).default('xingzhige').description('西瓜视频首选解析源'),
90
+ xiaohongshu: koishi_1.Schema.union(['universal', 'platform']).default('universal').description('小红书首选解析源'),
91
+ weibo: koishi_1.Schema.union(['universal', 'platform']).default('universal').description('微博首选解析源'),
92
+ toutiao: koishi_1.Schema.union(['universal', 'platform']).default('universal').description('今日头条首选解析源'),
93
+ pipigx: koishi_1.Schema.union(['universal', 'platform']).default('universal').description('皮皮搞笑首选解析源'),
94
+ pipixia: koishi_1.Schema.union(['universal', 'platform']).default('universal').description('皮皮虾首选解析源'),
95
+ zuiyou: koishi_1.Schema.union(['universal', 'platform']).default('universal').description('最右首选解析源'),
96
+ }).description('首选解析源设置(将优先尝试用户选择的API,失败后自动尝试其他)')
97
+ }).description('API选择设置'),
84
98
  ]);
85
- // 辅助函数:安全获取错误消息
86
99
  function getErrorMessage(error) {
87
100
  if (error instanceof Error)
88
101
  return error.message;
@@ -149,24 +162,24 @@ const PLATFORM_KEYWORDS = {
149
162
  universal_card: ['mini_program', '小程序卡片', 'lightapp', 'json', 'markdown', 'share', 'contact', 'location', 'music', 'forward', 'node', 'mface', 'file']
150
163
  };
151
164
  const API_CONFIG = {
152
- universal: 'https://api.bugpk.com/api/short_videos',
165
+ universal: 'https://api.bugpk.com/api/short_videos ',
153
166
  xingzhige: {
154
- bilibili: { url: 'https://api.xingzhige.com/API/b_parse/', vidUrl: 'https://api.xingzhige.com/API/b_video/', bangumiUrl: 'https://api.xingzhige.com/API/b_bangumi/' },
155
- kuaishou: { url: 'https://api.xingzhige.com/API/kuaishou/' },
156
- douyin: { url: 'https://api.xingzhige.com/API/douyin/' },
157
- xigua: { url: 'https://api.xingzhige.com/API/xigua/' }
167
+ bilibili: { url: 'https://api.xingzhige.com/API/b_parse/ ', vidUrl: 'https://api.xingzhige.com/API/b_parse/ ', bangumiUrl: 'https://api.xingzhige.com/API/b_bangumi/ ' },
168
+ kuaishou: { url: 'https://api.xingzhige.com/API/kuaishou/ ' },
169
+ douyin: { url: 'https://api.xingzhige.com/API/douyin/ ' },
170
+ xigua: { url: 'https://api.xingzhige.com/API/xigua/ ' }
158
171
  },
159
172
  platform: {
160
- bilibili: ['https://api.bugpk.com/api/bilibili'],
161
- 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'],
162
- xiaohongshu: ['https://api.bugpk.com/api/xhsjx', 'https://api.bugpk.com/api/xhsimg', 'https://api.bugpk.com/api/xhslive'],
163
- weibo: ['https://api.bugpk.com/api/weibo', 'https://api.bugpk.com/api/weibo_v'],
164
- toutiao: ['https://api.bugpk.com/api/toutiao'],
165
- pipigx: ['https://api.bugpk.com/api/pipigx', 'https://api.suyanw.cn/api/pipigx.php'],
166
- pipixia: ['https://api.bugpk.com/api/pipixia'],
167
- douyin: ['https://api.bugpk.com/api/douyin', 'https://api.bugpk.com/api/dyjx', 'https://api.bugpk.com/api/dylive'],
168
- zuiyou: ['https://api.suyanw.cn/api/zuiyou.php'],
169
- xigua: ['https://api.bugpk.com/api/toutiao']
173
+ bilibili: ['https://api.bugpk.com/api/bilibili '],
174
+ 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 '],
175
+ xiaohongshu: ['https://api.bugpk.com/api/xhsjx ', 'https://api.bugpk.com/api/xhsimg ', 'https://api.bugpk.com/api/xhslive '],
176
+ weibo: ['https://api.bugpk.com/api/weibo ', 'https://api.bugpk.com/api/weibo_v '],
177
+ toutiao: ['https://api.bugpk.com/api/toutiao '],
178
+ pipigx: ['https://api.bugpk.com/api/pipigx ', 'https://api.suyanw.cn/api/pipigx.php '],
179
+ pipixia: ['https://api.bugpk.com/api/pipixia '],
180
+ douyin: ['https://api.bugpk.com/api/douyin ', 'https://api.bugpk.com/api/dyjx ', 'https://api.bugpk.com/api/dylive '],
181
+ zuiyou: ['https://api.suyanw.cn/api/zuiyou.php '],
182
+ xigua: ['https://api.bugpk.com/api/toutiao ']
170
183
  }
171
184
  };
172
185
  function vid_type_parse(id) {
@@ -187,10 +200,10 @@ async function fetch_bilibili_official_info(id, userAgent) {
187
200
  let url = '';
188
201
  switch (vid.type) {
189
202
  case "av":
190
- url = `https://api.bilibili.com/x/web-interface/view?aid=${vid.id}`;
203
+ url = `https://api.bilibili.com/x/web-interface/view?aid= ${vid.id}`;
191
204
  break;
192
205
  case "bv":
193
- url = `https://api.bilibili.com/x/web-interface/view?bvid=${vid.id}`;
206
+ url = `https://api.bilibili.com/x/web-interface/view?bvid= ${vid.id}`;
194
207
  break;
195
208
  default:
196
209
  return null;
@@ -208,11 +221,11 @@ async function fetch_bilibili_official_info(id, userAgent) {
208
221
  }
209
222
  async function get_bilibili_play_url(bvid, cid, userAgent) {
210
223
  try {
211
- const playUrl = `https://api.bilibili.com/x/player/playurl?fnval=80&cid=${cid}&bvid=${bvid}`;
224
+ const playUrl = `https://api.bilibili.com/x/player/playurl?fnval=80&cid= ${cid}&bvid=${bvid}`;
212
225
  const playData = await axios_1.default.get(playUrl, {
213
226
  headers: {
214
227
  "User-Agent": userAgent,
215
- "Referer": "https://www.bilibili.com/"
228
+ "Referer": "https://www.bilibili.com/ "
216
229
  },
217
230
  timeout: 10000
218
231
  });
@@ -285,20 +298,21 @@ function parse_xingzhige_data(resData, platform) {
285
298
  result.type = result.images.length > 0 ? 'image' : 'video';
286
299
  }
287
300
  else if (platform === 'bilibili') {
288
- result.title = resData.title || '';
289
- result.author = resData.name || '未知UP主';
290
- result.desc = resData.desc || '';
291
- result.cover = resData.fm || '';
292
- result.video = resData.url || '';
301
+ const d = resData.data || resData;
302
+ result.title = d.video?.title || d.title || '';
303
+ result.author = d.owner?.name || d.name || '未知UP主';
304
+ result.desc = d.video?.desc || d.desc || '';
305
+ result.cover = d.video?.fm || d.fm || '';
306
+ result.video = d.video?.url || d.url || '';
293
307
  result.stat = {
294
- view: resData.view || 0,
295
- reply: resData.reply || 0,
296
- favorite: resData.favorite || 0,
297
- like: resData.like || 0,
298
- coin: resData.coin || 0,
299
- share: resData.share || 0,
300
- danmuku: resData.danmuku || 0,
301
- duration: resData.duration || 0
308
+ view: d.stat?.view || 0,
309
+ reply: d.stat?.reply || 0,
310
+ favorite: d.stat?.favorite || 0,
311
+ like: d.stat?.like || 0,
312
+ coin: d.stat?.coin || 0,
313
+ share: d.stat?.share || 0,
314
+ danmuku: d.stat?.danmuku || 0,
315
+ duration: d.duration || 0
302
316
  };
303
317
  }
304
318
  else if (platform === 'bilibili_bangumi') {
@@ -359,7 +373,7 @@ function extractCardUrl(content) {
359
373
  if (appid === '1108291530') {
360
374
  const vidMatch = jsonData.data.pagePath.match(/vid=(\w+)/);
361
375
  if (vidMatch)
362
- realUrls.push(`https://www.bilibili.com/video/${vidMatch[1]}`);
376
+ realUrls.push(`https://www.bilibili.com/video/ ${vidMatch[1]}`);
363
377
  }
364
378
  }
365
379
  }
@@ -455,7 +469,7 @@ async function resolveShortUrl(url) {
455
469
  }
456
470
  async function shortUrl(url) {
457
471
  try {
458
- const res = await axios_1.default.get('https://api.oick.cn/dwz/api.php', { params: { url }, timeout: 5000 });
472
+ const res = await axios_1.default.get('https://api.oick.cn/dwz/api.php ', { params: { url }, timeout: 5000 });
459
473
  if (res.data.code === 200)
460
474
  return res.data.short_url;
461
475
  }
@@ -591,15 +605,12 @@ function buildForwardNode(session, content, botName) {
591
605
  else {
592
606
  messageContent = [koishi_1.h.text(String(content))];
593
607
  }
594
- return {
595
- type: 'node',
596
- data: {
597
- name: botName.substring(0, 15),
598
- uin: session.selfId.toString(),
599
- content: messageContent,
600
- time: Math.floor(Date.now() / 1000)
608
+ return (0, koishi_1.h)('node', {
609
+ user: {
610
+ nickname: botName.substring(0, 15),
611
+ user_id: session.selfId
601
612
  }
602
- };
613
+ }, messageContent);
603
614
  }
604
615
  function apply(ctx, config) {
605
616
  if (!worker_threads_1.isMainThread)
@@ -619,177 +630,187 @@ function apply(ctx, config) {
619
630
  return { data: null, msg: platform ? '该平台解析已关闭' : '不支持该平台链接' };
620
631
  }
621
632
  if (platform === 'bilibili') {
622
- const bangumiIds = extract_bangumi_ids(realUrl);
623
- if (bangumiIds.ss_id || bangumiIds.ep_id) {
624
- try {
625
- const params = {};
626
- if (bangumiIds.ss_id)
627
- params.ss_id = bangumiIds.ss_id;
628
- if (bangumiIds.ep_id)
629
- params.ep_id = bangumiIds.ep_id;
630
- if (config.bilibiliAccessKey)
631
- params.access_key = config.bilibiliAccessKey;
632
- if (config.debug)
633
- ctx.logger.debug(`请求B站番剧API: ${API_CONFIG.xingzhige.bilibili.bangumiUrl}, 参数: ${JSON.stringify(params)}`);
634
- const res = await http({
635
- method: 'GET',
636
- url: API_CONFIG.xingzhige.bilibili.bangumiUrl,
637
- params
638
- });
639
- if (config.debug)
640
- ctx.logger.debug(`B站番剧API响应状态: ${res.status}`);
641
- if (res.data && (res.data.season || res.data.bangumi)) {
642
- const xgData = parse_xingzhige_data(res.data, 'bilibili_bangumi');
643
- const parseResult = parseData(xgData, config.maxDescLength, 'bilibili_bangumi');
644
- if (config.debug)
645
- ctx.logger.debug('B站番剧解析成功');
646
- return { data: parseResult, msg: 'B站解析成功' };
647
- }
648
- else {
649
- if (config.debug)
650
- ctx.logger.debug('B站番剧API返回数据无效');
651
- }
652
- }
653
- catch (error) {
654
- if (config.debug) {
655
- ctx.logger.debug(`B站番剧API请求失败: ${getErrorMessage(error)}`);
656
- }
657
- else {
658
- ctx.logger.error(`B站番剧解析失败: ${getErrorMessage(error)}`);
659
- }
660
- }
661
- }
662
- try {
663
- const apiUrl = API_CONFIG.xingzhige.bilibili.vidUrl;
664
- const params = (() => {
665
- const biliId = realUrl.startsWith('BV') || realUrl.startsWith('av') || realUrl.startsWith('AV') ? realUrl : extract_bilibili_id(realUrl);
666
- if (!biliId)
667
- return { url: realUrl };
668
- const vid = vid_type_parse(biliId);
669
- return vid.type === 'bv' ? { bvid: vid.id } : { aid: vid.id };
670
- })();
671
- if (config.debug)
672
- ctx.logger.debug(`请求B站VID API: ${apiUrl}, 参数: ${JSON.stringify(params)}`);
673
- const res = await http({
674
- method: 'GET',
675
- url: apiUrl,
676
- params
677
- });
678
- if (config.debug)
679
- ctx.logger.debug(`B站VID API响应状态: ${res.status}`);
680
- if (res.data && (res.data.url || res.data.title)) {
681
- const xgData = parse_xingzhige_data(res.data, platform);
682
- const parseResult = parseData(xgData, config.maxDescLength, platform);
683
- if (config.debug)
684
- ctx.logger.debug('B站VID解析成功');
685
- return { data: parseResult, msg: 'B站解析成功' };
686
- }
687
- else {
688
- if (config.debug)
689
- ctx.logger.debug('B站VID API返回数据无效');
690
- }
633
+ const preferred = config.preferredApi?.bilibili || 'xingzhige';
634
+ // 根据首选源构建尝试顺序
635
+ const tryOrder = [];
636
+ if (preferred === 'xingzhige') {
637
+ tryOrder.push('xingzhige_vid', 'xingzhige_bangumi', 'universal', 'official', 'platform');
691
638
  }
692
- catch (error) {
693
- if (config.debug) {
694
- ctx.logger.debug(`B站VID API请求失败: ${getErrorMessage(error)}`);
695
- }
696
- else {
697
- ctx.logger.error(`B站VID解析失败: ${getErrorMessage(error)}`);
698
- }
639
+ else if (preferred === 'universal') {
640
+ tryOrder.push('universal', 'xingzhige_vid', 'xingzhige_bangumi', 'official', 'platform');
699
641
  }
700
- try {
701
- const universalUrl = API_CONFIG.universal;
702
- if (config.debug)
703
- ctx.logger.debug(`请求通用API: ${universalUrl}, 参数: { url: ${realUrl} }`);
704
- const res = await http.get(universalUrl, { params: { url: realUrl } });
705
- if (config.debug)
706
- ctx.logger.debug(`通用API响应状态: ${res.status}`);
707
- if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
708
- const parseResult = parseData(res.data.data, config.maxDescLength, platform);
709
- if (config.debug)
710
- ctx.logger.debug('通用API解析成功');
711
- return { data: parseResult, msg: 'B站解析成功' };
712
- }
713
- else {
714
- if (config.debug)
715
- ctx.logger.debug('通用API返回数据无效');
716
- }
642
+ else if (preferred === 'official') {
643
+ tryOrder.push('official', 'xingzhige_vid', 'xingzhige_bangumi', 'universal', 'platform');
717
644
  }
718
- catch (error) {
719
- if (config.debug) {
720
- ctx.logger.debug(`通用API请求失败: ${getErrorMessage(error)}`);
721
- }
722
- else {
723
- ctx.logger.error(`通用API解析失败: ${getErrorMessage(error)}`);
724
- }
645
+ else if (preferred === 'platform') {
646
+ tryOrder.push('platform', 'xingzhige_vid', 'xingzhige_bangumi', 'universal', 'official');
725
647
  }
726
- try {
727
- const biliId = realUrl.startsWith('BV') || realUrl.startsWith('av') || realUrl.startsWith('AV') ? realUrl : extract_bilibili_id(realUrl);
728
- if (biliId) {
729
- if (config.debug)
730
- ctx.logger.debug(`请求B站官方API: 获取信息 ${biliId}`);
731
- const officialInfo = await fetch_bilibili_official_info(biliId, config.userAgent);
732
- if (officialInfo && officialInfo.code === 0 && officialInfo.data) {
733
- const { bvid, cid } = officialInfo.data;
648
+ for (const step of tryOrder) {
649
+ if (step === 'xingzhige_vid') {
650
+ try {
651
+ const apiUrl = API_CONFIG.xingzhige.bilibili.vidUrl;
652
+ const params = { url: realUrl };
653
+ if (config.debug)
654
+ ctx.logger.debug(`${apiUrl}?${new URLSearchParams(params).toString()}`);
655
+ const res = await http({
656
+ method: 'GET',
657
+ url: apiUrl,
658
+ params
659
+ });
734
660
  if (config.debug)
735
- ctx.logger.debug(`请求B站官方播放地址: bvid=${bvid}, cid=${cid}`);
736
- const playInfo = await get_bilibili_play_url(bvid, cid, config.userAgent);
737
- if (playInfo) {
738
- const parseResult = parseData({
739
- ...officialInfo,
740
- playUrl: playInfo.url,
741
- duration: playInfo.duration
742
- }, config.maxDescLength, platform);
661
+ ctx.logger.debug(`响应状态: ${res.status}`);
662
+ if (res.data && (res.data.data || res.data.title)) {
663
+ const xgData = parse_xingzhige_data(res.data, platform);
664
+ const parseResult = parseData(xgData, config.maxDescLength, platform);
743
665
  if (config.debug)
744
- ctx.logger.debug('B站官方API解析成功');
666
+ ctx.logger.debug('解析成功');
745
667
  return { data: parseResult, msg: 'B站解析成功' };
746
668
  }
747
669
  else {
748
670
  if (config.debug)
749
- ctx.logger.debug('B站官方播放地址获取失败');
671
+ ctx.logger.debug('返回数据无效');
750
672
  }
751
673
  }
752
- else {
753
- if (config.debug)
754
- ctx.logger.debug('B站官方信息获取失败');
674
+ catch (error) {
675
+ if (config.debug) {
676
+ ctx.logger.debug(`请求失败: ${getErrorMessage(error)}`);
677
+ }
755
678
  }
756
679
  }
757
- }
758
- catch (error) {
759
- if (config.debug) {
760
- ctx.logger.debug(`B站官方API请求失败: ${getErrorMessage(error)}`);
761
- }
762
- else {
763
- ctx.logger.error(`B站官方API解析失败: ${getErrorMessage(error)}`);
680
+ else if (step === 'xingzhige_bangumi') {
681
+ const bangumiIds = extract_bangumi_ids(realUrl);
682
+ if (bangumiIds.ss_id || bangumiIds.ep_id) {
683
+ try {
684
+ const params = {};
685
+ if (bangumiIds.ss_id)
686
+ params.ss_id = bangumiIds.ss_id;
687
+ if (bangumiIds.ep_id)
688
+ params.ep_id = bangumiIds.ep_id;
689
+ if (config.bilibiliAccessKey)
690
+ params.access_key = config.bilibiliAccessKey;
691
+ const apiUrl = API_CONFIG.xingzhige.bilibili.bangumiUrl;
692
+ if (config.debug)
693
+ ctx.logger.debug(`${apiUrl}?${new URLSearchParams(params).toString()}`);
694
+ const res = await http({
695
+ method: 'GET',
696
+ url: apiUrl,
697
+ params
698
+ });
699
+ if (config.debug)
700
+ ctx.logger.debug(`响应状态: ${res.status}`);
701
+ if (res.data && (res.data.season || res.data.bangumi)) {
702
+ const xgData = parse_xingzhige_data(res.data, 'bilibili_bangumi');
703
+ const parseResult = parseData(xgData, config.maxDescLength, 'bilibili_bangumi');
704
+ if (config.debug)
705
+ ctx.logger.debug('解析成功');
706
+ return { data: parseResult, msg: 'B站解析成功' };
707
+ }
708
+ else {
709
+ if (config.debug)
710
+ ctx.logger.debug('返回数据无效');
711
+ }
712
+ }
713
+ catch (error) {
714
+ if (config.debug) {
715
+ ctx.logger.debug(`请求失败: ${getErrorMessage(error)}`);
716
+ }
717
+ }
718
+ }
764
719
  }
765
- }
766
- const platformApis = API_CONFIG.platform.bilibili || [];
767
- for (const apiUrl of platformApis) {
768
- try {
769
- if (config.debug)
770
- ctx.logger.debug(`请求B站平台API: ${apiUrl}, 参数: { url: ${realUrl} }`);
771
- const res = await http.get(apiUrl, { params: { url: realUrl } });
772
- if (config.debug)
773
- ctx.logger.debug(`B站平台API响应状态: ${res.status}`);
774
- if ((res.data.code === 0 || res.data.code === 200) && res.data.data) {
775
- const parseResult = parseData(res.data.data, config.maxDescLength, platform);
720
+ else if (step === 'universal') {
721
+ try {
722
+ const universalUrl = API_CONFIG.universal;
776
723
  if (config.debug)
777
- ctx.logger.debug('B站平台API解析成功');
778
- return { data: parseResult, msg: 'B站解析成功' };
779
- }
780
- else {
724
+ ctx.logger.debug(`${universalUrl}?url=${encodeURIComponent(realUrl)}`);
725
+ const res = await http.get(universalUrl, { params: { url: realUrl } });
781
726
  if (config.debug)
782
- ctx.logger.debug('B站平台API返回数据无效');
727
+ ctx.logger.debug(`响应状态: ${res.status}`);
728
+ if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
729
+ const parseResult = parseData(res.data.data, config.maxDescLength, platform);
730
+ if (config.debug)
731
+ ctx.logger.debug('解析成功');
732
+ return { data: parseResult, msg: 'B站解析成功' };
733
+ }
734
+ else {
735
+ if (config.debug)
736
+ ctx.logger.debug('返回数据无效');
737
+ }
738
+ }
739
+ catch (error) {
740
+ if (config.debug) {
741
+ ctx.logger.debug(`请求失败: ${getErrorMessage(error)}`);
742
+ }
743
+ }
744
+ }
745
+ else if (step === 'official') {
746
+ try {
747
+ const biliId = realUrl.startsWith('BV') || realUrl.startsWith('av') || realUrl.startsWith('AV') ? realUrl : extract_bilibili_id(realUrl);
748
+ if (biliId) {
749
+ if (config.debug)
750
+ ctx.logger.debug(`官方信息获取: ${biliId}`);
751
+ const officialInfo = await fetch_bilibili_official_info(biliId, config.userAgent);
752
+ if (officialInfo && officialInfo.code === 0 && officialInfo.data) {
753
+ const { bvid, cid } = officialInfo.data;
754
+ if (config.debug)
755
+ ctx.logger.debug(`官方播放地址: bvid=${bvid}, cid=${cid}`);
756
+ const playInfo = await get_bilibili_play_url(bvid, cid, config.userAgent);
757
+ if (playInfo) {
758
+ const parseResult = parseData({
759
+ ...officialInfo,
760
+ playUrl: playInfo.url,
761
+ duration: playInfo.duration
762
+ }, config.maxDescLength, platform);
763
+ if (config.debug)
764
+ ctx.logger.debug('解析成功');
765
+ return { data: parseResult, msg: 'B站解析成功' };
766
+ }
767
+ else {
768
+ if (config.debug)
769
+ ctx.logger.debug('播放地址获取失败');
770
+ }
771
+ }
772
+ else {
773
+ if (config.debug)
774
+ ctx.logger.debug('官方信息获取失败');
775
+ }
776
+ }
777
+ }
778
+ catch (error) {
779
+ if (config.debug) {
780
+ ctx.logger.debug(`官方API请求失败: ${getErrorMessage(error)}`);
781
+ }
783
782
  }
784
783
  }
785
- catch (error) {
786
- if (config.debug) {
787
- ctx.logger.debug(`B站平台API请求失败: ${apiUrl}, 错误: ${getErrorMessage(error)}`);
784
+ else if (step === 'platform') {
785
+ const platformApis = API_CONFIG.platform.bilibili || [];
786
+ for (const apiUrl of platformApis) {
787
+ try {
788
+ if (config.debug)
789
+ ctx.logger.debug(`${apiUrl}?url=${encodeURIComponent(realUrl)}`);
790
+ const res = await http.get(apiUrl, { params: { url: realUrl } });
791
+ if (config.debug)
792
+ ctx.logger.debug(`响应状态: ${res.status}`);
793
+ if ((res.data.code === 0 || res.data.code === 200) && res.data.data) {
794
+ const parseResult = parseData(res.data.data, config.maxDescLength, platform);
795
+ if (config.debug)
796
+ ctx.logger.debug('解析成功');
797
+ return { data: parseResult, msg: 'B站解析成功' };
798
+ }
799
+ else {
800
+ if (config.debug)
801
+ ctx.logger.debug('返回数据无效');
802
+ }
803
+ }
804
+ catch (error) {
805
+ if (config.debug) {
806
+ ctx.logger.debug(`请求失败: ${apiUrl}, 错误: ${getErrorMessage(error)}`);
807
+ }
808
+ }
788
809
  }
789
810
  }
790
811
  }
791
812
  if (config.debug) {
792
- ctx.logger.debug(`所有B站API尝试失败, URL: ${realUrl}`);
813
+ ctx.logger.debug(`所有API尝试失败, URL: ${realUrl}`);
793
814
  }
794
815
  else {
795
816
  ctx.logger.error(`B站解析失败: ${realUrl}`);
@@ -797,85 +818,91 @@ function apply(ctx, config) {
797
818
  return { data: null, msg: 'B站解析失败' };
798
819
  }
799
820
  if (platform === 'kuaishou') {
800
- try {
801
- const apiUrl = API_CONFIG.xingzhige.kuaishou.url;
802
- if (config.debug)
803
- ctx.logger.debug(`请求快手xingzhige API: ${apiUrl}, 参数: { url: ${realUrl} }`);
804
- const res = await http({
805
- method: 'GET',
806
- url: apiUrl,
807
- params: { url: realUrl }
808
- });
809
- if (config.debug)
810
- ctx.logger.debug(`快手xingzhige API响应状态: ${res.status}`);
811
- if (res.data && res.data.jx && res.data.jx.length > 0) {
812
- const xgData = parse_xingzhige_data(res.data, platform);
813
- const parseResult = parseData(xgData, config.maxDescLength, platform);
814
- if (config.debug)
815
- ctx.logger.debug('快手xingzhige解析成功');
816
- return { data: parseResult, msg: '快手解析成功' };
817
- }
818
- else {
819
- if (config.debug)
820
- ctx.logger.debug('快手xingzhige API返回数据无效');
821
- }
822
- }
823
- catch (error) {
824
- if (config.debug) {
825
- ctx.logger.debug(`快手xingzhige API请求失败: ${getErrorMessage(error)}`);
826
- }
827
- else {
828
- ctx.logger.error(`快手xingzhige解析失败: ${getErrorMessage(error)}`);
829
- }
830
- }
831
- try {
832
- const universalUrl = API_CONFIG.universal;
833
- if (config.debug)
834
- ctx.logger.debug(`请求通用API: ${universalUrl}, 参数: { url: ${realUrl} }`);
835
- const res = await http.get(universalUrl, { params: { url: realUrl } });
836
- if (config.debug)
837
- ctx.logger.debug(`通用API响应状态: ${res.status}`);
838
- if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
839
- const parseResult = parseData(res.data.data, config.maxDescLength, platform);
840
- if (config.debug)
841
- ctx.logger.debug('通用API解析成功');
842
- return { data: parseResult, msg: '快手解析成功' };
843
- }
844
- else {
845
- if (config.debug)
846
- ctx.logger.debug('通用API返回数据无效');
847
- }
848
- }
849
- catch (error) {
850
- if (config.debug) {
851
- ctx.logger.debug(`通用API请求失败: ${getErrorMessage(error)}`);
852
- }
853
- else {
854
- ctx.logger.error(`通用API解析失败: ${getErrorMessage(error)}`);
855
- }
856
- }
857
- const platformApis = API_CONFIG.platform.kuaishou || [];
858
- for (const apiUrl of platformApis) {
859
- try {
860
- if (config.debug)
861
- ctx.logger.debug(`请求快手平台API: ${apiUrl}, 参数: { url: ${realUrl} }`);
862
- const res = await http.get(apiUrl, { params: { url: realUrl } });
863
- if (config.debug)
864
- ctx.logger.debug(`快手平台API响应状态: ${res.status}`);
865
- if ((res.data.code === 200 || res.data.code === 0) && (res.data.data || res.data.image)) {
866
- const parseResult = parseData(res.data.data || res.data, config.maxDescLength, platform);
821
+ const preferred = config.preferredApi?.kuaishou || 'xingzhige';
822
+ const tryOrder = preferred === 'xingzhige' ? ['xingzhige', 'universal', 'platform'] :
823
+ preferred === 'universal' ? ['universal', 'xingzhige', 'platform'] :
824
+ ['platform', 'xingzhige', 'universal'];
825
+ for (const step of tryOrder) {
826
+ if (step === 'xingzhige') {
827
+ try {
828
+ const apiUrl = API_CONFIG.xingzhige.kuaishou.url;
829
+ if (config.debug)
830
+ ctx.logger.debug(`${apiUrl}?url=${encodeURIComponent(realUrl)}`);
831
+ const res = await http({
832
+ method: 'GET',
833
+ url: apiUrl,
834
+ params: { url: realUrl }
835
+ });
867
836
  if (config.debug)
868
- ctx.logger.debug('快手平台API解析成功');
869
- return { data: parseResult, msg: '快手解析成功' };
837
+ ctx.logger.debug(`响应状态: ${res.status}`);
838
+ if (res.data && res.data.jx && res.data.jx.length > 0) {
839
+ const xgData = parse_xingzhige_data(res.data, platform);
840
+ const parseResult = parseData(xgData, config.maxDescLength, platform);
841
+ if (config.debug)
842
+ ctx.logger.debug('解析成功');
843
+ return { data: parseResult, msg: '快手解析成功' };
844
+ }
845
+ else {
846
+ if (config.debug)
847
+ ctx.logger.debug('返回数据无效');
848
+ }
870
849
  }
871
- else {
850
+ catch (error) {
851
+ if (config.debug) {
852
+ ctx.logger.debug(`请求失败: ${getErrorMessage(error)}`);
853
+ }
854
+ }
855
+ }
856
+ else if (step === 'universal') {
857
+ try {
858
+ const universalUrl = API_CONFIG.universal;
859
+ if (config.debug)
860
+ ctx.logger.debug(`${universalUrl}?url=${encodeURIComponent(realUrl)}`);
861
+ const res = await http.get(universalUrl, { params: { url: realUrl } });
872
862
  if (config.debug)
873
- ctx.logger.debug('快手平台API返回数据无效');
863
+ ctx.logger.debug(`响应状态: ${res.status}`);
864
+ if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
865
+ const parseResult = parseData(res.data.data, config.maxDescLength, platform);
866
+ if (config.debug)
867
+ ctx.logger.debug('解析成功');
868
+ return { data: parseResult, msg: '快手解析成功' };
869
+ }
870
+ else {
871
+ if (config.debug)
872
+ ctx.logger.debug('返回数据无效');
873
+ }
874
+ }
875
+ catch (error) {
876
+ if (config.debug) {
877
+ ctx.logger.debug(`请求失败: ${getErrorMessage(error)}`);
878
+ }
874
879
  }
875
880
  }
876
- catch (error) {
877
- if (config.debug) {
878
- ctx.logger.debug(`快手平台API请求失败: ${apiUrl}, 错误: ${getErrorMessage(error)}`);
881
+ else if (step === 'platform') {
882
+ const platformApis = API_CONFIG.platform.kuaishou || [];
883
+ for (const apiUrl of platformApis) {
884
+ try {
885
+ if (config.debug)
886
+ ctx.logger.debug(`${apiUrl}?url=${encodeURIComponent(realUrl)}`);
887
+ const res = await http.get(apiUrl, { params: { url: realUrl } });
888
+ if (config.debug)
889
+ ctx.logger.debug(`响应状态: ${res.status}`);
890
+ if ((res.data.code === 200 || res.data.code === 0) && (res.data.data || res.data.image)) {
891
+ const parseResult = parseData(res.data.data || res.data, config.maxDescLength, platform);
892
+ if (config.debug)
893
+ ctx.logger.debug('解析成功');
894
+ return { data: parseResult, msg: '快手解析成功' };
895
+ }
896
+ else {
897
+ if (config.debug)
898
+ ctx.logger.debug('返回数据无效');
899
+ }
900
+ }
901
+ catch (error) {
902
+ if (config.debug) {
903
+ ctx.logger.debug(`请求失败: ${apiUrl}, 错误: ${getErrorMessage(error)}`);
904
+ }
905
+ }
879
906
  }
880
907
  }
881
908
  }
@@ -888,85 +915,91 @@ function apply(ctx, config) {
888
915
  return { data: null, msg: '快手解析失败' };
889
916
  }
890
917
  if (platform === 'douyin') {
891
- try {
892
- const apiUrl = API_CONFIG.xingzhige.douyin.url;
893
- if (config.debug)
894
- ctx.logger.debug(`请求抖音xingzhige API: ${apiUrl}, 参数: { url: ${realUrl} }`);
895
- const res = await http({
896
- method: 'GET',
897
- url: apiUrl,
898
- params: { url: realUrl }
899
- });
900
- if (config.debug)
901
- ctx.logger.debug(`抖音xingzhige API响应状态: ${res.status}`);
902
- if (res.data && res.data.jx && res.data.jx.length > 0) {
903
- const xgData = parse_xingzhige_data(res.data, platform);
904
- const parseResult = parseData(xgData, config.maxDescLength, platform);
905
- if (config.debug)
906
- ctx.logger.debug('抖音xingzhige解析成功');
907
- return { data: parseResult, msg: '抖音解析成功' };
908
- }
909
- else {
910
- if (config.debug)
911
- ctx.logger.debug('抖音xingzhige API返回数据无效');
912
- }
913
- }
914
- catch (error) {
915
- if (config.debug) {
916
- ctx.logger.debug(`抖音xingzhige API请求失败: ${getErrorMessage(error)}`);
917
- }
918
- else {
919
- ctx.logger.error(`抖音xingzhige解析失败: ${getErrorMessage(error)}`);
920
- }
921
- }
922
- try {
923
- const universalUrl = API_CONFIG.universal;
924
- if (config.debug)
925
- ctx.logger.debug(`请求通用API: ${universalUrl}, 参数: { url: ${realUrl} }`);
926
- const res = await http.get(universalUrl, { params: { url: realUrl } });
927
- if (config.debug)
928
- ctx.logger.debug(`通用API响应状态: ${res.status}`);
929
- if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
930
- const parseResult = parseData(res.data.data, config.maxDescLength, platform);
931
- if (config.debug)
932
- ctx.logger.debug('通用API解析成功');
933
- return { data: parseResult, msg: '抖音解析成功' };
934
- }
935
- else {
936
- if (config.debug)
937
- ctx.logger.debug('通用API返回数据无效');
938
- }
939
- }
940
- catch (error) {
941
- if (config.debug) {
942
- ctx.logger.debug(`通用API请求失败: ${getErrorMessage(error)}`);
943
- }
944
- else {
945
- ctx.logger.error(`通用API解析失败: ${getErrorMessage(error)}`);
946
- }
947
- }
948
- const platformApis = API_CONFIG.platform.douyin || [];
949
- for (const apiUrl of platformApis) {
950
- try {
951
- if (config.debug)
952
- ctx.logger.debug(`请求抖音平台API: ${apiUrl}, 参数: { url: ${realUrl} }`);
953
- const res = await http.get(apiUrl, { params: { url: realUrl } });
954
- if (config.debug)
955
- ctx.logger.debug(`抖音平台API响应状态: ${res.status}`);
956
- if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
957
- const parseResult = parseData(res.data.data, config.maxDescLength, platform);
918
+ const preferred = config.preferredApi?.douyin || 'xingzhige';
919
+ const tryOrder = preferred === 'xingzhige' ? ['xingzhige', 'universal', 'platform'] :
920
+ preferred === 'universal' ? ['universal', 'xingzhige', 'platform'] :
921
+ ['platform', 'xingzhige', 'universal'];
922
+ for (const step of tryOrder) {
923
+ if (step === 'xingzhige') {
924
+ try {
925
+ const apiUrl = API_CONFIG.xingzhige.douyin.url;
926
+ if (config.debug)
927
+ ctx.logger.debug(`${apiUrl}?url=${encodeURIComponent(realUrl)}`);
928
+ const res = await http({
929
+ method: 'GET',
930
+ url: apiUrl,
931
+ params: { url: realUrl }
932
+ });
958
933
  if (config.debug)
959
- ctx.logger.debug('抖音平台API解析成功');
960
- return { data: parseResult, msg: '抖音解析成功' };
934
+ ctx.logger.debug(`响应状态: ${res.status}`);
935
+ if (res.data && res.data.jx && res.data.jx.length > 0) {
936
+ const xgData = parse_xingzhige_data(res.data, platform);
937
+ const parseResult = parseData(xgData, config.maxDescLength, platform);
938
+ if (config.debug)
939
+ ctx.logger.debug('解析成功');
940
+ return { data: parseResult, msg: '抖音解析成功' };
941
+ }
942
+ else {
943
+ if (config.debug)
944
+ ctx.logger.debug('返回数据无效');
945
+ }
961
946
  }
962
- else {
947
+ catch (error) {
948
+ if (config.debug) {
949
+ ctx.logger.debug(`请求失败: ${getErrorMessage(error)}`);
950
+ }
951
+ }
952
+ }
953
+ else if (step === 'universal') {
954
+ try {
955
+ const universalUrl = API_CONFIG.universal;
963
956
  if (config.debug)
964
- ctx.logger.debug('抖音平台API返回数据无效');
957
+ ctx.logger.debug(`${universalUrl}?url=${encodeURIComponent(realUrl)}`);
958
+ const res = await http.get(universalUrl, { params: { url: realUrl } });
959
+ if (config.debug)
960
+ ctx.logger.debug(`响应状态: ${res.status}`);
961
+ if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
962
+ const parseResult = parseData(res.data.data, config.maxDescLength, platform);
963
+ if (config.debug)
964
+ ctx.logger.debug('解析成功');
965
+ return { data: parseResult, msg: '抖音解析成功' };
966
+ }
967
+ else {
968
+ if (config.debug)
969
+ ctx.logger.debug('返回数据无效');
970
+ }
971
+ }
972
+ catch (error) {
973
+ if (config.debug) {
974
+ ctx.logger.debug(`请求失败: ${getErrorMessage(error)}`);
975
+ }
965
976
  }
966
977
  }
967
- catch (error) {
968
- if (config.debug) {
969
- ctx.logger.debug(`抖音平台API请求失败: ${apiUrl}, 错误: ${getErrorMessage(error)}`);
978
+ else if (step === 'platform') {
979
+ const platformApis = API_CONFIG.platform.douyin || [];
980
+ for (const apiUrl of platformApis) {
981
+ try {
982
+ if (config.debug)
983
+ ctx.logger.debug(`${apiUrl}?url=${encodeURIComponent(realUrl)}`);
984
+ const res = await http.get(apiUrl, { params: { url: realUrl } });
985
+ if (config.debug)
986
+ ctx.logger.debug(`响应状态: ${res.status}`);
987
+ if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
988
+ const parseResult = parseData(res.data.data, config.maxDescLength, platform);
989
+ if (config.debug)
990
+ ctx.logger.debug('解析成功');
991
+ return { data: parseResult, msg: '抖音解析成功' };
992
+ }
993
+ else {
994
+ if (config.debug)
995
+ ctx.logger.debug('返回数据无效');
996
+ }
997
+ }
998
+ catch (error) {
999
+ if (config.debug) {
1000
+ ctx.logger.debug(`请求失败: ${apiUrl}, 错误: ${getErrorMessage(error)}`);
1001
+ }
1002
+ }
970
1003
  }
971
1004
  }
972
1005
  }
@@ -979,85 +1012,91 @@ function apply(ctx, config) {
979
1012
  return { data: null, msg: '抖音解析失败' };
980
1013
  }
981
1014
  if (platform === 'xigua') {
982
- try {
983
- const apiUrl = API_CONFIG.xingzhige.xigua.url;
984
- if (config.debug)
985
- ctx.logger.debug(`请求西瓜xingzhige API: ${apiUrl}, 参数: { url: ${realUrl} }`);
986
- const res = await http({
987
- method: 'GET',
988
- url: apiUrl,
989
- params: { url: realUrl }
990
- });
991
- if (config.debug)
992
- ctx.logger.debug(`西瓜xingzhige API响应状态: ${res.status}`);
993
- if (res.data && res.data.jx && res.data.jx.length > 0) {
994
- const xgData = parse_xingzhige_data(res.data, platform);
995
- const parseResult = parseData(xgData, config.maxDescLength, platform);
996
- if (config.debug)
997
- ctx.logger.debug('西瓜xingzhige解析成功');
998
- return { data: parseResult, msg: '西瓜视频解析成功' };
999
- }
1000
- else {
1001
- if (config.debug)
1002
- ctx.logger.debug('西瓜xingzhige API返回数据无效');
1003
- }
1004
- }
1005
- catch (error) {
1006
- if (config.debug) {
1007
- ctx.logger.debug(`西瓜xingzhige API请求失败: ${getErrorMessage(error)}`);
1008
- }
1009
- else {
1010
- ctx.logger.error(`西瓜xingzhige解析失败: ${getErrorMessage(error)}`);
1011
- }
1012
- }
1013
- try {
1014
- const universalUrl = API_CONFIG.universal;
1015
- if (config.debug)
1016
- ctx.logger.debug(`请求通用API: ${universalUrl}, 参数: { url: ${realUrl} }`);
1017
- const res = await http.get(universalUrl, { params: { url: realUrl } });
1018
- if (config.debug)
1019
- ctx.logger.debug(`通用API响应状态: ${res.status}`);
1020
- if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
1021
- const parseResult = parseData(res.data.data, config.maxDescLength, platform);
1022
- if (config.debug)
1023
- ctx.logger.debug('通用API解析成功');
1024
- return { data: parseResult, msg: '西瓜视频解析成功' };
1025
- }
1026
- else {
1027
- if (config.debug)
1028
- ctx.logger.debug('通用API返回数据无效');
1029
- }
1030
- }
1031
- catch (error) {
1032
- if (config.debug) {
1033
- ctx.logger.debug(`通用API请求失败: ${getErrorMessage(error)}`);
1034
- }
1035
- else {
1036
- ctx.logger.error(`通用API解析失败: ${getErrorMessage(error)}`);
1037
- }
1038
- }
1039
- const platformApis = API_CONFIG.platform.xigua || [];
1040
- for (const apiUrl of platformApis) {
1041
- try {
1042
- if (config.debug)
1043
- ctx.logger.debug(`请求西瓜平台API: ${apiUrl}, 参数: { url: ${realUrl} }`);
1044
- const res = await http.get(apiUrl, { params: { url: realUrl } });
1045
- if (config.debug)
1046
- ctx.logger.debug(`西瓜平台API响应状态: ${res.status}`);
1047
- if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
1048
- const parseResult = parseData(res.data.data, config.maxDescLength, platform);
1015
+ const preferred = config.preferredApi?.xigua || 'xingzhige';
1016
+ const tryOrder = preferred === 'xingzhige' ? ['xingzhige', 'universal', 'platform'] :
1017
+ preferred === 'universal' ? ['universal', 'xingzhige', 'platform'] :
1018
+ ['platform', 'xingzhige', 'universal'];
1019
+ for (const step of tryOrder) {
1020
+ if (step === 'xingzhige') {
1021
+ try {
1022
+ const apiUrl = API_CONFIG.xingzhige.xigua.url;
1049
1023
  if (config.debug)
1050
- ctx.logger.debug('西瓜平台API解析成功');
1051
- return { data: parseResult, msg: '西瓜视频解析成功' };
1024
+ ctx.logger.debug(`${apiUrl}?url=${encodeURIComponent(realUrl)}`);
1025
+ const res = await http({
1026
+ method: 'GET',
1027
+ url: apiUrl,
1028
+ params: { url: realUrl }
1029
+ });
1030
+ if (config.debug)
1031
+ ctx.logger.debug(`响应状态: ${res.status}`);
1032
+ if (res.data && res.data.jx && res.data.jx.length > 0) {
1033
+ const xgData = parse_xingzhige_data(res.data, platform);
1034
+ const parseResult = parseData(xgData, config.maxDescLength, platform);
1035
+ if (config.debug)
1036
+ ctx.logger.debug('解析成功');
1037
+ return { data: parseResult, msg: '西瓜视频解析成功' };
1038
+ }
1039
+ else {
1040
+ if (config.debug)
1041
+ ctx.logger.debug('返回数据无效');
1042
+ }
1052
1043
  }
1053
- else {
1044
+ catch (error) {
1045
+ if (config.debug) {
1046
+ ctx.logger.debug(`请求失败: ${getErrorMessage(error)}`);
1047
+ }
1048
+ }
1049
+ }
1050
+ else if (step === 'universal') {
1051
+ try {
1052
+ const universalUrl = API_CONFIG.universal;
1053
+ if (config.debug)
1054
+ ctx.logger.debug(`${universalUrl}?url=${encodeURIComponent(realUrl)}`);
1055
+ const res = await http.get(universalUrl, { params: { url: realUrl } });
1054
1056
  if (config.debug)
1055
- ctx.logger.debug('西瓜平台API返回数据无效');
1057
+ ctx.logger.debug(`响应状态: ${res.status}`);
1058
+ if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
1059
+ const parseResult = parseData(res.data.data, config.maxDescLength, platform);
1060
+ if (config.debug)
1061
+ ctx.logger.debug('解析成功');
1062
+ return { data: parseResult, msg: '西瓜视频解析成功' };
1063
+ }
1064
+ else {
1065
+ if (config.debug)
1066
+ ctx.logger.debug('返回数据无效');
1067
+ }
1068
+ }
1069
+ catch (error) {
1070
+ if (config.debug) {
1071
+ ctx.logger.debug(`请求失败: ${getErrorMessage(error)}`);
1072
+ }
1056
1073
  }
1057
1074
  }
1058
- catch (error) {
1059
- if (config.debug) {
1060
- ctx.logger.debug(`西瓜平台API请求失败: ${apiUrl}, 错误: ${getErrorMessage(error)}`);
1075
+ else if (step === 'platform') {
1076
+ const platformApis = API_CONFIG.platform.xigua || [];
1077
+ for (const apiUrl of platformApis) {
1078
+ try {
1079
+ if (config.debug)
1080
+ ctx.logger.debug(`${apiUrl}?url=${encodeURIComponent(realUrl)}`);
1081
+ const res = await http.get(apiUrl, { params: { url: realUrl } });
1082
+ if (config.debug)
1083
+ ctx.logger.debug(`响应状态: ${res.status}`);
1084
+ if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
1085
+ const parseResult = parseData(res.data.data, config.maxDescLength, platform);
1086
+ if (config.debug)
1087
+ ctx.logger.debug('解析成功');
1088
+ return { data: parseResult, msg: '西瓜视频解析成功' };
1089
+ }
1090
+ else {
1091
+ if (config.debug)
1092
+ ctx.logger.debug('返回数据无效');
1093
+ }
1094
+ }
1095
+ catch (error) {
1096
+ if (config.debug) {
1097
+ ctx.logger.debug(`请求失败: ${apiUrl}, 错误: ${getErrorMessage(error)}`);
1098
+ }
1099
+ }
1061
1100
  }
1062
1101
  }
1063
1102
  }
@@ -1072,112 +1111,122 @@ function apply(ctx, config) {
1072
1111
  const currentPlatform = platform;
1073
1112
  const nonKuaishouPlatforms = ['xiaohongshu', 'weibo', 'toutiao', 'pipigx', 'pipixia', 'zuiyou'];
1074
1113
  if (nonKuaishouPlatforms.includes(currentPlatform)) {
1075
- for (let retry = 0; retry <= config.retryTimes; retry++) {
1076
- try {
1077
- const universalUrl = API_CONFIG.universal;
1078
- if (config.debug)
1079
- ctx.logger.debug(`请求通用API: ${universalUrl}, 参数: { url: ${realUrl} }`);
1080
- const res = await http.get(universalUrl, { params: { url: realUrl } });
1081
- if (config.debug)
1082
- ctx.logger.debug(`通用API响应状态: ${res.status}`);
1083
- if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
1084
- const parseResult = parseData(res.data.data, config.maxDescLength, currentPlatform);
1085
- if (config.debug)
1086
- ctx.logger.debug('通用API解析成功');
1087
- return { data: parseResult, msg: '解析成功' };
1088
- }
1089
- else if (res.data.code === 201) {
1090
- if (config.debug)
1091
- ctx.logger.debug('通用API返回code 201');
1092
- break;
1093
- }
1094
- else {
1095
- if (config.debug)
1096
- ctx.logger.debug('通用API返回数据无效');
1097
- }
1098
- }
1099
- catch (error) {
1100
- if (config.debug) {
1101
- ctx.logger.debug(`通用API请求失败: ${getErrorMessage(error)}`);
1102
- }
1103
- if (retry === config.retryTimes)
1104
- break;
1105
- await delay(config.retryInterval);
1106
- }
1107
- }
1108
- }
1109
- const platformApis = API_CONFIG.platform[currentPlatform] || [];
1110
- for (let apiIndex = 0; apiIndex < platformApis.length; apiIndex++) {
1111
- const apiUrl = platformApis[apiIndex];
1112
- for (let retry = 0; retry <= config.retryTimes; retry++) {
1113
- try {
1114
- if (config.debug)
1115
- ctx.logger.debug(`请求平台API: ${apiUrl}, 参数: { url: ${realUrl} }`);
1116
- const res = await http.get(apiUrl, { params: { url: realUrl } });
1117
- if (config.debug)
1118
- ctx.logger.debug(`平台API响应状态: ${res.status}`);
1119
- let shouldContinue = false;
1120
- if ((res.data.code === 200 || res.data.code === 0)) {
1121
- let parseResult = null;
1122
- if (currentPlatform === 'kuaishou') {
1123
- if (res.data.image && !res.data.data) {
1124
- parseResult = parseData({
1125
- title: res.data.data?.title || '快手图集',
1126
- author: res.data.data?.author || '未知作者',
1127
- images: res.data.image,
1128
- type: 'image'
1129
- }, config.maxDescLength, currentPlatform);
1114
+ const preferred = config.preferredApi?.[currentPlatform] || 'universal';
1115
+ const tryOrder = preferred === 'universal' ? ['universal', 'platform'] : ['platform', 'universal'];
1116
+ for (const step of tryOrder) {
1117
+ if (step === 'universal') {
1118
+ for (let retry = 0; retry <= config.retryTimes; retry++) {
1119
+ try {
1120
+ const universalUrl = API_CONFIG.universal;
1121
+ if (config.debug)
1122
+ ctx.logger.debug(`${universalUrl}?url=${encodeURIComponent(realUrl)}`);
1123
+ const res = await http.get(universalUrl, { params: { url: realUrl } });
1124
+ if (config.debug)
1125
+ ctx.logger.debug(`响应状态: ${res.status}`);
1126
+ if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
1127
+ const parseResult = parseData(res.data.data, config.maxDescLength, currentPlatform);
1128
+ if (config.debug)
1129
+ ctx.logger.debug('解析成功');
1130
+ return { data: parseResult, msg: '解析成功' };
1130
1131
  }
1131
- else if (res.data.data) {
1132
- parseResult = parseData(res.data.data, config.maxDescLength, currentPlatform);
1132
+ else if (res.data.code === 201) {
1133
+ if (config.debug)
1134
+ ctx.logger.debug('返回code 201');
1135
+ break;
1133
1136
  }
1134
1137
  else {
1135
- shouldContinue = true;
1138
+ if (config.debug)
1139
+ ctx.logger.debug('返回数据无效');
1136
1140
  }
1137
1141
  }
1138
- else {
1139
- if (res.data.data) {
1140
- parseResult = parseData(res.data.data, config.maxDescLength, currentPlatform);
1141
- }
1142
- else {
1143
- shouldContinue = true;
1142
+ catch (error) {
1143
+ if (config.debug) {
1144
+ ctx.logger.debug(`请求失败: ${getErrorMessage(error)}`);
1144
1145
  }
1146
+ if (retry === config.retryTimes)
1147
+ break;
1148
+ await delay(config.retryInterval);
1145
1149
  }
1146
- if (parseResult) {
1147
- if (config.debug)
1148
- ctx.logger.debug('平台API解析成功');
1149
- return { data: parseResult, msg: '解析成功' };
1150
- }
1151
- }
1152
- if (shouldContinue && retry < config.retryTimes) {
1153
- if (config.debug)
1154
- ctx.logger.debug('平台API返回数据无效,准备重试');
1155
- await delay(config.retryInterval);
1156
- continue;
1157
- }
1158
- else {
1159
- if (config.debug)
1160
- ctx.logger.debug('平台API返回数据无效,放弃');
1161
- break;
1162
1150
  }
1163
1151
  }
1164
- catch (error) {
1165
- if (config.debug) {
1166
- ctx.logger.debug(`平台API请求失败: ${apiUrl}, 错误: ${getErrorMessage(error)}`);
1152
+ else if (step === 'platform') {
1153
+ const platformApis = API_CONFIG.platform[currentPlatform] || [];
1154
+ for (let apiIndex = 0; apiIndex < platformApis.length; apiIndex++) {
1155
+ const apiUrl = platformApis[apiIndex];
1156
+ for (let retry = 0; retry <= config.retryTimes; retry++) {
1157
+ try {
1158
+ if (config.debug)
1159
+ ctx.logger.debug(`${apiUrl}?url=${encodeURIComponent(realUrl)}`);
1160
+ const res = await http.get(apiUrl, { params: { url: realUrl } });
1161
+ if (config.debug)
1162
+ ctx.logger.debug(`响应状态: ${res.status}`);
1163
+ let shouldContinue = false;
1164
+ if ((res.data.code === 200 || res.data.code === 0)) {
1165
+ let parseResult = null;
1166
+ if (currentPlatform === 'kuaishou') {
1167
+ if (res.data.image && !res.data.data) {
1168
+ parseResult = parseData({
1169
+ title: res.data.data?.title || '快手图集',
1170
+ author: res.data.data?.author || '未知作者',
1171
+ images: res.data.image,
1172
+ type: 'image'
1173
+ }, config.maxDescLength, currentPlatform);
1174
+ }
1175
+ else if (res.data.data) {
1176
+ parseResult = parseData(res.data.data, config.maxDescLength, currentPlatform);
1177
+ }
1178
+ else {
1179
+ shouldContinue = true;
1180
+ }
1181
+ }
1182
+ else {
1183
+ if (res.data.data) {
1184
+ parseResult = parseData(res.data.data, config.maxDescLength, currentPlatform);
1185
+ }
1186
+ else {
1187
+ shouldContinue = true;
1188
+ }
1189
+ }
1190
+ if (parseResult) {
1191
+ if (config.debug)
1192
+ ctx.logger.debug('解析成功');
1193
+ return { data: parseResult, msg: '解析成功' };
1194
+ }
1195
+ }
1196
+ if (shouldContinue && retry < config.retryTimes) {
1197
+ if (config.debug)
1198
+ ctx.logger.debug('返回数据无效,准备重试');
1199
+ await delay(config.retryInterval);
1200
+ continue;
1201
+ }
1202
+ else {
1203
+ if (config.debug)
1204
+ ctx.logger.debug('返回数据无效,放弃');
1205
+ break;
1206
+ }
1207
+ }
1208
+ catch (error) {
1209
+ if (config.debug) {
1210
+ ctx.logger.debug(`请求失败: ${apiUrl}, 错误: ${getErrorMessage(error)}`);
1211
+ }
1212
+ if (retry === config.retryTimes)
1213
+ break;
1214
+ await delay(config.retryInterval);
1215
+ }
1216
+ }
1167
1217
  }
1168
- if (retry === config.retryTimes)
1169
- break;
1170
- await delay(config.retryInterval);
1171
1218
  }
1172
1219
  }
1220
+ if (config.debug) {
1221
+ ctx.logger.debug(`所有API尝试失败,平台: ${platform}, URL: ${realUrl}`);
1222
+ }
1223
+ else {
1224
+ ctx.logger.error(`解析失败: ${platform} ${realUrl}`);
1225
+ }
1226
+ return { data: null, msg: '解析失败,请稍后重试' };
1173
1227
  }
1174
- if (config.debug) {
1175
- ctx.logger.debug(`所有API尝试失败,平台: ${platform}, URL: ${realUrl}`);
1176
- }
1177
- else {
1178
- ctx.logger.error(`解析失败: ${platform} ${realUrl}`);
1179
- }
1180
- return { data: null, msg: '解析失败,请稍后重试' };
1228
+ // 其他平台(不应该走到这里)
1229
+ return { data: null, msg: '未知平台' };
1181
1230
  }
1182
1231
  async function processSingleUrl(session, url) {
1183
1232
  const hash = crypto_1.default.createHash('md5').update(url).digest('hex');
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-video-parser-all",
3
3
  "description": "Koishi 全平台视频解析插件,支持抖音/快手/B站/小红书/微博/今日头条/皮皮搞笑/皮皮虾/西瓜视频/最右视频链接解析",
4
- "version": "0.4.3",
4
+ "version": "0.4.4",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [