koishi-plugin-video-parser-all 0.4.4 → 0.4.5
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 +2 -0
- package/lib/index.js +81 -36
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Schema, Dict } from 'koishi';
|
|
|
2
2
|
export declare const name = "video-parser-all";
|
|
3
3
|
export declare const Config: Schema<{
|
|
4
4
|
enable?: boolean | null | undefined;
|
|
5
|
+
autoParse?: boolean | null | undefined;
|
|
5
6
|
botName?: string | null | undefined;
|
|
6
7
|
showWaitingTip?: boolean | null | undefined;
|
|
7
8
|
waitingTipText?: string | null | undefined;
|
|
@@ -72,6 +73,7 @@ export declare const Config: Schema<{
|
|
|
72
73
|
} & Dict) | null | undefined;
|
|
73
74
|
}, {
|
|
74
75
|
enable: boolean;
|
|
76
|
+
autoParse: boolean;
|
|
75
77
|
botName: string;
|
|
76
78
|
showWaitingTip: boolean;
|
|
77
79
|
waitingTipText: string;
|
package/lib/index.js
CHANGED
|
@@ -12,10 +12,33 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
12
12
|
const path_1 = __importDefault(require("path"));
|
|
13
13
|
const promises_1 = require("stream/promises");
|
|
14
14
|
const worker_threads_1 = require("worker_threads");
|
|
15
|
+
// 先定义 API_CONFIG,以便在 Config 中使用
|
|
16
|
+
const API_CONFIG = {
|
|
17
|
+
universal: 'https://api.bugpk.com/api/short_videos ',
|
|
18
|
+
xingzhige: {
|
|
19
|
+
bilibili: { url: 'https://api.xingzhige.com/API/b_parse/ ', vidUrl: 'https://api.xingzhige.com/API/b_parse/ ', bangumiUrl: 'https://api.xingzhige.com/API/b_bangumi/ ' },
|
|
20
|
+
kuaishou: { url: 'https://api.xingzhige.com/API/kuaishou/ ' },
|
|
21
|
+
douyin: { url: 'https://api.xingzhige.com/API/douyin/ ' },
|
|
22
|
+
xigua: { url: 'https://api.xingzhige.com/API/xigua/ ' }
|
|
23
|
+
},
|
|
24
|
+
platform: {
|
|
25
|
+
bilibili: ['https://api.bugpk.com/api/bilibili '],
|
|
26
|
+
kuaishou: ['https://api.bugpk.com/api/ksjx ', 'https://api.bugpk.com/api/kuaishou ', 'https://api.bugpk.com/api/ksimg ', 'https://api.suyanw.cn/api/kuaishou.php '],
|
|
27
|
+
xiaohongshu: ['https://api.bugpk.com/api/xhsjx ', 'https://api.bugpk.com/api/xhsimg ', 'https://api.bugpk.com/api/xhslive '],
|
|
28
|
+
weibo: ['https://api.bugpk.com/api/weibo ', 'https://api.bugpk.com/api/weibo_v '],
|
|
29
|
+
toutiao: ['https://api.bugpk.com/api/toutiao '],
|
|
30
|
+
pipigx: ['https://api.bugpk.com/api/pipigx ', 'https://api.suyanw.cn/api/pipigx.php '],
|
|
31
|
+
pipixia: ['https://api.bugpk.com/api/pipixia '],
|
|
32
|
+
douyin: ['https://api.bugpk.com/api/douyin ', 'https://api.bugpk.com/api/dyjx ', 'https://api.bugpk.com/api/dylive '],
|
|
33
|
+
zuiyou: ['https://api.suyanw.cn/api/zuiyou.php '],
|
|
34
|
+
xigua: ['https://api.bugpk.com/api/toutiao ']
|
|
35
|
+
}
|
|
36
|
+
};
|
|
15
37
|
exports.name = 'video-parser-all';
|
|
16
38
|
exports.Config = koishi_1.Schema.intersect([
|
|
17
39
|
koishi_1.Schema.object({
|
|
18
40
|
enable: koishi_1.Schema.boolean().default(true).description('是否启用视频解析插件'),
|
|
41
|
+
autoParse: koishi_1.Schema.boolean().default(true).description('是否自动解析消息中的视频链接(关闭后需手动使用 parse 命令解析)'),
|
|
19
42
|
botName: koishi_1.Schema.string().default('视频解析机器人').description('机器人显示名称'),
|
|
20
43
|
showWaitingTip: koishi_1.Schema.boolean().default(true).description('解析时显示等待提示'),
|
|
21
44
|
waitingTipText: koishi_1.Schema.string().default('正在解析视频,请稍候...').description('等待提示文本内容'),
|
|
@@ -36,7 +59,7 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
36
59
|
pipigx: koishi_1.Schema.boolean().default(true).description('皮皮搞笑'),
|
|
37
60
|
pipixia: koishi_1.Schema.boolean().default(true).description('皮皮虾'),
|
|
38
61
|
zuiyou: koishi_1.Schema.boolean().default(true).description('最右'),
|
|
39
|
-
}).description('
|
|
62
|
+
}).description('平台开关')
|
|
40
63
|
}).description('平台开关'),
|
|
41
64
|
koishi_1.Schema.object({
|
|
42
65
|
platformFormat: koishi_1.Schema.object({
|
|
@@ -83,16 +106,51 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
83
106
|
}).description('缓存清理设置'),
|
|
84
107
|
koishi_1.Schema.object({
|
|
85
108
|
preferredApi: koishi_1.Schema.object({
|
|
86
|
-
bilibili: koishi_1.Schema.union([
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
109
|
+
bilibili: koishi_1.Schema.union([
|
|
110
|
+
'xingzhige',
|
|
111
|
+
'universal',
|
|
112
|
+
'platform',
|
|
113
|
+
'official'
|
|
114
|
+
]).default('xingzhige').description(`B站首选解析源\n平台内置API列表:\n${(API_CONFIG.platform.bilibili || []).map(url => url.trim()).join('\n')}`),
|
|
115
|
+
douyin: koishi_1.Schema.union([
|
|
116
|
+
'xingzhige',
|
|
117
|
+
'universal',
|
|
118
|
+
'platform'
|
|
119
|
+
]).default('xingzhige').description(`抖音首选解析源\n平台内置API列表:\n${(API_CONFIG.platform.douyin || []).map(url => url.trim()).join('\n')}`),
|
|
120
|
+
kuaishou: koishi_1.Schema.union([
|
|
121
|
+
'xingzhige',
|
|
122
|
+
'universal',
|
|
123
|
+
'platform'
|
|
124
|
+
]).default('xingzhige').description(`快手首选解析源\n平台内置API列表:\n${(API_CONFIG.platform.kuaishou || []).map(url => url.trim()).join('\n')}`),
|
|
125
|
+
xigua: koishi_1.Schema.union([
|
|
126
|
+
'xingzhige',
|
|
127
|
+
'universal',
|
|
128
|
+
'platform'
|
|
129
|
+
]).default('xingzhige').description(`西瓜视频首选解析源\n平台内置API列表:\n${(API_CONFIG.platform.xigua || []).map(url => url.trim()).join('\n')}`),
|
|
130
|
+
xiaohongshu: koishi_1.Schema.union([
|
|
131
|
+
'universal',
|
|
132
|
+
'platform'
|
|
133
|
+
]).default('universal').description(`小红书首选解析源\n平台内置API列表:\n${(API_CONFIG.platform.xiaohongshu || []).map(url => url.trim()).join('\n')}`),
|
|
134
|
+
weibo: koishi_1.Schema.union([
|
|
135
|
+
'universal',
|
|
136
|
+
'platform'
|
|
137
|
+
]).default('universal').description(`微博首选解析源\n平台内置API列表:\n${(API_CONFIG.platform.weibo || []).map(url => url.trim()).join('\n')}`),
|
|
138
|
+
toutiao: koishi_1.Schema.union([
|
|
139
|
+
'universal',
|
|
140
|
+
'platform'
|
|
141
|
+
]).default('universal').description(`今日头条首选解析源\n平台内置API列表:\n${(API_CONFIG.platform.toutiao || []).map(url => url.trim()).join('\n')}`),
|
|
142
|
+
pipigx: koishi_1.Schema.union([
|
|
143
|
+
'universal',
|
|
144
|
+
'platform'
|
|
145
|
+
]).default('universal').description(`皮皮搞笑首选解析源\n平台内置API列表:\n${(API_CONFIG.platform.pipigx || []).map(url => url.trim()).join('\n')}`),
|
|
146
|
+
pipixia: koishi_1.Schema.union([
|
|
147
|
+
'universal',
|
|
148
|
+
'platform'
|
|
149
|
+
]).default('universal').description(`皮皮虾首选解析源\n平台内置API列表:\n${(API_CONFIG.platform.pipixia || []).map(url => url.trim()).join('\n')}`),
|
|
150
|
+
zuiyou: koishi_1.Schema.union([
|
|
151
|
+
'universal',
|
|
152
|
+
'platform'
|
|
153
|
+
]).default('universal').description(`最右首选解析源\n平台内置API列表:\n${(API_CONFIG.platform.zuiyou || []).map(url => url.trim()).join('\n')}`),
|
|
96
154
|
}).description('首选解析源设置(将优先尝试用户选择的API,失败后自动尝试其他)')
|
|
97
155
|
}).description('API选择设置'),
|
|
98
156
|
]);
|
|
@@ -161,27 +219,6 @@ const PLATFORM_KEYWORDS = {
|
|
|
161
219
|
xigua: ['ixigua', '西瓜视频', 'xigua.com', '699pic.com', 'ixigua.com/video', 'ixigua.com/album'],
|
|
162
220
|
universal_card: ['mini_program', '小程序卡片', 'lightapp', 'json', 'markdown', 'share', 'contact', 'location', 'music', 'forward', 'node', 'mface', 'file']
|
|
163
221
|
};
|
|
164
|
-
const API_CONFIG = {
|
|
165
|
-
universal: 'https://api.bugpk.com/api/short_videos ',
|
|
166
|
-
xingzhige: {
|
|
167
|
-
bilibili: { url: 'https://api.xingzhige.com/API/b_parse/ ', vidUrl: 'https://api.xingzhige.com/API/b_parse/ ', bangumiUrl: 'https://api.xingzhige.com/API/b_bangumi/ ' },
|
|
168
|
-
kuaishou: { url: 'https://api.xingzhige.com/API/kuaishou/ ' },
|
|
169
|
-
douyin: { url: 'https://api.xingzhige.com/API/douyin/ ' },
|
|
170
|
-
xigua: { url: 'https://api.xingzhige.com/API/xigua/ ' }
|
|
171
|
-
},
|
|
172
|
-
platform: {
|
|
173
|
-
bilibili: ['https://api.bugpk.com/api/bilibili '],
|
|
174
|
-
kuaishou: ['https://api.bugpk.com/api/ksjx ', 'https://api.bugpk.com/api/kuaishou ', 'https://api.bugpk.com/api/ksimg ', 'https://api.suyanw.cn/api/kuaishou.php '],
|
|
175
|
-
xiaohongshu: ['https://api.bugpk.com/api/xhsjx ', 'https://api.bugpk.com/api/xhsimg ', 'https://api.bugpk.com/api/xhslive '],
|
|
176
|
-
weibo: ['https://api.bugpk.com/api/weibo ', 'https://api.bugpk.com/api/weibo_v '],
|
|
177
|
-
toutiao: ['https://api.bugpk.com/api/toutiao '],
|
|
178
|
-
pipigx: ['https://api.bugpk.com/api/pipigx ', 'https://api.suyanw.cn/api/pipigx.php '],
|
|
179
|
-
pipixia: ['https://api.bugpk.com/api/pipixia '],
|
|
180
|
-
douyin: ['https://api.bugpk.com/api/douyin ', 'https://api.bugpk.com/api/dyjx ', 'https://api.bugpk.com/api/dylive '],
|
|
181
|
-
zuiyou: ['https://api.suyanw.cn/api/zuiyou.php '],
|
|
182
|
-
xigua: ['https://api.bugpk.com/api/toutiao ']
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
222
|
function vid_type_parse(id) {
|
|
186
223
|
const idRegex = [
|
|
187
224
|
{ pattern: /av([0-9]+)/i, type: "av" },
|
|
@@ -516,6 +553,9 @@ function parseData(data, maxDescLength, platform) {
|
|
|
516
553
|
let type = data.type || 'video';
|
|
517
554
|
let title = data.title || data.desc || '无标题';
|
|
518
555
|
let author = data.author || data.name || '未知作者';
|
|
556
|
+
if (author && typeof author === 'object') {
|
|
557
|
+
author = author.name || author.nickname || author.username || '未知作者';
|
|
558
|
+
}
|
|
519
559
|
let desc = (data.desc || data.description || title).slice(0, maxDescLength);
|
|
520
560
|
let cover = data.cover || data.imgurl || data.pic || data.fm || '';
|
|
521
561
|
let images = data.images || [];
|
|
@@ -631,7 +671,6 @@ function apply(ctx, config) {
|
|
|
631
671
|
}
|
|
632
672
|
if (platform === 'bilibili') {
|
|
633
673
|
const preferred = config.preferredApi?.bilibili || 'xingzhige';
|
|
634
|
-
// 根据首选源构建尝试顺序
|
|
635
674
|
const tryOrder = [];
|
|
636
675
|
if (preferred === 'xingzhige') {
|
|
637
676
|
tryOrder.push('xingzhige_vid', 'xingzhige_bangumi', 'universal', 'official', 'platform');
|
|
@@ -1225,7 +1264,6 @@ function apply(ctx, config) {
|
|
|
1225
1264
|
}
|
|
1226
1265
|
return { data: null, msg: '解析失败,请稍后重试' };
|
|
1227
1266
|
}
|
|
1228
|
-
// 其他平台(不应该走到这里)
|
|
1229
1267
|
return { data: null, msg: '未知平台' };
|
|
1230
1268
|
}
|
|
1231
1269
|
async function processSingleUrl(session, url) {
|
|
@@ -1266,7 +1304,7 @@ function apply(ctx, config) {
|
|
|
1266
1304
|
async function flush(session, manualUrls) {
|
|
1267
1305
|
const key = `${session.platform}:${session.userId}:${session.channelId}`;
|
|
1268
1306
|
const buffer = linkBuffer.get(key);
|
|
1269
|
-
const urls = manualUrls || buffer?.urls || [];
|
|
1307
|
+
const urls = [...new Set(manualUrls || buffer?.urls || [])];
|
|
1270
1308
|
if (buffer) {
|
|
1271
1309
|
clearTimeout(buffer.timer);
|
|
1272
1310
|
linkBuffer.delete(key);
|
|
@@ -1278,7 +1316,7 @@ function apply(ctx, config) {
|
|
|
1278
1316
|
if (result.data) {
|
|
1279
1317
|
items.push(result.data);
|
|
1280
1318
|
}
|
|
1281
|
-
else {
|
|
1319
|
+
else if (result.msg !== '请勿重复解析') {
|
|
1282
1320
|
errs.push(`【${url.slice(0, 22)}...】:${result.msg}`);
|
|
1283
1321
|
if (config.debug) {
|
|
1284
1322
|
ctx.logger.debug(`解析失败: ${url}, 原因: ${result.msg}`);
|
|
@@ -1287,6 +1325,10 @@ function apply(ctx, config) {
|
|
|
1287
1325
|
ctx.logger.error(`解析失败: ${url}, 原因: ${result.msg}`);
|
|
1288
1326
|
}
|
|
1289
1327
|
}
|
|
1328
|
+
else {
|
|
1329
|
+
if (config.debug)
|
|
1330
|
+
ctx.logger.debug(`忽略重复解析: ${url}`);
|
|
1331
|
+
}
|
|
1290
1332
|
}
|
|
1291
1333
|
if (errs.length) {
|
|
1292
1334
|
ctx.logger.error(`解析失败数量: ${errs.length}, 示例: ${errs[0]}`);
|
|
@@ -1425,6 +1467,8 @@ function apply(ctx, config) {
|
|
|
1425
1467
|
ctx.on('message', async (session) => {
|
|
1426
1468
|
if (!config.enable)
|
|
1427
1469
|
return;
|
|
1470
|
+
if (!config.autoParse)
|
|
1471
|
+
return;
|
|
1428
1472
|
const content = session.content.trim();
|
|
1429
1473
|
let urls = extractUrl(content);
|
|
1430
1474
|
if (urls.length === 0 && hasPlatformKeyword(content)) {
|
|
@@ -1434,6 +1478,7 @@ function apply(ctx, config) {
|
|
|
1434
1478
|
if (urls.length === 0)
|
|
1435
1479
|
return;
|
|
1436
1480
|
const key = `${session.platform}:${session.userId}:${session.channelId}`;
|
|
1481
|
+
urls = [...new Set(urls)];
|
|
1437
1482
|
if (linkBuffer.has(key)) {
|
|
1438
1483
|
const buffer = linkBuffer.get(key);
|
|
1439
1484
|
const newUrls = urls.filter(url => !buffer.urls.includes(url));
|
package/package.json
CHANGED