koishi-plugin-video-parser-all 1.3.6 → 1.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.d.ts CHANGED
@@ -58,7 +58,7 @@ export declare const Config: Schema<{
58
58
  downloadConcurrency?: number | null | undefined;
59
59
  mediaDownloadTimeout?: number | null | undefined;
60
60
  maxMediaSize?: number | null | undefined;
61
- downloadEngine?: "internal" | "aria2" | null | undefined;
61
+ downloadEngine?: "internal" | "aria2" | "downloads" | null | undefined;
62
62
  aria2Host?: string | null | undefined;
63
63
  aria2Port?: number | null | undefined;
64
64
  aria2Secret?: string | null | undefined;
@@ -93,11 +93,6 @@ export declare const Config: Schema<{
93
93
  } & {
94
94
  primaryApiUrl?: string | null | undefined;
95
95
  backupApiUrl?: string | null | undefined;
96
- apiKeys?: ({
97
- key?: string | null | undefined;
98
- weight?: number | null | undefined;
99
- } & import("cosmokit").Dict)[] | null | undefined;
100
- rotationMode?: "sequential" | "load_balance" | null | undefined;
101
96
  platformDedicatedFirst?: ({
102
97
  bilibili?: boolean | null | undefined;
103
98
  douyin?: boolean | null | undefined;
@@ -210,7 +205,7 @@ export declare const Config: Schema<{
210
205
  downloadConcurrency: number;
211
206
  mediaDownloadTimeout: number;
212
207
  maxMediaSize: number;
213
- downloadEngine: "internal" | "aria2";
208
+ downloadEngine: "internal" | "aria2" | "downloads";
214
209
  aria2Host: string;
215
210
  aria2Port: number;
216
211
  aria2Secret: string;
@@ -248,11 +243,6 @@ export declare const Config: Schema<{
248
243
  } & {
249
244
  primaryApiUrl: string;
250
245
  backupApiUrl: string;
251
- apiKeys: Schemastery.ObjectT<{
252
- key: Schema<string, string>;
253
- weight: Schema<number, number>;
254
- }>[];
255
- rotationMode: "sequential" | "load_balance";
256
246
  platformDedicatedFirst: Schemastery.ObjectT<{
257
247
  bilibili: Schema<boolean, boolean>;
258
248
  douyin: Schema<boolean, boolean>;
package/lib/index.js CHANGED
@@ -115,7 +115,7 @@ exports.Config = koishi_1.Schema.intersect([
115
115
  }).description('媒体发送'),
116
116
  koishi_1.Schema.object({
117
117
  showMusicVoice: koishi_1.Schema.boolean().default(false).description('音乐链接以语音形式发送'),
118
- showMusicVoiceFile: koishi_1.Schema.boolean().default(true).description('音乐语音是否以文件形式发送(关闭则只发送链接)'),
118
+ showMusicVoiceFile: koishi_1.Schema.boolean().default(true).description('音乐链接是否以语音形式发送(关闭则只发送链接)'),
119
119
  forceDownloadMusicVoice: koishi_1.Schema.boolean().default(false).description('强制下载音乐语音'),
120
120
  }).description('音乐语音(需 silk 和 ffmpeg)'),
121
121
  koishi_1.Schema.object({
@@ -127,6 +127,7 @@ exports.Config = koishi_1.Schema.intersect([
127
127
  downloadEngine: koishi_1.Schema.union([
128
128
  koishi_1.Schema.const('internal').description('内置下载'),
129
129
  koishi_1.Schema.const('aria2').description('aria2 下载'),
130
+ koishi_1.Schema.const('downloads').description('downloads 服务下载'),
130
131
  ]).default('internal').description('下载引擎'),
131
132
  aria2Host: koishi_1.Schema.string().default('127.0.0.1').description('aria2 RPC 地址'),
132
133
  aria2Port: koishi_1.Schema.number().default(6800).description('aria2 RPC 端口'),
@@ -169,14 +170,6 @@ exports.Config = koishi_1.Schema.intersect([
169
170
  koishi_1.Schema.object({
170
171
  primaryApiUrl: koishi_1.Schema.string().default('https://api.bugpk.com/api/short_videos').hidden(),
171
172
  backupApiUrl: koishi_1.Schema.string().default('https://api.bugpk.com/api/svparse').hidden(),
172
- apiKeys: koishi_1.Schema.array(koishi_1.Schema.object({
173
- key: koishi_1.Schema.string().required().description('API Key'),
174
- weight: koishi_1.Schema.number().min(1).default(1).description('权重(负载均衡模式)'),
175
- })).default([]).description('多 API 密钥(轮换使用)'),
176
- rotationMode: koishi_1.Schema.union([
177
- koishi_1.Schema.const('sequential').description('顺序模式(无效时切换)'),
178
- koishi_1.Schema.const('load_balance').description('负载均衡模式(轮询)'),
179
- ]).default('sequential').description('密钥轮换模式'),
180
173
  platformDedicatedFirst: koishi_1.Schema.object({
181
174
  bilibili: koishi_1.Schema.boolean().default(false).description('哔哩哔哩'),
182
175
  douyin: koishi_1.Schema.boolean().default(false).description('抖音'),
@@ -693,8 +686,6 @@ function parseFieldMapping(mappingStr) {
693
686
  }
694
687
  }
695
688
  function apply(ctx, config) {
696
- // @ts-expect-error koishi runtime supports optional service dependencies
697
- ctx.using(['downloads', 'silk', 'ffmpeg'], { optional: true });
698
689
  debugEnabled = config.debug || false;
699
690
  debugLog('INFO', 'plugin start');
700
691
  const dedupCache = new SimpleLRUCache(1000, config.deduplicationInterval * 1000);
@@ -740,38 +731,6 @@ function apply(ctx, config) {
740
731
  logger.warn('aria2 连接失败,回退到内置下载');
741
732
  }
742
733
  }
743
- const apiKeyList = (config.apiKeys || []).map((k) => ({
744
- key: k.key,
745
- weight: k.weight || 1,
746
- lastUsed: 0
747
- }));
748
- let keyIndex = 0;
749
- function getNextApiKey() {
750
- if (apiKeyList.length === 0)
751
- return '';
752
- if (config.rotationMode === 'load_balance') {
753
- const totalWeight = apiKeyList.reduce((sum, k) => sum + k.weight, 0);
754
- let rand = Math.random() * totalWeight;
755
- for (const k of apiKeyList) {
756
- rand -= k.weight;
757
- if (rand <= 0)
758
- return k.key;
759
- }
760
- return apiKeyList[0].key;
761
- }
762
- else {
763
- const current = apiKeyList[keyIndex % apiKeyList.length];
764
- keyIndex++;
765
- return current.key;
766
- }
767
- }
768
- function markApiKeyInvalid(key) {
769
- if (config.rotationMode === 'sequential') {
770
- const idx = apiKeyList.findIndex(k => k.key === key);
771
- if (idx !== -1)
772
- apiKeyList.splice(idx, 1);
773
- }
774
- }
775
734
  function getPlatformConfig(type) {
776
735
  if (type.startsWith('custom_')) {
777
736
  const name = type.slice(7);
@@ -780,7 +739,7 @@ function apply(ctx, config) {
780
739
  return {
781
740
  apiUrl: custom.apiUrl,
782
741
  dedicatedFirst: true,
783
- apiKey: custom.apiKey || getNextApiKey(),
742
+ apiKey: custom.apiKey || '',
784
743
  authHeaderType: custom.authHeaderType,
785
744
  customHeaderName: custom.customHeaderName,
786
745
  fieldMapping: custom.fieldMapping,
@@ -812,13 +771,13 @@ function apply(ctx, config) {
812
771
  let fieldMapping = undefined;
813
772
  if (custom && custom.apiUrl) {
814
773
  apiUrl = custom.apiUrl;
815
- apiKey = custom.apiKey || getNextApiKey();
774
+ apiKey = custom.apiKey || '';
816
775
  authHeaderType = custom.authHeaderType || 'Bearer';
817
776
  customHeaderName = custom.customHeaderName || 'X-API-Key';
818
777
  fieldMapping = parseFieldMapping(custom.fieldMapping);
819
778
  }
820
779
  else {
821
- apiKey = getNextApiKey();
780
+ apiKey = '';
822
781
  }
823
782
  const dedicatedFirst = config.platformDedicatedFirst?.[type] ?? false;
824
783
  if (!fieldMapping) {
@@ -852,18 +811,18 @@ function apply(ctx, config) {
852
811
  return cleanUrl(url);
853
812
  }
854
813
  }
814
+ const extRegexCache = {};
855
815
  async function downloadFile(url, timeout, maxSize, filePrefix, fileExts) {
856
816
  if (!url)
857
817
  throw new Error('链接为空');
858
818
  await promises_1.default.mkdir(cacheDir, { recursive: true });
859
- const extRegexCache = {};
860
819
  const ext = fileExts.find(e => {
861
820
  const r = extRegexCache[e] || (extRegexCache[e] = new RegExp('\\.' + e + '(\\?|$)', 'i'));
862
821
  return r.test(url);
863
822
  }) || fileExts[0];
864
823
  const fileName = `${filePrefix}_${Date.now()}_${(0, crypto_1.randomBytes)(4).toString('hex')}.${ext}`;
865
824
  const filePath = path_1.default.resolve(cacheDir, fileName);
866
- if (ctx.downloads) {
825
+ if (downloadEngine === 'downloads' && ctx.downloads) {
867
826
  try {
868
827
  const dest = await ctx.downloads.download(url, path_1.default.join(cacheDir, fileName), {
869
828
  headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' },
@@ -877,10 +836,10 @@ function apply(ctx, config) {
877
836
  return dest;
878
837
  }
879
838
  catch (e) {
880
- debugLog('ERROR', `downloads 服务下载失败,回退: ${getErrorMessage(e)}`);
839
+ debugLog('ERROR', `downloads 服务下载失败,回退内置下载: ${getErrorMessage(e)}`);
881
840
  }
882
841
  }
883
- if (aria2 && config.resumeDownload) {
842
+ else if (downloadEngine === 'aria2' && aria2 && config.resumeDownload) {
884
843
  try {
885
844
  const gid = await aria2.call('aria2.addUri', [url], {
886
845
  dir: cacheDir,
@@ -1199,10 +1158,6 @@ function apply(ctx, config) {
1199
1158
  urlCacheLocal.set(cacheKey, { data: parsed, expire: Date.now() + cacheTTL });
1200
1159
  return parsed;
1201
1160
  }
1202
- if (res.data?.code === 403 || res.data?.code === 401) {
1203
- if (api.apiKey)
1204
- markApiKeyInvalid(api.apiKey);
1205
- }
1206
1161
  throw new Error(res.data?.msg || `API返回错误码: ${res.data?.code}`);
1207
1162
  }
1208
1163
  catch (error) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-video-parser-all",
3
3
  "description": "Koishi 全平台视频/图集解析插件,支持抖音/快手/B站/微博/小红书/剪映/YouTube/TikTok等20+平台",
4
- "version": "1.3.6",
4
+ "version": "1.3.8",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
@@ -98,11 +98,15 @@
98
98
  "peerDependencies": {
99
99
  "@koishijs/plugin-console": "^5.30.4",
100
100
  "koishi": "^4.18.7",
101
+ "@koishijs/plugin-downloads": "^5.30.4",
101
102
  "koishi-plugin-silk": "^1.0.0",
102
103
  "koishi-plugin-ffmpeg": "^1.0.0",
103
104
  "aria2": "^4.1.2"
104
105
  },
105
106
  "peerDependenciesMeta": {
107
+ "@koishijs/plugin-downloads": {
108
+ "optional": true
109
+ },
106
110
  "koishi-plugin-silk": {
107
111
  "optional": true
108
112
  },