koishi-plugin-video-parser-all 1.5.7 → 1.5.8
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 +126 -111
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -283,68 +283,76 @@ let debugEnabled = false;
|
|
|
283
283
|
function debugLog(level, ...args) {
|
|
284
284
|
if (!debugEnabled)
|
|
285
285
|
return;
|
|
286
|
-
|
|
286
|
+
const safe = args.map(a => {
|
|
287
|
+
try {
|
|
288
|
+
return typeof a === 'object' ? JSON.stringify(a) : String(a);
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
return '[unserializable]';
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
logger.info(`[${new Date().toISOString()}] [${level}] ${safe.join(' ')}`);
|
|
287
295
|
}
|
|
288
296
|
const BUILTIN_LINK_RULES = [
|
|
289
|
-
{ pattern: /https?:\/\/(?:www\.)?bilibili\.com\/video\/([ab]v[0-9a-zA-Z_-]+)[^\s]
|
|
290
|
-
{ pattern: /https?:\/\/b23\.tv\/[0-9a-zA-Z_\/-]
|
|
291
|
-
{ pattern: /https?:\/\/bili\d+\.cn\/[0-9a-zA-Z_\/-]
|
|
292
|
-
{ pattern: /https?:\/\/b23\.wtf\/[0-9a-zA-Z_\/-]
|
|
293
|
-
{ pattern: /https?:\/\/bili2233\.cn\/[0-9a-zA-Z_\/-]
|
|
294
|
-
{ pattern: /https?:\/\/(?:www\.)?douyin\.com\/video\/\d{10,}
|
|
295
|
-
{ pattern: /https?:\/\/v\.douyin\.com\/[0-9a-zA-Z_\/-]
|
|
296
|
-
{ pattern: /https?:\/\/(?:www\.)?kuaishou\.com\/short-video\/[0-9a-zA-Z_\/-]
|
|
297
|
-
{ pattern: /https?:\/\/v\.kuaishou\.com\/[0-9a-zA-Z_\/-]
|
|
298
|
-
{ pattern: /https?:\/\/(?:www\.)?kuaishou\.com\/f\/[0-9a-zA-Z_\/-]
|
|
299
|
-
{ pattern: /https?:\/\/(?:www\.)?xiaohongshu\.com\/discovery\/item\/[0-9a-zA-Z_\/-]
|
|
300
|
-
{ pattern: /https?:\/\/xhslink\.com\/[0-9a-zA-Z_\/-]
|
|
301
|
-
{ pattern: /https?:\/\/(?:www\.)?xiaohongshu\.com\/explore\/[0-9a-zA-Z_\/-]
|
|
302
|
-
{ pattern: /https?:\/\/(?:www\.)?xiaohongshu\.com\/board\/[0-9a-zA-Z_\/-]
|
|
303
|
-
{ pattern: /https?:\/\/weibo\.com\/\d+\/[0-9a-zA-Z_\/-]
|
|
304
|
-
{ pattern: /https?:\/\/video\.weibo\.com\/show\?fid=[0-9a-zA-Z_\/-]
|
|
305
|
-
{ pattern: /https?:\/\/t\.cn\/[0-9a-zA-Z_\/-]
|
|
306
|
-
{ pattern: /https?:\/\/m\.weibo\.cn\/[0-9a-zA-Z_\/-]
|
|
307
|
-
{ pattern: /https?:\/\/(?:www\.)?ixigua\.com\/\d{10,}
|
|
308
|
-
{ pattern: /https?:\/\/(?:www\.)?youtube\.com\/watch\?v=[a-zA-Z0-9_-]{11}
|
|
309
|
-
{ pattern: /https?:\/\/youtu\.be\/[0-9a-zA-Z_\/-]
|
|
310
|
-
{ pattern: /https?:\/\/(?:www\.)?youtube\.com\/shorts\/[0-9a-zA-Z_\/-]
|
|
311
|
-
{ pattern: /https?:\/\/(?:www\.)?tiktok\.com\/@[\w.]+\/video\/\d{10,}
|
|
312
|
-
{ pattern: /https?:\/\/vm\.tiktok\.com\/[0-9a-zA-Z_\/-]
|
|
313
|
-
{ pattern: /https?:\/\/vt\.tiktok\.com\/[0-9a-zA-Z_\/-]
|
|
314
|
-
{ pattern: /https?:\/\/(?:www\.)?acfun\.cn\/v\/ac\d{10,}
|
|
315
|
-
{ pattern: /https?:\/\/(?:www\.)?zhihu\.com\/video\/\d{10,}
|
|
316
|
-
{ pattern: /https?:\/\/(?:www\.|m\.)?zhihu\.com\/question\/\d+\/answer\/\d
|
|
317
|
-
{ pattern: /https?:\/\/zhuanlan\.zhihu\.com\/p\/\d
|
|
318
|
-
{ pattern: /https?:\/\/(?:www\.|m\.)?zhihu\.com\/zvideo\/\d
|
|
319
|
-
{ pattern: /https?:\/\/weishi\.qq\.com\/weishi\/feed\/[0-9a-zA-Z_\/-]
|
|
320
|
-
{ pattern: /https?:\/\/(?:www\.)?huya\.com\/video\/[0-9a-zA-Z_\/-]
|
|
321
|
-
{ pattern: /https?:\/\/haokan\.baidu\.com\/v\?vid=[0-9a-zA-Z_\/-]
|
|
322
|
-
{ pattern: /https?:\/\/(?:www\.)?meipai\.com\/media\/\d{10,}
|
|
323
|
-
{ pattern: /https?:\/\/twitter\.com\/\w+\/status\/\d{10,}
|
|
324
|
-
{ pattern: /https?:\/\/x\.com\/\w+\/status\/\d{10,}
|
|
325
|
-
{ pattern: /https?:\/\/(?:www\.)?instagram\.com\/p\/[0-9a-zA-Z_\/-]
|
|
326
|
-
{ pattern: /https?:\/\/(?:www\.)?instagram\.com\/reel\/[0-9a-zA-Z_\/-]
|
|
327
|
-
{ pattern: /https?:\/\/(?:www\.)?instagram\.com\/share\/(?:reel|p)\/[0-9a-zA-Z_\/-]
|
|
328
|
-
{ pattern: /https?:\/\/(?:www\.)?doubao\.com\/video\/\d{10,}
|
|
329
|
-
{ pattern: /https?:\/\/(?:www\.)?doubao\.com\/video-sharing\?[^\s]*/gi, type: 'doubao' },
|
|
330
|
-
{ pattern: /https?:\/\/(?:www\.)?doubao\.com\/thread\/[^\s]+/gi, type: 'doubao_image' },
|
|
331
|
-
{ pattern: /https?:\/\/(?:www\.)?jimeng\.jianying\.com\/[^\s]*/gi, type: 'jimeng' },
|
|
332
|
-
{ pattern: /https?:\/\/(?:www\.)?jimeng\.cn\/[^\s]*/gi, type: 'jimeng' },
|
|
333
|
-
{ pattern: /https?:\/\/(?:www\.)?dreamina\.jianying\.com\/[^\s]*/gi, type: 'jimeng' },
|
|
334
|
-
{ pattern: /https?:\/\/(?:www\.)?dreamina\.capcut\.com\/[^\s]*/gi, type: 'jimeng' },
|
|
335
|
-
{ pattern: /https?:\/\/(?:www\.)?oasis\.weibo\.com\/v\/[0-9a-zA-Z_\/-]
|
|
336
|
-
{ pattern: /https?:\/\/channels\.weixin\.qq\.com\/[0-9a-zA-Z_\/-]
|
|
337
|
-
{ pattern: /https?:\/\/weixin\.qq\.com\/sph\/[0-9a-zA-Z_\/-]
|
|
338
|
-
{ pattern: /https?:\/\/(?:www\.)?pearvideo\.com\/video_\d
|
|
339
|
-
{ pattern: /https?:\/\/video\.li\/[0-9a-zA-Z_\/-]
|
|
340
|
-
{ pattern: /https?:\/\/(?:www\.)?quanmin\.tv\/[0-9a-zA-Z_\/-]
|
|
341
|
-
{ pattern: /https?:\/\/(?:www\.)?quanmintv\.cn\/[0-9a-zA-Z_\/-]
|
|
342
|
-
{ pattern: /https?:\/\/h5\.pipigx\.com\/pp\/post\/\d
|
|
343
|
-
{ pattern: /https?:\/\/(?:www\.)?ippzone\.com\/[0-9a-zA-Z_\/-]
|
|
344
|
-
{ pattern: /https?:\/\/(?:h5|www)\.pipix\.com\/[0-9a-zA-Z_\/-]
|
|
345
|
-
{ pattern: /https?:\/\/(?:www\.)?pipixia\.com\/[0-9a-zA-Z_\/-]
|
|
346
|
-
{ pattern: /https?:\/\/share\.xiaochuankeji\.cn\/hybrid\/share\/post\?pid=\d
|
|
347
|
-
{ pattern: /https?:\/\/(?:h5|www)\.izuiyou\.com\/[0-9a-zA-Z_\/-]
|
|
297
|
+
{ pattern: /https?:\/\/(?:www\.)?bilibili\.com\/video\/([ab]v[0-9a-zA-Z_-]+)(?:\?[^\s'"“”‘’]*)?/gi, type: 'bilibili' },
|
|
298
|
+
{ pattern: /https?:\/\/b23\.tv\/[0-9a-zA-Z_\/-]+/gi, type: 'bilibili' },
|
|
299
|
+
{ pattern: /https?:\/\/bili\d+\.cn\/[0-9a-zA-Z_\/-]+/gi, type: 'bilibili' },
|
|
300
|
+
{ pattern: /https?:\/\/b23\.wtf\/[0-9a-zA-Z_\/-]+/gi, type: 'bilibili' },
|
|
301
|
+
{ pattern: /https?:\/\/bili2233\.cn\/[0-9a-zA-Z_\/-]+/gi, type: 'bilibili' },
|
|
302
|
+
{ pattern: /https?:\/\/(?:www\.)?douyin\.com\/video\/\d{10,}/gi, type: 'douyin' },
|
|
303
|
+
{ pattern: /https?:\/\/v\.douyin\.com\/[0-9a-zA-Z_\/-]+/gi, type: 'douyin' },
|
|
304
|
+
{ pattern: /https?:\/\/(?:www\.)?kuaishou\.com\/short-video\/[0-9a-zA-Z_\/-]+/gi, type: 'kuaishou' },
|
|
305
|
+
{ pattern: /https?:\/\/v\.kuaishou\.com\/[0-9a-zA-Z_\/-]+/gi, type: 'kuaishou' },
|
|
306
|
+
{ pattern: /https?:\/\/(?:www\.)?kuaishou\.com\/f\/[0-9a-zA-Z_\/-]+/gi, type: 'kuaishou' },
|
|
307
|
+
{ pattern: /https?:\/\/(?:www\.)?xiaohongshu\.com\/discovery\/item\/[0-9a-zA-Z_\/-]+/gi, type: 'xiaohongshu' },
|
|
308
|
+
{ pattern: /https?:\/\/xhslink\.com\/[0-9a-zA-Z_\/-]+/gi, type: 'xiaohongshu' },
|
|
309
|
+
{ pattern: /https?:\/\/(?:www\.)?xiaohongshu\.com\/explore\/[0-9a-zA-Z_\/-]+/gi, type: 'xiaohongshu' },
|
|
310
|
+
{ pattern: /https?:\/\/(?:www\.)?xiaohongshu\.com\/board\/[0-9a-zA-Z_\/-]+/gi, type: 'xiaohongshu' },
|
|
311
|
+
{ pattern: /https?:\/\/weibo\.com\/\d+\/[0-9a-zA-Z_\/-]+/gi, type: 'weibo' },
|
|
312
|
+
{ pattern: /https?:\/\/video\.weibo\.com\/show\?fid=[0-9a-zA-Z_\/-]+/gi, type: 'weibo' },
|
|
313
|
+
{ pattern: /https?:\/\/t\.cn\/[0-9a-zA-Z_\/-]+/gi, type: 'weibo' },
|
|
314
|
+
{ pattern: /https?:\/\/m\.weibo\.cn\/[0-9a-zA-Z_\/-]+/gi, type: 'weibo' },
|
|
315
|
+
{ pattern: /https?:\/\/(?:www\.)?ixigua\.com\/\d{10,}/gi, type: 'xigua' },
|
|
316
|
+
{ pattern: /https?:\/\/(?:www\.)?youtube\.com\/watch\?v=[a-zA-Z0-9_-]{11}/gi, type: 'youtube' },
|
|
317
|
+
{ pattern: /https?:\/\/youtu\.be\/[0-9a-zA-Z_\/-]+/gi, type: 'youtube' },
|
|
318
|
+
{ pattern: /https?:\/\/(?:www\.)?youtube\.com\/shorts\/[0-9a-zA-Z_\/-]+/gi, type: 'youtube' },
|
|
319
|
+
{ pattern: /https?:\/\/(?:www\.)?tiktok\.com\/@[\w.]+\/video\/\d{10,}/gi, type: 'tiktok' },
|
|
320
|
+
{ pattern: /https?:\/\/vm\.tiktok\.com\/[0-9a-zA-Z_\/-]+/gi, type: 'tiktok' },
|
|
321
|
+
{ pattern: /https?:\/\/vt\.tiktok\.com\/[0-9a-zA-Z_\/-]+/gi, type: 'tiktok' },
|
|
322
|
+
{ pattern: /https?:\/\/(?:www\.)?acfun\.cn\/v\/ac\d{10,}/gi, type: 'acfun' },
|
|
323
|
+
{ pattern: /https?:\/\/(?:www\.)?zhihu\.com\/video\/\d{10,}/gi, type: 'zhihu' },
|
|
324
|
+
{ pattern: /https?:\/\/(?:www\.|m\.)?zhihu\.com\/question\/\d+\/answer\/\d+/gi, type: 'zhihu' },
|
|
325
|
+
{ pattern: /https?:\/\/zhuanlan\.zhihu\.com\/p\/\d+/gi, type: 'zhihu' },
|
|
326
|
+
{ pattern: /https?:\/\/(?:www\.|m\.)?zhihu\.com\/zvideo\/\d+/gi, type: 'zhihu' },
|
|
327
|
+
{ pattern: /https?:\/\/weishi\.qq\.com\/weishi\/feed\/[0-9a-zA-Z_\/-]+/gi, type: 'weishi' },
|
|
328
|
+
{ pattern: /https?:\/\/(?:www\.)?huya\.com\/video\/[0-9a-zA-Z_\/-]+/gi, type: 'huya' },
|
|
329
|
+
{ pattern: /https?:\/\/haokan\.baidu\.com\/v\?vid=[0-9a-zA-Z_\/-]+/gi, type: 'haokan' },
|
|
330
|
+
{ pattern: /https?:\/\/(?:www\.)?meipai\.com\/media\/\d{10,}/gi, type: 'meipai' },
|
|
331
|
+
{ pattern: /https?:\/\/twitter\.com\/\w+\/status\/\d{10,}/gi, type: 'twitter' },
|
|
332
|
+
{ pattern: /https?:\/\/x\.com\/\w+\/status\/\d{10,}/gi, type: 'twitter' },
|
|
333
|
+
{ pattern: /https?:\/\/(?:www\.)?instagram\.com\/p\/[0-9a-zA-Z_\/-]+/gi, type: 'instagram' },
|
|
334
|
+
{ pattern: /https?:\/\/(?:www\.)?instagram\.com\/reel\/[0-9a-zA-Z_\/-]+/gi, type: 'instagram' },
|
|
335
|
+
{ pattern: /https?:\/\/(?:www\.)?instagram\.com\/share\/(?:reel|p)\/[0-9a-zA-Z_\/-]+/gi, type: 'instagram' },
|
|
336
|
+
{ pattern: /https?:\/\/(?:www\.)?doubao\.com\/video\/\d{10,}/gi, type: 'doubao' },
|
|
337
|
+
{ pattern: /https?:\/\/(?:www\.)?doubao\.com\/video-sharing\?[^\s'"“”‘’]*/gi, type: 'doubao' },
|
|
338
|
+
{ pattern: /https?:\/\/(?:www\.)?doubao\.com\/thread\/[^\s'"“”‘’]+/gi, type: 'doubao_image' },
|
|
339
|
+
{ pattern: /https?:\/\/(?:www\.)?jimeng\.jianying\.com\/[^\s'"“”‘’]*/gi, type: 'jimeng' },
|
|
340
|
+
{ pattern: /https?:\/\/(?:www\.)?jimeng\.cn\/[^\s'"“”‘’]*/gi, type: 'jimeng' },
|
|
341
|
+
{ pattern: /https?:\/\/(?:www\.)?dreamina\.jianying\.com\/[^\s'"“”‘’]*/gi, type: 'jimeng' },
|
|
342
|
+
{ pattern: /https?:\/\/(?:www\.)?dreamina\.capcut\.com\/[^\s'"“”‘’]*/gi, type: 'jimeng' },
|
|
343
|
+
{ pattern: /https?:\/\/(?:www\.)?oasis\.weibo\.com\/v\/[0-9a-zA-Z_\/-]+/gi, type: 'oasis' },
|
|
344
|
+
{ pattern: /https?:\/\/channels\.weixin\.qq\.com\/[0-9a-zA-Z_\/-]+/gi, type: 'wechat_channel' },
|
|
345
|
+
{ pattern: /https?:\/\/weixin\.qq\.com\/sph\/[0-9a-zA-Z_\/-]+/gi, type: 'wechat_channel' },
|
|
346
|
+
{ pattern: /https?:\/\/(?:www\.)?pearvideo\.com\/video_\d+/gi, type: 'lishi' },
|
|
347
|
+
{ pattern: /https?:\/\/video\.li\/[0-9a-zA-Z_\/-]+/gi, type: 'lishi' },
|
|
348
|
+
{ pattern: /https?:\/\/(?:www\.)?quanmin\.tv\/[0-9a-zA-Z_\/-]+/gi, type: 'quanmin' },
|
|
349
|
+
{ pattern: /https?:\/\/(?:www\.)?quanmintv\.cn\/[0-9a-zA-Z_\/-]+/gi, type: 'quanmin' },
|
|
350
|
+
{ pattern: /https?:\/\/h5\.pipigx\.com\/pp\/post\/\d+/gi, type: 'pipigx' },
|
|
351
|
+
{ pattern: /https?:\/\/(?:www\.)?ippzone\.com\/[0-9a-zA-Z_\/-]+/gi, type: 'pipigx' },
|
|
352
|
+
{ pattern: /https?:\/\/(?:h5|www)\.pipix\.com\/[0-9a-zA-Z_\/-]+/gi, type: 'pipixia' },
|
|
353
|
+
{ pattern: /https?:\/\/(?:www\.)?pipixia\.com\/[0-9a-zA-Z_\/-]+/gi, type: 'pipixia' },
|
|
354
|
+
{ pattern: /https?:\/\/share\.xiaochuankeji\.cn\/hybrid\/share\/post\?pid=\d+/gi, type: 'zuiyou' },
|
|
355
|
+
{ pattern: /https?:\/\/(?:h5|www)\.izuiyou\.com\/[0-9a-zA-Z_\/-]+/gi, type: 'zuiyou' },
|
|
348
356
|
];
|
|
349
357
|
function buildCustomLinkRules(customPlatforms) {
|
|
350
358
|
if (!Array.isArray(customPlatforms) || customPlatforms.length === 0)
|
|
@@ -356,7 +364,7 @@ function buildCustomLinkRules(customPlatforms) {
|
|
|
356
364
|
if (keywords.length === 0)
|
|
357
365
|
return null;
|
|
358
366
|
const escaped = keywords.map((k) => k.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
|
|
359
|
-
const pattern = new RegExp(
|
|
367
|
+
const pattern = new RegExp(`https?://[^/\\s"'“”‘’]*(${escaped.join('|')})[^\\s"'“”‘’]*`, 'gi');
|
|
360
368
|
return { pattern, type: `custom_${p.name}` };
|
|
361
369
|
})
|
|
362
370
|
.filter(Boolean);
|
|
@@ -370,7 +378,10 @@ function linkTypeParser(content, customRules) {
|
|
|
370
378
|
let match;
|
|
371
379
|
rule.pattern.lastIndex = 0;
|
|
372
380
|
while ((match = rule.pattern.exec(content)) !== null) {
|
|
373
|
-
|
|
381
|
+
let url = match[0];
|
|
382
|
+
url = cleanUrl(url);
|
|
383
|
+
if (!url)
|
|
384
|
+
continue;
|
|
374
385
|
if (seen.has(url))
|
|
375
386
|
continue;
|
|
376
387
|
seen.add(url);
|
|
@@ -385,8 +396,8 @@ function cleanUrl(url) {
|
|
|
385
396
|
.replace(/</g, '<')
|
|
386
397
|
.replace(/>/g, '>')
|
|
387
398
|
.replace(/\\\//g, '/');
|
|
388
|
-
url = url.replace(/^[\s"'
|
|
389
|
-
url = url.replace(/[\s"'<>\{\}\[\]
|
|
399
|
+
url = url.replace(/^[\s"'<“”‘’]+/, '');
|
|
400
|
+
url = url.replace(/[\s"'<>\{\}\[\]`,;,。!?:;“”‘’…—~]+$/, '');
|
|
390
401
|
if (!/^https?:\/\//i.test(url)) {
|
|
391
402
|
if (/^\/\//.test(url))
|
|
392
403
|
url = 'https:' + url;
|
|
@@ -630,7 +641,7 @@ function parseApiResponse(raw, maxDescLen, fieldMapping) {
|
|
|
630
641
|
return { type, title, desc, author, uid, avatar, cover, video, videos, images, live_photo, music, like, comment, collect, share, play, duration, publishTime, author_followers, author_signature, admire };
|
|
631
642
|
}
|
|
632
643
|
const formatVarRegex = /\$\{([^}]+)\}/g;
|
|
633
|
-
function generateFormattedText(p, format) {
|
|
644
|
+
function generateFormattedText(p, format, index, total) {
|
|
634
645
|
const imageCount = p.images.length || p.live_photo.length;
|
|
635
646
|
const vars = {
|
|
636
647
|
'标题': p.title,
|
|
@@ -648,10 +659,6 @@ function generateFormattedText(p, format) {
|
|
|
648
659
|
'音乐标题': p.music.title || '',
|
|
649
660
|
'音乐作者': p.music.author || '',
|
|
650
661
|
};
|
|
651
|
-
const varReplacements = Object.entries(vars).map(([key, val]) => ({
|
|
652
|
-
regex: new RegExp(`\\$\\{${key}\\}`, 'g'),
|
|
653
|
-
value: val,
|
|
654
|
-
}));
|
|
655
662
|
const lines = format.split('\n');
|
|
656
663
|
const resultLines = [];
|
|
657
664
|
for (const line of lines) {
|
|
@@ -670,12 +677,16 @@ function generateFormattedText(p, format) {
|
|
|
670
677
|
continue;
|
|
671
678
|
}
|
|
672
679
|
let newLine = line;
|
|
673
|
-
for (const
|
|
674
|
-
newLine = newLine.replace(
|
|
680
|
+
for (const [key, val] of Object.entries(vars)) {
|
|
681
|
+
newLine = newLine.replace(new RegExp(`\\$\\{${key}\\}`, 'g'), val);
|
|
675
682
|
}
|
|
676
683
|
resultLines.push(newLine);
|
|
677
684
|
}
|
|
678
|
-
|
|
685
|
+
let text = resultLines.join('\n').trim();
|
|
686
|
+
if (index !== undefined && total !== undefined && total > 1) {
|
|
687
|
+
text = `【${index}/${total}】\n${text}`;
|
|
688
|
+
}
|
|
689
|
+
return text;
|
|
679
690
|
}
|
|
680
691
|
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
681
692
|
function buildForwardNode(session, content, botName) {
|
|
@@ -806,6 +817,31 @@ function apply(ctx, config) {
|
|
|
806
817
|
return { [customHeaderName]: apiKey };
|
|
807
818
|
return {};
|
|
808
819
|
}
|
|
820
|
+
async function sendWithTimeout(session, content, customRetries) {
|
|
821
|
+
const maxRetries = customRetries ?? config.retryTimes ?? 3;
|
|
822
|
+
const retryDelay = config.retryInterval || 1000;
|
|
823
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
824
|
+
try {
|
|
825
|
+
let sendPromise = session.send(content);
|
|
826
|
+
if (config.videoSendTimeout > 0) {
|
|
827
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('发送超时')), config.videoSendTimeout));
|
|
828
|
+
return await Promise.race([sendPromise, timeoutPromise]);
|
|
829
|
+
}
|
|
830
|
+
else {
|
|
831
|
+
return await sendPromise;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
catch (err) {
|
|
835
|
+
const errMsg = getErrorMessage(err);
|
|
836
|
+
debugLog('ERROR', `发送失败尝试 ${attempt + 1}: ${errMsg}`);
|
|
837
|
+
if (attempt < maxRetries)
|
|
838
|
+
await delay(retryDelay);
|
|
839
|
+
else if (!config.ignoreSendError)
|
|
840
|
+
throw err;
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
return null;
|
|
844
|
+
}
|
|
809
845
|
async function sendMedia(session, url, type, showFile) {
|
|
810
846
|
if (!url)
|
|
811
847
|
return;
|
|
@@ -875,13 +911,16 @@ function apply(ctx, config) {
|
|
|
875
911
|
await sendWithTimeout(session, `${getText('parseErrorPrefix')}\n${errors.join('\n')}`);
|
|
876
912
|
if (!items.length)
|
|
877
913
|
return;
|
|
914
|
+
const totalItems = items.length;
|
|
878
915
|
const enableForward = config.enableForward && (session.platform === 'onebot' || session.platform === 'satori');
|
|
879
916
|
const botName = config.botName || '视频解析机器人';
|
|
880
917
|
if (enableForward) {
|
|
881
918
|
const forwardMessages = [];
|
|
882
|
-
for (
|
|
919
|
+
for (let i = 0; i < items.length; i++) {
|
|
920
|
+
const item = items[i];
|
|
883
921
|
const p = item.parsed;
|
|
884
|
-
|
|
922
|
+
const textWithIndex = (totalItems > 1) ? `【${i + 1}/${totalItems}】\n${item.text}` : item.text;
|
|
923
|
+
let text = textWithIndex;
|
|
885
924
|
if (config.showAuthorAvatar && p.avatar && config.showAuthorAvatarText) {
|
|
886
925
|
text = text ? text + '\n' + (config.authorAvatarText || '作者头像:') : (config.authorAvatarText || '作者头像:');
|
|
887
926
|
}
|
|
@@ -934,9 +973,11 @@ function apply(ctx, config) {
|
|
|
934
973
|
}
|
|
935
974
|
}
|
|
936
975
|
else {
|
|
937
|
-
for (
|
|
976
|
+
for (let i = 0; i < items.length; i++) {
|
|
977
|
+
const item = items[i];
|
|
938
978
|
const p = item.parsed;
|
|
939
|
-
|
|
979
|
+
const textWithIndex = (totalItems > 1) ? `【${i + 1}/${totalItems}】\n${item.text}` : item.text;
|
|
980
|
+
let text = textWithIndex;
|
|
940
981
|
if (config.showAuthorAvatar && p.avatar && config.showAuthorAvatarText) {
|
|
941
982
|
text = text ? text + '\n' + (config.authorAvatarText || '作者头像:') : (config.authorAvatarText || '作者头像:');
|
|
942
983
|
}
|
|
@@ -966,9 +1007,9 @@ function apply(ctx, config) {
|
|
|
966
1007
|
}
|
|
967
1008
|
else if (p.type === 'image' || (p.type === 'live' && (p.live_photo?.length || p.images?.length))) {
|
|
968
1009
|
const imageUrls = p.images?.length ? p.images : (p.live_photo?.map(lp => lp.image) ?? []);
|
|
969
|
-
for (let
|
|
970
|
-
logger.info(`[发送] 图片 ${
|
|
971
|
-
await sendMedia(session, imageUrls[
|
|
1010
|
+
for (let j = 0; j < imageUrls.length; j++) {
|
|
1011
|
+
logger.info(`[发送] 图片 ${j + 1}/${imageUrls.length}`);
|
|
1012
|
+
await sendMedia(session, imageUrls[j], 'image', config.showImageFileNew).catch(() => { });
|
|
972
1013
|
await delay(1000);
|
|
973
1014
|
}
|
|
974
1015
|
}
|
|
@@ -1073,18 +1114,17 @@ function apply(ctx, config) {
|
|
|
1073
1114
|
throw lastError || new Error('所有API请求全部失败');
|
|
1074
1115
|
}
|
|
1075
1116
|
async function parseUrl(url, type, fieldMapping, platformConf) {
|
|
1076
|
-
const cleanedUrl = cleanUrl(url);
|
|
1077
1117
|
try {
|
|
1078
|
-
const info = await fetchApi(
|
|
1118
|
+
const info = await fetchApi(url, type, fieldMapping, platformConf);
|
|
1079
1119
|
if (info.video || info.images.length > 0 || info.live_photo.length > 0)
|
|
1080
1120
|
return { success: true, data: info };
|
|
1081
|
-
debugLog('WARN', `解析成功但无内容: ${
|
|
1121
|
+
debugLog('WARN', `解析成功但无内容: ${url}`);
|
|
1122
|
+
return { success: false, msg: '解析接口返回空内容' };
|
|
1082
1123
|
}
|
|
1083
1124
|
catch (error) {
|
|
1084
|
-
debugLog('ERROR', `解析失败: ${
|
|
1125
|
+
debugLog('ERROR', `解析失败: ${url}`, getErrorMessage(error));
|
|
1085
1126
|
return { success: false, msg: getErrorMessage(error) };
|
|
1086
1127
|
}
|
|
1087
|
-
return { success: false, msg: getText('unsupportedPlatformText') };
|
|
1088
1128
|
}
|
|
1089
1129
|
async function processSingleUrl(url, type, fieldMapping, platformConf) {
|
|
1090
1130
|
const result = await parseUrl(url, type, fieldMapping, platformConf);
|
|
@@ -1093,31 +1133,6 @@ function apply(ctx, config) {
|
|
|
1093
1133
|
const text = generateFormattedText(result.data, config.unifiedMessageFormat);
|
|
1094
1134
|
return { success: true, data: { text, parsed: result.data } };
|
|
1095
1135
|
}
|
|
1096
|
-
async function sendWithTimeout(session, content, customRetries) {
|
|
1097
|
-
const maxRetries = customRetries ?? config.retryTimes ?? 3;
|
|
1098
|
-
const retryDelay = config.retryInterval || 1000;
|
|
1099
|
-
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
1100
|
-
try {
|
|
1101
|
-
let sendPromise = session.send(content);
|
|
1102
|
-
if (config.videoSendTimeout > 0) {
|
|
1103
|
-
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('发送超时')), config.videoSendTimeout));
|
|
1104
|
-
return await Promise.race([sendPromise, timeoutPromise]);
|
|
1105
|
-
}
|
|
1106
|
-
else {
|
|
1107
|
-
return await sendPromise;
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
|
-
catch (err) {
|
|
1111
|
-
const errMsg = getErrorMessage(err);
|
|
1112
|
-
debugLog('ERROR', `发送失败尝试 ${attempt + 1}: ${errMsg}`);
|
|
1113
|
-
if (attempt < maxRetries)
|
|
1114
|
-
await delay(retryDelay);
|
|
1115
|
-
else if (!config.ignoreSendError)
|
|
1116
|
-
throw err;
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1119
|
-
return null;
|
|
1120
|
-
}
|
|
1121
1136
|
const customRules = buildCustomLinkRules(config.customPlatforms || []);
|
|
1122
1137
|
const axiosConfig = {
|
|
1123
1138
|
timeout: config.timeout,
|
|
@@ -1156,7 +1171,7 @@ function apply(ctx, config) {
|
|
|
1156
1171
|
debugLog('INFO', `检测到 ${matches.length} 个链接`);
|
|
1157
1172
|
if (config.showWaitingTip) {
|
|
1158
1173
|
try {
|
|
1159
|
-
await sendWithTimeout(session, getText('waitingTipText'));
|
|
1174
|
+
await sendWithTimeout(session, koishi_1.h.quote(session.messageId) + getText('waitingTipText'));
|
|
1160
1175
|
}
|
|
1161
1176
|
catch (e) {
|
|
1162
1177
|
debugLog('WARN', '等待提示发送失败:', e);
|
|
@@ -1176,7 +1191,7 @@ function apply(ctx, config) {
|
|
|
1176
1191
|
}
|
|
1177
1192
|
if (config.showWaitingTip) {
|
|
1178
1193
|
try {
|
|
1179
|
-
await sendWithTimeout(session, getText('waitingTipText'));
|
|
1194
|
+
await sendWithTimeout(session, koishi_1.h.quote(session?.messageId) + getText('waitingTipText'));
|
|
1180
1195
|
}
|
|
1181
1196
|
catch { }
|
|
1182
1197
|
}
|
package/package.json
CHANGED