koishi-plugin-video-parser-all 0.3.7 → 0.3.9
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 +115 -53
- package/lib/index.js +821 -228
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -12,48 +12,116 @@ 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
|
|
15
|
+
const __filename = typeof __dirname !== 'undefined'
|
|
16
|
+
? path_1.default.join(__dirname, 'index.js')
|
|
17
|
+
: process.cwd() + '/index.js';
|
|
16
18
|
exports.name = 'video-parser-all';
|
|
17
|
-
exports.Config = koishi_1.Schema.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
19
|
+
exports.Config = koishi_1.Schema.intersect([
|
|
20
|
+
koishi_1.Schema.object({
|
|
21
|
+
enable: koishi_1.Schema.boolean().default(true),
|
|
22
|
+
botName: koishi_1.Schema.string().default('视频解析机器人'),
|
|
23
|
+
showWaitingTip: koishi_1.Schema.boolean().default(true),
|
|
24
|
+
waitingTipText: koishi_1.Schema.string().default('正在解析视频,请稍候...'),
|
|
25
|
+
sameLinkInterval: koishi_1.Schema.number().min(0).default(180),
|
|
26
|
+
maxVideoSize: koishi_1.Schema.number().min(0).default(50),
|
|
27
|
+
downloadThreads: koishi_1.Schema.number().min(0).default(4),
|
|
28
|
+
}),
|
|
29
|
+
koishi_1.Schema.object({
|
|
30
|
+
platformEnable: koishi_1.Schema.object({
|
|
31
|
+
bilibili: koishi_1.Schema.boolean().default(true),
|
|
32
|
+
douyin: koishi_1.Schema.boolean().default(true),
|
|
33
|
+
kuaishou: koishi_1.Schema.boolean().default(true),
|
|
34
|
+
xigua: koishi_1.Schema.boolean().default(true),
|
|
35
|
+
xiaohongshu: koishi_1.Schema.boolean().default(true),
|
|
36
|
+
weibo: koishi_1.Schema.boolean().default(true),
|
|
37
|
+
toutiao: koishi_1.Schema.boolean().default(true),
|
|
38
|
+
pipigx: koishi_1.Schema.boolean().default(true),
|
|
39
|
+
pipixia: koishi_1.Schema.boolean().default(true),
|
|
40
|
+
zuiyou: koishi_1.Schema.boolean().default(true),
|
|
41
|
+
})
|
|
42
|
+
}),
|
|
43
|
+
koishi_1.Schema.object({
|
|
44
|
+
platformFormat: koishi_1.Schema.object({
|
|
45
|
+
bilibili: koishi_1.Schema.string().role('textarea').default('标题:${标题}\nUP主:${作者}\n简介:${简介}\n时长:${视频时长}\n点赞:${点赞数}\n投币:${投币数}\n收藏:${收藏数}\n转发:${转发数}'),
|
|
46
|
+
douyin: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n点赞:${点赞数}\n收藏:${收藏数}\n转发:${转发数}'),
|
|
47
|
+
kuaishou: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n点赞:${点赞数}\n播放:${播放数}\n转发:${转发数}'),
|
|
48
|
+
xigua: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n播放:${播放数}\n点赞:${点赞数}\n视频大小:${视频大小}MB'),
|
|
49
|
+
xiaohongshu: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
50
|
+
weibo: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
51
|
+
toutiao: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
52
|
+
pipigx: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
53
|
+
pipixia: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
54
|
+
zuiyou: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}'),
|
|
55
|
+
})
|
|
56
|
+
}),
|
|
57
|
+
koishi_1.Schema.object({
|
|
58
|
+
showImageText: koishi_1.Schema.boolean().default(true),
|
|
59
|
+
showVideoUrl: koishi_1.Schema.boolean().default(false),
|
|
60
|
+
showVideoFile: koishi_1.Schema.boolean().default(true),
|
|
61
|
+
}),
|
|
62
|
+
koishi_1.Schema.object({
|
|
63
|
+
maxDescLength: koishi_1.Schema.number().default(200),
|
|
64
|
+
}),
|
|
65
|
+
koishi_1.Schema.object({
|
|
66
|
+
timeout: koishi_1.Schema.number().min(0).default(180000),
|
|
67
|
+
videoSendTimeout: koishi_1.Schema.number().min(0).default(0),
|
|
68
|
+
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'),
|
|
69
|
+
bilibiliAccessKey: koishi_1.Schema.string().default(''),
|
|
70
|
+
}),
|
|
71
|
+
koishi_1.Schema.object({
|
|
72
|
+
ignoreSendError: koishi_1.Schema.boolean().default(true),
|
|
73
|
+
retryTimes: koishi_1.Schema.number().min(0).default(0),
|
|
74
|
+
retryInterval: koishi_1.Schema.number().min(0).default(0),
|
|
75
|
+
}),
|
|
76
|
+
koishi_1.Schema.object({
|
|
77
|
+
enableForward: koishi_1.Schema.boolean().default(false),
|
|
78
|
+
downloadVideoBeforeSend: koishi_1.Schema.boolean().default(false),
|
|
79
|
+
}),
|
|
80
|
+
koishi_1.Schema.object({
|
|
81
|
+
messageBufferDelay: koishi_1.Schema.number().min(0).default(0),
|
|
82
|
+
}),
|
|
83
|
+
koishi_1.Schema.object({
|
|
84
|
+
autoClearCacheInterval: koishi_1.Schema.number().min(0).default(0),
|
|
85
|
+
}),
|
|
86
|
+
]);
|
|
39
87
|
if (!worker_threads_1.isMainThread) {
|
|
40
|
-
const
|
|
88
|
+
const workerDataTyped = worker_threads_1.workerData;
|
|
89
|
+
const { url, filePath, maxSize } = workerDataTyped;
|
|
41
90
|
(async () => {
|
|
42
91
|
try {
|
|
43
92
|
if (url.endsWith('.m4a') || url.endsWith('.mp3')) {
|
|
44
93
|
worker_threads_1.parentPort?.postMessage({ success: false, error: '不支持音频' });
|
|
45
94
|
return;
|
|
46
95
|
}
|
|
96
|
+
let downloadedSize = 0;
|
|
97
|
+
const maxSizeBytes = maxSize * 1024 * 1024;
|
|
47
98
|
const response = await (0, axios_1.default)({
|
|
48
99
|
url,
|
|
49
100
|
method: 'GET',
|
|
50
101
|
responseType: 'stream',
|
|
51
102
|
timeout: 60000,
|
|
52
103
|
headers: {
|
|
53
|
-
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
|
|
104
|
+
'User-Agent': workerDataTyped.userAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
|
|
54
105
|
}
|
|
55
106
|
});
|
|
56
|
-
|
|
107
|
+
if (maxSize > 0 && response.headers['content-length']) {
|
|
108
|
+
const contentLength = parseInt(response.headers['content-length']);
|
|
109
|
+
if (contentLength > maxSizeBytes) {
|
|
110
|
+
worker_threads_1.parentPort?.postMessage({ success: false, error: `视频大小超过限制(${maxSize}MB)` });
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const writeStream = fs_1.default.createWriteStream(filePath);
|
|
115
|
+
response.data.on('data', (chunk) => {
|
|
116
|
+
downloadedSize += chunk.length;
|
|
117
|
+
if (maxSize > 0 && downloadedSize > maxSizeBytes) {
|
|
118
|
+
response.data.destroy();
|
|
119
|
+
writeStream.destroy();
|
|
120
|
+
fs_1.default.unlinkSync(filePath);
|
|
121
|
+
worker_threads_1.parentPort?.postMessage({ success: false, error: `视频大小超过限制(${maxSize}MB)` });
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
await (0, promises_1.pipeline)(response.data, writeStream);
|
|
57
125
|
worker_threads_1.parentPort?.postMessage({ success: true, filePath });
|
|
58
126
|
}
|
|
59
127
|
catch (error) {
|
|
@@ -64,61 +132,295 @@ if (!worker_threads_1.isMainThread) {
|
|
|
64
132
|
const processed = new Map();
|
|
65
133
|
const linkBuffer = new Map();
|
|
66
134
|
const PLATFORM_KEYWORDS = {
|
|
67
|
-
bilibili: ['bilibili', 'b23', 'B站', 'www.bilibili.com', 'm.bilibili.com'],
|
|
68
|
-
kuaishou: ['kuaishou', '快手', 'v.
|
|
69
|
-
xiaohongshu: ['xiaohongshu', '小红书', 'xhslink.com', 'xiaohongshu.com', 'xhscdn.com'],
|
|
70
|
-
weibo: ['weibo', '微博', 'weibo.com', 'video.weibo.com', '
|
|
71
|
-
toutiao: ['toutiao', '今日头条', 'm.toutiao.com', 'toutiao.com', 'ixigua.com'],
|
|
72
|
-
pipigx: ['pipigx', '皮皮搞笑', 'h5.pipigx.com', 'ippzone.com'],
|
|
73
|
-
pipixia: ['pipixia', '皮皮虾', 'h5.pipix.com', 'ppxsign.byteimg.com'],
|
|
74
|
-
douyin: ['douyin', '抖音', 'v.douyin.com', 'douyinpic.com', 'douyinvod.com']
|
|
135
|
+
bilibili: ['bilibili', 'b23', 'B站', 'www.bilibili.com', 'm.bilibili.com', '哔哩哔哩', 'bilibili.com/opus', 'bilibili.com/video', 'b23.tv', 't.bilibili.com', 'bilibili.com/bangumi'],
|
|
136
|
+
kuaishou: ['kuaishou', '快手', 'v.kuaishou.com', 'www.kuaishou.com', 'kwimgs.com', 'kuaishou.com/app', 'kuaishou.com/short-video'],
|
|
137
|
+
xiaohongshu: ['xiaohongshu', '小红书', 'xhslink.com', 'xiaohongshu.com', 'xhscdn.com', 'xiaohongshu.com/explore', 'xhslink.com/'],
|
|
138
|
+
weibo: ['weibo', '微博', 'weibo.com', 'video.weibo.com', 'm.weibo.cn', 'weibo.com/tv/show', 'weibo.com/feed'],
|
|
139
|
+
toutiao: ['toutiao', '今日头条', 'm.toutiao.com', 'toutiao.com', 'ixigua.com', '西瓜视频', 'toutiao.com/video', 'ixigua.com/i'],
|
|
140
|
+
pipigx: ['pipigx', '皮皮搞笑', 'h5.pipigx.com', 'ippzone.com', 'pipigx.com/share'],
|
|
141
|
+
pipixia: ['pipixia', '皮皮虾', 'h5.pipix.com', 'ppxsign.byteimg.com', 'pipix.com/s', 'pipix.com/home'],
|
|
142
|
+
douyin: ['douyin', '抖音', 'v.douyin.com', 'douyinpic.com', 'douyinvod.com', 'douyin.com/video', 'douyin.com/note', 'www.douyin.com', 'tiktok.com'],
|
|
143
|
+
zuiyou: ['zuiyou', '最右', 'xiaochuankeji.cn', 'izuiyou.com', 'izuiyou.com/topic'],
|
|
144
|
+
xigua: ['ixigua', '西瓜视频', 'xigua.com', '699pic.com', 'ixigua.com/video', 'ixigua.com/album'],
|
|
145
|
+
universal_card: ['mini_program', '小程序卡片', 'lightapp', 'json', 'markdown', 'share', 'contact', 'location', 'music', 'forward', 'node', 'mface', 'file']
|
|
75
146
|
};
|
|
76
147
|
const API_CONFIG = {
|
|
77
148
|
universal: 'https://api.bugpk.com/api/short_videos',
|
|
149
|
+
xingzhige: {
|
|
150
|
+
bilibili: { url: 'https://api.xingzhige.com/API/b_parse/', vidUrl: 'https://api.xingzhige.com/API/b_video/', bangumiUrl: 'https://api.xingzhige.com/API/b_bangumi/' },
|
|
151
|
+
kuaishou: { url: 'https://api.xingzhige.com/API/kuaishou/' },
|
|
152
|
+
douyin: { url: 'https://api.xingzhige.com/API/douyin/' },
|
|
153
|
+
xigua: { url: 'https://api.xingzhige.com/API/xigua/' }
|
|
154
|
+
},
|
|
78
155
|
platform: {
|
|
79
156
|
bilibili: ['https://api.bugpk.com/api/bilibili'],
|
|
80
|
-
kuaishou: [
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
'https://api.bugpk.com/api/ksimg'
|
|
84
|
-
],
|
|
85
|
-
xiaohongshu: [
|
|
86
|
-
'https://api.bugpk.com/api/xhsjx',
|
|
87
|
-
'https://api.bugpk.com/api/xhsimg',
|
|
88
|
-
'https://api.bugpk.com/api/xhslive'
|
|
89
|
-
],
|
|
90
|
-
weibo: [
|
|
91
|
-
'https://api.bugpk.com/api/weibo',
|
|
92
|
-
'https://api.bugpk.com/api/weibo_v'
|
|
93
|
-
],
|
|
157
|
+
kuaishou: ['https://api.bugpk.com/api/ksjx', 'https://api.bugpk.com/api/kuaishou', 'https://api.bugpk.com/api/ksimg', 'https://api.suyanw.cn/api/kuaishou.php'],
|
|
158
|
+
xiaohongshu: ['https://api.bugpk.com/api/xhsjx', 'https://api.bugpk.com/api/xhsimg', 'https://api.bugpk.com/api/xhslive'],
|
|
159
|
+
weibo: ['https://api.bugpk.com/api/weibo', 'https://api.bugpk.com/api/weibo_v'],
|
|
94
160
|
toutiao: ['https://api.bugpk.com/api/toutiao'],
|
|
95
|
-
pipigx: ['https://api.bugpk.com/api/pipigx'],
|
|
161
|
+
pipigx: ['https://api.bugpk.com/api/pipigx', 'https://api.suyanw.cn/api/pipigx.php'],
|
|
96
162
|
pipixia: ['https://api.bugpk.com/api/pipixia'],
|
|
97
|
-
douyin: [
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
'https://api.bugpk.com/api/dylive'
|
|
101
|
-
]
|
|
163
|
+
douyin: ['https://api.bugpk.com/api/douyin', 'https://api.bugpk.com/api/dyjx', 'https://api.bugpk.com/api/dylive'],
|
|
164
|
+
zuiyou: ['https://api.suyanw.cn/api/zuiyou.php'],
|
|
165
|
+
xigua: ['https://api.bugpk.com/api/toutiao']
|
|
102
166
|
}
|
|
103
167
|
};
|
|
168
|
+
function vid_type_parse(id) {
|
|
169
|
+
const idRegex = [
|
|
170
|
+
{ pattern: /av([0-9]+)/i, type: "av" },
|
|
171
|
+
{ pattern: /bv([0-9a-zA-Z]+)/i, type: "bv" },
|
|
172
|
+
];
|
|
173
|
+
for (const rule of idRegex) {
|
|
174
|
+
const match = id.match(rule.pattern);
|
|
175
|
+
if (match) {
|
|
176
|
+
return { type: rule.type, id: match[1] };
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return { type: null, id: null };
|
|
180
|
+
}
|
|
181
|
+
async function fetch_bilibili_official_info(id, userAgent) {
|
|
182
|
+
const vid = vid_type_parse(id);
|
|
183
|
+
let url = '';
|
|
184
|
+
switch (vid.type) {
|
|
185
|
+
case "av":
|
|
186
|
+
url = `https://api.bilibili.com/x/web-interface/view?aid=${vid.id}`;
|
|
187
|
+
break;
|
|
188
|
+
case "bv":
|
|
189
|
+
url = `https://api.bilibili.com/x/web-interface/view?bvid=${vid.id}`;
|
|
190
|
+
break;
|
|
191
|
+
default:
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
try {
|
|
195
|
+
const response = await axios_1.default.get(url, {
|
|
196
|
+
headers: { 'User-Agent': userAgent },
|
|
197
|
+
timeout: 10000
|
|
198
|
+
});
|
|
199
|
+
return response.data;
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async function get_bilibili_play_url(bvid, cid, userAgent) {
|
|
206
|
+
try {
|
|
207
|
+
const playUrl = `https://api.bilibili.com/x/player/playurl?fnval=80&cid=${cid}&bvid=${bvid}`;
|
|
208
|
+
const playData = await axios_1.default.get(playUrl, {
|
|
209
|
+
headers: {
|
|
210
|
+
"User-Agent": userAgent,
|
|
211
|
+
"Referer": "https://www.bilibili.com/"
|
|
212
|
+
},
|
|
213
|
+
timeout: 10000
|
|
214
|
+
});
|
|
215
|
+
if (playData.data.code === 0 && playData.data.data && playData.data.data.dash && playData.data.data.dash.video?.[0]?.baseUrl) {
|
|
216
|
+
return {
|
|
217
|
+
url: playData.data.data.dash.video[0].baseUrl,
|
|
218
|
+
duration: playData.data.data.dash.duration
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function extract_bilibili_id(url) {
|
|
228
|
+
const bvMatch = url.match(/BV[a-zA-Z0-9]{10}/);
|
|
229
|
+
if (bvMatch)
|
|
230
|
+
return bvMatch[0];
|
|
231
|
+
const avMatch = url.match(/av\d+/i);
|
|
232
|
+
if (avMatch)
|
|
233
|
+
return avMatch[0];
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
function extract_bangumi_ids(url) {
|
|
237
|
+
const ssMatch = url.match(/ss(\d+)/);
|
|
238
|
+
const epMatch = url.match(/ep(\d+)/);
|
|
239
|
+
return {
|
|
240
|
+
ss_id: ssMatch ? ssMatch[1] : null,
|
|
241
|
+
ep_id: epMatch ? epMatch[1] : null
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function parse_xingzhige_data(resData, platform) {
|
|
245
|
+
const result = {
|
|
246
|
+
title: '',
|
|
247
|
+
author: '未知作者',
|
|
248
|
+
desc: '',
|
|
249
|
+
cover: '',
|
|
250
|
+
video: '',
|
|
251
|
+
images: [],
|
|
252
|
+
stat: {},
|
|
253
|
+
type: 'video'
|
|
254
|
+
};
|
|
255
|
+
if (platform === 'kuaishou' && resData.jx && resData.jx.length > 0) {
|
|
256
|
+
const item = resData.jx[0];
|
|
257
|
+
result.title = item.title || '';
|
|
258
|
+
result.cover = item.cover || '';
|
|
259
|
+
result.video = item.url || item.video || '';
|
|
260
|
+
result.images = item.images || [];
|
|
261
|
+
result.stat = {
|
|
262
|
+
like: resData.stat?.like || 0,
|
|
263
|
+
comment: resData.stat?.comment || 0,
|
|
264
|
+
view: resData.stat?.view || 0,
|
|
265
|
+
share: resData.stat?.share || 0
|
|
266
|
+
};
|
|
267
|
+
result.type = result.images.length > 0 ? 'image' : 'video';
|
|
268
|
+
}
|
|
269
|
+
else if (platform === 'douyin' && resData.jx && resData.jx.length > 0) {
|
|
270
|
+
const item = resData.jx[0];
|
|
271
|
+
result.title = item.title || '';
|
|
272
|
+
result.cover = item.cover || '';
|
|
273
|
+
result.video = item.url || '';
|
|
274
|
+
result.images = item.images || [];
|
|
275
|
+
result.stat = {
|
|
276
|
+
like: resData.stat?.like || 0,
|
|
277
|
+
comment: resData.stat?.comment || 0,
|
|
278
|
+
collect: resData.stat?.collect || 0,
|
|
279
|
+
share: resData.stat?.share || 0
|
|
280
|
+
};
|
|
281
|
+
result.type = result.images.length > 0 ? 'image' : 'video';
|
|
282
|
+
}
|
|
283
|
+
else if (platform === 'bilibili') {
|
|
284
|
+
result.title = resData.title || '';
|
|
285
|
+
result.author = resData.name || '未知UP主';
|
|
286
|
+
result.desc = resData.desc || '';
|
|
287
|
+
result.cover = resData.fm || '';
|
|
288
|
+
result.video = resData.url || '';
|
|
289
|
+
result.stat = {
|
|
290
|
+
view: resData.view || 0,
|
|
291
|
+
reply: resData.reply || 0,
|
|
292
|
+
favorite: resData.favorite || 0,
|
|
293
|
+
like: resData.like || 0,
|
|
294
|
+
coin: resData.coin || 0,
|
|
295
|
+
share: resData.share || 0,
|
|
296
|
+
danmuku: resData.danmuku || 0,
|
|
297
|
+
duration: resData.duration || 0
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
else if (platform === 'bilibili_bangumi') {
|
|
301
|
+
result.title = resData.season?.[0]?.title || resData.bangumi?.[0]?.long_title || '';
|
|
302
|
+
result.desc = resData.season?.[0]?.evaluate || '';
|
|
303
|
+
result.cover = resData.season?.[0]?.cover || '';
|
|
304
|
+
result.video = resData.bangumi?.[0]?.url || '';
|
|
305
|
+
result.stat = {
|
|
306
|
+
duration: resData.bangumi?.[0]?.duration || 0,
|
|
307
|
+
size: resData.bangumi?.[0]?.byte || resData.bangumi?.[0]?.mib || 0,
|
|
308
|
+
like: 0,
|
|
309
|
+
coin: 0,
|
|
310
|
+
favorite: 0,
|
|
311
|
+
share: 0
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
else if (platform === 'xigua' && resData.jx && resData.jx.length > 0) {
|
|
315
|
+
const item = resData.jx[0];
|
|
316
|
+
result.title = item.title || '';
|
|
317
|
+
result.cover = item.cover || '';
|
|
318
|
+
result.video = item.url || '';
|
|
319
|
+
result.stat = {
|
|
320
|
+
like: resData.stat?.like || 0,
|
|
321
|
+
view: resData.stat?.view || 0,
|
|
322
|
+
size: item.size || 0,
|
|
323
|
+
duration: 0,
|
|
324
|
+
share: 0
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
return result;
|
|
328
|
+
}
|
|
329
|
+
function extractCardUrl(content) {
|
|
330
|
+
let realUrls = [];
|
|
331
|
+
try {
|
|
332
|
+
if (typeof content === 'string') {
|
|
333
|
+
let jsonData = null;
|
|
334
|
+
try {
|
|
335
|
+
jsonData = JSON.parse(content);
|
|
336
|
+
}
|
|
337
|
+
catch (e) {
|
|
338
|
+
const jsonMatch = content.match(/\{[\s\S]*\}/);
|
|
339
|
+
if (jsonMatch)
|
|
340
|
+
jsonData = JSON.parse(jsonMatch[0]);
|
|
341
|
+
}
|
|
342
|
+
if (jsonData) {
|
|
343
|
+
if (jsonData.type === 'json' && jsonData.data?.data) {
|
|
344
|
+
const innerData = jsonData.data.data;
|
|
345
|
+
if (innerData.meta?.news?.jumpUrl)
|
|
346
|
+
realUrls.push(innerData.meta.news.jumpUrl);
|
|
347
|
+
if (innerData.jumpUrl)
|
|
348
|
+
realUrls.push(innerData.jumpUrl);
|
|
349
|
+
}
|
|
350
|
+
if (jsonData.type === 'miniprogram' && jsonData.data) {
|
|
351
|
+
if (jsonData.data.jumpUrl)
|
|
352
|
+
realUrls.push(jsonData.data.jumpUrl);
|
|
353
|
+
if (jsonData.data.pagePath) {
|
|
354
|
+
const appid = jsonData.data.appid || '';
|
|
355
|
+
if (appid === '1108291530') {
|
|
356
|
+
const vidMatch = jsonData.data.pagePath.match(/vid=(\w+)/);
|
|
357
|
+
if (vidMatch)
|
|
358
|
+
realUrls.push(`https://www.bilibili.com/video/${vidMatch[1]}`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
const jsonMatches = content.match(/\{[\s\S]*"url":\s*"([^"]+)"/gi) || [];
|
|
364
|
+
jsonMatches.forEach(match => {
|
|
365
|
+
const urlMatch = match.match(/"url":\s*"([^"]+)"/);
|
|
366
|
+
if (urlMatch && urlMatch[1])
|
|
367
|
+
realUrls.push(urlMatch[1]);
|
|
368
|
+
});
|
|
369
|
+
const jumpUrlMatches = content.match(/"jumpUrl":\s*"([^"]+)"/gi) || [];
|
|
370
|
+
jumpUrlMatches.forEach(match => {
|
|
371
|
+
const urlMatch = match.match(/"jumpUrl":\s*"([^"]+)"/);
|
|
372
|
+
if (urlMatch && urlMatch[1])
|
|
373
|
+
realUrls.push(urlMatch[1]);
|
|
374
|
+
});
|
|
375
|
+
const miniAppMatches = content.match(/(https?:\/\/[^\s\"\'\>]+)/gi) || [];
|
|
376
|
+
realUrls.push(...miniAppMatches);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
catch (e) { }
|
|
380
|
+
return [...new Set(realUrls)];
|
|
381
|
+
}
|
|
382
|
+
function extractBVorAV(content) {
|
|
383
|
+
const bvMatch = content.match(/BV[a-zA-Z0-9]{10}/);
|
|
384
|
+
if (bvMatch)
|
|
385
|
+
return [bvMatch[0]];
|
|
386
|
+
const avMatch = content.match(/av\d+/i);
|
|
387
|
+
if (avMatch)
|
|
388
|
+
return [avMatch[0]];
|
|
389
|
+
return [];
|
|
390
|
+
}
|
|
104
391
|
function extractUrl(content) {
|
|
105
|
-
|
|
392
|
+
let urlMatches = content.match(/https?:\/\/[^\s\"\'\>]+/gi) || [];
|
|
393
|
+
const cardUrls = extractCardUrl(content);
|
|
394
|
+
const bvUrls = extractBVorAV(content);
|
|
395
|
+
urlMatches = [...urlMatches, ...cardUrls, ...bvUrls];
|
|
106
396
|
return urlMatches.filter(url => {
|
|
397
|
+
if (url.startsWith('BV') || url.startsWith('av') || url.startsWith('AV'))
|
|
398
|
+
return true;
|
|
107
399
|
const lower = url.toLowerCase();
|
|
108
400
|
return Object.values(PLATFORM_KEYWORDS).some(group => group.some(keyword => lower.includes(keyword)));
|
|
109
401
|
});
|
|
110
402
|
}
|
|
403
|
+
function hasPlatformKeyword(content) {
|
|
404
|
+
const lower = content.toLowerCase();
|
|
405
|
+
if (content.match(/BV[a-zA-Z0-9]{10}/) || content.match(/av\d+/i))
|
|
406
|
+
return true;
|
|
407
|
+
return Object.values(PLATFORM_KEYWORDS).some(group => group.some(keyword => lower.includes(keyword)));
|
|
408
|
+
}
|
|
111
409
|
function getPlatformType(url) {
|
|
410
|
+
if (url.startsWith('BV') || url.startsWith('av') || url.startsWith('AV'))
|
|
411
|
+
return 'bilibili';
|
|
112
412
|
const lower = url.toLowerCase();
|
|
113
|
-
if (PLATFORM_KEYWORDS.kuaishou.some(k => lower.includes(k)))
|
|
114
|
-
return 'kuaishou';
|
|
115
413
|
if (PLATFORM_KEYWORDS.bilibili.some(k => lower.includes(k)))
|
|
116
414
|
return 'bilibili';
|
|
415
|
+
if (PLATFORM_KEYWORDS.kuaishou.some(k => lower.includes(k)))
|
|
416
|
+
return 'kuaishou';
|
|
117
417
|
if (PLATFORM_KEYWORDS.xiaohongshu.some(k => lower.includes(k)))
|
|
118
418
|
return 'xiaohongshu';
|
|
119
419
|
if (PLATFORM_KEYWORDS.weibo.some(k => lower.includes(k)))
|
|
120
420
|
return 'weibo';
|
|
121
|
-
if (PLATFORM_KEYWORDS.
|
|
421
|
+
if (PLATFORM_KEYWORDS.xigua.some(k => lower.includes(k)))
|
|
422
|
+
return 'xigua';
|
|
423
|
+
if (PLATFORM_KEYWORDS.toutiao.some(k => lower.includes(k)) && !PLATFORM_KEYWORDS.xigua.some(k => lower.includes(k)))
|
|
122
424
|
return 'toutiao';
|
|
123
425
|
if (PLATFORM_KEYWORDS.pipigx.some(k => lower.includes(k)))
|
|
124
426
|
return 'pipigx';
|
|
@@ -126,25 +428,47 @@ function getPlatformType(url) {
|
|
|
126
428
|
return 'pipixia';
|
|
127
429
|
if (PLATFORM_KEYWORDS.douyin.some(k => lower.includes(k)))
|
|
128
430
|
return 'douyin';
|
|
431
|
+
if (PLATFORM_KEYWORDS.zuiyou.some(k => lower.includes(k)))
|
|
432
|
+
return 'zuiyou';
|
|
129
433
|
return null;
|
|
130
434
|
}
|
|
435
|
+
async function resolveShortUrl(url) {
|
|
436
|
+
if (url.startsWith('BV') || url.startsWith('av') || url.startsWith('AV'))
|
|
437
|
+
return url;
|
|
438
|
+
try {
|
|
439
|
+
const res = await axios_1.default.head(url, {
|
|
440
|
+
timeout: 5000,
|
|
441
|
+
maxRedirects: 5,
|
|
442
|
+
headers: {
|
|
443
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
return res.request.res?.responseUrl || url;
|
|
447
|
+
}
|
|
448
|
+
catch (e) {
|
|
449
|
+
return url;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
131
452
|
async function shortUrl(url) {
|
|
132
453
|
try {
|
|
133
454
|
const res = await axios_1.default.get('https://api.oick.cn/dwz/api.php', { params: { url }, timeout: 5000 });
|
|
134
455
|
if (res.data.code === 200)
|
|
135
456
|
return res.data.short_url;
|
|
136
457
|
}
|
|
137
|
-
catch (error) {
|
|
138
|
-
}
|
|
458
|
+
catch (error) { }
|
|
139
459
|
return url;
|
|
140
460
|
}
|
|
141
|
-
async function downloadVideoWithThreads(url, filename) {
|
|
461
|
+
async function downloadVideoWithThreads(url, filename, maxSize, threads, userAgent) {
|
|
142
462
|
return new Promise((resolve, reject) => {
|
|
143
463
|
const dir = path_1.default.join(process.cwd(), 'temp_videos');
|
|
144
464
|
if (!fs_1.default.existsSync(dir))
|
|
145
465
|
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
146
466
|
const filePath = path_1.default.join(dir, `${filename}.mp4`);
|
|
147
|
-
const
|
|
467
|
+
const workerData = { url, filePath, maxSize, userAgent };
|
|
468
|
+
if (threads > 0) {
|
|
469
|
+
workerData.threads = threads;
|
|
470
|
+
}
|
|
471
|
+
const worker = new worker_threads_1.Worker(__filename, { workerData });
|
|
148
472
|
worker.on('message', (result) => {
|
|
149
473
|
if (result.success && result.filePath) {
|
|
150
474
|
resolve(result.filePath);
|
|
@@ -160,53 +484,81 @@ async function downloadVideoWithThreads(url, filename) {
|
|
|
160
484
|
});
|
|
161
485
|
});
|
|
162
486
|
}
|
|
487
|
+
function formatDuration(seconds) {
|
|
488
|
+
if (!seconds)
|
|
489
|
+
return '00:00';
|
|
490
|
+
const hours = Math.floor(seconds / 3600);
|
|
491
|
+
const minutes = Math.floor((seconds % 3600) / 60);
|
|
492
|
+
const secs = Math.floor(seconds % 60);
|
|
493
|
+
return hours > 0
|
|
494
|
+
? `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
|
|
495
|
+
: `${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
|
|
496
|
+
}
|
|
163
497
|
function parseData(data, maxDescLength, platform) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
let author = '';
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
author = '未知作者';
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
else if (data.imgurl && Array.isArray(data.imgurl))
|
|
183
|
-
images = data.imgurl;
|
|
184
|
-
let video = '';
|
|
185
|
-
if (platform === 'douyin') {
|
|
186
|
-
if (typeof data.url === 'string' && data.url.trim() && data.url.startsWith('http')) {
|
|
187
|
-
video = data.url;
|
|
188
|
-
}
|
|
189
|
-
else if (Array.isArray(data.video_backup) && data.video_backup.length > 0) {
|
|
190
|
-
video = data.video_backup[0]?.url || '';
|
|
191
|
-
}
|
|
192
|
-
if (video && (video.endsWith('.m4a') || video.endsWith('.mp3')))
|
|
193
|
-
video = '';
|
|
194
|
-
}
|
|
195
|
-
else if (platform === 'bilibili') {
|
|
196
|
-
if (data.videos && Array.isArray(data.videos) && data.videos.length > 0) {
|
|
197
|
-
const hdVideo = data.videos.find((v) => v.title.includes('1080') || (v.url && v.url.includes('192')) || v.index === 1);
|
|
198
|
-
video = hdVideo?.url || data.videos[0]?.url || '';
|
|
199
|
-
}
|
|
200
|
-
else if (data.url) {
|
|
201
|
-
video = data.url;
|
|
202
|
-
}
|
|
498
|
+
let type = data.type || 'video';
|
|
499
|
+
let title = data.title || data.desc || '无标题';
|
|
500
|
+
let author = data.author || data.name || '未知作者';
|
|
501
|
+
let desc = (data.desc || data.description || title).slice(0, maxDescLength);
|
|
502
|
+
let cover = data.cover || data.imgurl || data.pic || data.fm || '';
|
|
503
|
+
let images = data.images || [];
|
|
504
|
+
let video = data.video || data.url || data.playUrl || '';
|
|
505
|
+
let duration = data.duration || 0;
|
|
506
|
+
let stat = data.stat || {};
|
|
507
|
+
const durationFormatted = formatDuration(duration);
|
|
508
|
+
if (platform === 'bilibili' && data.data) {
|
|
509
|
+
title = data.data.title || title;
|
|
510
|
+
author = data.data.owner?.name || '未知作者';
|
|
511
|
+
desc = (data.data.desc || title).slice(0, maxDescLength);
|
|
512
|
+
cover = data.data.pic || cover;
|
|
513
|
+
duration = data.data.duration || 0;
|
|
514
|
+
video = data.playUrl || video;
|
|
515
|
+
stat = data.data.stat || stat;
|
|
203
516
|
}
|
|
204
|
-
|
|
205
|
-
|
|
517
|
+
if (platform === 'bilibili_bangumi') {
|
|
518
|
+
title = data.title || title;
|
|
519
|
+
desc = data.desc || desc;
|
|
520
|
+
cover = data.cover || cover;
|
|
521
|
+
video = data.video || video;
|
|
522
|
+
duration = data.stat?.duration || duration;
|
|
206
523
|
}
|
|
207
|
-
if (
|
|
524
|
+
if (images.length > 0 && !video)
|
|
525
|
+
type = 'image';
|
|
526
|
+
if (video && (video.endsWith('.m4a') || video.endsWith('.mp3')))
|
|
208
527
|
video = '';
|
|
209
|
-
return {
|
|
528
|
+
return {
|
|
529
|
+
type,
|
|
530
|
+
title,
|
|
531
|
+
author,
|
|
532
|
+
desc,
|
|
533
|
+
cover,
|
|
534
|
+
images,
|
|
535
|
+
video,
|
|
536
|
+
duration,
|
|
537
|
+
durationFormatted,
|
|
538
|
+
stat: {
|
|
539
|
+
like: stat.like || 0,
|
|
540
|
+
coin: stat.coin || 0,
|
|
541
|
+
favorite: stat.favorite || 0,
|
|
542
|
+
share: stat.share || 0,
|
|
543
|
+
view: stat.view || 0,
|
|
544
|
+
size: stat.size || 0,
|
|
545
|
+
duration: durationFormatted
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
function generateFormattedText(platform, parseData, config) {
|
|
550
|
+
const format = config.platformFormat[platform] || '${标题}\n${作者}';
|
|
551
|
+
return format
|
|
552
|
+
.replace(/\${标题}/g, parseData.title)
|
|
553
|
+
.replace(/\${作者}/g, parseData.author)
|
|
554
|
+
.replace(/\${简介}/g, parseData.desc)
|
|
555
|
+
.replace(/\${视频时长}/g, parseData.stat.duration)
|
|
556
|
+
.replace(/\${点赞数}/g, parseData.stat.like)
|
|
557
|
+
.replace(/\${投币数}/g, parseData.stat.coin)
|
|
558
|
+
.replace(/\${收藏数}/g, parseData.stat.favorite)
|
|
559
|
+
.replace(/\${转发数}/g, parseData.stat.share)
|
|
560
|
+
.replace(/\${播放数}/g, parseData.stat.view)
|
|
561
|
+
.replace(/\${视频大小}/g, parseData.stat.size);
|
|
210
562
|
}
|
|
211
563
|
function clearAllCache() {
|
|
212
564
|
processed.clear();
|
|
@@ -218,31 +570,247 @@ function clearAllCache() {
|
|
|
218
570
|
try {
|
|
219
571
|
fs_1.default.unlinkSync(path_1.default.join(tempDir, file));
|
|
220
572
|
}
|
|
221
|
-
catch (error) {
|
|
222
|
-
}
|
|
573
|
+
catch (error) { }
|
|
223
574
|
});
|
|
224
575
|
}
|
|
225
576
|
return true;
|
|
226
577
|
}
|
|
227
578
|
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
579
|
+
function buildForwardNode(session, content, botName) {
|
|
580
|
+
return {
|
|
581
|
+
type: 'node',
|
|
582
|
+
data: {
|
|
583
|
+
name: botName.substring(0, 15),
|
|
584
|
+
uin: session.selfId.toString(),
|
|
585
|
+
content: Array.isArray(content) ? content : [koishi_1.h.text(content)],
|
|
586
|
+
time: Math.floor(Date.now() / 1000)
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
}
|
|
228
590
|
function apply(ctx, config) {
|
|
229
591
|
if (!worker_threads_1.isMainThread)
|
|
230
592
|
return;
|
|
231
593
|
clearAllCache();
|
|
232
594
|
const http = axios_1.default.create({
|
|
233
595
|
timeout: config.timeout,
|
|
234
|
-
headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' }
|
|
596
|
+
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' }
|
|
235
597
|
});
|
|
236
598
|
async function parse(url) {
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
599
|
+
const realUrl = await resolveShortUrl(url);
|
|
600
|
+
const platform = getPlatformType(realUrl);
|
|
601
|
+
if (!platform || !config.platformEnable[platform]) {
|
|
602
|
+
return { data: null, msg: platform ? '该平台解析已关闭' : '不支持该平台链接' };
|
|
603
|
+
}
|
|
604
|
+
if (platform === 'bilibili') {
|
|
605
|
+
const bangumiIds = extract_bangumi_ids(realUrl);
|
|
606
|
+
if (bangumiIds.ss_id || bangumiIds.ep_id) {
|
|
607
|
+
try {
|
|
608
|
+
const params = {};
|
|
609
|
+
if (bangumiIds.ss_id)
|
|
610
|
+
params.ss_id = bangumiIds.ss_id;
|
|
611
|
+
if (bangumiIds.ep_id)
|
|
612
|
+
params.ep_id = bangumiIds.ep_id;
|
|
613
|
+
if (config.bilibiliAccessKey)
|
|
614
|
+
params.access_key = config.bilibiliAccessKey;
|
|
615
|
+
const res = await http({
|
|
616
|
+
method: 'GET',
|
|
617
|
+
url: API_CONFIG.xingzhige.bilibili.bangumiUrl,
|
|
618
|
+
params
|
|
619
|
+
});
|
|
620
|
+
if (res.data && (res.data.season || res.data.bangumi)) {
|
|
621
|
+
const xgData = parse_xingzhige_data(res.data, 'bilibili_bangumi');
|
|
622
|
+
const parseResult = parseData(xgData, config.maxDescLength, 'bilibili_bangumi');
|
|
623
|
+
return { data: parseResult, msg: 'B站解析成功' };
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
catch (error) { }
|
|
627
|
+
}
|
|
628
|
+
try {
|
|
629
|
+
const res = await http({
|
|
630
|
+
method: 'GET',
|
|
631
|
+
url: API_CONFIG.xingzhige.bilibili.vidUrl,
|
|
632
|
+
params: (() => {
|
|
633
|
+
const biliId = realUrl.startsWith('BV') || realUrl.startsWith('av') || realUrl.startsWith('AV') ? realUrl : extract_bilibili_id(realUrl);
|
|
634
|
+
if (!biliId)
|
|
635
|
+
return { url: realUrl };
|
|
636
|
+
const vid = vid_type_parse(biliId);
|
|
637
|
+
return vid.type === 'bv' ? { bvid: vid.id } : { aid: vid.id };
|
|
638
|
+
})()
|
|
639
|
+
});
|
|
640
|
+
if (res.data && (res.data.url || res.data.title)) {
|
|
641
|
+
const xgData = parse_xingzhige_data(res.data, platform);
|
|
642
|
+
const parseResult = parseData(xgData, config.maxDescLength, platform);
|
|
643
|
+
return { data: parseResult, msg: 'B站解析成功' };
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
catch (error) {
|
|
647
|
+
try {
|
|
648
|
+
const res = await http.get(API_CONFIG.universal, { params: { url: realUrl } });
|
|
649
|
+
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
650
|
+
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
651
|
+
return { data: parseResult, msg: 'B站解析成功' };
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
catch (e) { }
|
|
655
|
+
try {
|
|
656
|
+
const biliId = realUrl.startsWith('BV') || realUrl.startsWith('av') || realUrl.startsWith('AV') ? realUrl : extract_bilibili_id(realUrl);
|
|
657
|
+
if (biliId) {
|
|
658
|
+
const officialInfo = await fetch_bilibili_official_info(biliId, config.userAgent);
|
|
659
|
+
if (officialInfo && officialInfo.code === 0 && officialInfo.data) {
|
|
660
|
+
const { bvid, cid } = officialInfo.data;
|
|
661
|
+
const playInfo = await get_bilibili_play_url(bvid, cid, config.userAgent);
|
|
662
|
+
if (playInfo) {
|
|
663
|
+
const parseResult = parseData({
|
|
664
|
+
...officialInfo,
|
|
665
|
+
playUrl: playInfo.url,
|
|
666
|
+
duration: playInfo.duration
|
|
667
|
+
}, config.maxDescLength, platform);
|
|
668
|
+
return { data: parseResult, msg: 'B站解析成功' };
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
catch (e) { }
|
|
674
|
+
const platformApis = API_CONFIG.platform.bilibili || [];
|
|
675
|
+
for (const apiUrl of platformApis) {
|
|
676
|
+
try {
|
|
677
|
+
const res = await http.get(apiUrl, { params: { url: realUrl } });
|
|
678
|
+
if ((res.data.code === 0 || res.data.code === 200) && res.data.data) {
|
|
679
|
+
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
680
|
+
return { data: parseResult, msg: 'B站解析成功' };
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
catch (error) {
|
|
684
|
+
continue;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
return { data: null, msg: 'B站解析失败' };
|
|
689
|
+
}
|
|
690
|
+
if (platform === 'kuaishou') {
|
|
691
|
+
try {
|
|
692
|
+
const res = await http({
|
|
693
|
+
method: 'GET',
|
|
694
|
+
url: API_CONFIG.xingzhige.kuaishou.url,
|
|
695
|
+
params: { url: realUrl }
|
|
696
|
+
});
|
|
697
|
+
if (res.data && res.data.jx && res.data.jx.length > 0) {
|
|
698
|
+
const xgData = parse_xingzhige_data(res.data, platform);
|
|
699
|
+
const parseResult = parseData(xgData, config.maxDescLength, platform);
|
|
700
|
+
return { data: parseResult, msg: '快手解析成功' };
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
catch (error) {
|
|
242
704
|
try {
|
|
243
|
-
const res = await http.get(API_CONFIG.universal, { params: { url } });
|
|
705
|
+
const res = await http.get(API_CONFIG.universal, { params: { url: realUrl } });
|
|
244
706
|
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
245
707
|
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
708
|
+
return { data: parseResult, msg: '快手解析成功' };
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
catch (e) { }
|
|
712
|
+
const platformApis = API_CONFIG.platform.kuaishou || [];
|
|
713
|
+
for (const apiUrl of platformApis) {
|
|
714
|
+
try {
|
|
715
|
+
const res = await http.get(apiUrl, { params: { url: realUrl } });
|
|
716
|
+
if ((res.data.code === 200 || res.data.code === 0) && (res.data.data || res.data.image)) {
|
|
717
|
+
const parseResult = parseData(res.data.data || res.data, config.maxDescLength, platform);
|
|
718
|
+
return { data: parseResult, msg: '快手解析成功' };
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
catch (error) {
|
|
722
|
+
continue;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
return { data: null, msg: '快手解析失败' };
|
|
727
|
+
}
|
|
728
|
+
if (platform === 'douyin') {
|
|
729
|
+
try {
|
|
730
|
+
const res = await http({
|
|
731
|
+
method: 'GET',
|
|
732
|
+
url: API_CONFIG.xingzhige.douyin.url,
|
|
733
|
+
params: { url: realUrl }
|
|
734
|
+
});
|
|
735
|
+
if (res.data && res.data.jx && res.data.jx.length > 0) {
|
|
736
|
+
const xgData = parse_xingzhige_data(res.data, platform);
|
|
737
|
+
const parseResult = parseData(xgData, config.maxDescLength, platform);
|
|
738
|
+
return { data: parseResult, msg: '抖音解析成功' };
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
catch (error) {
|
|
742
|
+
try {
|
|
743
|
+
const res = await http.get(API_CONFIG.universal, { params: { url: realUrl } });
|
|
744
|
+
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
745
|
+
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
746
|
+
return { data: parseResult, msg: '抖音解析成功' };
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
catch (e) { }
|
|
750
|
+
const platformApis = API_CONFIG.platform.douyin || [];
|
|
751
|
+
for (const apiUrl of platformApis) {
|
|
752
|
+
try {
|
|
753
|
+
const res = await http.get(apiUrl, { params: { url: realUrl } });
|
|
754
|
+
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
755
|
+
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
756
|
+
return { data: parseResult, msg: '抖音解析成功' };
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
catch (error) {
|
|
760
|
+
continue;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
return { data: null, msg: '抖音解析失败' };
|
|
765
|
+
}
|
|
766
|
+
if (platform === 'xigua') {
|
|
767
|
+
try {
|
|
768
|
+
const res = await http({
|
|
769
|
+
method: 'GET',
|
|
770
|
+
url: API_CONFIG.xingzhige.xigua.url,
|
|
771
|
+
params: { url: realUrl }
|
|
772
|
+
});
|
|
773
|
+
if (res.data && res.data.jx && res.data.jx.length > 0) {
|
|
774
|
+
const xgData = parse_xingzhige_data(res.data, platform);
|
|
775
|
+
const parseResult = parseData(xgData, config.maxDescLength, platform);
|
|
776
|
+
return { data: parseResult, msg: '西瓜视频解析成功' };
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
catch (error) {
|
|
780
|
+
try {
|
|
781
|
+
const res = await http.get(API_CONFIG.universal, { params: { url: realUrl } });
|
|
782
|
+
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
783
|
+
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
784
|
+
return { data: parseResult, msg: '西瓜视频解析成功' };
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
catch (e) { }
|
|
788
|
+
const platformApis = API_CONFIG.platform.xigua || [];
|
|
789
|
+
for (const apiUrl of platformApis) {
|
|
790
|
+
try {
|
|
791
|
+
const res = await http.get(apiUrl, { params: { url: realUrl } });
|
|
792
|
+
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
793
|
+
const parseResult = parseData(res.data.data, config.maxDescLength, platform);
|
|
794
|
+
return { data: parseResult, msg: '西瓜视频解析成功' };
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
catch (error) {
|
|
798
|
+
continue;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
return { data: null, msg: '西瓜视频解析失败' };
|
|
803
|
+
}
|
|
804
|
+
// 修复:确保 currentPlatform 不为 null
|
|
805
|
+
const currentPlatform = platform;
|
|
806
|
+
const nonKuaishouPlatforms = ['xiaohongshu', 'weibo', 'toutiao', 'pipigx', 'pipixia', 'zuiyou'];
|
|
807
|
+
if (nonKuaishouPlatforms.includes(currentPlatform)) {
|
|
808
|
+
for (let retry = 0; retry <= config.retryTimes; retry++) {
|
|
809
|
+
try {
|
|
810
|
+
const res = await http.get(API_CONFIG.universal, { params: { url: realUrl } });
|
|
811
|
+
if ((res.data.code === 200 || res.data.code === 0) && res.data.data) {
|
|
812
|
+
// currentPlatform 已经被断言为非 null,安全传递给 parseData
|
|
813
|
+
const parseResult = parseData(res.data.data, config.maxDescLength, currentPlatform);
|
|
246
814
|
return { data: parseResult, msg: '解析成功' };
|
|
247
815
|
}
|
|
248
816
|
else if (res.data.code === 201) {
|
|
@@ -256,28 +824,44 @@ function apply(ctx, config) {
|
|
|
256
824
|
}
|
|
257
825
|
}
|
|
258
826
|
}
|
|
259
|
-
const platformApis = API_CONFIG.platform[
|
|
827
|
+
const platformApis = API_CONFIG.platform[currentPlatform] || [];
|
|
260
828
|
for (let apiIndex = 0; apiIndex < platformApis.length; apiIndex++) {
|
|
261
829
|
const apiUrl = platformApis[apiIndex];
|
|
262
830
|
for (let retry = 0; retry <= config.retryTimes; retry++) {
|
|
263
831
|
try {
|
|
264
|
-
const res = await http.get(apiUrl, { params: { url } });
|
|
265
|
-
|
|
832
|
+
const res = await http.get(apiUrl, { params: { url: realUrl } });
|
|
833
|
+
let shouldContinue = false;
|
|
834
|
+
if ((res.data.code === 200 || res.data.code === 0)) {
|
|
266
835
|
let parseResult = null;
|
|
267
|
-
if (
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
836
|
+
if (currentPlatform === 'kuaishou') {
|
|
837
|
+
if (res.data.image && !res.data.data) {
|
|
838
|
+
parseResult = parseData({
|
|
839
|
+
title: res.data.data?.title || '快手图集',
|
|
840
|
+
author: res.data.data?.author || '未知作者',
|
|
841
|
+
images: res.data.image,
|
|
842
|
+
type: 'image'
|
|
843
|
+
}, config.maxDescLength, currentPlatform);
|
|
844
|
+
}
|
|
845
|
+
else if (res.data.data) {
|
|
846
|
+
parseResult = parseData(res.data.data, config.maxDescLength, currentPlatform);
|
|
847
|
+
}
|
|
848
|
+
else {
|
|
849
|
+
shouldContinue = true;
|
|
850
|
+
}
|
|
274
851
|
}
|
|
275
852
|
else {
|
|
276
|
-
|
|
853
|
+
if (res.data.data) {
|
|
854
|
+
parseResult = parseData(res.data.data, config.maxDescLength, currentPlatform);
|
|
855
|
+
}
|
|
856
|
+
else {
|
|
857
|
+
shouldContinue = true;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
if (parseResult) {
|
|
861
|
+
return { data: parseResult, msg: '解析成功' };
|
|
277
862
|
}
|
|
278
|
-
return { data: parseResult, msg: '解析成功' };
|
|
279
863
|
}
|
|
280
|
-
|
|
864
|
+
if (shouldContinue && retry < config.retryTimes) {
|
|
281
865
|
await delay(config.retryInterval);
|
|
282
866
|
continue;
|
|
283
867
|
}
|
|
@@ -292,7 +876,7 @@ function apply(ctx, config) {
|
|
|
292
876
|
}
|
|
293
877
|
}
|
|
294
878
|
}
|
|
295
|
-
return { data: null, msg: '
|
|
879
|
+
return { data: null, msg: '解析失败,请稍后重试' };
|
|
296
880
|
}
|
|
297
881
|
async function processSingleUrl(session, url) {
|
|
298
882
|
const hash = crypto_1.default.createHash('md5').update(url).digest('hex');
|
|
@@ -305,31 +889,29 @@ function apply(ctx, config) {
|
|
|
305
889
|
if (!result.data)
|
|
306
890
|
return { data: null, msg: result.msg };
|
|
307
891
|
const parseData = result.data;
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
.replace(/\${UP主}/g, parseData.author)
|
|
311
|
-
.replace(/\${简介}/g, parseData.desc)
|
|
312
|
-
.replace(/\${tab}/g, '\t')
|
|
313
|
-
.replace(/\${~~~}/g, '\n');
|
|
892
|
+
const platform = getPlatformType(url);
|
|
893
|
+
const text = generateFormattedText(platform || 'bilibili', parseData, config);
|
|
314
894
|
return {
|
|
315
|
-
data: {
|
|
316
|
-
text,
|
|
317
|
-
cover: parseData.cover,
|
|
318
|
-
images: parseData.images,
|
|
319
|
-
video: parseData.video,
|
|
320
|
-
type: parseData.type
|
|
321
|
-
},
|
|
895
|
+
data: { text, cover: parseData.cover, images: parseData.images, video: parseData.video, type: parseData.type },
|
|
322
896
|
msg: 'ok'
|
|
323
897
|
};
|
|
324
898
|
}
|
|
325
899
|
async function sendTimeout(session, content) {
|
|
326
900
|
if (config.videoSendTimeout <= 0) {
|
|
327
|
-
return session.send(content).catch(() =>
|
|
901
|
+
return session.send(content).catch((err) => {
|
|
902
|
+
if (!config.ignoreSendError)
|
|
903
|
+
ctx.logger.error('发送消息失败:', err.message);
|
|
904
|
+
return null;
|
|
905
|
+
});
|
|
328
906
|
}
|
|
329
907
|
return Promise.race([
|
|
330
908
|
session.send(content),
|
|
331
|
-
new Promise((_, reject) => setTimeout(() => reject('timeout'), config.videoSendTimeout))
|
|
332
|
-
]).catch(() =>
|
|
909
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), config.videoSendTimeout))
|
|
910
|
+
]).catch((err) => {
|
|
911
|
+
if (!config.ignoreSendError)
|
|
912
|
+
ctx.logger.error('发送消息超时:', err.message);
|
|
913
|
+
return null;
|
|
914
|
+
});
|
|
333
915
|
}
|
|
334
916
|
async function flush(session, manualUrls) {
|
|
335
917
|
const key = `${session.platform}:${session.userId}:${session.channelId}`;
|
|
@@ -350,15 +932,13 @@ function apply(ctx, config) {
|
|
|
350
932
|
errs.push(`【${url.slice(0, 22)}...】:${result.msg}`);
|
|
351
933
|
}
|
|
352
934
|
}
|
|
935
|
+
const enableForward = config.enableForward && session.platform === 'onebot';
|
|
353
936
|
const forwardMessages = [];
|
|
354
|
-
const botName = '视频解析机器人';
|
|
937
|
+
const botName = config.botName || '视频解析机器人';
|
|
355
938
|
if (errs.length) {
|
|
356
|
-
const errorMsg =
|
|
357
|
-
if (
|
|
358
|
-
forwardMessages.push((
|
|
359
|
-
(0, koishi_1.h)('author', { id: session.selfId, name: botName }),
|
|
360
|
-
errorMsg
|
|
361
|
-
]));
|
|
939
|
+
const errorMsg = `⚠ 部分解析失败\n${errs.join('\n')}`;
|
|
940
|
+
if (enableForward) {
|
|
941
|
+
forwardMessages.push(buildForwardNode(session, errorMsg, botName));
|
|
362
942
|
}
|
|
363
943
|
else {
|
|
364
944
|
await sendTimeout(session, errorMsg);
|
|
@@ -367,11 +947,8 @@ function apply(ctx, config) {
|
|
|
367
947
|
}
|
|
368
948
|
if (items.length === 0) {
|
|
369
949
|
const failMsg = `❌ 全部解析失败\n${errs.join('\n')}`;
|
|
370
|
-
if (
|
|
371
|
-
forwardMessages.push((
|
|
372
|
-
(0, koishi_1.h)('author', { id: session.selfId, name: botName }),
|
|
373
|
-
failMsg
|
|
374
|
-
]));
|
|
950
|
+
if (enableForward) {
|
|
951
|
+
forwardMessages.push(buildForwardNode(session, failMsg, botName));
|
|
375
952
|
}
|
|
376
953
|
else {
|
|
377
954
|
await sendTimeout(session, failMsg);
|
|
@@ -379,95 +956,109 @@ function apply(ctx, config) {
|
|
|
379
956
|
return;
|
|
380
957
|
}
|
|
381
958
|
for (const item of items) {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
(
|
|
385
|
-
|
|
386
|
-
]));
|
|
387
|
-
if (item.cover) {
|
|
388
|
-
forwardMessages.push((0, koishi_1.h)('message', [
|
|
389
|
-
(0, koishi_1.h)('author', { id: session.selfId, name: botName }),
|
|
390
|
-
koishi_1.h.image(item.cover)
|
|
391
|
-
]));
|
|
392
|
-
}
|
|
393
|
-
if (item.video && config.returnContent.showVideoFile) {
|
|
394
|
-
let videoElem = koishi_1.h.video(item.video);
|
|
395
|
-
if (config.downloadVideoBeforeSend) {
|
|
396
|
-
try {
|
|
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);
|
|
403
|
-
}
|
|
959
|
+
try {
|
|
960
|
+
if (enableForward) {
|
|
961
|
+
if (item.text) {
|
|
962
|
+
forwardMessages.push(buildForwardNode(session, item.text, botName));
|
|
404
963
|
}
|
|
405
|
-
forwardMessages.
|
|
406
|
-
(
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
forwardMessages.push((0, koishi_1.h)('message', [
|
|
413
|
-
(0, koishi_1.h)('author', { id: session.selfId, name: botName }),
|
|
414
|
-
`🔗 无水印:${shortLink}`
|
|
415
|
-
]));
|
|
416
|
-
}
|
|
417
|
-
if (item.type === 'image' && item.images?.length) {
|
|
418
|
-
item.images.forEach(imgUrl => {
|
|
419
|
-
forwardMessages.push((0, koishi_1.h)('message', [
|
|
420
|
-
(0, koishi_1.h)('author', { id: session.selfId, name: botName }),
|
|
421
|
-
koishi_1.h.image(imgUrl)
|
|
422
|
-
]));
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
else {
|
|
427
|
-
await sendTimeout(session, item.text);
|
|
428
|
-
await delay(300);
|
|
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);
|
|
432
|
-
}
|
|
433
|
-
else {
|
|
434
|
-
if (item.cover) {
|
|
435
|
-
await sendTimeout(session, koishi_1.h.image(item.cover));
|
|
436
|
-
await delay(300);
|
|
964
|
+
if (item.cover && forwardMessages.length < 100) {
|
|
965
|
+
forwardMessages.push(buildForwardNode(session, koishi_1.h.image(item.cover), botName));
|
|
966
|
+
}
|
|
967
|
+
if (item.type === 'image' && item.images?.length) {
|
|
968
|
+
for (let i = 0; i < item.images.length && forwardMessages.length < 100; i++) {
|
|
969
|
+
forwardMessages.push(buildForwardNode(session, koishi_1.h.image(item.images[i]), botName));
|
|
970
|
+
}
|
|
437
971
|
}
|
|
438
|
-
if (item.video && config.
|
|
439
|
-
let videoElem
|
|
972
|
+
if (item.video && config.showVideoFile && forwardMessages.length < 100) {
|
|
973
|
+
let videoElem;
|
|
440
974
|
if (config.downloadVideoBeforeSend) {
|
|
441
975
|
try {
|
|
442
976
|
const filename = crypto_1.default.createHash('md5').update(item.video).digest('hex');
|
|
443
|
-
const filePath = await downloadVideoWithThreads(item.video, filename);
|
|
977
|
+
const filePath = await downloadVideoWithThreads(item.video, filename, config.maxVideoSize, config.downloadThreads, config.userAgent);
|
|
444
978
|
videoElem = koishi_1.h.file(filePath);
|
|
445
979
|
}
|
|
446
980
|
catch (error) {
|
|
447
981
|
videoElem = koishi_1.h.video(item.video);
|
|
448
982
|
}
|
|
449
983
|
}
|
|
450
|
-
|
|
984
|
+
else {
|
|
985
|
+
videoElem = koishi_1.h.video(item.video);
|
|
986
|
+
}
|
|
987
|
+
forwardMessages.push(buildForwardNode(session, videoElem, botName));
|
|
451
988
|
}
|
|
452
|
-
if (item.video && config.
|
|
453
|
-
await delay(300);
|
|
989
|
+
if (item.video && config.showVideoUrl && forwardMessages.length < 100) {
|
|
454
990
|
const shortLink = await shortUrl(item.video);
|
|
455
|
-
|
|
991
|
+
forwardMessages.push(buildForwardNode(session, `🔗 无水印:${shortLink}`, botName));
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
else {
|
|
995
|
+
if (item.text) {
|
|
996
|
+
await sendTimeout(session, item.text);
|
|
997
|
+
await delay(300);
|
|
998
|
+
}
|
|
999
|
+
if (item.type === 'image' && item.images?.length) {
|
|
1000
|
+
const imgMsg = (0, koishi_1.h)('message', ...item.images.map((url) => koishi_1.h.image(url)));
|
|
1001
|
+
await sendTimeout(session, imgMsg);
|
|
1002
|
+
}
|
|
1003
|
+
else {
|
|
1004
|
+
if (item.cover) {
|
|
1005
|
+
await sendTimeout(session, koishi_1.h.image(item.cover));
|
|
1006
|
+
await delay(300);
|
|
1007
|
+
}
|
|
1008
|
+
if (item.video && config.showVideoFile) {
|
|
1009
|
+
let videoElem;
|
|
1010
|
+
if (config.downloadVideoBeforeSend) {
|
|
1011
|
+
try {
|
|
1012
|
+
const filename = crypto_1.default.createHash('md5').update(item.video).digest('hex');
|
|
1013
|
+
const filePath = await downloadVideoWithThreads(item.video, filename, config.maxVideoSize, config.downloadThreads, config.userAgent);
|
|
1014
|
+
videoElem = koishi_1.h.file(filePath);
|
|
1015
|
+
}
|
|
1016
|
+
catch (error) {
|
|
1017
|
+
videoElem = koishi_1.h.video(item.video);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
else {
|
|
1021
|
+
videoElem = koishi_1.h.video(item.video);
|
|
1022
|
+
}
|
|
1023
|
+
await sendTimeout(session, videoElem);
|
|
1024
|
+
}
|
|
1025
|
+
if (item.video && config.showVideoUrl) {
|
|
1026
|
+
await delay(300);
|
|
1027
|
+
const shortLink = await shortUrl(item.video);
|
|
1028
|
+
await sendTimeout(session, `🔗 无水印:${shortLink}`);
|
|
1029
|
+
}
|
|
456
1030
|
}
|
|
1031
|
+
await delay(1000);
|
|
457
1032
|
}
|
|
458
|
-
|
|
1033
|
+
}
|
|
1034
|
+
catch (error) {
|
|
1035
|
+
await sendTimeout(session, `❌ 处理${item.type}内容失败: ${error.message}`);
|
|
459
1036
|
}
|
|
460
1037
|
}
|
|
461
|
-
if (
|
|
462
|
-
|
|
463
|
-
|
|
1038
|
+
if (enableForward && forwardMessages.length) {
|
|
1039
|
+
try {
|
|
1040
|
+
const safeForwardMessages = forwardMessages.slice(0, 100);
|
|
1041
|
+
const forwardMsg = (0, koishi_1.h)('message', { forward: true }, safeForwardMessages);
|
|
1042
|
+
await sendTimeout(session, forwardMsg);
|
|
1043
|
+
}
|
|
1044
|
+
catch (error) {
|
|
1045
|
+
for (const node of forwardMessages) {
|
|
1046
|
+
await sendTimeout(session, node.data.content);
|
|
1047
|
+
await delay(500);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
464
1050
|
}
|
|
465
1051
|
}
|
|
466
1052
|
ctx.on('message', async (session) => {
|
|
467
1053
|
if (!config.enable)
|
|
468
1054
|
return;
|
|
469
|
-
const
|
|
470
|
-
|
|
1055
|
+
const content = session.content.trim();
|
|
1056
|
+
let urls = extractUrl(content);
|
|
1057
|
+
if (urls.length === 0 && hasPlatformKeyword(content)) {
|
|
1058
|
+
const allLinks = content.match(/https?:\/\/[^\s\"\'\>\]]+/gi) || [];
|
|
1059
|
+
urls = allLinks.filter((u) => getPlatformType(u));
|
|
1060
|
+
}
|
|
1061
|
+
if (urls.length === 0)
|
|
471
1062
|
return;
|
|
472
1063
|
const key = `${session.platform}:${session.userId}:${session.channelId}`;
|
|
473
1064
|
if (linkBuffer.has(key)) {
|
|
@@ -495,8 +1086,12 @@ function apply(ctx, config) {
|
|
|
495
1086
|
.action(async ({ session }, url) => {
|
|
496
1087
|
if (!url)
|
|
497
1088
|
return '请输入视频链接';
|
|
498
|
-
|
|
499
|
-
if (
|
|
1089
|
+
let urls = extractUrl(url);
|
|
1090
|
+
if (urls.length === 0 && hasPlatformKeyword(url)) {
|
|
1091
|
+
const allLinks = url.match(/https?:\/\/[^\s\"\'\>\]]+/gi) || [];
|
|
1092
|
+
urls = allLinks.filter((u) => getPlatformType(u));
|
|
1093
|
+
}
|
|
1094
|
+
if (urls.length === 0)
|
|
500
1095
|
return '不支持该链接';
|
|
501
1096
|
await flush(session, urls);
|
|
502
1097
|
});
|
|
@@ -524,14 +1119,12 @@ function apply(ctx, config) {
|
|
|
524
1119
|
fs_1.default.unlinkSync(path_1.default.join(tempDir, file));
|
|
525
1120
|
}
|
|
526
1121
|
}
|
|
527
|
-
catch (error) {
|
|
528
|
-
}
|
|
1122
|
+
catch (error) { }
|
|
529
1123
|
});
|
|
530
1124
|
}, 1800000);
|
|
531
1125
|
if (config.autoClearCacheInterval > 0) {
|
|
532
1126
|
setInterval(() => {
|
|
533
1127
|
clearAllCache();
|
|
534
|
-
ctx.logger.info('自动清理缓存完成');
|
|
535
1128
|
}, config.autoClearCacheInterval * 60000);
|
|
536
1129
|
}
|
|
537
1130
|
process.on('exit', clearAllCache);
|