koishi-plugin-video-parser-all 0.8.6 → 0.8.7

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
@@ -4,7 +4,6 @@ export declare const Config: Schema<{
4
4
  enable?: boolean | null | undefined;
5
5
  botName?: string | null | undefined;
6
6
  showWaitingTip?: boolean | null | undefined;
7
- sameLinkInterval?: number | null | undefined;
8
7
  debug?: boolean | null | undefined;
9
8
  } & import("cosmokit").Dict & {
10
9
  unifiedMessageFormat?: string | null | undefined;
@@ -23,23 +22,16 @@ export declare const Config: Schema<{
23
22
  retryInterval?: number | null | undefined;
24
23
  } & {
25
24
  enableForward?: boolean | null | undefined;
26
- } & {
27
- messageBufferDelay?: number | null | undefined;
28
- } & {
29
- autoClearCacheInterval?: number | null | undefined;
30
25
  } & {
31
26
  waitingTipText?: string | null | undefined;
32
- duplicateLinkText?: string | null | undefined;
33
27
  unsupportedPlatformText?: string | null | undefined;
34
28
  invalidLinkText?: string | null | undefined;
35
- cacheClearedText?: string | null | undefined;
36
29
  parseErrorPrefix?: string | null | undefined;
37
30
  parseErrorItemFormat?: string | null | undefined;
38
31
  }, {
39
32
  enable: boolean;
40
33
  botName: string;
41
34
  showWaitingTip: boolean;
42
- sameLinkInterval: number;
43
35
  debug: boolean;
44
36
  } & import("cosmokit").Dict & {
45
37
  unifiedMessageFormat: string;
@@ -58,16 +50,10 @@ export declare const Config: Schema<{
58
50
  retryInterval: number;
59
51
  } & {
60
52
  enableForward: boolean;
61
- } & {
62
- messageBufferDelay: number;
63
- } & {
64
- autoClearCacheInterval: number;
65
53
  } & {
66
54
  waitingTipText: string;
67
- duplicateLinkText: string;
68
55
  unsupportedPlatformText: string;
69
56
  invalidLinkText: string;
70
- cacheClearedText: string;
71
57
  parseErrorPrefix: string;
72
58
  parseErrorItemFormat: string;
73
59
  }>;
package/lib/index.js CHANGED
@@ -7,16 +7,12 @@ exports.Config = exports.name = void 0;
7
7
  exports.apply = apply;
8
8
  const koishi_1 = require("koishi");
9
9
  const axios_1 = __importDefault(require("axios"));
10
- const crypto_1 = __importDefault(require("crypto"));
11
- const fs_1 = __importDefault(require("fs"));
12
- const path_1 = __importDefault(require("path"));
13
10
  exports.name = 'video-parser-all';
14
11
  exports.Config = koishi_1.Schema.intersect([
15
12
  koishi_1.Schema.object({
16
13
  enable: koishi_1.Schema.boolean().default(true).description('是否启用视频解析插件'),
17
14
  botName: koishi_1.Schema.string().default('视频解析机器人').description('合并转发消息中显示的机器人名称'),
18
15
  showWaitingTip: koishi_1.Schema.boolean().default(true).description('解析时显示等待提示'),
19
- sameLinkInterval: koishi_1.Schema.number().min(0).default(180).description('相同链接重复解析间隔(秒)'),
20
16
  debug: koishi_1.Schema.boolean().default(false).description('开启调试模式,在控制台输出详细日志'),
21
17
  }).description('基础设置'),
22
18
  koishi_1.Schema.object({
@@ -41,24 +37,14 @@ exports.Config = koishi_1.Schema.intersect([
41
37
  koishi_1.Schema.object({
42
38
  enableForward: koishi_1.Schema.boolean().default(false).description('启用合并转发(仅 OneBot 平台)'),
43
39
  }).description('发送方式设置'),
44
- koishi_1.Schema.object({
45
- messageBufferDelay: koishi_1.Schema.number().min(0).default(0).description('消息缓冲延迟(毫秒)'),
46
- }).description('消息缓冲'),
47
- koishi_1.Schema.object({
48
- autoClearCacheInterval: koishi_1.Schema.number().min(0).default(0).description('自动清理缓存间隔(分钟,0 为关闭)'),
49
- }).description('缓存清理'),
50
40
  koishi_1.Schema.object({
51
41
  waitingTipText: koishi_1.Schema.string().default('正在解析视频,请稍候...').description('解析等待提示'),
52
- duplicateLinkText: koishi_1.Schema.string().default('请勿重复解析相同链接').description('重复链接提示'),
53
42
  unsupportedPlatformText: koishi_1.Schema.string().default('不支持该平台链接').description('不支持的平台提示'),
54
43
  invalidLinkText: koishi_1.Schema.string().default('无效的视频链接').description('无效链接提示(parse 指令)'),
55
- cacheClearedText: koishi_1.Schema.string().default('✅ 缓存已清空').description('缓存清理提示'),
56
44
  parseErrorPrefix: koishi_1.Schema.string().default('❌ 解析失败:').description('解析失败消息前缀'),
57
45
  parseErrorItemFormat: koishi_1.Schema.string().default('【${url}】: ${msg}').description('每条解析失败格式,可用 ${url} ${msg}'),
58
46
  }).description('界面文字设置'),
59
47
  ]);
60
- const processed = new Map();
61
- const linkBuffer = new Map();
62
48
  const logger = new koishi_1.Logger(exports.name);
63
49
  let debugEnabled = false;
64
50
  function debugLog(level, ...args) {
@@ -246,14 +232,12 @@ function parseApiResponse(raw, maxDescLen) {
246
232
  else if (extra.create_time) {
247
233
  publishTime = extra.create_time * 1000;
248
234
  }
249
- const result = {
235
+ return {
250
236
  type, title, desc, author, uid, avatar, cover,
251
237
  video, videos, images, live_photo, music,
252
238
  like, comment, collect, share, play,
253
239
  duration, publishTime
254
240
  };
255
- debugLog('DEBUG', '解析后的数据:', result);
256
- return result;
257
241
  }
258
242
  function generateFormattedText(p, format) {
259
243
  const vars = {
@@ -278,24 +262,7 @@ function generateFormattedText(p, format) {
278
262
  for (const [key, value] of Object.entries(vars)) {
279
263
  result = result.replace(new RegExp(`\\$\\{${key}\\}`, 'g'), value);
280
264
  }
281
- const final = result.replace(/^\s*\n/gm, '').trim();
282
- debugLog('DEBUG', '生成格式化文本:', final);
283
- return final;
284
- }
285
- function clearAllCache() {
286
- processed.clear();
287
- linkBuffer.forEach(buf => clearTimeout(buf.timer));
288
- linkBuffer.clear();
289
- const tempDir = path_1.default.join(process.cwd(), 'temp_videos');
290
- if (fs_1.default.existsSync(tempDir)) {
291
- fs_1.default.readdirSync(tempDir).forEach(file => {
292
- try {
293
- fs_1.default.unlinkSync(path_1.default.join(tempDir, file));
294
- }
295
- catch (error) { }
296
- });
297
- }
298
- return true;
265
+ return result.replace(/^\s*\n/gm, '').trim();
299
266
  }
300
267
  const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
301
268
  function buildForwardNode(session, content, botName) {
@@ -311,17 +278,13 @@ function buildForwardNode(session, content, botName) {
311
278
  function apply(ctx, config) {
312
279
  debugEnabled = config.debug || false;
313
280
  debugLog('INFO', '插件初始化开始');
314
- debugLog('INFO', '当前配置:', config);
315
281
  const texts = {
316
282
  waitingTipText: config.waitingTipText || '正在解析视频,请稍候...',
317
- duplicateLinkText: config.duplicateLinkText || '请勿重复解析相同链接',
318
283
  unsupportedPlatformText: config.unsupportedPlatformText || '不支持该平台链接',
319
284
  invalidLinkText: config.invalidLinkText || '无效的视频链接',
320
- cacheClearedText: config.cacheClearedText || '✅ 缓存已清空',
321
285
  parseErrorPrefix: config.parseErrorPrefix || '❌ 解析失败:',
322
286
  parseErrorItemFormat: config.parseErrorItemFormat || '【${url}】: ${msg}',
323
287
  };
324
- clearAllCache();
325
288
  const http = axios_1.default.create({
326
289
  timeout: config.timeout,
327
290
  headers: {
@@ -338,8 +301,7 @@ function apply(ctx, config) {
338
301
  params: { url },
339
302
  timeout: config.timeout
340
303
  });
341
- debugLog('INFO', `API响应: code=${res.data?.code}, msg=${res.data?.msg}`);
342
- debugLog('DEBUG', 'API完整响应:', res.data);
304
+ debugLog('DEBUG', `API响应: ${JSON.stringify(res.data)}`);
343
305
  if (res.data && (res.data.code === 200 || res.data.code === 0)) {
344
306
  return parseApiResponse(res.data, config.maxDescLength);
345
307
  }
@@ -354,34 +316,23 @@ function apply(ctx, config) {
354
316
  throw new Error('API请求全部失败');
355
317
  }
356
318
  async function parseUrl(url) {
357
- debugLog('INFO', `开始解析链接: ${url}`);
358
319
  const realUrl = await resolveShortUrl(url);
359
- debugLog('DEBUG', `重定向后的URL: ${realUrl}`);
360
320
  const platform = getPlatformType(realUrl);
361
321
  if (!platform) {
362
322
  return { success: false, msg: texts.unsupportedPlatformText };
363
323
  }
364
- const candidates = [url, realUrl];
365
- let lastError = null;
366
- for (const candidate of candidates) {
324
+ for (const candidate of [url, realUrl]) {
367
325
  try {
368
326
  const info = await fetchApi(candidate);
369
327
  return { success: true, data: info };
370
328
  }
371
329
  catch (error) {
372
- lastError = getErrorMessage(error);
330
+ debugLog('ERROR', `候选链接解析失败: ${candidate}`);
373
331
  }
374
332
  }
375
- return { success: false, msg: lastError || '解析失败' };
333
+ return { success: false, msg: '解析失败' };
376
334
  }
377
- async function processSingleUrl(session, url) {
378
- const hash = crypto_1.default.createHash('md5').update(url).digest('hex');
379
- const now = Date.now();
380
- const last = processed.get(hash);
381
- if (last && (now - last) < config.sameLinkInterval * 1000) {
382
- return { success: false, msg: texts.duplicateLinkText };
383
- }
384
- processed.set(hash, now);
335
+ async function processSingleUrl(url) {
385
336
  const result = await parseUrl(url);
386
337
  if (!result.success)
387
338
  return result;
@@ -411,18 +362,11 @@ function apply(ctx, config) {
411
362
  return null;
412
363
  }
413
364
  }
414
- async function flush(session, manualUrls) {
415
- const key = `${session.platform}:${session.userId}:${session.channelId}`;
416
- const buffer = linkBuffer.get(key);
417
- const urls = manualUrls || buffer?.urls || [];
418
- if (buffer) {
419
- clearTimeout(buffer.timer);
420
- linkBuffer.delete(key);
421
- }
365
+ async function flush(session, urls) {
422
366
  const items = [];
423
367
  const errors = [];
424
368
  for (const url of urls) {
425
- const res = await processSingleUrl(session, url);
369
+ const res = await processSingleUrl(url);
426
370
  if (res.success) {
427
371
  items.push(res.data);
428
372
  }
@@ -542,20 +486,5 @@ function apply(ctx, config) {
542
486
  }
543
487
  await flush(session, us);
544
488
  });
545
- ctx.command('clear-cache', '清空缓存').action(async ({ session }) => {
546
- clearAllCache();
547
- await sendWithTimeout(session, texts.cacheClearedText);
548
- });
549
- setInterval(() => {
550
- const now = Date.now();
551
- processed.forEach((t, h) => { if (now - t > 86400000)
552
- processed.delete(h); });
553
- }, 3600000);
554
- if (config.autoClearCacheInterval > 0) {
555
- setInterval(() => {
556
- clearAllCache();
557
- debugLog('INFO', '自动清理缓存');
558
- }, config.autoClearCacheInterval * 60 * 1000);
559
- }
560
489
  debugLog('INFO', '插件初始化完成');
561
490
  }
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": "0.8.6",
4
+ "version": "0.8.7",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [