koishi-plugin-video-parser-all 1.2.9 → 1.3.1
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 +8 -4
- package/lib/index.js +107 -29
- package/package.json +1 -1
- package/readme.md +13 -14
package/lib/index.d.ts
CHANGED
|
@@ -22,7 +22,8 @@ export declare const Config: Schema<{
|
|
|
22
22
|
videoSendTimeout?: number | null | undefined;
|
|
23
23
|
userAgent?: string | null | undefined;
|
|
24
24
|
proxy?: ({
|
|
25
|
-
|
|
25
|
+
enabled?: boolean | null | undefined;
|
|
26
|
+
protocol?: "http" | "https" | null | undefined;
|
|
26
27
|
host?: string | null | undefined;
|
|
27
28
|
port?: number | null | undefined;
|
|
28
29
|
auth?: ({
|
|
@@ -64,11 +65,12 @@ export declare const Config: Schema<{
|
|
|
64
65
|
twitter?: boolean | null | undefined;
|
|
65
66
|
instagram?: boolean | null | undefined;
|
|
66
67
|
doubao?: boolean | null | undefined;
|
|
68
|
+
doubao_chat?: boolean | null | undefined;
|
|
67
69
|
oasis?: boolean | null | undefined;
|
|
68
70
|
wechat_channel?: boolean | null | undefined;
|
|
69
71
|
} & import("cosmokit").Dict) | null | undefined;
|
|
70
72
|
customApis?: ({
|
|
71
|
-
platform?: "bilibili" | "douyin" | "kuaishou" | "xiaohongshu" | "weibo" | "xigua" | "youtube" | "tiktok" | "acfun" | "zhihu" | "weishi" | "huya" | "haokan" | "meipai" | "twitter" | "instagram" | "doubao" | "oasis" | "wechat_channel" | null | undefined;
|
|
73
|
+
platform?: "bilibili" | "douyin" | "kuaishou" | "xiaohongshu" | "weibo" | "xigua" | "youtube" | "tiktok" | "acfun" | "zhihu" | "weishi" | "huya" | "haokan" | "meipai" | "twitter" | "instagram" | "doubao" | "doubao_chat" | "oasis" | "wechat_channel" | null | undefined;
|
|
72
74
|
apiUrl?: string | null | undefined;
|
|
73
75
|
apiKey?: string | null | undefined;
|
|
74
76
|
authHeaderType?: "Bearer" | "X-API-Key" | "Custom" | null | undefined;
|
|
@@ -104,7 +106,8 @@ export declare const Config: Schema<{
|
|
|
104
106
|
videoSendTimeout: number;
|
|
105
107
|
userAgent: string;
|
|
106
108
|
proxy: Schemastery.ObjectT<{
|
|
107
|
-
|
|
109
|
+
enabled: Schema<boolean, boolean>;
|
|
110
|
+
protocol: Schema<"http" | "https", "http" | "https">;
|
|
108
111
|
host: Schema<string, string>;
|
|
109
112
|
port: Schema<number, number>;
|
|
110
113
|
auth: Schema<Schemastery.ObjectS<{
|
|
@@ -149,11 +152,12 @@ export declare const Config: Schema<{
|
|
|
149
152
|
twitter: Schema<boolean, boolean>;
|
|
150
153
|
instagram: Schema<boolean, boolean>;
|
|
151
154
|
doubao: Schema<boolean, boolean>;
|
|
155
|
+
doubao_chat: Schema<boolean, boolean>;
|
|
152
156
|
oasis: Schema<boolean, boolean>;
|
|
153
157
|
wechat_channel: Schema<boolean, boolean>;
|
|
154
158
|
}>;
|
|
155
159
|
customApis: Schemastery.ObjectT<{
|
|
156
|
-
platform: Schema<"bilibili" | "douyin" | "kuaishou" | "xiaohongshu" | "weibo" | "xigua" | "youtube" | "tiktok" | "acfun" | "zhihu" | "weishi" | "huya" | "haokan" | "meipai" | "twitter" | "instagram" | "doubao" | "oasis" | "wechat_channel", "bilibili" | "douyin" | "kuaishou" | "xiaohongshu" | "weibo" | "xigua" | "youtube" | "tiktok" | "acfun" | "zhihu" | "weishi" | "huya" | "haokan" | "meipai" | "twitter" | "instagram" | "doubao" | "oasis" | "wechat_channel">;
|
|
160
|
+
platform: Schema<"bilibili" | "douyin" | "kuaishou" | "xiaohongshu" | "weibo" | "xigua" | "youtube" | "tiktok" | "acfun" | "zhihu" | "weishi" | "huya" | "haokan" | "meipai" | "twitter" | "instagram" | "doubao" | "doubao_chat" | "oasis" | "wechat_channel", "bilibili" | "douyin" | "kuaishou" | "xiaohongshu" | "weibo" | "xigua" | "youtube" | "tiktok" | "acfun" | "zhihu" | "weishi" | "huya" | "haokan" | "meipai" | "twitter" | "instagram" | "doubao" | "doubao_chat" | "oasis" | "wechat_channel">;
|
|
157
161
|
apiUrl: Schema<string, string>;
|
|
158
162
|
apiKey: Schema<string, string>;
|
|
159
163
|
authHeaderType: Schema<"Bearer" | "X-API-Key" | "Custom", "Bearer" | "X-API-Key" | "Custom">;
|
package/lib/index.js
CHANGED
|
@@ -76,7 +76,7 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
76
76
|
debug: koishi_1.Schema.boolean().default(false).description('开启调试模式,在控制台输出详细日志'),
|
|
77
77
|
}).description('基础设置'),
|
|
78
78
|
koishi_1.Schema.object({
|
|
79
|
-
unifiedMessageFormat: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}\n点赞:${点赞数}\n收藏:${收藏数}\n转发:${转发数}\n播放:${播放数}\n评论:${评论数}\n图片数量:${图片数量}').description('统一消息格式,可用变量:${标题} ${作者} ${简介} ${点赞数} ${收藏数} ${转发数} ${播放数} ${评论数} ${视频时长} ${发布时间} ${图片数量} ${作者ID} ${
|
|
79
|
+
unifiedMessageFormat: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}\n点赞:${点赞数}\n收藏:${收藏数}\n转发:${转发数}\n播放:${播放数}\n评论:${评论数}\n图片数量:${图片数量}').description('统一消息格式,可用变量:${标题} ${作者} ${简介} ${点赞数} ${收藏数} ${转发数} ${播放数} ${评论数} ${视频时长} ${发布时间} ${图片数量} ${作者ID} ${音乐标题} ${音乐作者} ${音乐封面} ${音乐链接}'),
|
|
80
80
|
}).description('消息格式设置'),
|
|
81
81
|
koishi_1.Schema.object({
|
|
82
82
|
showImageText: koishi_1.Schema.boolean().default(true).description('是否发送解析后的文字内容'),
|
|
@@ -94,14 +94,18 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
94
94
|
videoSendTimeout: koishi_1.Schema.number().min(0).step(1).default(60000).description('视频消息发送超时(毫秒,0 为不限制)'),
|
|
95
95
|
userAgent: koishi_1.Schema.string().default('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36').description('API 请求 UA'),
|
|
96
96
|
proxy: koishi_1.Schema.object({
|
|
97
|
-
|
|
97
|
+
enabled: koishi_1.Schema.boolean().default(false).description('是否启用 HTTP/HTTPS 代理'),
|
|
98
|
+
protocol: koishi_1.Schema.union([
|
|
99
|
+
koishi_1.Schema.const('http').description('HTTP'),
|
|
100
|
+
koishi_1.Schema.const('https').description('HTTPS'),
|
|
101
|
+
]).default('http').description('代理协议'),
|
|
98
102
|
host: koishi_1.Schema.string().default('127.0.0.1').description('代理地址'),
|
|
99
103
|
port: koishi_1.Schema.number().default(7890).description('代理端口'),
|
|
100
104
|
auth: koishi_1.Schema.object({
|
|
101
105
|
username: koishi_1.Schema.string().default('').description('代理用户名'),
|
|
102
106
|
password: koishi_1.Schema.string().default('').description('代理密码'),
|
|
103
107
|
}).description('代理认证'),
|
|
104
|
-
}).description('HTTP
|
|
108
|
+
}).description('HTTP/HTTPS 代理设置(需开启 enabled)'),
|
|
105
109
|
customHeaders: koishi_1.Schema.array(koishi_1.Schema.object({
|
|
106
110
|
name: koishi_1.Schema.string().required().description('请求头名称'),
|
|
107
111
|
value: koishi_1.Schema.string().required().description('请求头值'),
|
|
@@ -140,6 +144,7 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
140
144
|
twitter: koishi_1.Schema.boolean().default(false).description('Twitter/X - 优先使用专属 API'),
|
|
141
145
|
instagram: koishi_1.Schema.boolean().default(false).description('Instagram - 优先使用专属 API'),
|
|
142
146
|
doubao: koishi_1.Schema.boolean().default(false).description('豆包 - 优先使用专属 API'),
|
|
147
|
+
doubao_chat: koishi_1.Schema.boolean().default(false).description('豆包图片 - 优先使用专属 API'),
|
|
143
148
|
oasis: koishi_1.Schema.boolean().default(false).description('绿洲 - 优先使用专属 API'),
|
|
144
149
|
wechat_channel: koishi_1.Schema.boolean().default(false).description('视频号 - 优先使用专属 API'),
|
|
145
150
|
}).description('各平台独立开关:是否优先使用专属 API'),
|
|
@@ -162,6 +167,7 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
162
167
|
koishi_1.Schema.const('twitter').description('Twitter/X'),
|
|
163
168
|
koishi_1.Schema.const('instagram').description('Instagram'),
|
|
164
169
|
koishi_1.Schema.const('doubao').description('豆包'),
|
|
170
|
+
koishi_1.Schema.const('doubao_chat').description('豆包图片'),
|
|
165
171
|
koishi_1.Schema.const('oasis').description('绿洲'),
|
|
166
172
|
koishi_1.Schema.const('wechat_channel').description('视频号'),
|
|
167
173
|
]).description('选择平台'),
|
|
@@ -175,7 +181,29 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
175
181
|
customHeaderName: koishi_1.Schema.string().description('自定义 Header 名称(仅当选择 Custom 时有效)').default('X-API-Key'),
|
|
176
182
|
fieldMapping: koishi_1.Schema.string().role('textarea').default('{}').description('字段映射 JSON,例如 {"title":"data.info.name"},支持点号路径'),
|
|
177
183
|
})).default([]).description('自定义平台专属 API 地址,留空则使用内置默认专属 API'),
|
|
178
|
-
globalFieldMapping: koishi_1.Schema.string().role('textarea').default('{
|
|
184
|
+
globalFieldMapping: koishi_1.Schema.string().role('textarea').default('{\n' +
|
|
185
|
+
' "title": "data.title",\n' +
|
|
186
|
+
' "desc": "data.description",\n' +
|
|
187
|
+
' "author": "data.author.name",\n' +
|
|
188
|
+
' "uid": "data.author.id",\n' +
|
|
189
|
+
' "avatar": "data.author.avatar",\n' +
|
|
190
|
+
' "cover": "data.cover_url",\n' +
|
|
191
|
+
' "video": "data.video_url",\n' +
|
|
192
|
+
' "video_backup": "data.video_qualities",\n' +
|
|
193
|
+
' "videos": "data.videos",\n' +
|
|
194
|
+
' "type": "data.type",\n' +
|
|
195
|
+
' "like": "data.statistics.likes",\n' +
|
|
196
|
+
' "comment": "data.statistics.comments",\n' +
|
|
197
|
+
' "collect": "data.statistics.favorites",\n' +
|
|
198
|
+
' "share": "data.statistics.shares",\n' +
|
|
199
|
+
' "play": "data.statistics.plays",\n' +
|
|
200
|
+
' "duration": "data.duration",\n' +
|
|
201
|
+
' "publishTime": "data.create_time",\n' +
|
|
202
|
+
' "music_title": "data.music.title",\n' +
|
|
203
|
+
' "music_author": "data.music.author",\n' +
|
|
204
|
+
' "music_cover": "data.music.cover",\n' +
|
|
205
|
+
' "music_url": "data.music.url"\n' +
|
|
206
|
+
'}').description('全局字段映射 JSON,优先级低于专属 API 映射'),
|
|
179
207
|
}).description('API 选择设置'),
|
|
180
208
|
koishi_1.Schema.object({
|
|
181
209
|
waitingTipText: koishi_1.Schema.string().default('正在解析视频,请稍候...').description('解析等待提示文字'),
|
|
@@ -219,6 +247,7 @@ const LINK_RULES = [
|
|
|
219
247
|
{ pattern: /https?:\/\/x\.com\/\w+\/status\/\d{10,}/gi, type: 'twitter' },
|
|
220
248
|
{ pattern: /https?:\/\/(?:www\.)?instagram\.com\/p\/[0-9a-zA-Z_-]{10,}/gi, type: 'instagram' },
|
|
221
249
|
{ pattern: /https?:\/\/(?:www\.)?doubao\.com\/video\/\d{10,}/gi, type: 'doubao' },
|
|
250
|
+
{ pattern: /https?:\/\/(?:www\.)?doubao\.com\/thread\/[0-9a-zA-Z_-]+/gi, type: 'doubao_chat' },
|
|
222
251
|
{ pattern: /https?:\/\/(?:www\.)?oasis\.weibo\.com\/v\/[0-9a-zA-Z_-]+/gi, type: 'oasis' },
|
|
223
252
|
{ pattern: /https?:\/\/channels\.weixin\.qq\.com\/[0-9a-zA-Z_-]+/gi, type: 'wechat_channel' },
|
|
224
253
|
{ pattern: /https?:\/\/weixin\.qq\.com\/sph\/[0-9a-zA-Z_-]+/gi, type: 'wechat_channel' },
|
|
@@ -342,6 +371,23 @@ function getNestedValue(obj, path) {
|
|
|
342
371
|
}
|
|
343
372
|
return current;
|
|
344
373
|
}
|
|
374
|
+
function parseCount(val) {
|
|
375
|
+
if (val === undefined || val === null)
|
|
376
|
+
return 0;
|
|
377
|
+
if (typeof val === 'number')
|
|
378
|
+
return val;
|
|
379
|
+
const str = String(val).trim();
|
|
380
|
+
if (str.includes('万')) {
|
|
381
|
+
const num = parseFloat(str);
|
|
382
|
+
return isNaN(num) ? 0 : Math.round(num * 10000);
|
|
383
|
+
}
|
|
384
|
+
if (str.includes('亿')) {
|
|
385
|
+
const num = parseFloat(str);
|
|
386
|
+
return isNaN(num) ? 0 : Math.round(num * 100000000);
|
|
387
|
+
}
|
|
388
|
+
const num = parseInt(str, 10);
|
|
389
|
+
return isNaN(num) ? 0 : num;
|
|
390
|
+
}
|
|
345
391
|
function parseApiResponse(raw, maxDescLen, fieldMapping) {
|
|
346
392
|
debugLog('DEBUG', 'API raw response', raw);
|
|
347
393
|
const data = raw?.data || {};
|
|
@@ -355,7 +401,7 @@ function parseApiResponse(raw, maxDescLen, fieldMapping) {
|
|
|
355
401
|
return fallback();
|
|
356
402
|
};
|
|
357
403
|
let type = mapField('type', () => {
|
|
358
|
-
let t = data.type || '';
|
|
404
|
+
let t = data.type || data.videoType || '';
|
|
359
405
|
if (!t) {
|
|
360
406
|
if (data.images?.length > 0 && !data.url)
|
|
361
407
|
t = 'image';
|
|
@@ -368,16 +414,16 @@ function parseApiResponse(raw, maxDescLen, fieldMapping) {
|
|
|
368
414
|
}
|
|
369
415
|
return t;
|
|
370
416
|
});
|
|
371
|
-
|
|
417
|
+
let authorObj = mapField('author', () => data.author || data.user);
|
|
372
418
|
let author = '', uid = '', avatar = '';
|
|
373
419
|
if (authorObj && typeof authorObj === 'object') {
|
|
374
420
|
author = authorObj.name || authorObj.author || '';
|
|
375
|
-
uid = String(authorObj.id || data.uid || '');
|
|
421
|
+
uid = String(authorObj.id || authorObj.userID || data.uid || data.userID || data.author_id || '');
|
|
376
422
|
avatar = authorObj.avatar || data.avatar || '';
|
|
377
423
|
}
|
|
378
424
|
else {
|
|
379
425
|
author = mapField('author', () => data.author || data.auther || '');
|
|
380
|
-
uid = String(mapField('uid', () => data.uid || ''));
|
|
426
|
+
uid = String(mapField('uid', () => data.uid || data.userID || data.author_id || ''));
|
|
381
427
|
avatar = mapField('avatar', () => data.avatar || '');
|
|
382
428
|
}
|
|
383
429
|
const title = mapField('title', () => data.title || '');
|
|
@@ -402,37 +448,53 @@ function parseApiResponse(raw, maxDescLen, fieldMapping) {
|
|
|
402
448
|
}
|
|
403
449
|
}
|
|
404
450
|
}
|
|
451
|
+
if (!video && data.quality_urls && typeof data.quality_urls === 'object') {
|
|
452
|
+
const entries = Object.entries(data.quality_urls);
|
|
453
|
+
videos = entries.map(([label, url]) => ({ quality: label, url: String(url) }));
|
|
454
|
+
if (videos.length)
|
|
455
|
+
video = videos[0].url;
|
|
456
|
+
}
|
|
405
457
|
if (!video)
|
|
406
458
|
video = mapField('video', () => data.url || '');
|
|
407
459
|
if (video && !video.startsWith('http'))
|
|
408
460
|
video = 'https:' + video;
|
|
409
|
-
|
|
461
|
+
let images = [];
|
|
462
|
+
const directImages = mapField('images', () => data.images);
|
|
463
|
+
if (Array.isArray(directImages)) {
|
|
464
|
+
images = directImages.filter((img) => img && typeof img === 'string').map((img) => img.startsWith('http') ? img : 'https:' + img);
|
|
465
|
+
}
|
|
466
|
+
else if (Array.isArray(data.imgurl)) {
|
|
467
|
+
images = data.imgurl.filter((img) => img && typeof img === 'string').map((img) => img.startsWith('http') ? img : 'https:' + img);
|
|
468
|
+
}
|
|
410
469
|
const live_photo = Array.isArray(data.live_photo) ? data.live_photo.filter((lp) => lp && lp.image).map((lp) => ({
|
|
411
470
|
image: lp.image.startsWith('http') ? lp.image : 'https:' + lp.image,
|
|
412
471
|
video: lp.video ? (lp.video.startsWith('http') ? lp.video : 'https:' + lp.video) : ''
|
|
413
472
|
})) : [];
|
|
473
|
+
const musicCoverRaw = mapField('music_cover', () => data.music?.cover || data.music?.albumCover?.url || '');
|
|
474
|
+
const musicUrlRaw = mapField('music_url', () => data.music?.url || data.music?.playURL || '');
|
|
414
475
|
const music = {
|
|
415
476
|
title: mapField('music_title', () => data.music?.title || data.music?.name || ''),
|
|
416
477
|
author: mapField('music_author', () => data.music?.author || data.music?.artist || ''),
|
|
417
|
-
cover:
|
|
418
|
-
url:
|
|
478
|
+
cover: musicCoverRaw ? (String(musicCoverRaw).startsWith('http') ? String(musicCoverRaw) : 'https:' + musicCoverRaw) : '',
|
|
479
|
+
url: musicUrlRaw ? (String(musicUrlRaw).startsWith('http') ? String(musicUrlRaw) : 'https:' + musicUrlRaw) : '',
|
|
419
480
|
};
|
|
420
|
-
const
|
|
421
|
-
const
|
|
422
|
-
const
|
|
423
|
-
const
|
|
424
|
-
const
|
|
425
|
-
const play = Number(mapField('play', () => data.play ?? stats.play_count ?? stats.view_count ?? stats.plays ?? 0));
|
|
481
|
+
const like = parseCount(mapField('like', () => data.like ?? data.statistics?.digg_count ?? data.statistics?.like_count ?? data.statistics?.likes ?? extra.statistics?.digg_count ?? extra.statistics?.like_count ?? extra.statistics?.likes ?? data.attitudes_count ?? 0));
|
|
482
|
+
const comment = parseCount(mapField('comment', () => data.comment ?? data.statistics?.comment_count ?? data.statistics?.comments ?? extra.statistics?.comment_count ?? extra.statistics?.comments ?? data.comments_count ?? 0));
|
|
483
|
+
const collect = parseCount(mapField('collect', () => data.collect ?? data.statistics?.collect_count ?? data.statistics?.favorite_count ?? data.statistics?.favorites ?? extra.statistics?.collect_count ?? extra.statistics?.favorite_count ?? extra.statistics?.favorites ?? data.favorites_count ?? 0));
|
|
484
|
+
const share = parseCount(mapField('share', () => data.share ?? data.statistics?.share_count ?? data.statistics?.forward_count ?? data.statistics?.shares ?? extra.statistics?.share_count ?? extra.statistics?.forward_count ?? extra.statistics?.shares ?? data.reposts_count ?? 0));
|
|
485
|
+
const play = parseCount(mapField('play', () => data.play ?? data.statistics?.play_count ?? data.statistics?.view_count ?? data.statistics?.plays ?? extra.statistics?.play_count ?? extra.statistics?.view_count ?? extra.statistics?.plays ?? data.play_count ?? data.view_count ?? 0));
|
|
426
486
|
let duration = 0;
|
|
427
|
-
|
|
428
|
-
if (durRaw) {
|
|
429
|
-
duration = typeof durRaw === 'string' ? parseInt(durRaw, 10) : Number(durRaw);
|
|
430
|
-
if (duration > 1000000)
|
|
431
|
-
duration = Math.floor(duration / 1000);
|
|
432
|
-
}
|
|
433
|
-
else if (extra.duration_ms) {
|
|
487
|
+
if (extra.duration_ms) {
|
|
434
488
|
duration = Math.floor(Number(extra.duration_ms) / 1000);
|
|
435
489
|
}
|
|
490
|
+
else {
|
|
491
|
+
const durRaw = mapField('duration', () => data.duration);
|
|
492
|
+
if (durRaw) {
|
|
493
|
+
duration = typeof durRaw === 'string' ? parseInt(durRaw, 10) : Number(durRaw);
|
|
494
|
+
if (duration > 3600)
|
|
495
|
+
duration = Math.floor(duration / 1000);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
436
498
|
let publishTime = 0;
|
|
437
499
|
const timeRaw = mapField('publishTime', () => data.time);
|
|
438
500
|
if (timeRaw) {
|
|
@@ -463,17 +525,32 @@ function generateFormattedText(p, format) {
|
|
|
463
525
|
'作者ID': p.uid,
|
|
464
526
|
'封面': p.cover,
|
|
465
527
|
'视频链接': p.video,
|
|
528
|
+
'音乐标题': p.music.title || '',
|
|
529
|
+
'音乐作者': p.music.author || '',
|
|
530
|
+
'音乐封面': p.music.cover || '',
|
|
531
|
+
'音乐链接': p.music.url || '',
|
|
466
532
|
};
|
|
467
533
|
const lines = format.split('\n');
|
|
468
534
|
const resultLines = [];
|
|
469
535
|
for (const line of lines) {
|
|
536
|
+
const varMatches = line.match(formatVarRegex);
|
|
537
|
+
if (varMatches && varMatches.length > 0) {
|
|
538
|
+
let allEmptyOrZero = true;
|
|
539
|
+
for (const match of varMatches) {
|
|
540
|
+
const varName = match.slice(2, -1);
|
|
541
|
+
const val = vars[varName];
|
|
542
|
+
if (val && val !== '0') {
|
|
543
|
+
allEmptyOrZero = false;
|
|
544
|
+
break;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
if (allEmptyOrZero)
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
470
550
|
let newLine = line;
|
|
471
551
|
for (const [key, val] of Object.entries(vars)) {
|
|
472
552
|
newLine = newLine.replace(new RegExp(`\\$\\{${key}\\}`, 'g'), val);
|
|
473
553
|
}
|
|
474
|
-
const stripped = newLine.replace(/[\s::,,。.、;;!!??【】\[\]「」『』()()《》""''""·—\-_/\\|@#$%^&*+=~`]/g, '').trim();
|
|
475
|
-
if (stripped.length === 0)
|
|
476
|
-
continue;
|
|
477
554
|
resultLines.push(newLine);
|
|
478
555
|
}
|
|
479
556
|
return resultLines.join('\n').trim();
|
|
@@ -531,7 +608,7 @@ function apply(ctx, config) {
|
|
|
531
608
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
532
609
|
}
|
|
533
610
|
};
|
|
534
|
-
if (proxyConfig.host) {
|
|
611
|
+
if (proxyConfig.enabled && proxyConfig.host) {
|
|
535
612
|
axiosConfig.proxy = {
|
|
536
613
|
protocol: proxyConfig.protocol || 'http',
|
|
537
614
|
host: proxyConfig.host,
|
|
@@ -547,6 +624,7 @@ function apply(ctx, config) {
|
|
|
547
624
|
bilibili: 'https://api.bugpk.com/api/bilibili',
|
|
548
625
|
douyin: 'https://api.bugpk.com/api/douyin',
|
|
549
626
|
doubao: 'https://api.bugpk.com/api/dbvideos',
|
|
627
|
+
doubao_chat: 'https://api.bugpk.com/api/dbduihua',
|
|
550
628
|
kuaishou: 'https://api.bugpk.com/api/kuaishou',
|
|
551
629
|
xiaohongshu: 'https://api.bugpk.com/api/xhs',
|
|
552
630
|
jimeng: 'https://api.bugpk.com/api/jimengai',
|
|
@@ -712,7 +790,7 @@ function apply(ctx, config) {
|
|
|
712
790
|
for (const candidate of candidates) {
|
|
713
791
|
try {
|
|
714
792
|
const info = await fetchApi(candidate, type, fieldMapping);
|
|
715
|
-
if (info.video || info.images.length > 0)
|
|
793
|
+
if (info.video || info.images.length > 0 || info.live_photo.length > 0)
|
|
716
794
|
return { success: true, data: info };
|
|
717
795
|
debugLog('WARN', `解析成功但无内容: ${candidate}`);
|
|
718
796
|
}
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -31,15 +31,7 @@ This is a **multi-platform video/image parsing plugin** developed for the Koishi
|
|
|
31
31
|
### 统一消息格式 (Unified Message Format)
|
|
32
32
|
| 配置项 | 类型 | 默认值 | 说明 |
|
|
33
33
|
|--------|------|--------|------|
|
|
34
|
-
| `unifiedMessageFormat` | string | `标题:${标题}
|
|
35
|
-
作者:${作者}
|
|
36
|
-
简介:${简介}
|
|
37
|
-
点赞:${点赞数}
|
|
38
|
-
收藏:${收藏数}
|
|
39
|
-
转发:${转发数}
|
|
40
|
-
播放:${播放数}
|
|
41
|
-
评论:${评论数}
|
|
42
|
-
图片数量:${图片数量}` | 自定义解析结果的输出格式,支持变量替换。某行所有变量均为空(或为"0")时自动隐藏该行 |
|
|
34
|
+
| `unifiedMessageFormat` | string | `标题:${标题}\n作者:${作者}\n简介:${简介}\n点赞:${点赞数}\n收藏:${收藏数}\n转发:${转发数}\n播放:${播放数}\n评论:${评论数}\n图片数量:${图片数量}` | 自定义解析结果的输出格式,支持变量替换。某行所有变量均为空(或为"0")时自动隐藏该行 |
|
|
43
35
|
|
|
44
36
|
### 内容显示设置 (Content Display Settings)
|
|
45
37
|
| 配置项 | 类型 | 默认值 | 说明 |
|
|
@@ -60,7 +52,7 @@ This is a **multi-platform video/image parsing plugin** developed for the Koishi
|
|
|
60
52
|
| `timeout` | number | 180000 | API 请求超时时间(毫秒) |
|
|
61
53
|
| `videoSendTimeout` | number | 60000 | 视频消息发送超时时间(毫秒,0 为不限制) |
|
|
62
54
|
| `userAgent` | string | `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36` | API 请求使用的 User-Agent |
|
|
63
|
-
| `proxy` | object | `{ protocol: "http", host: "127.0.0.1", port: 7890, auth: { username: "", password: "" } }` | HTTP
|
|
55
|
+
| `proxy` | object | `{ enabled: false, protocol: "http", host: "127.0.0.1", port: 7890, auth: { username: "", password: "" } }` | HTTP/HTTPS 代理设置。`enabled` 开关(默认关闭),`protocol` 下拉选择 `http` 或 `https`。需开启 `enabled` 并填写 `host` 后生效 |
|
|
64
56
|
| `customHeaders` | array | [] | 自定义请求头,会附加到所有 API 请求中。每项包含 `name`(头名称)和 `value`(头值) |
|
|
65
57
|
|
|
66
58
|
### API 选择与回退设置 (API Selection & Fallback)
|
|
@@ -68,9 +60,9 @@ This is a **multi-platform video/image parsing plugin** developed for the Koishi
|
|
|
68
60
|
|--------|------|--------|------|
|
|
69
61
|
| `primaryApiUrl` | string | `https://api.bugpk.com/api/short_videos` | 主 API 地址,解析时优先使用 |
|
|
70
62
|
| `backupApiUrl` | string | `https://api.bugpk.com/api/svparse` | 备用主 API 地址,仅支持抖音、小红书、Instagram、即梦平台解析 |
|
|
71
|
-
| `platformDedicatedFirst` | object | 各平台均为 `false` | 各平台独立开关:是否优先使用平台专属 API。对象键为平台标识(英文),值为布尔值。支持的键:`bilibili`、`douyin`、`kuaishou`、`xiaohongshu`、`weibo`、`xigua`、`youtube`、`tiktok`、`acfun`、`zhihu`、`weishi`、`huya`、`haokan`、`meipai`、`twitter`、`instagram`、`doubao`、`oasis`、`wechat_channel` |
|
|
63
|
+
| `platformDedicatedFirst` | object | 各平台均为 `false` | 各平台独立开关:是否优先使用平台专属 API。对象键为平台标识(英文),值为布尔值。支持的键:`bilibili`、`douyin`、`kuaishou`、`xiaohongshu`、`weibo`、`xigua`、`youtube`、`tiktok`、`acfun`、`zhihu`、`weishi`、`huya`、`haokan`、`meipai`、`twitter`、`instagram`、`doubao`、`doubao_chat`、`oasis`、`wechat_channel` |
|
|
72
64
|
| `customApis` | array | [] | 自定义平台专属 API 列表。每项包含:`platform`(平台类型)、`apiUrl`(API 地址)、`apiKey`(API Key,可选)、`authHeaderType`(认证头类型,可选:`Bearer` / `X-API-Key` / `Custom`)、`customHeaderName`(自定义 Header 名称,仅当 `authHeaderType` 为 `Custom` 时有效)、`fieldMapping`(字段映射 JSON 字符串,用于适配非标准 API 响应,支持点号路径) |
|
|
73
|
-
| `globalFieldMapping` | string |
|
|
65
|
+
| `globalFieldMapping` | string | 预设完整字段映射JSON(见下方示例) | 全局字段映射 JSON,优先级低于专属 API 映射。用于统一适配所有平台的 API 响应格式,默认已包含常用路径示例 |
|
|
74
66
|
|
|
75
67
|
### 错误与重试设置 (Error & Retry Settings)
|
|
76
68
|
| 配置项 | 类型 | 默认值 | 说明 |
|
|
@@ -116,8 +108,11 @@ This is a **multi-platform video/image parsing plugin** developed for the Koishi
|
|
|
116
108
|
| `${发布时间}` | 发布时间(格式化) | 所有平台 |
|
|
117
109
|
| `${图片数量}` | 图集/实况图片数量 | 图集/实况 |
|
|
118
110
|
| `${作者ID}` | 作者唯一标识ID | 部分平台 |
|
|
119
|
-
| `${封面}` | 封面图片地址 | 所有平台 |
|
|
120
111
|
| `${视频链接}` | 视频原始链接 | 视频 |
|
|
112
|
+
| `${音乐标题}` | 音乐标题 | 部分平台 |
|
|
113
|
+
| `${音乐作者}` | 音乐作者 | 部分平台 |
|
|
114
|
+
| `${音乐封面}` | 音乐封面图片地址 | 部分平台 |
|
|
115
|
+
| `${音乐链接}` | 音乐原始链接 | 部分平台 |
|
|
121
116
|
|
|
122
117
|
> 注:部分变量可能因平台API返回数据不同而显示为空,某行所有变量为空(或为"0")时该行会自动隐藏。
|
|
123
118
|
|
|
@@ -143,7 +138,8 @@ This is a **multi-platform video/image parsing plugin** developed for the Koishi
|
|
|
143
138
|
| 全民直播 | quanmin (quanmin.tv) | 直播 |
|
|
144
139
|
| Twitter / X | twitter, x.com | 视频、图文 |
|
|
145
140
|
| Instagram | instagram, instagram.com | 图文、Reels |
|
|
146
|
-
| 豆包 | doubao (doubao.com) | 视频 |
|
|
141
|
+
| 豆包 | doubao (doubao.com/video) | 视频 |
|
|
142
|
+
| 豆包图片 | doubao (doubao.com/thread) | 图片 |
|
|
147
143
|
| 皮皮搞笑 | pipigx, h5.pipigx.com | 短视频 |
|
|
148
144
|
| 皮皮虾 | pipixia, h5.pipix.com | 短视频 |
|
|
149
145
|
| 最右 | zuiyou, xiaochuankeji.cn | 短视频 |
|
|
@@ -158,6 +154,9 @@ This is a **multi-platform video/image parsing plugin** developed for the Koishi
|
|
|
158
154
|
|----------------------|-------------------------|
|
|
159
155
|
| Minecraft-1314 | 插件完整开发 (Complete plugin development) |
|
|
160
156
|
| ShiraiKuroko003 | 修复消息格式设置问题并且PR-1.2.5版本已修复 |
|
|
157
|
+
| cyavb | 提交功能建议-给自定义API添加KEY认证-已修复 |
|
|
158
|
+
| Keep785 | 提交Bug-无法正常关闭发送封面-已修复 |
|
|
159
|
+
| dzt2008 + Apricityx | 提交Bug-会对非支持视频平台URL进行误解析-已修复 |
|
|
161
160
|
| JH-Ahua | BugPk-Api 支持 |
|
|
162
161
|
| shangxue | 灵感来源 |
|
|
163
162
|
|