koishi-plugin-video-parser-all 0.8.5 → 0.8.6
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 +4 -8
- package/lib/index.js +12 -169
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -3,8 +3,9 @@ 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
|
+
sameLinkInterval?: number | null | undefined;
|
|
6
8
|
debug?: boolean | null | undefined;
|
|
7
|
-
debugFile?: boolean | null | undefined;
|
|
8
9
|
} & import("cosmokit").Dict & {
|
|
9
10
|
unifiedMessageFormat?: string | null | undefined;
|
|
10
11
|
} & {
|
|
@@ -22,9 +23,6 @@ export declare const Config: Schema<{
|
|
|
22
23
|
retryInterval?: number | null | undefined;
|
|
23
24
|
} & {
|
|
24
25
|
enableForward?: boolean | null | undefined;
|
|
25
|
-
downloadVideoBeforeSend?: boolean | null | undefined;
|
|
26
|
-
maxVideoSize?: number | null | undefined;
|
|
27
|
-
downloadThreads?: number | null | undefined;
|
|
28
26
|
} & {
|
|
29
27
|
messageBufferDelay?: number | null | undefined;
|
|
30
28
|
} & {
|
|
@@ -40,8 +38,9 @@ export declare const Config: Schema<{
|
|
|
40
38
|
}, {
|
|
41
39
|
enable: boolean;
|
|
42
40
|
botName: string;
|
|
41
|
+
showWaitingTip: boolean;
|
|
42
|
+
sameLinkInterval: number;
|
|
43
43
|
debug: boolean;
|
|
44
|
-
debugFile: boolean;
|
|
45
44
|
} & import("cosmokit").Dict & {
|
|
46
45
|
unifiedMessageFormat: string;
|
|
47
46
|
} & {
|
|
@@ -59,9 +58,6 @@ export declare const Config: Schema<{
|
|
|
59
58
|
retryInterval: number;
|
|
60
59
|
} & {
|
|
61
60
|
enableForward: boolean;
|
|
62
|
-
downloadVideoBeforeSend: boolean;
|
|
63
|
-
maxVideoSize: number;
|
|
64
|
-
downloadThreads: number;
|
|
65
61
|
} & {
|
|
66
62
|
messageBufferDelay: number;
|
|
67
63
|
} & {
|
package/lib/index.js
CHANGED
|
@@ -10,18 +10,17 @@ 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 promises_1 = require("stream/promises");
|
|
14
|
-
const worker_threads_1 = require("worker_threads");
|
|
15
13
|
exports.name = 'video-parser-all';
|
|
16
14
|
exports.Config = koishi_1.Schema.intersect([
|
|
17
15
|
koishi_1.Schema.object({
|
|
18
16
|
enable: koishi_1.Schema.boolean().default(true).description('是否启用视频解析插件'),
|
|
19
17
|
botName: koishi_1.Schema.string().default('视频解析机器人').description('合并转发消息中显示的机器人名称'),
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
showWaitingTip: koishi_1.Schema.boolean().default(true).description('解析时显示等待提示'),
|
|
19
|
+
sameLinkInterval: koishi_1.Schema.number().min(0).default(180).description('相同链接重复解析间隔(秒)'),
|
|
20
|
+
debug: koishi_1.Schema.boolean().default(false).description('开启调试模式,在控制台输出详细日志'),
|
|
22
21
|
}).description('基础设置'),
|
|
23
22
|
koishi_1.Schema.object({
|
|
24
|
-
unifiedMessageFormat: koishi_1.Schema.string().role('textarea').default(
|
|
23
|
+
unifiedMessageFormat: koishi_1.Schema.string().role('textarea').default(`\${标题}\n\${作者}\n\${简介}\n点赞:\${点赞数}\n收藏:\${收藏数}\n转发:\${转发数}\n播放:\${播放数}\n评论:\${评论数}`).description('统一消息格式,可用变量:${标题} ${作者} ${简介} ${点赞数} ${收藏数} ${转发数} ${播放数} ${评论数} ${视频时长} ${发布时间} ${图片数量} ${作者ID} ${视频链接} ${封面} ${音乐作者} ${音乐标题}'),
|
|
25
24
|
}).description('消息格式设置'),
|
|
26
25
|
koishi_1.Schema.object({
|
|
27
26
|
showImageText: koishi_1.Schema.boolean().default(true).description('是否发送解析后的文字内容'),
|
|
@@ -41,9 +40,6 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
41
40
|
}).description('错误与重试设置'),
|
|
42
41
|
koishi_1.Schema.object({
|
|
43
42
|
enableForward: koishi_1.Schema.boolean().default(false).description('启用合并转发(仅 OneBot 平台)'),
|
|
44
|
-
downloadVideoBeforeSend: koishi_1.Schema.boolean().default(false).description('发送前先下载视频到本地'),
|
|
45
|
-
maxVideoSize: koishi_1.Schema.number().min(0).default(0).description('视频下载大小限制(MB,0 为不限制)'),
|
|
46
|
-
downloadThreads: koishi_1.Schema.number().min(0).max(10).default(0).description('多线程下载线程数(0 为单线程)'),
|
|
47
43
|
}).description('发送方式设置'),
|
|
48
44
|
koishi_1.Schema.object({
|
|
49
45
|
messageBufferDelay: koishi_1.Schema.number().min(0).default(0).description('消息缓冲延迟(毫秒)'),
|
|
@@ -65,26 +61,12 @@ const processed = new Map();
|
|
|
65
61
|
const linkBuffer = new Map();
|
|
66
62
|
const logger = new koishi_1.Logger(exports.name);
|
|
67
63
|
let debugEnabled = false;
|
|
68
|
-
let debugFileEnabled = false;
|
|
69
|
-
let debugStream = null;
|
|
70
64
|
function debugLog(level, ...args) {
|
|
71
65
|
if (!debugEnabled)
|
|
72
66
|
return;
|
|
73
67
|
const timestamp = new Date().toISOString();
|
|
74
68
|
const message = `[${timestamp}] [${level}] ${args.map(a => typeof a === 'object' ? JSON.stringify(a, null, 2) : String(a)).join(' ')}`;
|
|
75
69
|
logger.info(message);
|
|
76
|
-
if (debugFileEnabled && debugStream) {
|
|
77
|
-
debugStream.write(message + '\n');
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
function initDebug(enabled, fileEnabled) {
|
|
81
|
-
debugEnabled = enabled;
|
|
82
|
-
debugFileEnabled = fileEnabled;
|
|
83
|
-
if (fileEnabled && enabled) {
|
|
84
|
-
const logPath = path_1.default.join(process.cwd(), 'debug.log');
|
|
85
|
-
debugStream = fs_1.default.createWriteStream(logPath, { flags: 'a' });
|
|
86
|
-
debugStream.write(`\n=== Debug session started at ${new Date().toISOString()} ===\n`);
|
|
87
|
-
}
|
|
88
70
|
}
|
|
89
71
|
const PLATFORM_KEYWORDS = {
|
|
90
72
|
bilibili: ['bilibili', 'b23', 'www.bilibili.com', 'm.bilibili.com', 'b23.tv', 't.bilibili.com', 'bilibili.com/video', 'bilibili.com/opus', 'bilibili.com/bangumi'],
|
|
@@ -118,103 +100,6 @@ function getErrorMessage(error) {
|
|
|
118
100
|
return error.message;
|
|
119
101
|
return String(error);
|
|
120
102
|
}
|
|
121
|
-
async function getFileSize(url, userAgent) {
|
|
122
|
-
try {
|
|
123
|
-
const response = await axios_1.default.head(url, {
|
|
124
|
-
timeout: 10000,
|
|
125
|
-
headers: { 'User-Agent': userAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' }
|
|
126
|
-
});
|
|
127
|
-
const contentLength = response.headers['content-length'];
|
|
128
|
-
if (contentLength)
|
|
129
|
-
return Math.round(Number(contentLength) / 1024 / 1024 * 100) / 100;
|
|
130
|
-
}
|
|
131
|
-
catch (error) { }
|
|
132
|
-
return 0;
|
|
133
|
-
}
|
|
134
|
-
async function downloadVideoThread(workerData) {
|
|
135
|
-
return new Promise((resolve, reject) => {
|
|
136
|
-
const worker = new worker_threads_1.Worker(__filename, { workerData });
|
|
137
|
-
worker.on('message', resolve);
|
|
138
|
-
worker.on('error', reject);
|
|
139
|
-
worker.on('exit', (code) => {
|
|
140
|
-
if (code !== 0)
|
|
141
|
-
reject(new Error(`下载线程异常退出,代码:${code}`));
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
if (!worker_threads_1.isMainThread) {
|
|
146
|
-
const { url, start, end, filename, userAgent } = worker_threads_1.workerData;
|
|
147
|
-
const filePath = path_1.default.join(process.cwd(), 'temp_videos', `${filename}_${start}_${end}.part`);
|
|
148
|
-
(0, axios_1.default)({
|
|
149
|
-
url,
|
|
150
|
-
method: 'GET',
|
|
151
|
-
responseType: 'stream',
|
|
152
|
-
timeout: 60000,
|
|
153
|
-
headers: {
|
|
154
|
-
'User-Agent': userAgent,
|
|
155
|
-
'Range': `bytes=${start}-${end}`
|
|
156
|
-
}
|
|
157
|
-
}).then(response => {
|
|
158
|
-
const writeStream = fs_1.default.createWriteStream(filePath);
|
|
159
|
-
response.data.pipe(writeStream);
|
|
160
|
-
writeStream.on('finish', () => worker_threads_1.parentPort?.postMessage({ success: true, filePath, start, end }));
|
|
161
|
-
writeStream.on('error', (error) => worker_threads_1.parentPort?.postMessage({ success: false, error: error.message }));
|
|
162
|
-
}).catch((error) => worker_threads_1.parentPort?.postMessage({ success: false, error: error.message }));
|
|
163
|
-
}
|
|
164
|
-
async function downloadVideo(url, filename, userAgent, maxSize, threads) {
|
|
165
|
-
const dir = path_1.default.join(process.cwd(), 'temp_videos');
|
|
166
|
-
if (!fs_1.default.existsSync(dir))
|
|
167
|
-
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
168
|
-
const filePath = path_1.default.join(dir, `${filename}.mp4`);
|
|
169
|
-
try {
|
|
170
|
-
if (url.endsWith('.m4a') || url.endsWith('.mp3'))
|
|
171
|
-
return { filePath: '', success: false };
|
|
172
|
-
const fileSize = await getFileSize(url, userAgent);
|
|
173
|
-
if (maxSize > 0 && fileSize > maxSize)
|
|
174
|
-
return { filePath: '', success: false };
|
|
175
|
-
if (threads <= 0 || fileSize === 0) {
|
|
176
|
-
const response = await (0, axios_1.default)({
|
|
177
|
-
url,
|
|
178
|
-
method: 'GET',
|
|
179
|
-
responseType: 'stream',
|
|
180
|
-
timeout: 60000,
|
|
181
|
-
headers: { 'User-Agent': userAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' }
|
|
182
|
-
});
|
|
183
|
-
const writeStream = fs_1.default.createWriteStream(filePath);
|
|
184
|
-
await (0, promises_1.pipeline)(response.data, writeStream);
|
|
185
|
-
return { filePath, success: true };
|
|
186
|
-
}
|
|
187
|
-
const totalSize = fileSize * 1024 * 1024;
|
|
188
|
-
const chunkSize = Math.ceil(totalSize / threads);
|
|
189
|
-
const promises = [];
|
|
190
|
-
for (let i = 0; i < threads; i++) {
|
|
191
|
-
const start = i * chunkSize;
|
|
192
|
-
const end = i === threads - 1 ? totalSize - 1 : start + chunkSize - 1;
|
|
193
|
-
promises.push(downloadVideoThread({ url, start, end, filename, userAgent }));
|
|
194
|
-
}
|
|
195
|
-
const results = await Promise.all(promises);
|
|
196
|
-
const writeStream = fs_1.default.createWriteStream(filePath);
|
|
197
|
-
for (const result of results) {
|
|
198
|
-
if (!result.success)
|
|
199
|
-
throw new Error(result.error);
|
|
200
|
-
const readStream = fs_1.default.createReadStream(result.filePath);
|
|
201
|
-
await (0, promises_1.pipeline)(readStream, writeStream, { end: false });
|
|
202
|
-
fs_1.default.unlinkSync(result.filePath);
|
|
203
|
-
}
|
|
204
|
-
writeStream.end();
|
|
205
|
-
return { filePath, success: true };
|
|
206
|
-
}
|
|
207
|
-
catch (error) {
|
|
208
|
-
if (fs_1.default.existsSync(filePath))
|
|
209
|
-
fs_1.default.unlinkSync(filePath);
|
|
210
|
-
const partFiles = fs_1.default.readdirSync(dir).filter(file => file.startsWith(`${filename}_`) && file.endsWith('.part'));
|
|
211
|
-
partFiles.forEach(file => { try {
|
|
212
|
-
fs_1.default.unlinkSync(path_1.default.join(dir, file));
|
|
213
|
-
}
|
|
214
|
-
catch (e) { } });
|
|
215
|
-
return { filePath: '', success: false };
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
103
|
function extractUrl(content) {
|
|
219
104
|
const urlMatches = content.match(/https?:\/\/[^\s\"\'\>]+/gi) || [];
|
|
220
105
|
return urlMatches.filter(url => {
|
|
@@ -424,7 +309,7 @@ function buildForwardNode(session, content, botName) {
|
|
|
424
309
|
return (0, koishi_1.h)('node', { user: { nickname: botName.substring(0, 15), user_id: session.selfId } }, messageContent);
|
|
425
310
|
}
|
|
426
311
|
function apply(ctx, config) {
|
|
427
|
-
|
|
312
|
+
debugEnabled = config.debug || false;
|
|
428
313
|
debugLog('INFO', '插件初始化开始');
|
|
429
314
|
debugLog('INFO', '当前配置:', config);
|
|
430
315
|
const texts = {
|
|
@@ -474,7 +359,6 @@ function apply(ctx, config) {
|
|
|
474
359
|
debugLog('DEBUG', `重定向后的URL: ${realUrl}`);
|
|
475
360
|
const platform = getPlatformType(realUrl);
|
|
476
361
|
if (!platform) {
|
|
477
|
-
debugLog('WARN', `不支持的平台: ${realUrl}`);
|
|
478
362
|
return { success: false, msg: texts.unsupportedPlatformText };
|
|
479
363
|
}
|
|
480
364
|
const candidates = [url, realUrl];
|
|
@@ -482,23 +366,19 @@ function apply(ctx, config) {
|
|
|
482
366
|
for (const candidate of candidates) {
|
|
483
367
|
try {
|
|
484
368
|
const info = await fetchApi(candidate);
|
|
485
|
-
debugLog('INFO', `解析成功: ${info.title}`);
|
|
486
369
|
return { success: true, data: info };
|
|
487
370
|
}
|
|
488
371
|
catch (error) {
|
|
489
372
|
lastError = getErrorMessage(error);
|
|
490
|
-
debugLog('ERROR', `候选链接解析失败: ${candidate} => ${lastError}`);
|
|
491
373
|
}
|
|
492
374
|
}
|
|
493
375
|
return { success: false, msg: lastError || '解析失败' };
|
|
494
376
|
}
|
|
495
377
|
async function processSingleUrl(session, url) {
|
|
496
|
-
debugLog('INFO', `处理单个URL: ${url}, 用户: ${session.userId}`);
|
|
497
378
|
const hash = crypto_1.default.createHash('md5').update(url).digest('hex');
|
|
498
379
|
const now = Date.now();
|
|
499
380
|
const last = processed.get(hash);
|
|
500
381
|
if (last && (now - last) < config.sameLinkInterval * 1000) {
|
|
501
|
-
debugLog('WARN', `重复解析: ${url}`);
|
|
502
382
|
return { success: false, msg: texts.duplicateLinkText };
|
|
503
383
|
}
|
|
504
384
|
processed.set(hash, now);
|
|
@@ -509,13 +389,11 @@ function apply(ctx, config) {
|
|
|
509
389
|
return { success: true, data: { text, parsed: result.data } };
|
|
510
390
|
}
|
|
511
391
|
async function sendWithTimeout(session, content) {
|
|
512
|
-
debugLog('DEBUG', `发送消息: ${JSON.stringify(content)}`);
|
|
513
392
|
if (config.videoSendTimeout <= 0) {
|
|
514
393
|
try {
|
|
515
394
|
return await session.send(content);
|
|
516
395
|
}
|
|
517
396
|
catch (err) {
|
|
518
|
-
debugLog('ERROR', `发送消息失败: ${getErrorMessage(err)}`);
|
|
519
397
|
if (!config.ignoreSendError)
|
|
520
398
|
throw err;
|
|
521
399
|
return null;
|
|
@@ -528,7 +406,6 @@ function apply(ctx, config) {
|
|
|
528
406
|
]);
|
|
529
407
|
}
|
|
530
408
|
catch (err) {
|
|
531
|
-
debugLog('ERROR', `发送消息超时或失败: ${getErrorMessage(err)}`);
|
|
532
409
|
if (!config.ignoreSendError)
|
|
533
410
|
throw err;
|
|
534
411
|
return null;
|
|
@@ -568,9 +445,7 @@ function apply(ctx, config) {
|
|
|
568
445
|
for (const item of items) {
|
|
569
446
|
const p = item.parsed;
|
|
570
447
|
const text = item.text;
|
|
571
|
-
debugLog('INFO', `开始发送内容,类型: ${p.type}, 标题: ${p.title}`);
|
|
572
448
|
if (text && config.showImageText) {
|
|
573
|
-
debugLog('DEBUG', '发送文本消息');
|
|
574
449
|
if (enableForward)
|
|
575
450
|
forwardMessages.push(buildForwardNode(session, text, botName));
|
|
576
451
|
else {
|
|
@@ -579,7 +454,6 @@ function apply(ctx, config) {
|
|
|
579
454
|
}
|
|
580
455
|
}
|
|
581
456
|
if (p.cover && p.type !== 'live_photo') {
|
|
582
|
-
debugLog('DEBUG', '发送封面图片:', p.cover);
|
|
583
457
|
if (enableForward)
|
|
584
458
|
forwardMessages.push(buildForwardNode(session, koishi_1.h.image(p.cover), botName));
|
|
585
459
|
else {
|
|
@@ -588,41 +462,21 @@ function apply(ctx, config) {
|
|
|
588
462
|
}
|
|
589
463
|
}
|
|
590
464
|
if (p.video && config.showVideoFile && (p.type === 'video' || p.type === 'live')) {
|
|
591
|
-
const
|
|
592
|
-
if (config.downloadVideoBeforeSend) {
|
|
593
|
-
const fname = crypto_1.default.createHash('md5').update(p.video).digest('hex');
|
|
594
|
-
const dl = await downloadVideo(p.video, fname, config.userAgent, config.maxVideoSize, config.downloadThreads);
|
|
595
|
-
if (dl.success) {
|
|
596
|
-
debugLog('INFO', `视频下载成功,发送文件: ${dl.filePath}`);
|
|
597
|
-
return koishi_1.h.file(dl.filePath);
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
debugLog('INFO', `发送视频链接: ${p.video}`);
|
|
601
|
-
return koishi_1.h.video(p.video);
|
|
602
|
-
};
|
|
465
|
+
const videoMsg = koishi_1.h.video(p.video);
|
|
603
466
|
if (enableForward) {
|
|
604
|
-
|
|
605
|
-
forwardMessages.push(buildForwardNode(session, vMsg, botName));
|
|
467
|
+
forwardMessages.push(buildForwardNode(session, videoMsg, botName));
|
|
606
468
|
}
|
|
607
469
|
else {
|
|
608
470
|
try {
|
|
609
|
-
|
|
610
|
-
await sendWithTimeout(session, vMsg);
|
|
611
|
-
}
|
|
612
|
-
catch (e) {
|
|
613
|
-
debugLog('ERROR', `发送视频失败: ${getErrorMessage(e)},尝试直接发送链接`);
|
|
614
|
-
try {
|
|
615
|
-
await sendWithTimeout(session, koishi_1.h.video(p.video));
|
|
616
|
-
}
|
|
617
|
-
catch { }
|
|
471
|
+
await sendWithTimeout(session, videoMsg);
|
|
618
472
|
}
|
|
473
|
+
catch { }
|
|
619
474
|
await delay(500);
|
|
620
475
|
}
|
|
621
476
|
}
|
|
622
477
|
if (p.type === 'image' || p.type === 'live_photo') {
|
|
623
478
|
const mediaList = [];
|
|
624
479
|
if (p.type === 'live_photo' && p.live_photo?.length) {
|
|
625
|
-
debugLog('INFO', `发送实况图集,共 ${p.live_photo.length} 张`);
|
|
626
480
|
for (const lp of p.live_photo) {
|
|
627
481
|
if (lp.image)
|
|
628
482
|
mediaList.push({ type: 'image', url: lp.image });
|
|
@@ -631,7 +485,6 @@ function apply(ctx, config) {
|
|
|
631
485
|
}
|
|
632
486
|
}
|
|
633
487
|
else if (p.images?.length) {
|
|
634
|
-
debugLog('INFO', `发送图集,共 ${p.images.length} 张`);
|
|
635
488
|
p.images.forEach(url => mediaList.push({ type: 'image', url }));
|
|
636
489
|
}
|
|
637
490
|
if (enableForward) {
|
|
@@ -642,25 +495,20 @@ function apply(ctx, config) {
|
|
|
642
495
|
}
|
|
643
496
|
else {
|
|
644
497
|
for (const m of mediaList) {
|
|
645
|
-
debugLog('DEBUG', `发送${m.type}: ${m.url}`);
|
|
646
498
|
try {
|
|
647
499
|
await sendWithTimeout(session, m.type === 'image' ? koishi_1.h.image(m.url) : koishi_1.h.video(m.url));
|
|
648
500
|
await delay(200);
|
|
649
501
|
}
|
|
650
|
-
catch
|
|
651
|
-
debugLog('ERROR', `发送${m.type}失败: ${getErrorMessage(e)}`);
|
|
652
|
-
}
|
|
502
|
+
catch { }
|
|
653
503
|
}
|
|
654
504
|
}
|
|
655
505
|
}
|
|
656
506
|
}
|
|
657
507
|
if (enableForward && forwardMessages.length) {
|
|
658
|
-
debugLog('INFO', `合并转发消息,共 ${forwardMessages.length} 条`);
|
|
659
508
|
try {
|
|
660
509
|
await sendWithTimeout(session, (0, koishi_1.h)('message', { forward: true }, forwardMessages.slice(0, 100)));
|
|
661
510
|
}
|
|
662
|
-
catch
|
|
663
|
-
debugLog('ERROR', `合并转发失败,降级逐条发送: ${getErrorMessage(e)}`);
|
|
511
|
+
catch {
|
|
664
512
|
for (const node of forwardMessages) {
|
|
665
513
|
try {
|
|
666
514
|
await sendWithTimeout(session, node.data.content);
|
|
@@ -675,13 +523,9 @@ function apply(ctx, config) {
|
|
|
675
523
|
if (!config.enable)
|
|
676
524
|
return;
|
|
677
525
|
const content = session.content?.trim() || '';
|
|
678
|
-
debugLog('INFO', `收到消息: "${content}"`);
|
|
679
526
|
const urls = extractUrl(content);
|
|
680
|
-
if (!urls.length)
|
|
681
|
-
debugLog('DEBUG', '消息中未检测到平台链接');
|
|
527
|
+
if (!urls.length)
|
|
682
528
|
return;
|
|
683
|
-
}
|
|
684
|
-
debugLog('INFO', '检测到链接:', urls);
|
|
685
529
|
if (config.showWaitingTip) {
|
|
686
530
|
try {
|
|
687
531
|
await sendWithTimeout(session, texts.waitingTipText);
|
|
@@ -691,7 +535,6 @@ function apply(ctx, config) {
|
|
|
691
535
|
await flush(session, urls);
|
|
692
536
|
});
|
|
693
537
|
ctx.command('parse <url>', '手动解析视频').action(async ({ session }, url) => {
|
|
694
|
-
debugLog('INFO', `手动解析指令: ${url}`);
|
|
695
538
|
const us = extractUrl(url);
|
|
696
539
|
if (!us.length) {
|
|
697
540
|
await sendWithTimeout(session, texts.invalidLinkText);
|
package/package.json
CHANGED