koishi-plugin-video-parser-all 0.6.2 → 0.6.3
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 +114 -18
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -22,7 +22,37 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
22
22
|
sameLinkInterval: koishi_1.Schema.number().min(0).default(180).description('相同链接重复解析间隔(秒)'),
|
|
23
23
|
}).description('基础设置'),
|
|
24
24
|
koishi_1.Schema.object({
|
|
25
|
-
unifiedMessageFormat: koishi_1.Schema.string().role('textarea').default(
|
|
25
|
+
unifiedMessageFormat: koishi_1.Schema.string().role('textarea').default(`标题:${'${标题}'}
|
|
26
|
+
作者:${'${作者}'}
|
|
27
|
+
简介:${'${简介}'}
|
|
28
|
+
时长:${'${视频时长}'}
|
|
29
|
+
点赞:${'${点赞数}'}
|
|
30
|
+
投币:${'${投币数}'}
|
|
31
|
+
收藏:${'${收藏数}'}
|
|
32
|
+
转发:${'${转发数}'}
|
|
33
|
+
播放:${'${播放数}'}
|
|
34
|
+
评论:${'${评论数}'}
|
|
35
|
+
音乐:${'${音乐名}'}
|
|
36
|
+
IP属地:${'${IP属地}'}
|
|
37
|
+
发布时间:${'${发布时间}'}
|
|
38
|
+
粉丝数:${'${粉丝数}'}
|
|
39
|
+
在线人数:${'${在线人数}'}
|
|
40
|
+
关注数:${'${关注数}'}
|
|
41
|
+
视频质量:${'${视频质量}'}
|
|
42
|
+
帧率:${'${帧率}'}
|
|
43
|
+
码率:${'${码率}'}
|
|
44
|
+
文件大小:${'${文件大小}'}
|
|
45
|
+
分辨率:${'${分辨率}'}
|
|
46
|
+
音乐作者:${'${音乐作者}'}
|
|
47
|
+
音乐标题:${'${音乐标题}'}
|
|
48
|
+
直播间地址:${'${直播间地址}'}
|
|
49
|
+
直播间ID:${'${直播间ID}'}
|
|
50
|
+
直播间状态:${'${直播间状态}'}
|
|
51
|
+
默认画质:${'${默认画质}'}
|
|
52
|
+
图片数量:${'${图片数量}'}
|
|
53
|
+
作者ID:${'${作者ID}'}
|
|
54
|
+
封面链接:${'${封面链接}'}
|
|
55
|
+
视频链接:${'${视频链接}'}`).description('统一消息格式(无法获取的变量会自动隐藏)'),
|
|
26
56
|
}).description('统一消息格式'),
|
|
27
57
|
koishi_1.Schema.object({
|
|
28
58
|
showImageText: koishi_1.Schema.boolean().default(true).description('显示图文内容'),
|
|
@@ -125,17 +155,37 @@ const API_CONFIG = {
|
|
|
125
155
|
zuiyou: 'https://api.bugpk.com/api/zuiyou'
|
|
126
156
|
};
|
|
127
157
|
const VARIABLE_MAPPING = {
|
|
128
|
-
'标题': ['title', 'Title', 'TITLE', 'note_title', 'content_title'],
|
|
129
|
-
'作者': ['author.name', 'author', 'name', 'Author', 'Name', 'owner.name', 'nickname', 'user_name'],
|
|
130
|
-
'简介': ['desc', 'description', 'Desc', 'Description', 'content', 'Content', 'note_desc', 'text'],
|
|
131
|
-
'视频时长': ['duration', 'Duration', 'time', 'Time', 'video_duration'],
|
|
132
|
-
'点赞数': ['like', 'Like', 'attitudes_count', 'digg_count', 'praise', 'stat.like', 'liked_count'],
|
|
133
|
-
'投币数': ['coin', 'Coin', 'bi', 'Bi', 'stat.coin'],
|
|
134
|
-
'收藏数': ['collect', 'Collect', 'favorite', 'Favorite', 'star', 'Star', 'stat.collect', 'collected_count'],
|
|
135
|
-
'转发数': ['share', 'Share', 'forward', 'Forward', 'repost', 'stat.share', 'reposts_count', 'shared_count'],
|
|
136
|
-
'播放数': ['view', 'View', 'play_count', 'PlayCount', 'play', 'stat.view', 'play_times'],
|
|
137
|
-
'评论数': ['comment', 'Comment', 'comments_count', 'comment_count', 'discuss', 'stat.comment'],
|
|
138
|
-
'音乐名': ['music.title', 'music_name', 'audio_name', 'sound_name', 'muisic', 'music', 'bgm_name']
|
|
158
|
+
'标题': ['title', 'Title', 'TITLE', 'note_title', 'content_title', 'item.title', 'data.title', 'video.title', 'live.title'],
|
|
159
|
+
'作者': ['author.name', 'author', 'name', 'Author', 'Name', 'owner.name', 'nickname', 'user_name', 'data.author', 'item.author', 'user.name', 'live.author'],
|
|
160
|
+
'简介': ['desc', 'description', 'Desc', 'Description', 'content', 'Content', 'note_desc', 'text', 'data.desc', 'item.description', 'live.desc'],
|
|
161
|
+
'视频时长': ['duration', 'Duration', 'time', 'Time', 'video_duration', 'item.duration', 'stat.duration'],
|
|
162
|
+
'点赞数': ['like', 'Like', 'attitudes_count', 'digg_count', 'praise', 'stat.like', 'liked_count', 'data.like', 'data.attitudes_count', 'item.attitudes_count'],
|
|
163
|
+
'投币数': ['coin', 'Coin', 'bi', 'Bi', 'stat.coin', 'stast.coin'],
|
|
164
|
+
'收藏数': ['collect', 'Collect', 'favorite', 'Favorite', 'star', 'Star', 'stat.collect', 'collected_count', 'stast.favorite', 'data.favorite'],
|
|
165
|
+
'转发数': ['share', 'Share', 'forward', 'Forward', 'repost', 'stat.share', 'reposts_count', 'shared_count', 'stast.share', 'data.reposts_count'],
|
|
166
|
+
'播放数': ['view', 'View', 'play_count', 'PlayCount', 'play', 'stat.view', 'play_times', 'stast.view', 'data.play_count', 'item.play_count'],
|
|
167
|
+
'评论数': ['comment', 'Comment', 'comments_count', 'comment_count', 'discuss', 'stat.comment', 'stast.reply', 'data.comments_count', 'item.comments_count'],
|
|
168
|
+
'音乐名': ['music.title', 'music_name', 'audio_name', 'sound_name', 'muisic', 'music', 'bgm_name', 'data.music.name', 'item.music.title', 'music.author', 'music.albumName'],
|
|
169
|
+
'IP属地': ['ip_info_str', 'data.ip_info_str', 'item.ip_info'],
|
|
170
|
+
'发布时间': ['date', 'time', 'publish_time', 'data.date', 'item.publish_time', 'live.time', 'stast.publish_time'],
|
|
171
|
+
'粉丝数': ['followers_count', 'data.followers_count', 'item.followers', 'author.fans'],
|
|
172
|
+
'在线人数': ['online', 'data.online', 'live.online', 'room.online'],
|
|
173
|
+
'关注数': ['attention', 'data.attention', 'live.attention', 'stast.attention'],
|
|
174
|
+
'视频质量': ['quality', 'max_qxd', 'data.quality', 'item.quality', 'quality_urls'],
|
|
175
|
+
'帧率': ['fps', 'item.fps', 'data.fps'],
|
|
176
|
+
'码率': ['bitrate', 'item.bitrate', 'data.bitrate', 'br', 'item.br'],
|
|
177
|
+
'文件大小': ['size', 'size_str', 'item.size', 'item.size_str', 'data.size'],
|
|
178
|
+
'分辨率': ['height', 'width', 'h_w', 'item.h_w', 'data.resolution', 'item.height', 'item.width'],
|
|
179
|
+
'音乐作者': ['music.author', 'item.music.author', 'data.music.author', 'music.artist'],
|
|
180
|
+
'音乐标题': ['music.title', 'item.music.title', 'data.music.title', 'music.name'],
|
|
181
|
+
'直播间地址': ['room_url', 'live.room_url', 'data.room_url', 'live.url'],
|
|
182
|
+
'直播间ID': ['room_id', 'live.room_id', 'data.room_id', 'live.room_id'],
|
|
183
|
+
'直播间状态': ['status', 'live.status', 'data.status', 'room.status'],
|
|
184
|
+
'默认画质': ['default_quality', 'data.default_quality', 'item.default_quality'],
|
|
185
|
+
'图片数量': ['count', 'data.count', 'item.count', 'images.length', 'data.images.length'],
|
|
186
|
+
'作者ID': ['userId', 'userID', 'author_id', 'data.userId', 'item.userID', 'author.mid', 'user.mid'],
|
|
187
|
+
'封面链接': ['cover', 'imgurl', 'pic', 'thumbnail', 'cover_url', 'data.cover', 'item.cover', 'live.cover'],
|
|
188
|
+
'视频链接': ['url', 'video_url', 'playUrl', 'download_url', 'data.url', 'item.url', 'live.url', 'quality_urls.*'],
|
|
139
189
|
};
|
|
140
190
|
function getErrorInfo(code, detail) {
|
|
141
191
|
const baseMsg = exports.ErrorMessageMap[code] || exports.ErrorMessageMap[ErrorCode.UNKNOWN_ERROR];
|
|
@@ -393,14 +443,36 @@ function parseData(rawResponse, maxDescLength) {
|
|
|
393
443
|
const data = rootData.data || rootData.result || rootData || {};
|
|
394
444
|
const stat = {};
|
|
395
445
|
Object.entries(VARIABLE_MAPPING).forEach(([varName, keys]) => {
|
|
396
|
-
|
|
397
|
-
|
|
446
|
+
let value = findValueInObject(data, keys) || findValueInObject(rootData, keys);
|
|
447
|
+
if (varName === '图片数量' && value === undefined) {
|
|
448
|
+
value = Array.isArray(data.images) ? data.images.length : (Array.isArray(rootData.images) ? rootData.images.length : undefined);
|
|
449
|
+
}
|
|
450
|
+
if (varName === '分辨率' && value === undefined) {
|
|
451
|
+
const h = findValueInObject(data, ['height', 'item.height']) || findValueInObject(rootData, ['height', 'item.height']);
|
|
452
|
+
const w = findValueInObject(data, ['width', 'item.width']) || findValueInObject(rootData, ['width', 'item.width']);
|
|
453
|
+
if (h && w)
|
|
454
|
+
value = `${w}x${h}`;
|
|
455
|
+
else if (data.h_w && Array.isArray(data.h_w) && data.h_w.length)
|
|
456
|
+
value = data.h_w.join(', ');
|
|
457
|
+
}
|
|
458
|
+
if (varName === '视频链接' && value === undefined) {
|
|
459
|
+
value = data.url || data.video || data.download_url || rootData.url || rootData.video;
|
|
460
|
+
}
|
|
461
|
+
if (value !== undefined && value !== null && value !== '') {
|
|
462
|
+
stat[varName] = value;
|
|
463
|
+
}
|
|
398
464
|
});
|
|
399
465
|
let type = 'video';
|
|
400
466
|
if (data.jx?.type)
|
|
401
467
|
type = data.jx.type;
|
|
402
468
|
else if (data.type)
|
|
403
469
|
type = data.type;
|
|
470
|
+
else if (rootData.msg === 'cv')
|
|
471
|
+
type = 'cv';
|
|
472
|
+
else if (rootData.msg === 'live')
|
|
473
|
+
type = 'live';
|
|
474
|
+
else if (data.images && data.images.length > 0 && !data.url)
|
|
475
|
+
type = '图集';
|
|
404
476
|
const title = stat['标题'] || '无标题';
|
|
405
477
|
const author = stat['作者'] || '未知作者';
|
|
406
478
|
const desc = (stat['简介'] || title).slice(0, maxDescLength);
|
|
@@ -451,14 +523,32 @@ function parseData(rawResponse, maxDescLength) {
|
|
|
451
523
|
};
|
|
452
524
|
}
|
|
453
525
|
function generateFormattedText(parseData, config) {
|
|
454
|
-
let format = config.unifiedMessageFormat || '
|
|
526
|
+
let format = config.unifiedMessageFormat || '';
|
|
527
|
+
if (!format) {
|
|
528
|
+
format = `标题:${'${标题}'}
|
|
529
|
+
作者:${'${作者}'}
|
|
530
|
+
简介:${'${简介}'}
|
|
531
|
+
时长:${'${视频时长}'}
|
|
532
|
+
点赞:${'${点赞数}'}
|
|
533
|
+
投币:${'${投币数}'}
|
|
534
|
+
收藏:${'${收藏数}'}
|
|
535
|
+
转发:${'${转发数}'}
|
|
536
|
+
播放:${'${播放数}'}
|
|
537
|
+
评论:${'${评论数}'}
|
|
538
|
+
音乐:${'${音乐名}'}`;
|
|
539
|
+
}
|
|
455
540
|
let result = format;
|
|
456
541
|
const varMatches = result.match(/\$\{([^}]+)\}/g) || [];
|
|
457
542
|
varMatches.forEach((varMatch) => {
|
|
458
543
|
const varName = varMatch.replace(/\$\{|\}/g, '');
|
|
459
544
|
const value = parseData.stat[varName];
|
|
460
|
-
|
|
461
|
-
|
|
545
|
+
if (value === undefined || value === null || value === '') {
|
|
546
|
+
const lines = result.split('\n');
|
|
547
|
+
result = lines.filter((line) => !line.includes(varMatch)).join('\n');
|
|
548
|
+
}
|
|
549
|
+
else {
|
|
550
|
+
result = result.replace(varMatch, String(value));
|
|
551
|
+
}
|
|
462
552
|
});
|
|
463
553
|
return result.trim() || `标题:${parseData.title}\n作者:${parseData.author}\n简介:${parseData.desc}`;
|
|
464
554
|
}
|
|
@@ -556,7 +646,7 @@ function apply(ctx, config) {
|
|
|
556
646
|
return { data: null, code, msg };
|
|
557
647
|
}
|
|
558
648
|
const isSuccess = resData.code === 0 || resData.code === 200 || resData.code === 1 ||
|
|
559
|
-
(resData.msg && (resData.msg.includes('解析成功') || resData.msg.includes('success'))) ||
|
|
649
|
+
(resData.msg && (resData.msg.includes('解析成功') || resData.msg.includes('success') || resData.msg.includes('请求成功'))) ||
|
|
560
650
|
!!resData.data || !!resData.result || !!resData.video || !!resData.images;
|
|
561
651
|
if (!isSuccess) {
|
|
562
652
|
const apiErrorMsg = resData.msg || resData.error || '解析失败';
|
|
@@ -783,5 +873,11 @@ function apply(ctx, config) {
|
|
|
783
873
|
const now = Date.now();
|
|
784
874
|
processed.forEach((t, h) => now - t > 86400000 && processed.delete(h));
|
|
785
875
|
}, 3600000);
|
|
876
|
+
if (config.autoClearCacheInterval > 0) {
|
|
877
|
+
setInterval(() => {
|
|
878
|
+
clearAllCache();
|
|
879
|
+
logger.info('自动清理缓存完成');
|
|
880
|
+
}, config.autoClearCacheInterval * 60 * 1000);
|
|
881
|
+
}
|
|
786
882
|
logger.info('✅ 视频解析插件已启动');
|
|
787
883
|
}
|
package/package.json
CHANGED