koishi-plugin-video-parser-all 1.4.7 → 1.4.9
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 +18 -15
- package/lib/index.js +111 -38
- package/package.json +1 -1
- package/readme.md +18 -9
package/lib/index.d.ts
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
import { Context, Schema } from 'koishi';
|
|
2
|
-
declare module 'koishi' {
|
|
3
|
-
interface Context {
|
|
4
|
-
downloads?: {
|
|
5
|
-
download(url: string, dest: string, options?: Record<string, unknown>): Promise<string>;
|
|
6
|
-
};
|
|
7
|
-
aria2?: any;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
2
|
export declare const name = "video-parser-all";
|
|
11
3
|
export declare const Config: Schema<{
|
|
12
4
|
enable?: boolean | null | undefined;
|
|
@@ -45,10 +37,17 @@ export declare const Config: Schema<{
|
|
|
45
37
|
} & {
|
|
46
38
|
showImageText?: boolean | null | undefined;
|
|
47
39
|
showCoverImage?: boolean | null | undefined;
|
|
40
|
+
showCoverFile?: boolean | null | undefined;
|
|
41
|
+
showImageFileNew?: boolean | null | undefined;
|
|
42
|
+
showAuthorAvatar?: boolean | null | undefined;
|
|
43
|
+
showAuthorAvatarFile?: boolean | null | undefined;
|
|
44
|
+
showAuthorAvatarText?: boolean | null | undefined;
|
|
45
|
+
authorAvatarText?: string | null | undefined;
|
|
48
46
|
showMusicCover?: boolean | null | undefined;
|
|
49
|
-
showImageFile?: boolean | null | undefined;
|
|
50
47
|
showVideoFile?: boolean | null | undefined;
|
|
51
|
-
|
|
48
|
+
forceDownloadCover?: boolean | null | undefined;
|
|
49
|
+
forceDownloadImageNew?: boolean | null | undefined;
|
|
50
|
+
forceDownloadAuthorAvatar?: boolean | null | undefined;
|
|
52
51
|
forceDownloadVideo?: boolean | null | undefined;
|
|
53
52
|
} & {
|
|
54
53
|
showMusicVoice?: boolean | null | undefined;
|
|
@@ -190,10 +189,17 @@ export declare const Config: Schema<{
|
|
|
190
189
|
} & {
|
|
191
190
|
showImageText: boolean;
|
|
192
191
|
showCoverImage: boolean;
|
|
192
|
+
showCoverFile: boolean;
|
|
193
|
+
showImageFileNew: boolean;
|
|
194
|
+
showAuthorAvatar: boolean;
|
|
195
|
+
showAuthorAvatarFile: boolean;
|
|
196
|
+
showAuthorAvatarText: boolean;
|
|
197
|
+
authorAvatarText: string;
|
|
193
198
|
showMusicCover: boolean;
|
|
194
|
-
showImageFile: boolean;
|
|
195
199
|
showVideoFile: boolean;
|
|
196
|
-
|
|
200
|
+
forceDownloadCover: boolean;
|
|
201
|
+
forceDownloadImageNew: boolean;
|
|
202
|
+
forceDownloadAuthorAvatar: boolean;
|
|
197
203
|
forceDownloadVideo: boolean;
|
|
198
204
|
} & {
|
|
199
205
|
showMusicVoice: boolean;
|
|
@@ -318,6 +324,3 @@ export declare const Config: Schema<{
|
|
|
318
324
|
parseErrorItemFormat: string;
|
|
319
325
|
}>;
|
|
320
326
|
export declare function apply(ctx: Context, config: any): void;
|
|
321
|
-
export declare namespace apply {
|
|
322
|
-
var inject: string[];
|
|
323
|
-
}
|
package/lib/index.js
CHANGED
|
@@ -103,15 +103,22 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
103
103
|
}).description('各平台解析开关'),
|
|
104
104
|
}).description('基本设置'),
|
|
105
105
|
koishi_1.Schema.object({
|
|
106
|
-
unifiedMessageFormat: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}\n音乐标题:${音乐标题}\n音乐作者:${音乐作者}\n点赞:${点赞数}\n收藏:${收藏数}\n转发:${转发数}\n播放:${播放数}\n评论:${评论数}\n图片数量:${图片数量}').description('
|
|
106
|
+
unifiedMessageFormat: koishi_1.Schema.string().role('textarea').default('标题:${标题}\n作者:${作者}\n简介:${简介}\n音乐标题:${音乐标题}\n音乐作者:${音乐作者}\n点赞:${点赞数}\n收藏:${收藏数}\n转发:${转发数}\n播放:${播放数}\n评论:${评论数}\n图片数量:${图片数量}').description('文字格式,支持变量:${标题} ${作者} ${author-name} ${简介} ${视频时长} ${点赞数} ${收藏数} ${转发数} ${播放数} ${评论数} ${发布时间} ${图片数量} ${作者ID} ${author-id} ${音乐标题} ${music-title} ${音乐作者} ${music-author},空行自动隐藏'),
|
|
107
107
|
}).description('消息格式'),
|
|
108
108
|
koishi_1.Schema.object({
|
|
109
109
|
showImageText: koishi_1.Schema.boolean().default(true).description('发送文字内容'),
|
|
110
110
|
showCoverImage: koishi_1.Schema.boolean().default(true).description('发送封面图片'),
|
|
111
|
+
showCoverFile: koishi_1.Schema.boolean().default(true).description('封面是否以图片形式发送(关闭则只发送链接)'),
|
|
112
|
+
showImageFileNew: koishi_1.Schema.boolean().default(true).description('图片是否以图片形式发送(关闭则只发送链接)'),
|
|
113
|
+
showAuthorAvatar: koishi_1.Schema.boolean().default(true).description('发送作者头像图片'),
|
|
114
|
+
showAuthorAvatarFile: koishi_1.Schema.boolean().default(true).description('作者头像图片是否以图片形式发送(关闭则只发送链接)'),
|
|
115
|
+
showAuthorAvatarText: koishi_1.Schema.boolean().default(true).description('发送作者头像前显示文字提示'),
|
|
116
|
+
authorAvatarText: koishi_1.Schema.string().default('作者头像:').description('作者头像前显示的文字'),
|
|
111
117
|
showMusicCover: koishi_1.Schema.boolean().default(true).description('发送音乐封面图片'),
|
|
112
|
-
showImageFile: koishi_1.Schema.boolean().default(true).description('封面/图片是否以图片形式发送(关闭则只发送链接)'),
|
|
113
118
|
showVideoFile: koishi_1.Schema.boolean().default(true).description('视频是否以视频形式发送(关闭则只发送链接)'),
|
|
114
|
-
|
|
119
|
+
forceDownloadCover: koishi_1.Schema.boolean().default(false).description('强制下载封面'),
|
|
120
|
+
forceDownloadImageNew: koishi_1.Schema.boolean().default(false).description('强制下载图片'),
|
|
121
|
+
forceDownloadAuthorAvatar: koishi_1.Schema.boolean().default(false).description('强制下载作者头像'),
|
|
115
122
|
forceDownloadVideo: koishi_1.Schema.boolean().default(false).description('强制下载视频'),
|
|
116
123
|
}).description('媒体发送'),
|
|
117
124
|
koishi_1.Schema.object({
|
|
@@ -543,8 +550,8 @@ function parseApiResponse(raw, maxDescLen, fieldMapping) {
|
|
|
543
550
|
uid = String(mapField('uid', () => data.uid || data.userID || data.author_id || ''));
|
|
544
551
|
avatar = mapField('avatar', () => data.avatar || '');
|
|
545
552
|
}
|
|
546
|
-
|
|
547
|
-
|
|
553
|
+
let title = mapField('title', () => data.title || '');
|
|
554
|
+
let desc = mapField('desc', () => data.desc || data.description || '').slice(0, maxDescLen).trim();
|
|
548
555
|
const coverRaw = mapField('cover', () => data.cover || '');
|
|
549
556
|
const cover = coverRaw ? (String(coverRaw).startsWith('http') ? String(coverRaw) : 'https:' + coverRaw) : '';
|
|
550
557
|
let video = '';
|
|
@@ -620,7 +627,19 @@ function parseApiResponse(raw, maxDescLen, fieldMapping) {
|
|
|
620
627
|
else if (extra.create_time) {
|
|
621
628
|
publishTime = Number(extra.create_time) * 1000;
|
|
622
629
|
}
|
|
623
|
-
|
|
630
|
+
const author_followers = parseCount(mapField('author_followers', () => extra.author_extra?.follower_count ?? data.author_extra?.follower_count ?? 0));
|
|
631
|
+
const author_signature = String(mapField('author_signature', () => extra.author_extra?.signature ?? data.author_extra?.signature ?? ''));
|
|
632
|
+
const admire = parseCount(mapField('admire', () => extra.statistics?.admire_count ?? data.statistics?.admire_count ?? 0));
|
|
633
|
+
title = title.replace(/\[话题\]/g, '');
|
|
634
|
+
desc = desc.replace(/\[话题\]/g, '');
|
|
635
|
+
if (title && desc && title.trim() === desc.trim()) {
|
|
636
|
+
desc = '';
|
|
637
|
+
}
|
|
638
|
+
if (title.trim().startsWith('#'))
|
|
639
|
+
title = '';
|
|
640
|
+
if (desc.trim().startsWith('#'))
|
|
641
|
+
desc = '';
|
|
642
|
+
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 };
|
|
624
643
|
}
|
|
625
644
|
const formatVarRegex = /\$\{([^}]+)\}/g;
|
|
626
645
|
function generateFormattedText(p, format) {
|
|
@@ -628,6 +647,7 @@ function generateFormattedText(p, format) {
|
|
|
628
647
|
const vars = {
|
|
629
648
|
'标题': p.title,
|
|
630
649
|
'作者': p.author,
|
|
650
|
+
'author-name': p.author,
|
|
631
651
|
'简介': p.desc,
|
|
632
652
|
'视频时长': p.duration > 0 ? formatDuration(p.duration) : '',
|
|
633
653
|
'点赞数': String(p.like),
|
|
@@ -638,10 +658,11 @@ function generateFormattedText(p, format) {
|
|
|
638
658
|
'发布时间': p.publishTime ? formatPublishTime(p.publishTime) : '',
|
|
639
659
|
'图片数量': String(imageCount),
|
|
640
660
|
'作者ID': p.uid,
|
|
641
|
-
'
|
|
661
|
+
'author-id': p.uid,
|
|
642
662
|
'音乐标题': p.music.title || '',
|
|
663
|
+
'music-title': p.music.title || '',
|
|
643
664
|
'音乐作者': p.music.author || '',
|
|
644
|
-
'
|
|
665
|
+
'music-author': p.music.author || '',
|
|
645
666
|
};
|
|
646
667
|
const varReplacements = Object.entries(vars).map(([key, val]) => ({
|
|
647
668
|
regex: new RegExp(`\\$\\{${key}\\}`, 'g'),
|
|
@@ -736,9 +757,14 @@ function apply(ctx, config) {
|
|
|
736
757
|
const mediaDownloadTimeout = config.mediaDownloadTimeout ?? 120000;
|
|
737
758
|
const maxMediaSize = config.maxMediaSize ?? 0;
|
|
738
759
|
const downloadEngine = config.downloadEngine || 'internal';
|
|
739
|
-
|
|
760
|
+
const aria2Service = ctx.get('aria2');
|
|
761
|
+
const downloadsService = ctx.get('downloads');
|
|
762
|
+
if (downloadEngine === 'aria2' && !aria2Service) {
|
|
740
763
|
logger.warn('选择了 aria2 下载引擎,但未检测到 koishi-plugin-aria2-plus 服务,将回退到内置下载');
|
|
741
764
|
}
|
|
765
|
+
if (downloadEngine === 'downloads' && !downloadsService) {
|
|
766
|
+
logger.warn('选择了 downloads 下载引擎,但未检测到 koishi-plugin-downloads 服务,将回退到内置下载');
|
|
767
|
+
}
|
|
742
768
|
function getPlatformConfig(type) {
|
|
743
769
|
if (type.startsWith('custom_')) {
|
|
744
770
|
const name = type.slice(7);
|
|
@@ -806,7 +832,7 @@ function apply(ctx, config) {
|
|
|
806
832
|
return {};
|
|
807
833
|
}
|
|
808
834
|
const extRegexCache = {};
|
|
809
|
-
async function downloadFile(url, timeout, maxSize, filePrefix, fileExts) {
|
|
835
|
+
async function downloadFile(url, timeout, maxSize, filePrefix, fileExts, onProgress) {
|
|
810
836
|
if (!url)
|
|
811
837
|
throw new Error('链接为空');
|
|
812
838
|
await promises_1.default.mkdir(cacheDir, { recursive: true });
|
|
@@ -816,26 +842,24 @@ function apply(ctx, config) {
|
|
|
816
842
|
}) || fileExts[0];
|
|
817
843
|
const fileName = `${filePrefix}_${Date.now()}_${(0, crypto_1.randomBytes)(4).toString('hex')}.${ext}`;
|
|
818
844
|
const filePath = path_1.default.resolve(cacheDir, fileName);
|
|
819
|
-
if (downloadEngine === 'downloads' &&
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
}
|
|
832
|
-
catch (e) {
|
|
833
|
-
debugLog('ERROR', `downloads 服务下载失败,回退内置下载: ${getErrorMessage(e)}`);
|
|
845
|
+
if (downloadEngine === 'downloads' && downloadsService) {
|
|
846
|
+
logger.info(`开始下载: ${url}`);
|
|
847
|
+
const dest = await downloadsService.download(url, path_1.default.join(cacheDir, fileName), {
|
|
848
|
+
headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' },
|
|
849
|
+
timeout
|
|
850
|
+
});
|
|
851
|
+
const stat = await promises_1.default.stat(dest);
|
|
852
|
+
const sizeMB = (stat.size / (1024 * 1024)).toFixed(2);
|
|
853
|
+
logger.info(`下载完成: ${dest} (${sizeMB} MB)`);
|
|
854
|
+
if (maxSize > 0 && stat.size > maxSize * 1024 * 1024) {
|
|
855
|
+
await promises_1.default.unlink(dest).catch(() => { });
|
|
856
|
+
throw new Error(`文件过大(${Math.round(stat.size / 1024 / 1024)}MB),超过限制(${maxSize}MB)`);
|
|
834
857
|
}
|
|
858
|
+
return dest;
|
|
835
859
|
}
|
|
836
|
-
|
|
860
|
+
if (downloadEngine === 'aria2' && aria2Service) {
|
|
837
861
|
try {
|
|
838
|
-
const gid = await
|
|
862
|
+
const gid = await aria2Service.addUri([url], {
|
|
839
863
|
dir: cacheDir,
|
|
840
864
|
out: fileName,
|
|
841
865
|
split: 4,
|
|
@@ -848,20 +872,31 @@ function apply(ctx, config) {
|
|
|
848
872
|
header: [`User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36`, `Referer: https://www.baidu.com/`]
|
|
849
873
|
});
|
|
850
874
|
let completed = false;
|
|
851
|
-
const
|
|
875
|
+
const startTime = Date.now();
|
|
876
|
+
let lastProgressTime = 0;
|
|
852
877
|
while (!completed) {
|
|
853
|
-
if (Date.now() -
|
|
854
|
-
await
|
|
878
|
+
if (Date.now() - startTime > timeout) {
|
|
879
|
+
await aria2Service.remove(gid).catch(() => { });
|
|
855
880
|
throw new Error('aria2下载超时');
|
|
856
881
|
}
|
|
857
|
-
const status = await
|
|
882
|
+
const status = await aria2Service.tellStatus(gid);
|
|
858
883
|
if (status.status === 'complete') {
|
|
859
884
|
completed = true;
|
|
885
|
+
if (onProgress)
|
|
886
|
+
onProgress(100, '');
|
|
860
887
|
}
|
|
861
888
|
else if (status.status === 'error' || status.status === 'removed') {
|
|
862
889
|
throw new Error('aria2下载失败');
|
|
863
890
|
}
|
|
864
891
|
else {
|
|
892
|
+
if (onProgress && Date.now() - lastProgressTime > 500) {
|
|
893
|
+
lastProgressTime = Date.now();
|
|
894
|
+
const total = parseInt(status.totalLength) || 0;
|
|
895
|
+
const completed = parseInt(status.completedLength) || 0;
|
|
896
|
+
const percent = total > 0 ? Math.round((completed / total) * 100) : 0;
|
|
897
|
+
const speed = formatSpeed(parseInt(status.downloadSpeed) || 0);
|
|
898
|
+
onProgress(percent, speed);
|
|
899
|
+
}
|
|
865
900
|
await delay(1000);
|
|
866
901
|
}
|
|
867
902
|
}
|
|
@@ -901,8 +936,20 @@ function apply(ctx, config) {
|
|
|
901
936
|
await promises_1.default.unlink(filePath).catch(() => { });
|
|
902
937
|
throw new Error(`文件过大(${Math.round(contentLength / 1024 / 1024)}MB),超过限制(${maxSize}MB)`);
|
|
903
938
|
}
|
|
939
|
+
let downloaded = 0;
|
|
940
|
+
let lastProgressTime = 0;
|
|
941
|
+
response.data.on('data', (chunk) => {
|
|
942
|
+
downloaded += chunk.length;
|
|
943
|
+
if (onProgress && contentLength > 0 && Date.now() - lastProgressTime > 500) {
|
|
944
|
+
lastProgressTime = Date.now();
|
|
945
|
+
const percent = Math.round((downloaded / contentLength) * 100);
|
|
946
|
+
onProgress(percent, '');
|
|
947
|
+
}
|
|
948
|
+
});
|
|
904
949
|
try {
|
|
905
950
|
await (0, promises_2.pipeline)(response.data, writer);
|
|
951
|
+
if (onProgress)
|
|
952
|
+
onProgress(100, '');
|
|
906
953
|
return filePath;
|
|
907
954
|
}
|
|
908
955
|
catch (e) {
|
|
@@ -910,6 +957,18 @@ function apply(ctx, config) {
|
|
|
910
957
|
throw new Error(`写入文件失败: ${getErrorMessage(e)}`);
|
|
911
958
|
}
|
|
912
959
|
}
|
|
960
|
+
function formatSpeed(bytesPerSec) {
|
|
961
|
+
if (bytesPerSec <= 0)
|
|
962
|
+
return '';
|
|
963
|
+
const units = ['B/s', 'KB/s', 'MB/s', 'GB/s'];
|
|
964
|
+
let i = 0;
|
|
965
|
+
let speed = bytesPerSec;
|
|
966
|
+
while (speed >= 1024 && i < units.length - 1) {
|
|
967
|
+
speed /= 1024;
|
|
968
|
+
i++;
|
|
969
|
+
}
|
|
970
|
+
return `${speed.toFixed(1)}${units[i]}`;
|
|
971
|
+
}
|
|
913
972
|
async function sendMedia(session, url, type, forceDownload, showFile) {
|
|
914
973
|
if (!url)
|
|
915
974
|
return;
|
|
@@ -923,9 +982,13 @@ function apply(ctx, config) {
|
|
|
923
982
|
};
|
|
924
983
|
const prefixMap = { image: 'img', video: 'video', audio: 'music' };
|
|
925
984
|
const sendFunc = type === 'audio' ? koishi_1.h.audio : type === 'video' ? koishi_1.h.video : koishi_1.h.image;
|
|
985
|
+
const onProgress = forceDownload ? (percent, speed) => {
|
|
986
|
+
const text = `下载进度: ${percent}%` + (speed ? ` (${speed})` : '');
|
|
987
|
+
logger.info(text);
|
|
988
|
+
} : undefined;
|
|
926
989
|
if (forceDownload) {
|
|
927
990
|
try {
|
|
928
|
-
const localPath = await downloadFile(url, mediaDownloadTimeout, maxMediaSize, prefixMap[type], extMap[type]);
|
|
991
|
+
const localPath = await downloadFile(url, mediaDownloadTimeout, maxMediaSize, prefixMap[type], extMap[type], onProgress);
|
|
929
992
|
try {
|
|
930
993
|
await sendWithTimeout(session, sendFunc(`file://${localPath}`));
|
|
931
994
|
}
|
|
@@ -1033,7 +1096,12 @@ function apply(ctx, config) {
|
|
|
1033
1096
|
const text = item.text;
|
|
1034
1097
|
if (text && config.showImageText)
|
|
1035
1098
|
forwardMessages.push(buildForwardNode(session, text, botName));
|
|
1036
|
-
if (
|
|
1099
|
+
if (config.showAuthorAvatar && p.avatar) {
|
|
1100
|
+
if (config.showAuthorAvatarText)
|
|
1101
|
+
forwardMessages.push(buildForwardNode(session, config.authorAvatarText || '作者头像:', botName));
|
|
1102
|
+
forwardMessages.push(buildForwardNode(session, koishi_1.h.image(p.avatar), botName));
|
|
1103
|
+
}
|
|
1104
|
+
if (p.cover && config.showCoverImage && p.type !== 'live_photo' && p.type !== 'image' && !(p.type === 'live' && (p.live_photo?.length || p.images?.length))) {
|
|
1037
1105
|
forwardMessages.push(buildForwardNode(session, koishi_1.h.image(p.cover), botName));
|
|
1038
1106
|
}
|
|
1039
1107
|
if (config.showMusicCover && p.music.cover) {
|
|
@@ -1071,12 +1139,18 @@ function apply(ctx, config) {
|
|
|
1071
1139
|
await sendWithTimeout(session, text);
|
|
1072
1140
|
await delay(300);
|
|
1073
1141
|
}
|
|
1074
|
-
if (
|
|
1075
|
-
|
|
1142
|
+
if (config.showAuthorAvatar && p.avatar) {
|
|
1143
|
+
if (config.showAuthorAvatarText)
|
|
1144
|
+
await sendWithTimeout(session, config.authorAvatarText || '作者头像:');
|
|
1145
|
+
await sendMedia(session, p.avatar, 'image', config.forceDownloadAuthorAvatar, config.showAuthorAvatarFile).catch(() => { });
|
|
1146
|
+
await delay(300);
|
|
1147
|
+
}
|
|
1148
|
+
if (p.cover && config.showCoverImage && p.type !== 'live_photo' && p.type !== 'image' && !(p.type === 'live' && (p.live_photo?.length || p.images?.length))) {
|
|
1149
|
+
await sendMedia(session, p.cover, 'image', config.forceDownloadCover, config.showCoverFile).catch(() => { });
|
|
1076
1150
|
await delay(300);
|
|
1077
1151
|
}
|
|
1078
1152
|
if (config.showMusicCover && p.music.cover) {
|
|
1079
|
-
await sendMedia(session, p.music.cover, 'image',
|
|
1153
|
+
await sendMedia(session, p.music.cover, 'image', false, true).catch(() => { });
|
|
1080
1154
|
await delay(300);
|
|
1081
1155
|
}
|
|
1082
1156
|
if (p.video && (p.type === 'video' || (p.type === 'live' && !p.live_photo?.length && !p.images?.length))) {
|
|
@@ -1086,7 +1160,7 @@ function apply(ctx, config) {
|
|
|
1086
1160
|
if (p.type === 'image' || p.type === 'live_photo' || (p.type === 'live' && (p.live_photo?.length || p.images?.length))) {
|
|
1087
1161
|
const imageUrls = p.images?.length ? p.images : (p.live_photo?.map(lp => lp.image) ?? []);
|
|
1088
1162
|
for (const imgUrl of imageUrls) {
|
|
1089
|
-
await sendMedia(session, imgUrl, 'image', config.
|
|
1163
|
+
await sendMedia(session, imgUrl, 'image', config.forceDownloadImageNew, config.showImageFileNew).catch(() => { });
|
|
1090
1164
|
await delay(200);
|
|
1091
1165
|
}
|
|
1092
1166
|
}
|
|
@@ -1342,4 +1416,3 @@ function apply(ctx, config) {
|
|
|
1342
1416
|
});
|
|
1343
1417
|
debugLog('INFO', '插件初始化完成');
|
|
1344
1418
|
}
|
|
1345
|
-
apply.inject = ['aria2', 'downloads'];
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -39,11 +39,20 @@ This is a **multi-platform video/image parsing plugin** developed for the Koishi
|
|
|
39
39
|
|--------|------|--------|------|
|
|
40
40
|
| `showImageText` | boolean | true | 发送文字内容 |
|
|
41
41
|
| `showCoverImage` | boolean | true | 发送封面图片 |
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
42
|
+
| `showCoverFile` | boolean | true | 封面是否以图片形式发送(关闭则只发送链接) |
|
|
43
|
+
| `showImageFileNew` | boolean | true | 图片是否以图片形式发送(关闭则只发送链接) |
|
|
44
|
+
| `showAuthorAvatar` | boolean | true | 发送作者头像图片 |
|
|
45
|
+
| `showAuthorAvatarFile` | boolean | true | 作者头像图片是否以图片形式发送(关闭则只发送链接) |
|
|
46
|
+
| `showMusicCover` | boolean | true | 发送音乐封面图片 |
|
|
44
47
|
| `showVideoFile` | boolean | true | 视频是否以视频形式发送(关闭则只发送链接) |
|
|
45
|
-
| `
|
|
48
|
+
| `forceDownloadCover` | boolean | false | 强制下载封面 |
|
|
49
|
+
| `forceDownloadImageNew` | boolean | false | 强制下载图片 |
|
|
50
|
+
| `forceDownloadAuthorAvatar` | boolean | false | 强制下载作者头像 |
|
|
46
51
|
| `forceDownloadVideo` | boolean | false | 强制下载视频 |
|
|
52
|
+
| `forceDownloadAuthorAvatar` | boolean | false | 强制下载作者头像 |
|
|
53
|
+
| `forceDownloadVideo` | boolean | false | 强制下载视频 |
|
|
54
|
+
| `showAuthorAvatarText` | boolean | true | 发送作者头像前显示文字提示 |
|
|
55
|
+
| `authorAvatarText` | string | 作者头像: | 作者头像前显示的文字 |
|
|
47
56
|
|
|
48
57
|
### 音乐语音(需 silk 和 ffmpeg)
|
|
49
58
|
| 配置项 | 类型 | 默认值 | 说明 |
|
|
@@ -109,7 +118,7 @@ This is a **multi-platform video/image parsing plugin** developed for the Koishi
|
|
|
109
118
|
| 变量名 | 说明 |
|
|
110
119
|
|--------|------|
|
|
111
120
|
| `${标题}` | 视频/图集标题 |
|
|
112
|
-
| `${作者}` | 作者名称 |
|
|
121
|
+
| `${作者}` 或 `${author-name}` | 作者名称 |
|
|
113
122
|
| `${简介}` | 内容简介 |
|
|
114
123
|
| `${视频时长}` | 视频时长(时:分:秒) |
|
|
115
124
|
| `${点赞数}` | 点赞数量 |
|
|
@@ -119,10 +128,9 @@ This is a **multi-platform video/image parsing plugin** developed for the Koishi
|
|
|
119
128
|
| `${评论数}` | 评论数量 |
|
|
120
129
|
| `${发布时间}` | 发布时间(格式化) |
|
|
121
130
|
| `${图片数量}` | 图集/实况图片数量 |
|
|
122
|
-
| `${作者ID}` | 作者唯一标识ID |
|
|
123
|
-
| `${
|
|
124
|
-
| `${
|
|
125
|
-
| `${音乐作者}` | 音乐作者 |
|
|
131
|
+
| `${作者ID}` 或 `${author-id}` | 作者唯一标识ID |
|
|
132
|
+
| `${音乐标题}` 或 `${music-title}` | 音乐标题 |
|
|
133
|
+
| `${音乐作者}` 或 `${music-author}` | 音乐作者 |
|
|
126
134
|
|
|
127
135
|
## 依赖说明 (Dependencies)
|
|
128
136
|
### 音乐语音(可选)
|
|
@@ -166,7 +174,7 @@ This is a **multi-platform video/image parsing plugin** developed for the Koishi
|
|
|
166
174
|
| 皮皮搞笑 | `h5.pipigx.com/pp/post/`, `ippzone.com` | 短视频 |
|
|
167
175
|
| 皮皮虾 | `pipix.com`, `pipixia.com` | 短视频 |
|
|
168
176
|
| 最右 | `share.xiaochuankeji.cn/hybrid/share/post`, `izuiyou.com` | 短视频 |
|
|
169
|
-
|
|
|
177
|
+
| 自定义平台 | 通过 `customPlatforms` 配置添加 | 取决于提供的 API |
|
|
170
178
|
|
|
171
179
|
## 项目贡献者 (Contributors)
|
|
172
180
|
|
|
@@ -179,6 +187,7 @@ This is a **multi-platform video/image parsing plugin** developed for the Koishi
|
|
|
179
187
|
| dzt2008 + Apricityx | 提交Bug-会对非支持视频平台URL进行误解析-已修复 |
|
|
180
188
|
| JH-Ahua | BugPk-Api 支持 |
|
|
181
189
|
| shangxue | 灵感来源 |
|
|
190
|
+
| linyves | 提交Bug-小红书图集重复发送封面-已修复<br>提交Bug-话题显示异常 #**[话题]#-已修复<br>提交建议-Live Photo 全部按普通图片处理-已采纳<br>提交Bug-解析后会把作者头像一起发送-已修复 |
|
|
182
191
|
|
|
183
192
|
(欢迎通过 Issues 或 PR 加入贡献者列表)
|
|
184
193
|
|