koishi-plugin-video-parser-all 0.3.8 → 0.4.0
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.js +132 -123
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1,95 +1,98 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Config = exports.name = void 0;
|
|
7
|
+
exports.apply = apply;
|
|
8
|
+
const koishi_1 = require("koishi");
|
|
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
|
+
const promises_1 = require("stream/promises");
|
|
14
|
+
const worker_threads_1 = require("worker_threads");
|
|
15
|
+
exports.name = 'video-parser-all';
|
|
16
|
+
exports.Config = koishi_1.Schema.intersect([
|
|
17
|
+
koishi_1.Schema.object({
|
|
18
|
+
enable: koishi_1.Schema.boolean().default(true),
|
|
19
|
+
botName: koishi_1.Schema.string().default('视频解析机器人'),
|
|
20
|
+
showWaitingTip: koishi_1.Schema.boolean().default(true),
|
|
21
|
+
waitingTipText: koishi_1.Schema.string().default('正在解析视频,请稍候...'),
|
|
22
|
+
sameLinkInterval: koishi_1.Schema.number().min(0).default(180),
|
|
23
|
+
maxVideoSize: koishi_1.Schema.number().min(0).default(50),
|
|
24
|
+
downloadThreads: koishi_1.Schema.number().min(0).default(4),
|
|
22
25
|
}),
|
|
23
|
-
Schema.object({
|
|
24
|
-
platformEnable: Schema.object({
|
|
25
|
-
bilibili: Schema.boolean().default(true),
|
|
26
|
-
douyin: Schema.boolean().default(true),
|
|
27
|
-
kuaishou: Schema.boolean().default(true),
|
|
28
|
-
xigua: Schema.boolean().default(true),
|
|
29
|
-
xiaohongshu: Schema.boolean().default(true),
|
|
30
|
-
weibo: Schema.boolean().default(true),
|
|
31
|
-
toutiao: Schema.boolean().default(true),
|
|
32
|
-
pipigx: Schema.boolean().default(true),
|
|
33
|
-
pipixia: Schema.boolean().default(true),
|
|
34
|
-
zuiyou: Schema.boolean().default(true),
|
|
26
|
+
koishi_1.Schema.object({
|
|
27
|
+
platformEnable: koishi_1.Schema.object({
|
|
28
|
+
bilibili: koishi_1.Schema.boolean().default(true),
|
|
29
|
+
douyin: koishi_1.Schema.boolean().default(true),
|
|
30
|
+
kuaishou: koishi_1.Schema.boolean().default(true),
|
|
31
|
+
xigua: koishi_1.Schema.boolean().default(true),
|
|
32
|
+
xiaohongshu: koishi_1.Schema.boolean().default(true),
|
|
33
|
+
weibo: koishi_1.Schema.boolean().default(true),
|
|
34
|
+
toutiao: koishi_1.Schema.boolean().default(true),
|
|
35
|
+
pipigx: koishi_1.Schema.boolean().default(true),
|
|
36
|
+
pipixia: koishi_1.Schema.boolean().default(true),
|
|
37
|
+
zuiyou: koishi_1.Schema.boolean().default(true),
|
|
35
38
|
})
|
|
36
39
|
}),
|
|
37
|
-
Schema.object({
|
|
38
|
-
platformFormat: Schema.object({
|
|
39
|
-
bilibili: Schema.string().role('textarea').default('标题:${标题}\nUP主:${作者}\n简介:${简介}\n时长:${视频时长}\n点赞:${点赞数}\n投币:${投币数}\n收藏:${收藏数}\n转发:${转发数}'),
|
|
40
|
-
douyin: Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n点赞:${点赞数}\n收藏:${收藏数}\n转发:${转发数}'),
|
|
41
|
-
kuaishou: Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n点赞:${点赞数}\n播放:${播放数}\n转发:${转发数}'),
|
|
42
|
-
xigua: Schema.string().role('textarea').default('标题:${标题}\n播放:${播放数}\n点赞:${点赞数}\n视频大小:${视频大小}MB'),
|
|
43
|
-
xiaohongshu: Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
44
|
-
weibo: Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
45
|
-
toutiao: Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
46
|
-
pipigx: Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
47
|
-
pipixia: Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
48
|
-
zuiyou: Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
40
|
+
koishi_1.Schema.object({
|
|
41
|
+
platformFormat: koishi_1.Schema.object({
|
|
42
|
+
bilibili: koishi_1.Schema.string().role('textarea').default('标题:${标题}\nUP主:${作者}\n简介:${简介}\n时长:${视频时长}\n点赞:${点赞数}\n投币:${投币数}\n收藏:${收藏数}\n转发:${转发数}'),
|
|
43
|
+
douyin: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n点赞:${点赞数}\n收藏:${收藏数}\n转发:${转发数}'),
|
|
44
|
+
kuaishou: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n点赞:${点赞数}\n播放:${播放数}\n转发:${转发数}'),
|
|
45
|
+
xigua: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n播放:${播放数}\n点赞:${点赞数}\n视频大小:${视频大小}MB'),
|
|
46
|
+
xiaohongshu: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
47
|
+
weibo: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
48
|
+
toutiao: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
49
|
+
pipigx: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
50
|
+
pipixia: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
51
|
+
zuiyou: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
49
52
|
})
|
|
50
53
|
}),
|
|
51
|
-
Schema.object({
|
|
52
|
-
showImageText: Schema.boolean().default(true),
|
|
53
|
-
showVideoUrl: Schema.boolean().default(false),
|
|
54
|
-
showVideoFile: Schema.boolean().default(true),
|
|
54
|
+
koishi_1.Schema.object({
|
|
55
|
+
showImageText: koishi_1.Schema.boolean().default(true),
|
|
56
|
+
showVideoUrl: koishi_1.Schema.boolean().default(false),
|
|
57
|
+
showVideoFile: koishi_1.Schema.boolean().default(true),
|
|
55
58
|
}),
|
|
56
|
-
Schema.object({
|
|
57
|
-
maxDescLength: Schema.number().default(200),
|
|
59
|
+
koishi_1.Schema.object({
|
|
60
|
+
maxDescLength: koishi_1.Schema.number().default(200),
|
|
58
61
|
}),
|
|
59
|
-
Schema.object({
|
|
60
|
-
timeout: Schema.number().min(0).default(180000),
|
|
61
|
-
videoSendTimeout: Schema.number().min(0).default(0),
|
|
62
|
-
userAgent: 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'),
|
|
63
|
-
bilibiliAccessKey: Schema.string().default(''),
|
|
62
|
+
koishi_1.Schema.object({
|
|
63
|
+
timeout: koishi_1.Schema.number().min(0).default(180000),
|
|
64
|
+
videoSendTimeout: koishi_1.Schema.number().min(0).default(0),
|
|
65
|
+
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'),
|
|
66
|
+
bilibiliAccessKey: koishi_1.Schema.string().default(''),
|
|
64
67
|
}),
|
|
65
|
-
Schema.object({
|
|
66
|
-
ignoreSendError: Schema.boolean().default(true),
|
|
67
|
-
retryTimes: Schema.number().min(0).default(0),
|
|
68
|
-
retryInterval: Schema.number().min(0).default(0),
|
|
68
|
+
koishi_1.Schema.object({
|
|
69
|
+
ignoreSendError: koishi_1.Schema.boolean().default(true),
|
|
70
|
+
retryTimes: koishi_1.Schema.number().min(0).default(0),
|
|
71
|
+
retryInterval: koishi_1.Schema.number().min(0).default(0),
|
|
69
72
|
}),
|
|
70
|
-
Schema.object({
|
|
71
|
-
enableForward: Schema.boolean().default(false),
|
|
72
|
-
downloadVideoBeforeSend: Schema.boolean().default(false),
|
|
73
|
+
koishi_1.Schema.object({
|
|
74
|
+
enableForward: koishi_1.Schema.boolean().default(false),
|
|
75
|
+
downloadVideoBeforeSend: koishi_1.Schema.boolean().default(false),
|
|
73
76
|
}),
|
|
74
|
-
Schema.object({
|
|
75
|
-
messageBufferDelay: Schema.number().min(0).default(0),
|
|
77
|
+
koishi_1.Schema.object({
|
|
78
|
+
messageBufferDelay: koishi_1.Schema.number().min(0).default(0),
|
|
76
79
|
}),
|
|
77
|
-
Schema.object({
|
|
78
|
-
autoClearCacheInterval: Schema.number().min(0).default(0),
|
|
80
|
+
koishi_1.Schema.object({
|
|
81
|
+
autoClearCacheInterval: koishi_1.Schema.number().min(0).default(0),
|
|
79
82
|
}),
|
|
80
83
|
]);
|
|
81
|
-
if (!isMainThread) {
|
|
82
|
-
const workerDataTyped = workerData;
|
|
84
|
+
if (!worker_threads_1.isMainThread) {
|
|
85
|
+
const workerDataTyped = worker_threads_1.workerData;
|
|
83
86
|
const { url, filePath, maxSize } = workerDataTyped;
|
|
84
87
|
(async () => {
|
|
85
88
|
try {
|
|
86
89
|
if (url.endsWith('.m4a') || url.endsWith('.mp3')) {
|
|
87
|
-
parentPort?.postMessage({ success: false, error: '不支持音频' });
|
|
90
|
+
worker_threads_1.parentPort?.postMessage({ success: false, error: '不支持音频' });
|
|
88
91
|
return;
|
|
89
92
|
}
|
|
90
93
|
let downloadedSize = 0;
|
|
91
94
|
const maxSizeBytes = maxSize * 1024 * 1024;
|
|
92
|
-
const response = await
|
|
95
|
+
const response = await (0, axios_1.default)({
|
|
93
96
|
url,
|
|
94
97
|
method: 'GET',
|
|
95
98
|
responseType: 'stream',
|
|
@@ -101,25 +104,25 @@ if (!isMainThread) {
|
|
|
101
104
|
if (maxSize > 0 && response.headers['content-length']) {
|
|
102
105
|
const contentLength = parseInt(response.headers['content-length']);
|
|
103
106
|
if (contentLength > maxSizeBytes) {
|
|
104
|
-
parentPort?.postMessage({ success: false, error: `视频大小超过限制(${maxSize}MB)` });
|
|
107
|
+
worker_threads_1.parentPort?.postMessage({ success: false, error: `视频大小超过限制(${maxSize}MB)` });
|
|
105
108
|
return;
|
|
106
109
|
}
|
|
107
110
|
}
|
|
108
|
-
const writeStream =
|
|
111
|
+
const writeStream = fs_1.default.createWriteStream(filePath);
|
|
109
112
|
response.data.on('data', (chunk) => {
|
|
110
113
|
downloadedSize += chunk.length;
|
|
111
114
|
if (maxSize > 0 && downloadedSize > maxSizeBytes) {
|
|
112
115
|
response.data.destroy();
|
|
113
116
|
writeStream.destroy();
|
|
114
|
-
|
|
115
|
-
parentPort?.postMessage({ success: false, error: `视频大小超过限制(${maxSize}MB)` });
|
|
117
|
+
fs_1.default.unlinkSync(filePath);
|
|
118
|
+
worker_threads_1.parentPort?.postMessage({ success: false, error: `视频大小超过限制(${maxSize}MB)` });
|
|
116
119
|
}
|
|
117
120
|
});
|
|
118
|
-
await pipeline(response.data, writeStream);
|
|
119
|
-
parentPort?.postMessage({ success: true, filePath });
|
|
121
|
+
await (0, promises_1.pipeline)(response.data, writeStream);
|
|
122
|
+
worker_threads_1.parentPort?.postMessage({ success: true, filePath });
|
|
120
123
|
}
|
|
121
124
|
catch (error) {
|
|
122
|
-
parentPort?.postMessage({ success: false, error: error.message });
|
|
125
|
+
worker_threads_1.parentPort?.postMessage({ success: false, error: error.message });
|
|
123
126
|
}
|
|
124
127
|
})();
|
|
125
128
|
}
|
|
@@ -186,7 +189,7 @@ async function fetch_bilibili_official_info(id, userAgent) {
|
|
|
186
189
|
return null;
|
|
187
190
|
}
|
|
188
191
|
try {
|
|
189
|
-
const response = await
|
|
192
|
+
const response = await axios_1.default.get(url, {
|
|
190
193
|
headers: { 'User-Agent': userAgent },
|
|
191
194
|
timeout: 10000
|
|
192
195
|
});
|
|
@@ -199,7 +202,7 @@ async function fetch_bilibili_official_info(id, userAgent) {
|
|
|
199
202
|
async function get_bilibili_play_url(bvid, cid, userAgent) {
|
|
200
203
|
try {
|
|
201
204
|
const playUrl = `https://api.bilibili.com/x/player/playurl?fnval=80&cid=${cid}&bvid=${bvid}`;
|
|
202
|
-
const playData = await
|
|
205
|
+
const playData = await axios_1.default.get(playUrl, {
|
|
203
206
|
headers: {
|
|
204
207
|
"User-Agent": userAgent,
|
|
205
208
|
"Referer": "https://www.bilibili.com/"
|
|
@@ -430,7 +433,7 @@ async function resolveShortUrl(url) {
|
|
|
430
433
|
if (url.startsWith('BV') || url.startsWith('av') || url.startsWith('AV'))
|
|
431
434
|
return url;
|
|
432
435
|
try {
|
|
433
|
-
const res = await
|
|
436
|
+
const res = await axios_1.default.head(url, {
|
|
434
437
|
timeout: 5000,
|
|
435
438
|
maxRedirects: 5,
|
|
436
439
|
headers: {
|
|
@@ -445,7 +448,7 @@ async function resolveShortUrl(url) {
|
|
|
445
448
|
}
|
|
446
449
|
async function shortUrl(url) {
|
|
447
450
|
try {
|
|
448
|
-
const res = await
|
|
451
|
+
const res = await axios_1.default.get('https://api.oick.cn/dwz/api.php', { params: { url }, timeout: 5000 });
|
|
449
452
|
if (res.data.code === 200)
|
|
450
453
|
return res.data.short_url;
|
|
451
454
|
}
|
|
@@ -454,15 +457,15 @@ async function shortUrl(url) {
|
|
|
454
457
|
}
|
|
455
458
|
async function downloadVideoWithThreads(url, filename, maxSize, threads, userAgent) {
|
|
456
459
|
return new Promise((resolve, reject) => {
|
|
457
|
-
const dir =
|
|
458
|
-
if (!
|
|
459
|
-
|
|
460
|
-
const filePath =
|
|
460
|
+
const dir = path_1.default.join(process.cwd(), 'temp_videos');
|
|
461
|
+
if (!fs_1.default.existsSync(dir))
|
|
462
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
463
|
+
const filePath = path_1.default.join(dir, `${filename}.mp4`);
|
|
461
464
|
const workerData = { url, filePath, maxSize, userAgent };
|
|
462
465
|
if (threads > 0) {
|
|
463
466
|
workerData.threads = threads;
|
|
464
467
|
}
|
|
465
|
-
const worker = new Worker(__filename, { workerData });
|
|
468
|
+
const worker = new worker_threads_1.Worker(__filename, { workerData });
|
|
466
469
|
worker.on('message', (result) => {
|
|
467
470
|
if (result.success && result.filePath) {
|
|
468
471
|
resolve(result.filePath);
|
|
@@ -558,11 +561,11 @@ function clearAllCache() {
|
|
|
558
561
|
processed.clear();
|
|
559
562
|
linkBuffer.forEach(buf => clearTimeout(buf.timer));
|
|
560
563
|
linkBuffer.clear();
|
|
561
|
-
const tempDir =
|
|
562
|
-
if (
|
|
563
|
-
|
|
564
|
+
const tempDir = path_1.default.join(process.cwd(), 'temp_videos');
|
|
565
|
+
if (fs_1.default.existsSync(tempDir)) {
|
|
566
|
+
fs_1.default.readdirSync(tempDir).forEach(file => {
|
|
564
567
|
try {
|
|
565
|
-
|
|
568
|
+
fs_1.default.unlinkSync(path_1.default.join(tempDir, file));
|
|
566
569
|
}
|
|
567
570
|
catch (error) { }
|
|
568
571
|
});
|
|
@@ -576,16 +579,16 @@ function buildForwardNode(session, content, botName) {
|
|
|
576
579
|
data: {
|
|
577
580
|
name: botName.substring(0, 15),
|
|
578
581
|
uin: session.selfId.toString(),
|
|
579
|
-
content: Array.isArray(content) ? content : [h.text(content)],
|
|
582
|
+
content: Array.isArray(content) ? content : [koishi_1.h.text(content)],
|
|
580
583
|
time: Math.floor(Date.now() / 1000)
|
|
581
584
|
}
|
|
582
585
|
};
|
|
583
586
|
}
|
|
584
|
-
|
|
585
|
-
if (!isMainThread)
|
|
587
|
+
function apply(ctx, config) {
|
|
588
|
+
if (!worker_threads_1.isMainThread)
|
|
586
589
|
return;
|
|
587
590
|
clearAllCache();
|
|
588
|
-
const http =
|
|
591
|
+
const http = axios_1.default.create({
|
|
589
592
|
timeout: config.timeout,
|
|
590
593
|
headers: { 'User-Agent': config.userAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' }
|
|
591
594
|
});
|
|
@@ -795,13 +798,14 @@ export function apply(ctx, config) {
|
|
|
795
798
|
}
|
|
796
799
|
return { data: null, msg: '西瓜视频解析失败' };
|
|
797
800
|
}
|
|
801
|
+
const currentPlatform = platform;
|
|
798
802
|
const nonKuaishouPlatforms = ['xiaohongshu', 'weibo', 'toutiao', 'pipigx', 'pipixia', 'zuiyou'];
|
|
799
|
-
if (nonKuaishouPlatforms.includes(
|
|
803
|
+
if (nonKuaishouPlatforms.includes(currentPlatform)) {
|
|
800
804
|
for (let retry = 0; retry <= config.retryTimes; retry++) {
|
|
801
805
|
try {
|
|
802
806
|
const res = await http.get(API_CONFIG.universal, { params: { url: realUrl } });
|
|
803
807
|
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
804
|
-
const parseResult = parseData(res.data.data, config.maxDescLength,
|
|
808
|
+
const parseResult = parseData(res.data.data, config.maxDescLength, currentPlatform);
|
|
805
809
|
return { data: parseResult, msg: '解析成功' };
|
|
806
810
|
}
|
|
807
811
|
else if (res.data.code === 201) {
|
|
@@ -815,7 +819,7 @@ export function apply(ctx, config) {
|
|
|
815
819
|
}
|
|
816
820
|
}
|
|
817
821
|
}
|
|
818
|
-
const platformApis = API_CONFIG.platform[
|
|
822
|
+
const platformApis = API_CONFIG.platform[currentPlatform] || [];
|
|
819
823
|
for (let apiIndex = 0; apiIndex < platformApis.length; apiIndex++) {
|
|
820
824
|
const apiUrl = platformApis[apiIndex];
|
|
821
825
|
for (let retry = 0; retry <= config.retryTimes; retry++) {
|
|
@@ -824,17 +828,17 @@ export function apply(ctx, config) {
|
|
|
824
828
|
let shouldContinue = false;
|
|
825
829
|
if ((res.data.code === 200 || res.data.code === 0)) {
|
|
826
830
|
let parseResult = null;
|
|
827
|
-
if (
|
|
831
|
+
if (currentPlatform === 'kuaishou') {
|
|
828
832
|
if (res.data.image && !res.data.data) {
|
|
829
833
|
parseResult = parseData({
|
|
830
834
|
title: res.data.data?.title || '快手图集',
|
|
831
835
|
author: res.data.data?.author || '未知作者',
|
|
832
836
|
images: res.data.image,
|
|
833
837
|
type: 'image'
|
|
834
|
-
}, config.maxDescLength,
|
|
838
|
+
}, config.maxDescLength, currentPlatform);
|
|
835
839
|
}
|
|
836
840
|
else if (res.data.data) {
|
|
837
|
-
parseResult = parseData(res.data.data, config.maxDescLength,
|
|
841
|
+
parseResult = parseData(res.data.data, config.maxDescLength, currentPlatform);
|
|
838
842
|
}
|
|
839
843
|
else {
|
|
840
844
|
shouldContinue = true;
|
|
@@ -842,7 +846,7 @@ export function apply(ctx, config) {
|
|
|
842
846
|
}
|
|
843
847
|
else {
|
|
844
848
|
if (res.data.data) {
|
|
845
|
-
parseResult = parseData(res.data.data, config.maxDescLength,
|
|
849
|
+
parseResult = parseData(res.data.data, config.maxDescLength, currentPlatform);
|
|
846
850
|
}
|
|
847
851
|
else {
|
|
848
852
|
shouldContinue = true;
|
|
@@ -870,7 +874,7 @@ export function apply(ctx, config) {
|
|
|
870
874
|
return { data: null, msg: '解析失败,请稍后重试' };
|
|
871
875
|
}
|
|
872
876
|
async function processSingleUrl(session, url) {
|
|
873
|
-
const hash =
|
|
877
|
+
const hash = crypto_1.default.createHash('md5').update(url).digest('hex');
|
|
874
878
|
const now = Date.now();
|
|
875
879
|
if (processed.get(hash) && now - processed.get(hash) < config.sameLinkInterval * 1000) {
|
|
876
880
|
return { data: null, msg: '请勿重复解析' };
|
|
@@ -953,27 +957,27 @@ export function apply(ctx, config) {
|
|
|
953
957
|
forwardMessages.push(buildForwardNode(session, item.text, botName));
|
|
954
958
|
}
|
|
955
959
|
if (item.cover && forwardMessages.length < 100) {
|
|
956
|
-
forwardMessages.push(buildForwardNode(session, h.image(item.cover), botName));
|
|
960
|
+
forwardMessages.push(buildForwardNode(session, koishi_1.h.image(item.cover), botName));
|
|
957
961
|
}
|
|
958
962
|
if (item.type === 'image' && item.images?.length) {
|
|
959
963
|
for (let i = 0; i < item.images.length && forwardMessages.length < 100; i++) {
|
|
960
|
-
forwardMessages.push(buildForwardNode(session, h.image(item.images[i]), botName));
|
|
964
|
+
forwardMessages.push(buildForwardNode(session, koishi_1.h.image(item.images[i]), botName));
|
|
961
965
|
}
|
|
962
966
|
}
|
|
963
967
|
if (item.video && config.showVideoFile && forwardMessages.length < 100) {
|
|
964
968
|
let videoElem;
|
|
965
969
|
if (config.downloadVideoBeforeSend) {
|
|
966
970
|
try {
|
|
967
|
-
const filename =
|
|
971
|
+
const filename = crypto_1.default.createHash('md5').update(item.video).digest('hex');
|
|
968
972
|
const filePath = await downloadVideoWithThreads(item.video, filename, config.maxVideoSize, config.downloadThreads, config.userAgent);
|
|
969
|
-
videoElem = h.file(filePath);
|
|
973
|
+
videoElem = koishi_1.h.file(filePath);
|
|
970
974
|
}
|
|
971
975
|
catch (error) {
|
|
972
|
-
videoElem = h.video(item.video);
|
|
976
|
+
videoElem = koishi_1.h.video(item.video);
|
|
973
977
|
}
|
|
974
978
|
}
|
|
975
979
|
else {
|
|
976
|
-
videoElem = h.video(item.video);
|
|
980
|
+
videoElem = koishi_1.h.video(item.video);
|
|
977
981
|
}
|
|
978
982
|
forwardMessages.push(buildForwardNode(session, videoElem, botName));
|
|
979
983
|
}
|
|
@@ -988,28 +992,28 @@ export function apply(ctx, config) {
|
|
|
988
992
|
await delay(300);
|
|
989
993
|
}
|
|
990
994
|
if (item.type === 'image' && item.images?.length) {
|
|
991
|
-
const imgMsg = h('message', ...item.images.map(url => h.image(url)));
|
|
995
|
+
const imgMsg = (0, koishi_1.h)('message', ...item.images.map((url) => koishi_1.h.image(url)));
|
|
992
996
|
await sendTimeout(session, imgMsg);
|
|
993
997
|
}
|
|
994
998
|
else {
|
|
995
999
|
if (item.cover) {
|
|
996
|
-
await sendTimeout(session, h.image(item.cover));
|
|
1000
|
+
await sendTimeout(session, koishi_1.h.image(item.cover));
|
|
997
1001
|
await delay(300);
|
|
998
1002
|
}
|
|
999
1003
|
if (item.video && config.showVideoFile) {
|
|
1000
1004
|
let videoElem;
|
|
1001
1005
|
if (config.downloadVideoBeforeSend) {
|
|
1002
1006
|
try {
|
|
1003
|
-
const filename =
|
|
1007
|
+
const filename = crypto_1.default.createHash('md5').update(item.video).digest('hex');
|
|
1004
1008
|
const filePath = await downloadVideoWithThreads(item.video, filename, config.maxVideoSize, config.downloadThreads, config.userAgent);
|
|
1005
|
-
videoElem = h.file(filePath);
|
|
1009
|
+
videoElem = koishi_1.h.file(filePath);
|
|
1006
1010
|
}
|
|
1007
1011
|
catch (error) {
|
|
1008
|
-
videoElem = h.video(item.video);
|
|
1012
|
+
videoElem = koishi_1.h.video(item.video);
|
|
1009
1013
|
}
|
|
1010
1014
|
}
|
|
1011
1015
|
else {
|
|
1012
|
-
videoElem = h.video(item.video);
|
|
1016
|
+
videoElem = koishi_1.h.video(item.video);
|
|
1013
1017
|
}
|
|
1014
1018
|
await sendTimeout(session, videoElem);
|
|
1015
1019
|
}
|
|
@@ -1029,7 +1033,7 @@ export function apply(ctx, config) {
|
|
|
1029
1033
|
if (enableForward && forwardMessages.length) {
|
|
1030
1034
|
try {
|
|
1031
1035
|
const safeForwardMessages = forwardMessages.slice(0, 100);
|
|
1032
|
-
const forwardMsg = h('message', { forward: true }, safeForwardMessages);
|
|
1036
|
+
const forwardMsg = (0, koishi_1.h)('message', { forward: true }, safeForwardMessages);
|
|
1033
1037
|
await sendTimeout(session, forwardMsg);
|
|
1034
1038
|
}
|
|
1035
1039
|
catch (error) {
|
|
@@ -1047,7 +1051,7 @@ export function apply(ctx, config) {
|
|
|
1047
1051
|
let urls = extractUrl(content);
|
|
1048
1052
|
if (urls.length === 0 && hasPlatformKeyword(content)) {
|
|
1049
1053
|
const allLinks = content.match(/https?:\/\/[^\s\"\'\>\]]+/gi) || [];
|
|
1050
|
-
urls = allLinks.filter(u => getPlatformType(u));
|
|
1054
|
+
urls = allLinks.filter((u) => getPlatformType(u));
|
|
1051
1055
|
}
|
|
1052
1056
|
if (urls.length === 0)
|
|
1053
1057
|
return;
|
|
@@ -1080,7 +1084,7 @@ export function apply(ctx, config) {
|
|
|
1080
1084
|
let urls = extractUrl(url);
|
|
1081
1085
|
if (urls.length === 0 && hasPlatformKeyword(url)) {
|
|
1082
1086
|
const allLinks = url.match(/https?:\/\/[^\s\"\'\>\]]+/gi) || [];
|
|
1083
|
-
urls = allLinks.filter(u => getPlatformType(u));
|
|
1087
|
+
urls = allLinks.filter((u) => getPlatformType(u));
|
|
1084
1088
|
}
|
|
1085
1089
|
if (urls.length === 0)
|
|
1086
1090
|
return '不支持该链接';
|
|
@@ -1099,15 +1103,15 @@ export function apply(ctx, config) {
|
|
|
1099
1103
|
});
|
|
1100
1104
|
}, 3600000);
|
|
1101
1105
|
setInterval(() => {
|
|
1102
|
-
const tempDir =
|
|
1103
|
-
if (!
|
|
1106
|
+
const tempDir = path_1.default.join(process.cwd(), 'temp_videos');
|
|
1107
|
+
if (!fs_1.default.existsSync(tempDir))
|
|
1104
1108
|
return;
|
|
1105
1109
|
const now = Date.now();
|
|
1106
|
-
|
|
1110
|
+
fs_1.default.readdirSync(tempDir).forEach(file => {
|
|
1107
1111
|
try {
|
|
1108
|
-
const stat =
|
|
1112
|
+
const stat = fs_1.default.statSync(path_1.default.join(tempDir, file));
|
|
1109
1113
|
if (now - stat.mtimeMs > 3600000) {
|
|
1110
|
-
|
|
1114
|
+
fs_1.default.unlinkSync(path_1.default.join(tempDir, file));
|
|
1111
1115
|
}
|
|
1112
1116
|
}
|
|
1113
1117
|
catch (error) { }
|
|
@@ -1121,3 +1125,8 @@ export function apply(ctx, config) {
|
|
|
1121
1125
|
process.on('exit', clearAllCache);
|
|
1122
1126
|
ctx.logger.info('视频解析插件已加载');
|
|
1123
1127
|
}
|
|
1128
|
+
module.exports = {
|
|
1129
|
+
name: exports.name,
|
|
1130
|
+
Config: exports.Config,
|
|
1131
|
+
apply,
|
|
1132
|
+
};
|
package/package.json
CHANGED