koishi-plugin-video-parser-all 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +1 -0
- package/lib/index.js +76 -30
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -15,6 +15,7 @@ exports.name = 'video-parser-all';
|
|
|
15
15
|
exports.Config = koishi_1.Schema.object({
|
|
16
16
|
enable: koishi_1.Schema.boolean().default(true).description('是否启用插件'),
|
|
17
17
|
showWaitingTip: koishi_1.Schema.boolean().default(true).description('是否显示解析等待提示'),
|
|
18
|
+
showEstimatedTime: koishi_1.Schema.boolean().default(true).description('是否显示预计解析完成时间'),
|
|
18
19
|
revokeWaitingTip: koishi_1.Schema.boolean().default(true).description('是否撤回等待提示文本'),
|
|
19
20
|
waitingTipText: koishi_1.Schema.string().default('正在解析视频…').description('等待提示文本'),
|
|
20
21
|
sameLinkInterval: koishi_1.Schema.number().default(180).description('相同链接重复间隔秒'),
|
|
@@ -32,7 +33,7 @@ exports.Config = koishi_1.Schema.object({
|
|
|
32
33
|
ignoreSendError: koishi_1.Schema.boolean().default(true).description('忽略发送错误'),
|
|
33
34
|
enableForward: koishi_1.Schema.boolean().default(false).description('合并转发(仅onebot)'),
|
|
34
35
|
downloadVideoBeforeSend: koishi_1.Schema.boolean().default(false).description('先下载视频再发送(解决onebot问题)'),
|
|
35
|
-
messageBufferDelay: koishi_1.Schema.number().default(1).description('
|
|
36
|
+
messageBufferDelay: koishi_1.Schema.number().default(1).description('消息接收缓冲延迟秒'),
|
|
36
37
|
commonApi: koishi_1.Schema.string().default('https://api.bugpk.com/api/short_videos').description('通用解析API'),
|
|
37
38
|
douyin: koishi_1.Schema.object({
|
|
38
39
|
mode: koishi_1.Schema.union([
|
|
@@ -64,6 +65,7 @@ exports.Config = koishi_1.Schema.object({
|
|
|
64
65
|
});
|
|
65
66
|
const processed = new Map();
|
|
66
67
|
const linkBuffer = new Map();
|
|
68
|
+
const parseTimeRecords = new Map();
|
|
67
69
|
const PLATFORM_KEYWORDS = {
|
|
68
70
|
bilibili: ['bilibili', 'b23', 'B站'],
|
|
69
71
|
kuaishou: ['kuaishou', '快手'],
|
|
@@ -90,6 +92,33 @@ function getPlatformType(url) {
|
|
|
90
92
|
return 'bilibili';
|
|
91
93
|
return null;
|
|
92
94
|
}
|
|
95
|
+
function formatTime(date) {
|
|
96
|
+
const hours = date.getHours().toString().padStart(2, '0');
|
|
97
|
+
const minutes = date.getMinutes().toString().padStart(2, '0');
|
|
98
|
+
const seconds = date.getSeconds().toString().padStart(2, '0');
|
|
99
|
+
return `${hours}:${minutes}:${seconds}`;
|
|
100
|
+
}
|
|
101
|
+
function getEstimatedParseTime(urls) {
|
|
102
|
+
let totalSeconds = 0;
|
|
103
|
+
urls.forEach(url => {
|
|
104
|
+
const platform = getPlatformType(url);
|
|
105
|
+
if (platform) {
|
|
106
|
+
const records = parseTimeRecords.get(platform) || [];
|
|
107
|
+
if (records.length > 0) {
|
|
108
|
+
const avgTime = records.reduce((sum, time) => sum + time, 0) / records.length;
|
|
109
|
+
totalSeconds += avgTime / 1000;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
totalSeconds += 3;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
totalSeconds += 3;
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
totalSeconds += 1;
|
|
120
|
+
return Math.ceil(totalSeconds);
|
|
121
|
+
}
|
|
93
122
|
async function downloadVideo(url, filename) {
|
|
94
123
|
const dir = path_1.default.join(process.cwd(), 'temp_videos');
|
|
95
124
|
if (!fs_1.default.existsSync(dir))
|
|
@@ -125,6 +154,7 @@ function apply(ctx, config) {
|
|
|
125
154
|
return config.commonApi;
|
|
126
155
|
}
|
|
127
156
|
async function parse(url) {
|
|
157
|
+
const startTime = Date.now();
|
|
128
158
|
const pt = getPlatformType(url);
|
|
129
159
|
if (!pt)
|
|
130
160
|
return null;
|
|
@@ -133,8 +163,15 @@ function apply(ctx, config) {
|
|
|
133
163
|
return null;
|
|
134
164
|
try {
|
|
135
165
|
const { data } = await http.get(api, { params: { url } });
|
|
136
|
-
if (data.code === 200 && data.data)
|
|
166
|
+
if (data.code === 200 && data.data) {
|
|
167
|
+
const parseTime = Date.now() - startTime;
|
|
168
|
+
const records = parseTimeRecords.get(pt) || [];
|
|
169
|
+
records.push(parseTime);
|
|
170
|
+
if (records.length > 10)
|
|
171
|
+
records.shift();
|
|
172
|
+
parseTimeRecords.set(pt, records);
|
|
137
173
|
return parseData(data.data);
|
|
174
|
+
}
|
|
138
175
|
}
|
|
139
176
|
catch { }
|
|
140
177
|
return null;
|
|
@@ -219,15 +256,30 @@ function apply(ctx, config) {
|
|
|
219
256
|
if (!items.length)
|
|
220
257
|
return;
|
|
221
258
|
if (config.enableForward && session.platform === 'onebot') {
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
259
|
+
const nodeList = items.map(it => {
|
|
260
|
+
const content = [];
|
|
261
|
+
if (it.content)
|
|
262
|
+
content.push(it.content);
|
|
263
|
+
if (it.video)
|
|
264
|
+
content.push(it.video);
|
|
265
|
+
return {
|
|
266
|
+
user_id: session.selfId,
|
|
267
|
+
time: Math.floor(Date.now() / 1000),
|
|
268
|
+
content: content.join('\n')
|
|
269
|
+
};
|
|
270
|
+
});
|
|
226
271
|
try {
|
|
227
|
-
await session.send((0, koishi_1.h)('forward', {
|
|
272
|
+
await session.send((0, koishi_1.h)('forward', {
|
|
273
|
+
content: '群聊的聊天记录',
|
|
274
|
+
brief: '[聊天记录]',
|
|
275
|
+
data: nodeList
|
|
276
|
+
}));
|
|
228
277
|
return;
|
|
229
278
|
}
|
|
230
|
-
catch {
|
|
279
|
+
catch (e) {
|
|
280
|
+
if (!config.ignoreSendError)
|
|
281
|
+
ctx.logger.warn(`合并转发发送失败: ${e.message}`);
|
|
282
|
+
}
|
|
231
283
|
}
|
|
232
284
|
for (const it of items) {
|
|
233
285
|
if (it.content)
|
|
@@ -246,30 +298,24 @@ function apply(ctx, config) {
|
|
|
246
298
|
if (!urls.length)
|
|
247
299
|
return;
|
|
248
300
|
const key = `${session.platform}:${session.userId}:${session.channelId}`;
|
|
249
|
-
if (
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
else {
|
|
259
|
-
const ex = linkBuffer.get(key);
|
|
260
|
-
if (ex) {
|
|
261
|
-
clearTimeout(ex.timer);
|
|
262
|
-
ex.urls.push(...urls);
|
|
263
|
-
ex.timer = setTimeout(() => flush(session), config.messageBufferDelay * 1000);
|
|
264
|
-
linkBuffer.set(key, ex);
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
linkBuffer.set(key, {
|
|
268
|
-
urls,
|
|
269
|
-
timer: setTimeout(() => flush(session), config.messageBufferDelay * 1000),
|
|
270
|
-
});
|
|
301
|
+
if (linkBuffer.has(key))
|
|
302
|
+
return;
|
|
303
|
+
let mid;
|
|
304
|
+
if (config.showWaitingTip) {
|
|
305
|
+
let tipText = config.waitingTipText;
|
|
306
|
+
if (config.showEstimatedTime) {
|
|
307
|
+
const estimatedSeconds = getEstimatedParseTime(urls);
|
|
308
|
+
const estimatedTime = new Date(Date.now() + estimatedSeconds * 1000);
|
|
309
|
+
tipText += ` 预计${estimatedSeconds}秒后完成(${formatTime(estimatedTime)})`;
|
|
271
310
|
}
|
|
311
|
+
const tip = await session.send(tipText).catch(() => null);
|
|
312
|
+
mid = tip?.messageId || tip?.id;
|
|
272
313
|
}
|
|
314
|
+
linkBuffer.set(key, {
|
|
315
|
+
urls,
|
|
316
|
+
timer: setTimeout(() => flush(session), config.messageBufferDelay * 1000),
|
|
317
|
+
tipMsgId: mid,
|
|
318
|
+
});
|
|
273
319
|
});
|
|
274
320
|
setInterval(() => {
|
|
275
321
|
const now = Date.now();
|