koishi-plugin-video-parser-all 0.2.9 → 0.3.1
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 +53 -25
- package/lib/index.js +135 -104
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -1,26 +1,54 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Schema, Context } from 'koishi';
|
|
2
2
|
export declare const name = "video-parser-all";
|
|
3
|
-
export
|
|
4
|
-
enable: boolean
|
|
5
|
-
showWaitingTip: boolean
|
|
6
|
-
waitingTipText: string
|
|
7
|
-
sameLinkInterval: number
|
|
8
|
-
imageParseFormat: string
|
|
9
|
-
returnContent: {
|
|
10
|
-
showImageText: boolean
|
|
11
|
-
showVideoUrl: boolean
|
|
12
|
-
showVideoFile: boolean
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
3
|
+
export declare const Config: Schema<Schemastery.ObjectS<{
|
|
4
|
+
enable: Schema<boolean, boolean>;
|
|
5
|
+
showWaitingTip: Schema<boolean, boolean>;
|
|
6
|
+
waitingTipText: Schema<string, string>;
|
|
7
|
+
sameLinkInterval: Schema<number, number>;
|
|
8
|
+
imageParseFormat: Schema<string, string>;
|
|
9
|
+
returnContent: Schema<Schemastery.ObjectS<{
|
|
10
|
+
showImageText: Schema<boolean, boolean>;
|
|
11
|
+
showVideoUrl: Schema<boolean, boolean>;
|
|
12
|
+
showVideoFile: Schema<boolean, boolean>;
|
|
13
|
+
}>, Schemastery.ObjectT<{
|
|
14
|
+
showImageText: Schema<boolean, boolean>;
|
|
15
|
+
showVideoUrl: Schema<boolean, boolean>;
|
|
16
|
+
showVideoFile: Schema<boolean, boolean>;
|
|
17
|
+
}>>;
|
|
18
|
+
maxDescLength: Schema<number, number>;
|
|
19
|
+
timeout: Schema<number, number>;
|
|
20
|
+
ignoreSendError: Schema<boolean, boolean>;
|
|
21
|
+
enableForward: Schema<boolean, boolean>;
|
|
22
|
+
downloadVideoBeforeSend: Schema<boolean, boolean>;
|
|
23
|
+
messageBufferDelay: Schema<number, number>;
|
|
24
|
+
retryTimes: Schema<number, number>;
|
|
25
|
+
retryInterval: Schema<number, number>;
|
|
26
|
+
videoSendTimeout: Schema<number, number>;
|
|
27
|
+
autoClearCacheInterval: Schema<number, number>;
|
|
28
|
+
}>, Schemastery.ObjectT<{
|
|
29
|
+
enable: Schema<boolean, boolean>;
|
|
30
|
+
showWaitingTip: Schema<boolean, boolean>;
|
|
31
|
+
waitingTipText: Schema<string, string>;
|
|
32
|
+
sameLinkInterval: Schema<number, number>;
|
|
33
|
+
imageParseFormat: Schema<string, string>;
|
|
34
|
+
returnContent: Schema<Schemastery.ObjectS<{
|
|
35
|
+
showImageText: Schema<boolean, boolean>;
|
|
36
|
+
showVideoUrl: Schema<boolean, boolean>;
|
|
37
|
+
showVideoFile: Schema<boolean, boolean>;
|
|
38
|
+
}>, Schemastery.ObjectT<{
|
|
39
|
+
showImageText: Schema<boolean, boolean>;
|
|
40
|
+
showVideoUrl: Schema<boolean, boolean>;
|
|
41
|
+
showVideoFile: Schema<boolean, boolean>;
|
|
42
|
+
}>>;
|
|
43
|
+
maxDescLength: Schema<number, number>;
|
|
44
|
+
timeout: Schema<number, number>;
|
|
45
|
+
ignoreSendError: Schema<boolean, boolean>;
|
|
46
|
+
enableForward: Schema<boolean, boolean>;
|
|
47
|
+
downloadVideoBeforeSend: Schema<boolean, boolean>;
|
|
48
|
+
messageBufferDelay: Schema<number, number>;
|
|
49
|
+
retryTimes: Schema<number, number>;
|
|
50
|
+
retryInterval: Schema<number, number>;
|
|
51
|
+
videoSendTimeout: Schema<number, number>;
|
|
52
|
+
autoClearCacheInterval: Schema<number, number>;
|
|
53
|
+
}>>;
|
|
54
|
+
export declare function apply(ctx: Context, config: any): void;
|
package/lib/index.js
CHANGED
|
@@ -12,6 +12,7 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
12
12
|
const path_1 = __importDefault(require("path"));
|
|
13
13
|
const promises_1 = require("stream/promises");
|
|
14
14
|
const worker_threads_1 = require("worker_threads");
|
|
15
|
+
const currentFilePath = path_1.default.join(process.cwd(), 'src', 'index.ts');
|
|
15
16
|
exports.name = 'video-parser-all';
|
|
16
17
|
exports.Config = koishi_1.Schema.object({
|
|
17
18
|
enable: koishi_1.Schema.boolean().default(true).description('【基础设置】启用插件'),
|
|
@@ -104,13 +105,9 @@ function extractUrl(content) {
|
|
|
104
105
|
const urlMatches = content.match(/https?:\/\/[^\s]+/gi) || [];
|
|
105
106
|
return urlMatches.filter(url => {
|
|
106
107
|
const lower = url.toLowerCase();
|
|
107
|
-
return Object.values(PLATFORM_KEYWORDS).some(
|
|
108
|
+
return Object.values(PLATFORM_KEYWORDS).some(group => group.some(keyword => lower.includes(keyword)));
|
|
108
109
|
});
|
|
109
110
|
}
|
|
110
|
-
function hasPlatformKeyword(content) {
|
|
111
|
-
const lower = content.toLowerCase();
|
|
112
|
-
return Object.values(PLATFORM_KEYWORDS).some(g => g.some(k => lower.includes(k)));
|
|
113
|
-
}
|
|
114
111
|
function getPlatformType(url) {
|
|
115
112
|
const lower = url.toLowerCase();
|
|
116
113
|
if (PLATFORM_KEYWORDS.kuaishou.some(k => lower.includes(k)))
|
|
@@ -137,7 +134,8 @@ async function shortUrl(url) {
|
|
|
137
134
|
if (res.data.code === 200)
|
|
138
135
|
return res.data.short_url;
|
|
139
136
|
}
|
|
140
|
-
catch {
|
|
137
|
+
catch (error) {
|
|
138
|
+
}
|
|
141
139
|
return url;
|
|
142
140
|
}
|
|
143
141
|
async function downloadVideoWithThreads(url, filename) {
|
|
@@ -146,10 +144,20 @@ async function downloadVideoWithThreads(url, filename) {
|
|
|
146
144
|
if (!fs_1.default.existsSync(dir))
|
|
147
145
|
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
148
146
|
const filePath = path_1.default.join(dir, `${filename}.mp4`);
|
|
149
|
-
const worker = new worker_threads_1.Worker(
|
|
150
|
-
worker.on('message', (result) =>
|
|
147
|
+
const worker = new worker_threads_1.Worker(currentFilePath, { workerData: { url, filePath } });
|
|
148
|
+
worker.on('message', (result) => {
|
|
149
|
+
if (result.success && result.filePath) {
|
|
150
|
+
resolve(result.filePath);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
reject(new Error(result.error || '下载失败'));
|
|
154
|
+
}
|
|
155
|
+
});
|
|
151
156
|
worker.on('error', reject);
|
|
152
|
-
worker.on('exit', (code) =>
|
|
157
|
+
worker.on('exit', (code) => {
|
|
158
|
+
if (code !== 0)
|
|
159
|
+
reject(new Error('视频下载线程异常'));
|
|
160
|
+
});
|
|
153
161
|
});
|
|
154
162
|
}
|
|
155
163
|
function parseData(data, maxDescLength, platform) {
|
|
@@ -181,15 +189,12 @@ function parseData(data, maxDescLength, platform) {
|
|
|
181
189
|
else if (Array.isArray(data.video_backup) && data.video_backup.length > 0) {
|
|
182
190
|
video = data.video_backup[0]?.url || '';
|
|
183
191
|
}
|
|
184
|
-
if (video && (video.endsWith('.m4a') || video.endsWith('.mp3')))
|
|
192
|
+
if (video && (video.endsWith('.m4a') || video.endsWith('.mp3')))
|
|
185
193
|
video = '';
|
|
186
|
-
}
|
|
187
194
|
}
|
|
188
195
|
else if (platform === 'bilibili') {
|
|
189
196
|
if (data.videos && Array.isArray(data.videos) && data.videos.length > 0) {
|
|
190
|
-
const hdVideo = data.videos.find(v => v.title.includes('1080') ||
|
|
191
|
-
(v.url && v.url.includes('192')) ||
|
|
192
|
-
v.index === 1);
|
|
197
|
+
const hdVideo = data.videos.find((v) => v.title.includes('1080') || (v.url && v.url.includes('192')) || v.index === 1);
|
|
193
198
|
video = hdVideo?.url || data.videos[0]?.url || '';
|
|
194
199
|
}
|
|
195
200
|
else if (data.url) {
|
|
@@ -197,12 +202,7 @@ function parseData(data, maxDescLength, platform) {
|
|
|
197
202
|
}
|
|
198
203
|
}
|
|
199
204
|
else {
|
|
200
|
-
|
|
201
|
-
video = data.url;
|
|
202
|
-
else if (data.videos?.[0]?.url)
|
|
203
|
-
video = data.videos[0].url;
|
|
204
|
-
else if (data.video_backup?.[0]?.url)
|
|
205
|
-
video = data.video_backup[0].url;
|
|
205
|
+
video = data.url || data.videos?.[0]?.url || data.video_backup?.[0]?.url || '';
|
|
206
206
|
}
|
|
207
207
|
if (video.endsWith('.m4a') || video.endsWith('.mp3'))
|
|
208
208
|
video = '';
|
|
@@ -210,17 +210,21 @@ function parseData(data, maxDescLength, platform) {
|
|
|
210
210
|
}
|
|
211
211
|
function clearAllCache() {
|
|
212
212
|
processed.clear();
|
|
213
|
-
linkBuffer.forEach(
|
|
213
|
+
linkBuffer.forEach(buf => clearTimeout(buf.timer));
|
|
214
214
|
linkBuffer.clear();
|
|
215
|
-
const
|
|
216
|
-
if (fs_1.default.existsSync(
|
|
217
|
-
fs_1.default.readdirSync(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
215
|
+
const tempDir = path_1.default.join(process.cwd(), 'temp_videos');
|
|
216
|
+
if (fs_1.default.existsSync(tempDir)) {
|
|
217
|
+
fs_1.default.readdirSync(tempDir).forEach(file => {
|
|
218
|
+
try {
|
|
219
|
+
fs_1.default.unlinkSync(path_1.default.join(tempDir, file));
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
221
225
|
return true;
|
|
222
226
|
}
|
|
223
|
-
const delay = (ms) => new Promise(
|
|
227
|
+
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
224
228
|
function apply(ctx, config) {
|
|
225
229
|
if (!worker_threads_1.isMainThread)
|
|
226
230
|
return;
|
|
@@ -245,10 +249,9 @@ function apply(ctx, config) {
|
|
|
245
249
|
break;
|
|
246
250
|
}
|
|
247
251
|
}
|
|
248
|
-
catch (
|
|
249
|
-
if (retry === config.retryTimes)
|
|
252
|
+
catch (error) {
|
|
253
|
+
if (retry === config.retryTimes)
|
|
250
254
|
break;
|
|
251
|
-
}
|
|
252
255
|
await delay(config.retryInterval);
|
|
253
256
|
}
|
|
254
257
|
}
|
|
@@ -282,10 +285,9 @@ function apply(ctx, config) {
|
|
|
282
285
|
break;
|
|
283
286
|
}
|
|
284
287
|
}
|
|
285
|
-
catch (
|
|
286
|
-
if (retry === config.retryTimes)
|
|
288
|
+
catch (error) {
|
|
289
|
+
if (retry === config.retryTimes)
|
|
287
290
|
break;
|
|
288
|
-
}
|
|
289
291
|
await delay(config.retryInterval);
|
|
290
292
|
}
|
|
291
293
|
}
|
|
@@ -299,36 +301,54 @@ function apply(ctx, config) {
|
|
|
299
301
|
return { data: null, msg: '请勿重复解析' };
|
|
300
302
|
}
|
|
301
303
|
processed.set(hash, now);
|
|
302
|
-
const
|
|
303
|
-
if (!
|
|
304
|
-
return { data: null, msg:
|
|
305
|
-
const
|
|
304
|
+
const result = await parse(url);
|
|
305
|
+
if (!result.data)
|
|
306
|
+
return { data: null, msg: result.msg };
|
|
307
|
+
const parseData = result.data;
|
|
306
308
|
let text = config.imageParseFormat
|
|
307
|
-
.replace(/\${标题}/g,
|
|
308
|
-
.replace(/\${UP主}/g,
|
|
309
|
-
.replace(/\${简介}/g,
|
|
309
|
+
.replace(/\${标题}/g, parseData.title)
|
|
310
|
+
.replace(/\${UP主}/g, parseData.author)
|
|
311
|
+
.replace(/\${简介}/g, parseData.desc)
|
|
310
312
|
.replace(/\${tab}/g, '\t')
|
|
311
313
|
.replace(/\${~~~}/g, '\n');
|
|
312
|
-
return {
|
|
314
|
+
return {
|
|
315
|
+
data: {
|
|
316
|
+
text,
|
|
317
|
+
cover: parseData.cover,
|
|
318
|
+
images: parseData.images,
|
|
319
|
+
video: parseData.video,
|
|
320
|
+
type: parseData.type
|
|
321
|
+
},
|
|
322
|
+
msg: 'ok'
|
|
323
|
+
};
|
|
313
324
|
}
|
|
314
|
-
async function sendTimeout(session,
|
|
315
|
-
if (config.videoSendTimeout <= 0)
|
|
316
|
-
return session.send(
|
|
317
|
-
|
|
325
|
+
async function sendTimeout(session, content) {
|
|
326
|
+
if (config.videoSendTimeout <= 0) {
|
|
327
|
+
return session.send(content).catch(() => null);
|
|
328
|
+
}
|
|
329
|
+
return Promise.race([
|
|
330
|
+
session.send(content),
|
|
331
|
+
new Promise((_, reject) => setTimeout(() => reject('timeout'), config.videoSendTimeout))
|
|
332
|
+
]).catch(() => null);
|
|
318
333
|
}
|
|
319
334
|
async function flush(session, manualUrls) {
|
|
320
335
|
const key = `${session.platform}:${session.userId}:${session.channelId}`;
|
|
321
|
-
const
|
|
322
|
-
const urls = manualUrls ||
|
|
323
|
-
if (
|
|
324
|
-
clearTimeout(
|
|
336
|
+
const buffer = linkBuffer.get(key);
|
|
337
|
+
const urls = manualUrls || buffer?.urls || [];
|
|
338
|
+
if (buffer) {
|
|
339
|
+
clearTimeout(buffer.timer);
|
|
325
340
|
linkBuffer.delete(key);
|
|
326
341
|
}
|
|
327
342
|
const items = [];
|
|
328
343
|
const errs = [];
|
|
329
|
-
for (const
|
|
330
|
-
const
|
|
331
|
-
|
|
344
|
+
for (const url of urls) {
|
|
345
|
+
const result = await processSingleUrl(session, url);
|
|
346
|
+
if (result.data) {
|
|
347
|
+
items.push(result.data);
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
errs.push(`【${url.slice(0, 22)}...】:${result.msg}`);
|
|
351
|
+
}
|
|
332
352
|
}
|
|
333
353
|
const forwardMessages = [];
|
|
334
354
|
const botName = '视频解析机器人';
|
|
@@ -358,41 +378,44 @@ function apply(ctx, config) {
|
|
|
358
378
|
}
|
|
359
379
|
return;
|
|
360
380
|
}
|
|
361
|
-
for (const
|
|
381
|
+
for (const item of items) {
|
|
362
382
|
if (config.enableForward && session.platform === 'onebot') {
|
|
363
383
|
forwardMessages.push((0, koishi_1.h)('message', [
|
|
364
384
|
(0, koishi_1.h)('author', { id: session.selfId, name: botName }),
|
|
365
|
-
|
|
385
|
+
item.text
|
|
366
386
|
]));
|
|
367
|
-
if (
|
|
387
|
+
if (item.cover) {
|
|
368
388
|
forwardMessages.push((0, koishi_1.h)('message', [
|
|
369
389
|
(0, koishi_1.h)('author', { id: session.selfId, name: botName }),
|
|
370
|
-
koishi_1.h.image(
|
|
390
|
+
koishi_1.h.image(item.cover)
|
|
371
391
|
]));
|
|
372
392
|
}
|
|
373
|
-
if (
|
|
374
|
-
let
|
|
393
|
+
if (item.video && config.returnContent.showVideoFile) {
|
|
394
|
+
let videoElem = koishi_1.h.video(item.video);
|
|
375
395
|
if (config.downloadVideoBeforeSend) {
|
|
376
396
|
try {
|
|
377
|
-
const
|
|
378
|
-
|
|
397
|
+
const filename = crypto_1.default.createHash('md5').update(item.video).digest('hex');
|
|
398
|
+
const filePath = await downloadVideoWithThreads(item.video, filename);
|
|
399
|
+
videoElem = koishi_1.h.file(filePath);
|
|
400
|
+
}
|
|
401
|
+
catch (error) {
|
|
402
|
+
videoElem = koishi_1.h.video(item.video);
|
|
379
403
|
}
|
|
380
|
-
catch { }
|
|
381
404
|
}
|
|
382
405
|
forwardMessages.push((0, koishi_1.h)('message', [
|
|
383
406
|
(0, koishi_1.h)('author', { id: session.selfId, name: botName }),
|
|
384
|
-
|
|
407
|
+
videoElem
|
|
385
408
|
]));
|
|
386
409
|
}
|
|
387
|
-
if (
|
|
388
|
-
const
|
|
410
|
+
if (item.video && config.returnContent.showVideoUrl) {
|
|
411
|
+
const shortLink = await shortUrl(item.video);
|
|
389
412
|
forwardMessages.push((0, koishi_1.h)('message', [
|
|
390
413
|
(0, koishi_1.h)('author', { id: session.selfId, name: botName }),
|
|
391
|
-
`🔗 无水印:${
|
|
414
|
+
`🔗 无水印:${shortLink}`
|
|
392
415
|
]));
|
|
393
416
|
}
|
|
394
|
-
if (
|
|
395
|
-
|
|
417
|
+
if (item.type === 'image' && item.images?.length) {
|
|
418
|
+
item.images.forEach(imgUrl => {
|
|
396
419
|
forwardMessages.push((0, koishi_1.h)('message', [
|
|
397
420
|
(0, koishi_1.h)('author', { id: session.selfId, name: botName }),
|
|
398
421
|
koishi_1.h.image(imgUrl)
|
|
@@ -401,32 +424,35 @@ function apply(ctx, config) {
|
|
|
401
424
|
}
|
|
402
425
|
}
|
|
403
426
|
else {
|
|
404
|
-
await sendTimeout(session,
|
|
427
|
+
await sendTimeout(session, item.text);
|
|
405
428
|
await delay(300);
|
|
406
|
-
if (
|
|
407
|
-
const
|
|
408
|
-
await sendTimeout(session,
|
|
429
|
+
if (item.type === 'image' && item.images?.length) {
|
|
430
|
+
const imgMsg = (0, koishi_1.h)('message', ...item.images.map(url => koishi_1.h.image(url)));
|
|
431
|
+
await sendTimeout(session, imgMsg);
|
|
409
432
|
}
|
|
410
433
|
else {
|
|
411
|
-
if (
|
|
412
|
-
await sendTimeout(session, koishi_1.h.image(
|
|
434
|
+
if (item.cover) {
|
|
435
|
+
await sendTimeout(session, koishi_1.h.image(item.cover));
|
|
413
436
|
await delay(300);
|
|
414
437
|
}
|
|
415
|
-
if (
|
|
416
|
-
let
|
|
438
|
+
if (item.video && config.returnContent.showVideoFile) {
|
|
439
|
+
let videoElem = koishi_1.h.video(item.video);
|
|
417
440
|
if (config.downloadVideoBeforeSend) {
|
|
418
441
|
try {
|
|
419
|
-
const
|
|
420
|
-
|
|
442
|
+
const filename = crypto_1.default.createHash('md5').update(item.video).digest('hex');
|
|
443
|
+
const filePath = await downloadVideoWithThreads(item.video, filename);
|
|
444
|
+
videoElem = koishi_1.h.file(filePath);
|
|
445
|
+
}
|
|
446
|
+
catch (error) {
|
|
447
|
+
videoElem = koishi_1.h.video(item.video);
|
|
421
448
|
}
|
|
422
|
-
catch { }
|
|
423
449
|
}
|
|
424
|
-
await sendTimeout(session,
|
|
450
|
+
await sendTimeout(session, videoElem);
|
|
425
451
|
}
|
|
426
|
-
if (
|
|
452
|
+
if (item.video && config.returnContent.showVideoUrl) {
|
|
427
453
|
await delay(300);
|
|
428
|
-
const
|
|
429
|
-
await sendTimeout(session, `🔗 无水印:${
|
|
454
|
+
const shortLink = await shortUrl(item.video);
|
|
455
|
+
await sendTimeout(session, `🔗 无水印:${shortLink}`);
|
|
430
456
|
}
|
|
431
457
|
}
|
|
432
458
|
await delay(1000);
|
|
@@ -445,34 +471,34 @@ function apply(ctx, config) {
|
|
|
445
471
|
return;
|
|
446
472
|
const key = `${session.platform}:${session.userId}:${session.channelId}`;
|
|
447
473
|
if (linkBuffer.has(key)) {
|
|
448
|
-
const
|
|
449
|
-
const newUrls = urls.filter(
|
|
474
|
+
const buffer = linkBuffer.get(key);
|
|
475
|
+
const newUrls = urls.filter(url => !buffer.urls.includes(url));
|
|
450
476
|
if (newUrls.length) {
|
|
451
|
-
|
|
452
|
-
clearTimeout(
|
|
453
|
-
|
|
477
|
+
buffer.urls.push(...newUrls);
|
|
478
|
+
clearTimeout(buffer.timer);
|
|
479
|
+
buffer.timer = setTimeout(() => flush(session, undefined), config.messageBufferDelay * 1000);
|
|
454
480
|
}
|
|
455
481
|
return;
|
|
456
482
|
}
|
|
457
|
-
let
|
|
483
|
+
let tipMsgId;
|
|
458
484
|
if (config.showWaitingTip) {
|
|
459
|
-
const
|
|
460
|
-
|
|
485
|
+
const msg = await sendTimeout(session, config.waitingTipText);
|
|
486
|
+
tipMsgId = msg?.messageId || msg?.id || msg;
|
|
461
487
|
}
|
|
462
488
|
linkBuffer.set(key, {
|
|
463
489
|
urls,
|
|
464
|
-
timer: setTimeout(() => flush(session), config.messageBufferDelay * 1000),
|
|
465
|
-
tipMsgId
|
|
490
|
+
timer: setTimeout(() => flush(session, undefined), config.messageBufferDelay * 1000),
|
|
491
|
+
tipMsgId
|
|
466
492
|
});
|
|
467
493
|
});
|
|
468
494
|
ctx.command('parse <url>', '手动解析视频链接')
|
|
469
495
|
.action(async ({ session }, url) => {
|
|
470
496
|
if (!url)
|
|
471
497
|
return '请输入视频链接';
|
|
472
|
-
const
|
|
473
|
-
if (!
|
|
498
|
+
const urls = extractUrl(url);
|
|
499
|
+
if (!urls.length)
|
|
474
500
|
return '不支持该链接';
|
|
475
|
-
await flush(session,
|
|
501
|
+
await flush(session, urls);
|
|
476
502
|
});
|
|
477
503
|
ctx.command('clear-cache', '清空解析缓存与临时文件')
|
|
478
504
|
.action(() => {
|
|
@@ -481,20 +507,25 @@ function apply(ctx, config) {
|
|
|
481
507
|
});
|
|
482
508
|
setInterval(() => {
|
|
483
509
|
const now = Date.now();
|
|
484
|
-
processed.forEach((
|
|
510
|
+
processed.forEach((timestamp, hash) => {
|
|
511
|
+
if (now - timestamp > 86400000)
|
|
512
|
+
processed.delete(hash);
|
|
513
|
+
});
|
|
485
514
|
}, 3600000);
|
|
486
515
|
setInterval(() => {
|
|
487
|
-
const
|
|
488
|
-
if (!fs_1.default.existsSync(
|
|
516
|
+
const tempDir = path_1.default.join(process.cwd(), 'temp_videos');
|
|
517
|
+
if (!fs_1.default.existsSync(tempDir))
|
|
489
518
|
return;
|
|
490
519
|
const now = Date.now();
|
|
491
|
-
fs_1.default.readdirSync(
|
|
520
|
+
fs_1.default.readdirSync(tempDir).forEach(file => {
|
|
492
521
|
try {
|
|
493
|
-
const
|
|
494
|
-
if (now -
|
|
495
|
-
fs_1.default.unlinkSync(path_1.default.join(
|
|
522
|
+
const stat = fs_1.default.statSync(path_1.default.join(tempDir, file));
|
|
523
|
+
if (now - stat.mtimeMs > 3600000) {
|
|
524
|
+
fs_1.default.unlinkSync(path_1.default.join(tempDir, file));
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
catch (error) {
|
|
496
528
|
}
|
|
497
|
-
catch { }
|
|
498
529
|
});
|
|
499
530
|
}, 1800000);
|
|
500
531
|
if (config.autoClearCacheInterval > 0) {
|
package/package.json
CHANGED