koishi-plugin-video-parser-all 1.0.7 → 1.0.9

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
@@ -29,7 +29,11 @@ export declare const Config: Schema<{
29
29
  primaryApiUrl?: string | null | undefined;
30
30
  backupApiUrl?: string | null | undefined;
31
31
  useDedicatedApiFirst?: boolean | null | undefined;
32
- customApiUrls?: import("cosmokit").Dict<string, string> | null | undefined;
32
+ customApis?: ({
33
+ platform?: "bilibili" | "douyin" | "kuaishou" | "xiaohongshu" | "weibo" | "xigua" | "youtube" | "tiktok" | "acfun" | "zhihu" | "weishi" | "huya" | "haokan" | "meipai" | "twitter" | "instagram" | "doubao" | null | undefined;
34
+ apiUrl?: string | null | undefined;
35
+ useDedicatedFirst?: boolean | null | undefined;
36
+ } & import("cosmokit").Dict)[] | null | undefined;
33
37
  } & {
34
38
  waitingTipText?: string | null | undefined;
35
39
  unsupportedPlatformText?: string | null | undefined;
@@ -65,7 +69,11 @@ export declare const Config: Schema<{
65
69
  primaryApiUrl: string;
66
70
  backupApiUrl: string;
67
71
  useDedicatedApiFirst: boolean;
68
- customApiUrls: import("cosmokit").Dict<string, string>;
72
+ customApis: Schemastery.ObjectT<{
73
+ platform: Schema<"bilibili" | "douyin" | "kuaishou" | "xiaohongshu" | "weibo" | "xigua" | "youtube" | "tiktok" | "acfun" | "zhihu" | "weishi" | "huya" | "haokan" | "meipai" | "twitter" | "instagram" | "doubao", "bilibili" | "douyin" | "kuaishou" | "xiaohongshu" | "weibo" | "xigua" | "youtube" | "tiktok" | "acfun" | "zhihu" | "weishi" | "huya" | "haokan" | "meipai" | "twitter" | "instagram" | "doubao">;
74
+ apiUrl: Schema<string, string>;
75
+ useDedicatedFirst: Schema<boolean, boolean>;
76
+ }>[];
69
77
  } & {
70
78
  waitingTipText: string;
71
79
  unsupportedPlatformText: string;
package/lib/index.js CHANGED
@@ -48,8 +48,30 @@ exports.Config = koishi_1.Schema.intersect([
48
48
  koishi_1.Schema.object({
49
49
  primaryApiUrl: koishi_1.Schema.string().default('https://api.bugpk.com/api/short_videos').description('主 API 地址'),
50
50
  backupApiUrl: koishi_1.Schema.string().default('https://api.bugpk.com/api/svparse').description('备用主 API 地址(仅支持抖音/小红书/ins/即梦)'),
51
- useDedicatedApiFirst: koishi_1.Schema.boolean().default(false).description('优先使用平台专属 API,失败后回退到通用 API'),
52
- customApiUrls: koishi_1.Schema.dict(koishi_1.Schema.string()).default({}).description('自定义专属 API 地址,key 为平台类型(如 bilibili,douyin,doubao),value 为完整 API 地址,留空则使用内置默认专属 API'),
51
+ useDedicatedApiFirst: koishi_1.Schema.boolean().default(false).description('全局默认:是否优先使用平台专属 API(各平台可单独覆盖)'),
52
+ customApis: koishi_1.Schema.array(koishi_1.Schema.object({
53
+ platform: koishi_1.Schema.union([
54
+ koishi_1.Schema.const('bilibili').description('哔哩哔哩'),
55
+ koishi_1.Schema.const('douyin').description('抖音'),
56
+ koishi_1.Schema.const('kuaishou').description('快手'),
57
+ koishi_1.Schema.const('xiaohongshu').description('小红书'),
58
+ koishi_1.Schema.const('weibo').description('微博'),
59
+ koishi_1.Schema.const('xigua').description('西瓜视频'),
60
+ koishi_1.Schema.const('youtube').description('YouTube'),
61
+ koishi_1.Schema.const('tiktok').description('TikTok'),
62
+ koishi_1.Schema.const('acfun').description('AcFun'),
63
+ koishi_1.Schema.const('zhihu').description('知乎'),
64
+ koishi_1.Schema.const('weishi').description('微视'),
65
+ koishi_1.Schema.const('huya').description('虎牙'),
66
+ koishi_1.Schema.const('haokan').description('好看视频'),
67
+ koishi_1.Schema.const('meipai').description('美拍'),
68
+ koishi_1.Schema.const('twitter').description('Twitter/X'),
69
+ koishi_1.Schema.const('instagram').description('Instagram'),
70
+ koishi_1.Schema.const('doubao').description('豆包'),
71
+ ]).description('选择平台'),
72
+ apiUrl: koishi_1.Schema.string().description('API 地址'),
73
+ useDedicatedFirst: koishi_1.Schema.boolean().default(false).description('该平台优先使用此专属 API'),
74
+ })).default([]).description('自定义平台专属 API,可覆盖默认专属 API,并可单独设定优先策略'),
53
75
  }).description('API 选择设置'),
54
76
  koishi_1.Schema.object({
55
77
  waitingTipText: koishi_1.Schema.string().default('正在解析视频,请稍候...').description('解析等待提示'),
@@ -78,6 +100,11 @@ function debugLog(level, ...args) {
78
100
  }).join(' ')}`;
79
101
  logger.info(message);
80
102
  }
103
+ const urlCache = new lru_cache_1.LRUCache({
104
+ max: 500,
105
+ ttl: 10 * 60 * 1000,
106
+ updateAgeOnGet: false,
107
+ });
81
108
  function linkTypeParser(content) {
82
109
  content = content.replace(/\\\//g, '/');
83
110
  const rules = [
@@ -126,7 +153,54 @@ function linkTypeParser(content) {
126
153
  }
127
154
  function extractAllUrlsFromMessage(session) {
128
155
  const content = session.content?.trim() || '';
129
- return linkTypeParser(content);
156
+ const rawUrls = [];
157
+ const textMatch = content.match(/https?:\/\/[^\s<>"'(){}[\]]+/gi);
158
+ if (textMatch)
159
+ rawUrls.push(...textMatch);
160
+ if (session.elements) {
161
+ for (const elem of session.elements) {
162
+ if (elem.type === 'xml' && elem.data) {
163
+ const matches = elem.data.match(/https?:\/\/[^\s<>"'(){}[\]]+/gi);
164
+ if (matches)
165
+ rawUrls.push(...matches);
166
+ }
167
+ else if (elem.type === 'json' && elem.data) {
168
+ try {
169
+ const json = JSON.parse(elem.data);
170
+ const extract = (obj) => {
171
+ if (!obj || typeof obj !== 'object')
172
+ return;
173
+ for (const val of Object.values(obj)) {
174
+ if (typeof val === 'string') {
175
+ const matches = val.match(/https?:\/\/[^\s<>"'(){}[\]]+/gi);
176
+ if (matches)
177
+ rawUrls.push(...matches);
178
+ }
179
+ else if (typeof val === 'object')
180
+ extract(val);
181
+ }
182
+ };
183
+ extract(json);
184
+ }
185
+ catch { }
186
+ }
187
+ }
188
+ }
189
+ const seen = new Set();
190
+ const result = [];
191
+ for (const rawUrl of rawUrls) {
192
+ const cleanedUrl = rawUrl.replace(/&amp;/g, '&').replace(/[.,;:!?)]+$/, '');
193
+ if (seen.has(cleanedUrl))
194
+ continue;
195
+ const matches = linkTypeParser(cleanedUrl);
196
+ for (const match of matches) {
197
+ if (!seen.has(match.url)) {
198
+ seen.add(match.url);
199
+ result.push(match);
200
+ }
201
+ }
202
+ }
203
+ return result;
130
204
  }
131
205
  function cleanUrl(url) {
132
206
  try {
@@ -364,11 +438,6 @@ function buildForwardNode(session, content, botName) {
364
438
  }
365
439
  }, messageContent);
366
440
  }
367
- const urlCache = new lru_cache_1.LRUCache({
368
- max: 500,
369
- ttl: 10 * 60 * 1000,
370
- updateAgeOnGet: false,
371
- });
372
441
  async function downloadVideoFile(videoUrl, tempDir, timeout, maxSizeMB) {
373
442
  if (!videoUrl)
374
443
  throw new Error('视频链接为空');
@@ -462,11 +531,13 @@ function apply(ctx, config) {
462
531
  zuiyou: 'https://api.bugpk.com/api/zuiyou',
463
532
  };
464
533
  const backupSupportedPlatforms = new Set(['douyin', 'xiaohongshu', 'instagram', 'jimeng']);
465
- function getDedicatedApiUrl(type) {
466
- if (config.customApiUrls && config.customApiUrls[type]) {
467
- return config.customApiUrls[type];
534
+ function getPlatformConfig(type) {
535
+ const custom = config.customApis?.find((item) => item.platform === type);
536
+ if (custom && custom.apiUrl) {
537
+ return { apiUrl: custom.apiUrl, dedicatedFirst: custom.useDedicatedFirst ?? false };
468
538
  }
469
- return defaultDedicatedApis[type] || null;
539
+ const defaultUrl = defaultDedicatedApis[type] || null;
540
+ return { apiUrl: defaultUrl, dedicatedFirst: config.useDedicatedApiFirst ?? false };
470
541
  }
471
542
  async function fetchApi(url, type) {
472
543
  const cacheKey = url;
@@ -475,27 +546,23 @@ function apply(ctx, config) {
475
546
  debugLog('DEBUG', `使用缓存: ${url}`);
476
547
  return cached.data;
477
548
  }
478
- const dedicatedApiUrl = getDedicatedApiUrl(type);
549
+ const { apiUrl: dedicatedUrl, dedicatedFirst } = getPlatformConfig(type);
479
550
  const primaryApi = config.primaryApiUrl || 'https://api.bugpk.com/api/short_videos';
480
551
  const backupApi = config.backupApiUrl || 'https://api.bugpk.com/api/svparse';
481
552
  const backupAllowed = backupSupportedPlatforms.has(type);
482
553
  const apiList = [];
483
- if (config.useDedicatedApiFirst) {
484
- if (dedicatedApiUrl)
485
- apiList.push({ url: dedicatedApiUrl, label: `专属API(${type})` });
554
+ if (dedicatedFirst && dedicatedUrl) {
555
+ apiList.push({ url: dedicatedUrl, label: `专属API(${type})` });
486
556
  apiList.push({ url: primaryApi, label: '默认主API' });
487
557
  if (backupAllowed)
488
558
  apiList.push({ url: backupApi, label: '备用主API' });
489
- if (dedicatedApiUrl) {
490
- // already tried dedicated first, don't repeat
491
- }
492
559
  }
493
560
  else {
494
561
  apiList.push({ url: primaryApi, label: '默认主API' });
495
562
  if (backupAllowed)
496
563
  apiList.push({ url: backupApi, label: '备用主API' });
497
- if (dedicatedApiUrl)
498
- apiList.push({ url: dedicatedApiUrl, label: `专属API(${type})` });
564
+ if (dedicatedUrl)
565
+ apiList.push({ url: dedicatedUrl, label: `专属API(${type})` });
499
566
  }
500
567
  let lastError = null;
501
568
  for (const api of apiList) {
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.0.7",
4
+ "version": "1.0.9",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
@@ -76,4 +76,4 @@
76
76
  "engines": {
77
77
  "node": ">=16.0.0"
78
78
  }
79
- }
79
+ }
package/readme.md CHANGED
@@ -3,30 +3,10 @@
3
3
  ## 项目介绍 (Project Introduction)
4
4
 
5
5
  ### 中文
6
- 这是一个为 Koishi 机器人框架开发的**全平台视频/图集解析插件**,使用统一API接口,支持自动识别并解析抖音、快手、B站、小红书、微博、YouTube、TikTok、剪映、AcFun、知乎、虎牙等20+主流平台的短视频/图集/实况链接。核心特性:
7
- - 🌐 统一API解析,覆盖20+热门平台,无需繁琐配置
8
- - 🤖 自动识别链接来源,即丢即用,并支持解析 XML/JSON 卡片消息中的链接(如 QQ/OneBot 平台的分享卡片)
9
- - 🎨 完全自定义的解析结果格式,支持多项变量替换,变量无值自动隐藏行
10
- - 🐛 内置Debug调试模式,可详细记录所有操作与API交互日志
11
- - 📤 支持OneBot平台消息合并转发,优化多图文展示体验
12
- - 💬 所有提示文案均可自定义,适配多语言场景
13
- - 🔁 消息发送支持自动重试,与API重试配置联动,增强稳定性
14
- - 🚀 内置LRU内存缓存,避免短时间内重复解析同一链接;串行解析防止API限流
15
- - ⚡ 智能视频发送策略:优先直接发送URL,失败自动降级为本地文件发送
16
- - 🛡️ 可选视频大小限制,防止超大文件占满服务器磁盘;自动清理所有临时文件
6
+ 这是一个为 Koishi 机器人框架开发的**全平台视频/图集解析插件**,使用统一API接口,支持自动识别并解析抖音、快手、B站、小红书、微博、YouTube、TikTok、剪映、AcFun、知乎、虎牙等20+主流平台的短视频/图集/实况链接。
17
7
 
18
8
  ### English
19
- This is a **multi-platform video/image parsing plugin** developed for the Koishi bot framework, using a unified API interface to automatically recognize and parse short video/image/live photo links from 20+ mainstream platforms such as Douyin, Kuaishou, Bilibili, Xiaohongshu, Weibo, YouTube, TikTok, Jianying, AcFun, Zhihu, Huya and more. Core features:
20
- - 🌐 Unified API parsing, covering 20+ popular platforms without complex configuration
21
- - 🤖 Auto-detection of link sources, drop & go, and support for extracting links from XML/JSON card messages (e.g., share cards on QQ/OneBot)
22
- - 🎨 Fully customizable parsing result format with variable substitutions, empty variables hide the line automatically
23
- - 🐛 Built-in Debug mode, recording detailed operations and API interaction logs
24
- - 📤 Support OneBot message forwarding for better image/video display
25
- - 💬 All prompt texts are customizable for multilingual scenarios
26
- - 🔁 Message sending supports automatic retries, linked with API retry configuration for improved stability
27
- - 🚀 Built-in LRU memory cache to avoid repeated parsing of the same URL; serial parsing to prevent API rate limiting
28
- - ⚡ Smart video sending strategy: priority to send URL directly, auto downgrade to local file on failure
29
- - 🛡️ Optional video size limit to prevent oversized files from filling up server disk; automatic cleanup of all temporary files
9
+ This is a **multi-platform video/image parsing plugin** developed for the Koishi bot framework, using a unified API interface to automatically recognize and parse short video/image/live photo links from 20+ mainstream platforms such as Douyin, Kuaishou, Bilibili, Xiaohongshu, Weibo, YouTube, TikTok, Jianying, AcFun, Zhihu, Huya and more.
30
10
 
31
11
  ## 项目仓库 (Repository)
32
12
  - GitHub: `https://github.com/Minecraft-1314/koishi-plugin-video-parser-all`
@@ -71,6 +51,14 @@ This is a **multi-platform video/image parsing plugin** developed for the Koishi
71
51
  | `videoSendTimeout` | number | 60000 | 视频消息发送超时时间(毫秒,0 为不限制) |
72
52
  | `userAgent` | string | `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36` | API 请求使用的 User-Agent |
73
53
 
54
+ ### API 选择与回退设置
55
+ | 配置项 | 类型 | 默认值 | 说明 |
56
+ |--------|------|--------|------|
57
+ | `primaryApiUrl` | string | `https://api.bugpk.com/api/short_videos` | 主 API 地址,解析时优先使用 |
58
+ | `backupApiUrl` | string | `https://api.bugpk.com/api/svparse` | 备用主 API 地址,仅支持抖音、小红书、Instagram、即梦平台解析 |
59
+ | `useDedicatedApiFirst` | boolean | false | 是否优先使用平台专属 API,失败后依次回退到主 API、备用主 API |
60
+ | `customApis` | array | [] | 自定义平台专属 API 列表,每项需选择平台并填写 API 地址,可覆盖内置的默认专属 API |
61
+
74
62
  ### 错误与重试设置
75
63
  | 配置项 | 类型 | 默认值 | 说明 |
76
64
  |--------|------|--------|------|
@@ -81,7 +69,7 @@ This is a **multi-platform video/image parsing plugin** developed for the Koishi
81
69
  ### 发送方式设置
82
70
  | 配置项 | 类型 | 默认值 | 说明 |
83
71
  |--------|------|--------|------|
84
- | `enableForward` | boolean | false | 是否启用合并转发(仅 OneBot 平台),视频会单独发送 |
72
+ | `enableForward` | boolean | false | 是否启用合并转发(仅 OneBot 平台),启用后视频与图文将整合进同一条合并消息 |
85
73
 
86
74
  ### 界面文字设置
87
75
  | 配置项 | 类型 | 默认值 | 说明 |