koishi-plugin-video-parser-all 0.8.2 → 0.8.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.
package/lib/index.d.ts CHANGED
@@ -3,9 +3,6 @@ export declare const name = "video-parser-all";
3
3
  export declare const Config: Schema<{
4
4
  enable?: boolean | null | undefined;
5
5
  botName?: string | null | undefined;
6
- showWaitingTip?: boolean | null | undefined;
7
- waitingTipText?: string | null | undefined;
8
- sameLinkInterval?: number | null | undefined;
9
6
  debug?: boolean | null | undefined;
10
7
  debugFile?: boolean | null | undefined;
11
8
  } & import("cosmokit").Dict & {
@@ -14,7 +11,6 @@ export declare const Config: Schema<{
14
11
  showImageText?: boolean | null | undefined;
15
12
  showVideoFile?: boolean | null | undefined;
16
13
  sendLivePhotoVideos?: boolean | null | undefined;
17
- } & {
18
14
  maxDescLength?: number | null | undefined;
19
15
  } & {
20
16
  timeout?: number | null | undefined;
@@ -33,12 +29,17 @@ export declare const Config: Schema<{
33
29
  messageBufferDelay?: number | null | undefined;
34
30
  } & {
35
31
  autoClearCacheInterval?: number | null | undefined;
32
+ } & {
33
+ waitingTipText?: string | null | undefined;
34
+ duplicateLinkText?: string | null | undefined;
35
+ unsupportedPlatformText?: string | null | undefined;
36
+ invalidLinkText?: string | null | undefined;
37
+ cacheClearedText?: string | null | undefined;
38
+ parseErrorPrefix?: string | null | undefined;
39
+ parseErrorItemFormat?: string | null | undefined;
36
40
  }, {
37
41
  enable: boolean;
38
42
  botName: string;
39
- showWaitingTip: boolean;
40
- waitingTipText: string;
41
- sameLinkInterval: number;
42
43
  debug: boolean;
43
44
  debugFile: boolean;
44
45
  } & import("cosmokit").Dict & {
@@ -47,7 +48,6 @@ export declare const Config: Schema<{
47
48
  showImageText: boolean;
48
49
  showVideoFile: boolean;
49
50
  sendLivePhotoVideos: boolean;
50
- } & {
51
51
  maxDescLength: number;
52
52
  } & {
53
53
  timeout: number;
@@ -66,5 +66,13 @@ export declare const Config: Schema<{
66
66
  messageBufferDelay: number;
67
67
  } & {
68
68
  autoClearCacheInterval: number;
69
+ } & {
70
+ waitingTipText: string;
71
+ duplicateLinkText: string;
72
+ unsupportedPlatformText: string;
73
+ invalidLinkText: string;
74
+ cacheClearedText: string;
75
+ parseErrorPrefix: string;
76
+ parseErrorItemFormat: string;
69
77
  }>;
70
78
  export declare function apply(ctx: Context, config: any): void;
package/lib/index.js CHANGED
@@ -10,52 +10,57 @@ const axios_1 = __importDefault(require("axios"));
10
10
  const crypto_1 = __importDefault(require("crypto"));
11
11
  const fs_1 = __importDefault(require("fs"));
12
12
  const path_1 = __importDefault(require("path"));
13
+ const url_1 = require("url");
13
14
  const promises_1 = require("stream/promises");
14
15
  const worker_threads_1 = require("worker_threads");
15
16
  exports.name = 'video-parser-all';
16
17
  exports.Config = koishi_1.Schema.intersect([
17
18
  koishi_1.Schema.object({
18
19
  enable: koishi_1.Schema.boolean().default(true).description('是否启用视频解析插件'),
19
- botName: koishi_1.Schema.string().default('视频解析机器人').description('机器人显示名称'),
20
- showWaitingTip: koishi_1.Schema.boolean().default(true).description('解析时显示等待提示'),
21
- waitingTipText: koishi_1.Schema.string().default('正在解析视频,请稍候...').description('等待提示文本内容'),
22
- sameLinkInterval: koishi_1.Schema.number().min(0).default(180).description('相同链接重复解析间隔(秒)'),
23
- debug: koishi_1.Schema.boolean().default(false).description('开启调试模式'),
24
- debugFile: koishi_1.Schema.boolean().default(false).description('调试日志写入文件'),
20
+ botName: koishi_1.Schema.string().default('视频解析机器人').description('合并转发消息中显示的机器人名称'),
21
+ debug: koishi_1.Schema.boolean().default(false).description('开启调试模式(详细日志输出至控制台)'),
22
+ debugFile: koishi_1.Schema.boolean().default(false).description('调试日志同时写入本地 debug.log 文件'),
25
23
  }).description('基础设置'),
26
24
  koishi_1.Schema.object({
27
25
  unifiedMessageFormat: koishi_1.Schema.string().role('textarea').default(`标题:\${标题}\n作者:\${作者}\n点赞:\${点赞数}\n视频链接:\${视频链接}`).description('统一消息格式,可用变量:${标题} ${作者} ${简介} ${视频时长} ${点赞数} ${收藏数} ${转发数} ${播放数} ${评论数} ${发布时间} ${图片数量} ${作者ID} ${视频链接} ${封面} ${音乐作者} ${音乐标题}'),
28
- }).description('统一消息格式'),
26
+ }).description('消息格式设置'),
29
27
  koishi_1.Schema.object({
30
- showImageText: koishi_1.Schema.boolean().default(true).description('显示图文内容'),
31
- showVideoFile: koishi_1.Schema.boolean().default(true).description('发送视频文件(关闭则只发链接)'),
32
- sendLivePhotoVideos: koishi_1.Schema.boolean().default(true).description('发送实况图片对应的视频'),
28
+ showImageText: koishi_1.Schema.boolean().default(true).description('是否发送解析后的文字内容'),
29
+ showVideoFile: koishi_1.Schema.boolean().default(true).description('是否发送视频文件(关闭则只发送视频链接)'),
30
+ sendLivePhotoVideos: koishi_1.Schema.boolean().default(true).description('发送实况图集时是否附带短视频'),
31
+ maxDescLength: koishi_1.Schema.number().default(200).description('简介内容最大长度(字符),超出自动截断'),
33
32
  }).description('内容显示设置'),
34
33
  koishi_1.Schema.object({
35
- maxDescLength: koishi_1.Schema.number().default(200).description('简介内容最大长度(字符)'),
36
- }).description('内容长度限制'),
34
+ timeout: koishi_1.Schema.number().min(0).default(180000).description('API 请求超时(毫秒)'),
35
+ videoSendTimeout: koishi_1.Schema.number().min(0).default(60000).description('视频消息发送超时(毫秒,0 为不限制)'),
36
+ userAgent: koishi_1.Schema.string().default('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36').description('API 请求 UA'),
37
+ }).description('网络与 API 设置'),
37
38
  koishi_1.Schema.object({
38
- timeout: koishi_1.Schema.number().min(0).default(180000).description('API请求超时时间(毫秒)'),
39
- videoSendTimeout: koishi_1.Schema.number().min(0).default(60000).description('视频发送超时时间(毫秒,0为不限制)'),
40
- userAgent: koishi_1.Schema.string().default('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36').description('请求UA标识'),
41
- }).description('网络与API设置'),
42
- koishi_1.Schema.object({
43
- ignoreSendError: koishi_1.Schema.boolean().default(true).description('忽略发送失败错误'),
44
- retryTimes: koishi_1.Schema.number().min(0).default(3).description('API请求重试次数'),
45
- retryInterval: koishi_1.Schema.number().min(0).default(1000).description('重试间隔时间(毫秒)'),
39
+ ignoreSendError: koishi_1.Schema.boolean().default(true).description('忽略消息发送失败,避免插件崩溃'),
40
+ retryTimes: koishi_1.Schema.number().min(0).default(3).description('API 请求重试次数'),
41
+ retryInterval: koishi_1.Schema.number().min(0).default(1000).description('重试间隔(毫秒)'),
46
42
  }).description('错误与重试设置'),
47
43
  koishi_1.Schema.object({
48
- enableForward: koishi_1.Schema.boolean().default(false).description('启用合并转发(仅OneBot平台)'),
49
- downloadVideoBeforeSend: koishi_1.Schema.boolean().default(false).description('发送前先下载视频'),
50
- maxVideoSize: koishi_1.Schema.number().min(0).default(0).description('最大视频大小限制(MB,0为不限制)'),
51
- downloadThreads: koishi_1.Schema.number().min(0).max(10).default(0).description('多线程下载线程数(0为不使用多线程)'),
44
+ enableForward: koishi_1.Schema.boolean().default(false).description('启用合并转发(仅 OneBot 平台)'),
45
+ downloadVideoBeforeSend: koishi_1.Schema.boolean().default(false).description('发送前先下载视频到本地'),
46
+ maxVideoSize: koishi_1.Schema.number().min(0).default(0).description('视频下载大小限制(MB,0 为不限制)'),
47
+ downloadThreads: koishi_1.Schema.number().min(0).max(10).default(0).description('多线程下载线程数(0 为单线程)'),
52
48
  }).description('发送方式设置'),
53
49
  koishi_1.Schema.object({
54
50
  messageBufferDelay: koishi_1.Schema.number().min(0).default(0).description('消息缓冲延迟(毫秒)'),
55
- }).description('消息处理设置'),
51
+ }).description('消息缓冲'),
52
+ koishi_1.Schema.object({
53
+ autoClearCacheInterval: koishi_1.Schema.number().min(0).default(0).description('自动清理缓存间隔(分钟,0 为关闭)'),
54
+ }).description('缓存清理'),
56
55
  koishi_1.Schema.object({
57
- autoClearCacheInterval: koishi_1.Schema.number().min(0).default(0).description('自动清理缓存间隔(分钟,0为关闭)'),
58
- }).description('缓存清理设置'),
56
+ waitingTipText: koishi_1.Schema.string().default('正在解析视频,请稍候...').description('解析等待提示'),
57
+ duplicateLinkText: koishi_1.Schema.string().default('请勿重复解析相同链接').description('重复链接提示'),
58
+ unsupportedPlatformText: koishi_1.Schema.string().default('不支持该平台链接').description('不支持的平台提示'),
59
+ invalidLinkText: koishi_1.Schema.string().default('无效的视频链接').description('无效链接提示(parse 指令)'),
60
+ cacheClearedText: koishi_1.Schema.string().default('✅ 缓存已清空').description('缓存清理提示'),
61
+ parseErrorPrefix: koishi_1.Schema.string().default('❌ 解析失败:').description('解析失败消息前缀'),
62
+ parseErrorItemFormat: koishi_1.Schema.string().default('【${url}】: ${msg}').description('每条解析失败格式,可用 ${url} ${msg}'),
63
+ }).description('界面文字设置'),
59
64
  ]);
60
65
  const processed = new Map();
61
66
  const linkBuffer = new Map();
@@ -282,6 +287,7 @@ function pickBestQuality(videoBackup) {
282
287
  .sort((a, b) => (b.bit_rate || 0) - (a.bit_rate || 0));
283
288
  }
284
289
  function parseApiResponse(raw, maxDescLen) {
290
+ debugLog('DEBUG', '原始API返回数据:', raw);
285
291
  const data = raw?.data || {};
286
292
  const extra = data.extra || {};
287
293
  let type = data.type || '';
@@ -356,12 +362,14 @@ function parseApiResponse(raw, maxDescLen) {
356
362
  else if (extra.create_time) {
357
363
  publishTime = extra.create_time * 1000;
358
364
  }
359
- return {
365
+ const result = {
360
366
  type, title, desc, author, uid, avatar, cover,
361
367
  video, videos, images, live_photo, music,
362
368
  like, comment, collect, share, play,
363
369
  duration, publishTime
364
370
  };
371
+ debugLog('DEBUG', '解析后的数据:', result);
372
+ return result;
365
373
  }
366
374
  function generateFormattedText(p, format) {
367
375
  const vars = {
@@ -386,7 +394,9 @@ function generateFormattedText(p, format) {
386
394
  for (const [key, value] of Object.entries(vars)) {
387
395
  result = result.replace(new RegExp(`\\$\\{${key}\\}`, 'g'), value);
388
396
  }
389
- return result.replace(/^\s*\n/gm, '').trim();
397
+ const final = result.replace(/^\s*\n/gm, '').trim();
398
+ debugLog('DEBUG', '生成格式化文本:', final);
399
+ return final;
390
400
  }
391
401
  function clearAllCache() {
392
402
  processed.clear();
@@ -417,16 +427,28 @@ function buildForwardNode(session, content, botName) {
417
427
  function apply(ctx, config) {
418
428
  initDebug(config.debug, config.debugFile);
419
429
  debugLog('INFO', '插件初始化开始');
430
+ debugLog('INFO', '当前配置:', config);
431
+ // 合并默认文案
432
+ const texts = {
433
+ waitingTipText: config.waitingTipText || '正在解析视频,请稍候...',
434
+ duplicateLinkText: config.duplicateLinkText || '请勿重复解析相同链接',
435
+ unsupportedPlatformText: config.unsupportedPlatformText || '不支持该平台链接',
436
+ invalidLinkText: config.invalidLinkText || '无效的视频链接',
437
+ cacheClearedText: config.cacheClearedText || '✅ 缓存已清空',
438
+ parseErrorPrefix: config.parseErrorPrefix || '❌ 解析失败:',
439
+ parseErrorItemFormat: config.parseErrorItemFormat || '【${url}】: ${msg}',
440
+ };
420
441
  clearAllCache();
421
442
  const http = axios_1.default.create({
422
443
  timeout: config.timeout,
423
444
  headers: {
424
- 'User-Agent': config.userAgent,
445
+ 'User-Agent': config.userAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
425
446
  'Referer': 'https://www.baidu.com/',
426
447
  'Content-Type': 'application/x-www-form-urlencoded'
427
448
  }
428
449
  });
429
450
  async function fetchApi(url) {
451
+ debugLog('INFO', `调用API解析: ${url}`);
430
452
  for (let i = 0; i <= config.retryTimes; i++) {
431
453
  try {
432
454
  const res = await http.get('https://api.bugpk.com/api/short_videos', {
@@ -434,6 +456,7 @@ function apply(ctx, config) {
434
456
  timeout: config.timeout
435
457
  });
436
458
  debugLog('INFO', `API响应: code=${res.data?.code}, msg=${res.data?.msg}`);
459
+ debugLog('DEBUG', 'API完整响应:', res.data);
437
460
  if (res.data && (res.data.code === 200 || res.data.code === 0)) {
438
461
  return parseApiResponse(res.data, config.maxDescLength);
439
462
  }
@@ -448,50 +471,55 @@ function apply(ctx, config) {
448
471
  throw new Error('API请求全部失败');
449
472
  }
450
473
  async function parseUrl(url) {
451
- debugLog('INFO', `解析链接: ${url}`);
452
- let realUrl = await resolveShortUrl(url);
453
- realUrl = cleanUrl(realUrl);
454
- debugLog('DEBUG', `实际URL: ${realUrl}`);
474
+ debugLog('INFO', `开始解析链接: ${url}`);
475
+ // 尝试短链接解析
476
+ const realUrl = await resolveShortUrl(url);
477
+ debugLog('DEBUG', `重定向后的URL: ${realUrl}`);
455
478
  const platform = getPlatformType(realUrl);
456
479
  if (!platform) {
457
480
  debugLog('WARN', `不支持的平台: ${realUrl}`);
458
- return { success: false, msg: '不支持该平台链接' };
481
+ return { success: false, msg: texts.unsupportedPlatformText };
459
482
  }
460
- try {
461
- const info = await fetchApi(realUrl);
462
- debugLog('INFO', `解析成功: ${info.title}`);
463
- return { success: true, data: info };
464
- }
465
- catch (error) {
466
- debugLog('ERROR', `解析失败: ${getErrorMessage(error)}`);
467
- return { success: false, msg: getErrorMessage(error) };
483
+ // 优先使用原始短链接尝试,若失败再用重定向后的URL
484
+ const candidates = [url, realUrl];
485
+ let lastError = null;
486
+ for (const candidate of candidates) {
487
+ try {
488
+ const info = await fetchApi(candidate);
489
+ debugLog('INFO', `解析成功: ${info.title}`);
490
+ return { success: true, data: info };
491
+ }
492
+ catch (error) {
493
+ lastError = getErrorMessage(error);
494
+ debugLog('ERROR', `候选链接解析失败: ${candidate} => ${lastError}`);
495
+ }
468
496
  }
497
+ return { success: false, msg: lastError || '解析失败' };
469
498
  }
470
499
  async function processSingleUrl(session, url) {
500
+ debugLog('INFO', `处理单个URL: ${url}, 用户: ${session.userId}`);
471
501
  const hash = crypto_1.default.createHash('md5').update(url).digest('hex');
472
502
  const now = Date.now();
473
503
  const last = processed.get(hash);
474
504
  if (last && (now - last) < config.sameLinkInterval * 1000) {
475
505
  debugLog('WARN', `重复解析: ${url}`);
476
- return { success: false, msg: '请勿重复解析相同链接' };
506
+ return { success: false, msg: texts.duplicateLinkText };
477
507
  }
478
508
  processed.set(hash, now);
479
509
  const result = await parseUrl(url);
480
- if (!result.success) {
481
- return { success: false, msg: result.msg };
482
- }
510
+ if (!result.success)
511
+ return result;
483
512
  const text = generateFormattedText(result.data, config.unifiedMessageFormat);
484
- return {
485
- success: true,
486
- data: { text, parsed: result.data }
487
- };
513
+ return { success: true, data: { text, parsed: result.data } };
488
514
  }
489
515
  async function sendWithTimeout(session, content) {
516
+ debugLog('DEBUG', `发送消息: ${JSON.stringify(content)}`);
490
517
  if (config.videoSendTimeout <= 0) {
491
518
  try {
492
519
  return await session.send(content);
493
520
  }
494
521
  catch (err) {
522
+ debugLog('ERROR', `发送消息失败: ${getErrorMessage(err)}`);
495
523
  if (!config.ignoreSendError)
496
524
  throw err;
497
525
  return null;
@@ -504,6 +532,7 @@ function apply(ctx, config) {
504
532
  ]);
505
533
  }
506
534
  catch (err) {
535
+ debugLog('ERROR', `发送消息超时或失败: ${getErrorMessage(err)}`);
507
536
  if (!config.ignoreSendError)
508
537
  throw err;
509
538
  return null;
@@ -525,11 +554,14 @@ function apply(ctx, config) {
525
554
  items.push(res.data);
526
555
  }
527
556
  else {
528
- errors.push(`【${url.slice(0, 50)}...】: ${res.msg}`);
557
+ const item = texts.parseErrorItemFormat
558
+ .replace(/\$\{url\}/g, url.length > 50 ? url.slice(0, 50) + '...' : url)
559
+ .replace(/\$\{msg\}/g, res.msg);
560
+ errors.push(item);
529
561
  }
530
562
  }
531
563
  if (errors.length) {
532
- await sendWithTimeout(session, `❌ 解析失败:\n${errors.join('\n')}`).catch(() => { });
564
+ await sendWithTimeout(session, `${texts.parseErrorPrefix}\n${errors.join('\n')}`).catch(() => { });
533
565
  await delay(500);
534
566
  }
535
567
  if (!items.length)
@@ -540,7 +572,9 @@ function apply(ctx, config) {
540
572
  for (const item of items) {
541
573
  const p = item.parsed;
542
574
  const text = item.text;
543
- if (text) {
575
+ debugLog('INFO', `开始发送内容,类型: ${p.type}, 标题: ${p.title}`);
576
+ if (text && config.showImageText) {
577
+ debugLog('DEBUG', '发送文本消息');
544
578
  if (enableForward)
545
579
  forwardMessages.push(buildForwardNode(session, text, botName));
546
580
  else {
@@ -549,6 +583,7 @@ function apply(ctx, config) {
549
583
  }
550
584
  }
551
585
  if (p.cover && p.type !== 'live_photo') {
586
+ debugLog('DEBUG', '发送封面图片:', p.cover);
552
587
  if (enableForward)
553
588
  forwardMessages.push(buildForwardNode(session, koishi_1.h.image(p.cover), botName));
554
589
  else {
@@ -561,9 +596,13 @@ function apply(ctx, config) {
561
596
  if (config.downloadVideoBeforeSend) {
562
597
  const fname = crypto_1.default.createHash('md5').update(p.video).digest('hex');
563
598
  const dl = await downloadVideo(p.video, fname, config.userAgent, config.maxVideoSize, config.downloadThreads);
564
- if (dl.success)
565
- return koishi_1.h.file(dl.filePath);
599
+ if (dl.success) {
600
+ const fileUrl = (0, url_1.pathToFileURL)(dl.filePath).href;
601
+ debugLog('INFO', `视频下载成功,发送文件: ${fileUrl}`);
602
+ return koishi_1.h.file(fileUrl);
603
+ }
566
604
  }
605
+ debugLog('INFO', `发送视频链接: ${p.video}`);
567
606
  return koishi_1.h.video(p.video);
568
607
  };
569
608
  if (enableForward) {
@@ -575,7 +614,8 @@ function apply(ctx, config) {
575
614
  const vMsg = await sendVideo();
576
615
  await sendWithTimeout(session, vMsg);
577
616
  }
578
- catch {
617
+ catch (e) {
618
+ debugLog('ERROR', `发送视频失败: ${getErrorMessage(e)},尝试直接发送链接`);
579
619
  try {
580
620
  await sendWithTimeout(session, koishi_1.h.video(p.video));
581
621
  }
@@ -587,6 +627,7 @@ function apply(ctx, config) {
587
627
  if (p.type === 'image' || p.type === 'live_photo') {
588
628
  const mediaList = [];
589
629
  if (p.type === 'live_photo' && p.live_photo?.length) {
630
+ debugLog('INFO', `发送实况图集,共 ${p.live_photo.length} 张`);
590
631
  for (const lp of p.live_photo) {
591
632
  if (lp.image)
592
633
  mediaList.push({ type: 'image', url: lp.image });
@@ -595,6 +636,7 @@ function apply(ctx, config) {
595
636
  }
596
637
  }
597
638
  else if (p.images?.length) {
639
+ debugLog('INFO', `发送图集,共 ${p.images.length} 张`);
598
640
  p.images.forEach(url => mediaList.push({ type: 'image', url }));
599
641
  }
600
642
  if (enableForward) {
@@ -605,20 +647,25 @@ function apply(ctx, config) {
605
647
  }
606
648
  else {
607
649
  for (const m of mediaList) {
650
+ debugLog('DEBUG', `发送${m.type}: ${m.url}`);
608
651
  try {
609
652
  await sendWithTimeout(session, m.type === 'image' ? koishi_1.h.image(m.url) : koishi_1.h.video(m.url));
610
653
  await delay(200);
611
654
  }
612
- catch { }
655
+ catch (e) {
656
+ debugLog('ERROR', `发送${m.type}失败: ${getErrorMessage(e)}`);
657
+ }
613
658
  }
614
659
  }
615
660
  }
616
661
  }
617
662
  if (enableForward && forwardMessages.length) {
663
+ debugLog('INFO', `合并转发消息,共 ${forwardMessages.length} 条`);
618
664
  try {
619
665
  await sendWithTimeout(session, (0, koishi_1.h)('message', { forward: true }, forwardMessages.slice(0, 100)));
620
666
  }
621
- catch {
667
+ catch (e) {
668
+ debugLog('ERROR', `合并转发失败,降级逐条发送: ${getErrorMessage(e)}`);
622
669
  for (const node of forwardMessages) {
623
670
  try {
624
671
  await sendWithTimeout(session, node.data.content);
@@ -633,28 +680,33 @@ function apply(ctx, config) {
633
680
  if (!config.enable)
634
681
  return;
635
682
  const content = session.content?.trim() || '';
683
+ debugLog('INFO', `收到消息: "${content}"`);
636
684
  const urls = extractUrl(content);
637
- if (!urls.length)
685
+ if (!urls.length) {
686
+ debugLog('DEBUG', '消息中未检测到平台链接');
638
687
  return;
688
+ }
689
+ debugLog('INFO', '检测到链接:', urls);
639
690
  if (config.showWaitingTip) {
640
691
  try {
641
- await sendWithTimeout(session, config.waitingTipText);
692
+ await sendWithTimeout(session, texts.waitingTipText);
642
693
  }
643
694
  catch { }
644
695
  }
645
696
  await flush(session, urls);
646
697
  });
647
698
  ctx.command('parse <url>', '手动解析视频').action(async ({ session }, url) => {
699
+ debugLog('INFO', `手动解析指令: ${url}`);
648
700
  const us = extractUrl(url);
649
701
  if (!us.length) {
650
- await sendWithTimeout(session, '无效的视频链接');
702
+ await sendWithTimeout(session, texts.invalidLinkText);
651
703
  return;
652
704
  }
653
705
  await flush(session, us);
654
706
  });
655
707
  ctx.command('clear-cache', '清空缓存').action(async ({ session }) => {
656
708
  clearAllCache();
657
- await sendWithTimeout(session, '✅ 缓存已清空');
709
+ await sendWithTimeout(session, texts.cacheClearedText);
658
710
  });
659
711
  setInterval(() => {
660
712
  const now = Date.now();
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.2",
4
+ "version": "0.8.4",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [