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 CHANGED
@@ -3,6 +3,7 @@ export declare const name = "video-parser-all";
3
3
  export interface Config {
4
4
  enable: boolean;
5
5
  showWaitingTip: boolean;
6
+ showEstimatedTime: boolean;
6
7
  revokeWaitingTip: boolean;
7
8
  waitingTipText: string;
8
9
  sameLinkInterval: number;
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 msgs = items.map(it => [
223
- it.content ? (0, koishi_1.h)('message', { user_id: session.selfId }, [it.content]) : null,
224
- it.video ? (0, koishi_1.h)('message', { user_id: session.selfId }, [it.video]) : null,
225
- ].filter(Boolean)).flat();
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', { messages: msgs }));
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 (config.showWaitingTip && !linkBuffer.has(key)) {
250
- const tip = await session.send(config.waitingTipText).catch(() => null);
251
- const mid = tip?.messageId || tip?.id;
252
- linkBuffer.set(key, {
253
- urls,
254
- timer: setTimeout(() => flush(session), config.messageBufferDelay * 1000),
255
- tipMsgId: mid,
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();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-video-parser-all",
3
3
  "description": "Koishi 视频解析插件,支持抖音/快手/B站链接解析,可自定义API和解析规则",
4
- "version": "0.1.4",
4
+ "version": "0.1.6",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [