koishi-plugin-echo-cave 1.14.2 → 1.16.0
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.cjs +99 -5
- package/lib/index.d.ts +2 -0
- package/lib/media-helper.d.ts +1 -0
- package/lib/onebot-helper.d.ts +4 -0
- package/package.json +1 -1
package/lib/index.cjs
CHANGED
|
@@ -37,6 +37,7 @@ var require_zh_CN = __commonJS({
|
|
|
37
37
|
adminMessageProtection: "\u5F00\u542F\u7BA1\u7406\u5458\u6D88\u606F\u4FDD\u62A4\uFF0C\u5F00\u542F\u540E\u7BA1\u7406\u5458\u53D1\u5E03\u7684\u6D88\u606F\u53EA\u80FD\u7531\u7BA1\u7406\u5458\u5220\u9664",
|
|
38
38
|
allowContributorDelete: "\u5141\u8BB8\u6295\u7A3F\u8005\u5220\u9664\u81EA\u5DF1\u6295\u7A3F\u7684\u56DE\u58F0\u6D1E",
|
|
39
39
|
allowSenderDelete: "\u5141\u8BB8\u539F\u59CB\u53D1\u9001\u8005\u5220\u9664\u88AB\u6295\u7A3F\u7684\u56DE\u58F0\u6D1E",
|
|
40
|
+
deleteMediaWhenDeletingMsg: "\u5220\u9664\u56DE\u58F0\u6D1E\u6D88\u606F\u65F6\u662F\u5426\u540C\u65F6\u5220\u9664\u5173\u8054\u7684\u5A92\u4F53\u6587\u4EF6",
|
|
40
41
|
enableSizeLimit: "\u662F\u5426\u542F\u7528\u5A92\u4F53\u6587\u4EF6\u5927\u5C0F\u9650\u5236",
|
|
41
42
|
maxImageSize: "\u6700\u5927\u56FE\u7247\u5927\u5C0F (MB)",
|
|
42
43
|
maxVideoSize: "\u6700\u5927\u89C6\u9891\u5927\u5C0F (MB)",
|
|
@@ -95,7 +96,8 @@ var require_zh_CN = __commonJS({
|
|
|
95
96
|
noMsgQuoted: "\u{1F4A1} \u8BF7\u5F15\u7528\u4E00\u6761\u6D88\u606F\u540E\u518D\u4F7F\u7528\u6B64\u547D\u4EE4\uFF01",
|
|
96
97
|
existingMsg: "\u267B\uFE0F \u8BE5\u6D88\u606F\u5DF2\u5B58\u5728\u4E8E\u56DE\u58F0\u6D1E\u7A74\u4E2D\uFF01",
|
|
97
98
|
msgSaved: "\u2705 \u56DE\u58F0\u6D1E\u6D88\u606F\u5DF2\u6210\u529F\u5B58\u5165\uFF0C\u6D88\u606F ID\uFF1A{0}",
|
|
98
|
-
msgFailedToSave: "\u274C \u56DE\u58F0\u6D1E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\uFF01"
|
|
99
|
+
msgFailedToSave: "\u274C \u56DE\u58F0\u6D1E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\uFF01",
|
|
100
|
+
userNotInGroup: "\u274C \u63D0\u4F9B\u7684\u7528\u6237 ID \u4E0D\u5168\u5C5E\u4E8E\u8BE5\u7FA4\u7EC4\uFF01"
|
|
99
101
|
}
|
|
100
102
|
},
|
|
101
103
|
"cave.wipe": {
|
|
@@ -124,6 +126,17 @@ var require_zh_CN = __commonJS({
|
|
|
124
126
|
msgListHeader: "\u{1F4DC} \u60A8\u5728\u672C\u9891\u9053\u53D1\u8A00\u7684\u56DE\u58F0\u6D1E\u6D88\u606F\u5217\u8868\uFF1A\n",
|
|
125
127
|
msgListItem: "ID: {0} | \u521B\u5EFA\u65F6\u95F4: {1}\n"
|
|
126
128
|
}
|
|
129
|
+
},
|
|
130
|
+
"cave.bind": {
|
|
131
|
+
description: "\u5C06\u7528\u6237\u7ED1\u5B9A\u5230\u7279\u5B9A\u56DE\u58F0\u6D1E",
|
|
132
|
+
messages: {
|
|
133
|
+
noIdProvided: "\u274C \u8BF7\u63D0\u4F9B\u8981\u7ED1\u5B9A\u7528\u6237\u7684\u56DE\u58F0\u6D1E\u6D88\u606F ID\uFF01",
|
|
134
|
+
noUserIdProvided: "\u274C \u8BF7\u63D0\u4F9B\u8981\u7ED1\u5B9A\u7684\u7528\u6237 ID\uFF01",
|
|
135
|
+
msgNotFound: "\u{1F50D} \u672A\u627E\u5230\u8BE5 ID \u7684\u56DE\u58F0\u6D1E\u6D88\u606F",
|
|
136
|
+
userBoundSuccess: "\u2705 \u5DF2\u6210\u529F\u5C06\u7528\u6237\u7ED1\u5B9A\u5230\u56DE\u58F0\u6D1E #{0}\uFF01",
|
|
137
|
+
userAlreadyBound: "\u2139\uFE0F \u8BE5\u7528\u6237\u5DF2\u7ED1\u5B9A\u5230\u56DE\u58F0\u6D1E #{0}\uFF01",
|
|
138
|
+
userNotInGroup: "\u274C \u63D0\u4F9B\u7684\u7528\u6237 ID \u4E0D\u5168\u5C5E\u4E8E\u8BE5\u7FA4\u7EC4\uFF01"
|
|
139
|
+
}
|
|
127
140
|
}
|
|
128
141
|
}
|
|
129
142
|
};
|
|
@@ -325,6 +338,29 @@ async function checkAndCleanMediaFiles(ctx, cfg, type) {
|
|
|
325
338
|
ctx.logger.error(`Failed to check and clean ${type} files: ${err}`);
|
|
326
339
|
}
|
|
327
340
|
}
|
|
341
|
+
async function deleteMediaFilesFromMessage(ctx, content) {
|
|
342
|
+
try {
|
|
343
|
+
const elements = JSON.parse(content);
|
|
344
|
+
const mediaElements = Array.isArray(elements) ? elements : [elements];
|
|
345
|
+
for (const element of mediaElements) {
|
|
346
|
+
if (element.type === "image" || element.type === "video" || element.type === "file" || element.type === "record") {
|
|
347
|
+
const fileUri = element.data?.file;
|
|
348
|
+
if (fileUri && fileUri.startsWith("file:///")) {
|
|
349
|
+
const filePath = decodeURIComponent(fileUri.replace("file:///", ""));
|
|
350
|
+
try {
|
|
351
|
+
await import_node_fs.promises.access(filePath);
|
|
352
|
+
await import_node_fs.promises.unlink(filePath);
|
|
353
|
+
ctx.logger.info(`Deleted media file: ${filePath}`);
|
|
354
|
+
} catch (err) {
|
|
355
|
+
ctx.logger.warn(`Failed to delete media file: ${filePath}, error: ${err}`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
} catch (err) {
|
|
361
|
+
ctx.logger.error(`Failed to parse message content when deleting media: ${err}`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
328
364
|
|
|
329
365
|
// src/onebot-helper.ts
|
|
330
366
|
async function getUserName(ctx, session, userId) {
|
|
@@ -336,6 +372,16 @@ async function getUserName(ctx, session, userId) {
|
|
|
336
372
|
return userId;
|
|
337
373
|
}
|
|
338
374
|
}
|
|
375
|
+
async function checkUsersInGroup(ctx, session, userIds) {
|
|
376
|
+
try {
|
|
377
|
+
const groupMembers = await session.onebot.getGroupMemberList(session.channelId);
|
|
378
|
+
const memberIds = groupMembers.map((member) => member.user_id.toString());
|
|
379
|
+
return userIds.every((userId) => memberIds.includes(userId));
|
|
380
|
+
} catch (error) {
|
|
381
|
+
ctx.logger.warn(`\u83B7\u53D6\u7FA4\u6210\u5458\u5217\u8868\u5931\u8D25\uFF1A`, error);
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
339
385
|
|
|
340
386
|
// src/cave-helper.ts
|
|
341
387
|
async function sendCaveMsg(ctx, session, caveMsg, cfg) {
|
|
@@ -349,11 +395,19 @@ async function sendCaveMsg(ctx, session, caveMsg, cfg) {
|
|
|
349
395
|
const date = formatDate(caveMsg.createTime);
|
|
350
396
|
const originName = await getUserName(ctx, session, caveMsg.originUserId);
|
|
351
397
|
const userName = await getUserName(ctx, session, caveMsg.userId);
|
|
398
|
+
let relatedUsersFormatted = "";
|
|
399
|
+
if (caveMsg.relatedUsers && caveMsg.relatedUsers.length > 0) {
|
|
400
|
+
const relatedUserNames = await Promise.all(
|
|
401
|
+
caveMsg.relatedUsers.map(async (userId) => await getUserName(ctx, session, userId))
|
|
402
|
+
);
|
|
403
|
+
relatedUsersFormatted = relatedUserNames.join(", ");
|
|
404
|
+
}
|
|
352
405
|
const templateData = {
|
|
353
406
|
id: caveMsg.id.toString(),
|
|
354
407
|
date,
|
|
355
408
|
originName,
|
|
356
409
|
userName,
|
|
410
|
+
relatedUsers: relatedUsersFormatted,
|
|
357
411
|
nl: "\n"
|
|
358
412
|
};
|
|
359
413
|
const TEMPLATE_COUNT = 5;
|
|
@@ -464,6 +518,7 @@ var Config = import_koishi.Schema.object({
|
|
|
464
518
|
adminMessageProtection: import_koishi.Schema.boolean().default(false),
|
|
465
519
|
allowContributorDelete: import_koishi.Schema.boolean().default(true),
|
|
466
520
|
allowSenderDelete: import_koishi.Schema.boolean().default(true),
|
|
521
|
+
deleteMediaWhenDeletingMsg: import_koishi.Schema.boolean().default(true),
|
|
467
522
|
enableSizeLimit: import_koishi.Schema.boolean().default(false),
|
|
468
523
|
maxImageSize: import_koishi.Schema.number().default(2048),
|
|
469
524
|
maxVideoSize: import_koishi.Schema.number().default(512),
|
|
@@ -484,7 +539,8 @@ function apply(ctx, cfg) {
|
|
|
484
539
|
userId: "string",
|
|
485
540
|
originUserId: "string",
|
|
486
541
|
type: "string",
|
|
487
|
-
content: "text"
|
|
542
|
+
content: "text",
|
|
543
|
+
relatedUsers: "list"
|
|
488
544
|
},
|
|
489
545
|
{
|
|
490
546
|
primary: "id",
|
|
@@ -494,7 +550,9 @@ function apply(ctx, cfg) {
|
|
|
494
550
|
ctx.command("cave [id:number]").action(
|
|
495
551
|
async ({ session }, id) => await getCave(ctx, session, cfg, id)
|
|
496
552
|
);
|
|
497
|
-
ctx.command("cave.echo").action(
|
|
553
|
+
ctx.command("cave.echo [...userIds:string]").action(
|
|
554
|
+
async ({ session }, ...userIds) => await addCave(ctx, session, cfg, userIds)
|
|
555
|
+
);
|
|
498
556
|
ctx.command("cave.wipe <id:number>").action(
|
|
499
557
|
async ({ session }, id) => await deleteCave(ctx, session, cfg, id)
|
|
500
558
|
);
|
|
@@ -502,6 +560,9 @@ function apply(ctx, cfg) {
|
|
|
502
560
|
ctx.command("cave.trace").action(
|
|
503
561
|
async ({ session }) => await getCaveListByOriginUser(ctx, session)
|
|
504
562
|
);
|
|
563
|
+
ctx.command("cave.bind <id:number> <...userIds:string>", { authority: 4 }).action(
|
|
564
|
+
async ({ session }, id, ...userIds) => await bindUsersToCave(ctx, session, id, userIds)
|
|
565
|
+
);
|
|
505
566
|
}
|
|
506
567
|
async function getCaveListByUser(ctx, session) {
|
|
507
568
|
if (!session.guildId) {
|
|
@@ -601,10 +662,13 @@ async function deleteCave(ctx, session, cfg, id) {
|
|
|
601
662
|
return session.text(".permissionDenied");
|
|
602
663
|
}
|
|
603
664
|
}
|
|
665
|
+
if (cfg.deleteMediaWhenDeletingMsg) {
|
|
666
|
+
await deleteMediaFilesFromMessage(ctx, caveMsg.content);
|
|
667
|
+
}
|
|
604
668
|
await ctx.database.remove("echo_cave", id);
|
|
605
669
|
return session.text(".msgDeleted", [id]);
|
|
606
670
|
}
|
|
607
|
-
async function addCave(ctx, session, cfg) {
|
|
671
|
+
async function addCave(ctx, session, cfg, userIds) {
|
|
608
672
|
if (!session.guildId) {
|
|
609
673
|
return session.text("echo-cave.general.privateChatReminder");
|
|
610
674
|
}
|
|
@@ -643,6 +707,12 @@ async function addCave(ctx, session, cfg) {
|
|
|
643
707
|
return session.text(".existingMsg");
|
|
644
708
|
}
|
|
645
709
|
});
|
|
710
|
+
if (userIds && userIds.length > 0) {
|
|
711
|
+
const isAllUsersInGroup = await checkUsersInGroup(ctx, session, userIds);
|
|
712
|
+
if (!isAllUsersInGroup) {
|
|
713
|
+
return session.text(".userNotInGroup");
|
|
714
|
+
}
|
|
715
|
+
}
|
|
646
716
|
try {
|
|
647
717
|
const result = await ctx.database.create("echo_cave", {
|
|
648
718
|
channelId,
|
|
@@ -650,13 +720,37 @@ async function addCave(ctx, session, cfg) {
|
|
|
650
720
|
userId,
|
|
651
721
|
originUserId: quote.user.id,
|
|
652
722
|
type,
|
|
653
|
-
content
|
|
723
|
+
content,
|
|
724
|
+
relatedUsers: userIds || []
|
|
654
725
|
});
|
|
655
726
|
return session.text(".msgSaved", [result.id]);
|
|
656
727
|
} catch (error) {
|
|
657
728
|
return session.text(".msgFailedToSave");
|
|
658
729
|
}
|
|
659
730
|
}
|
|
731
|
+
async function bindUsersToCave(ctx, session, id, userIds) {
|
|
732
|
+
if (!session.guildId) {
|
|
733
|
+
return session.text("echo-cave.general.privateChatReminder");
|
|
734
|
+
}
|
|
735
|
+
if (!id) {
|
|
736
|
+
return session.text(".noIdProvided");
|
|
737
|
+
}
|
|
738
|
+
if (!userIds || userIds.length === 0) {
|
|
739
|
+
return session.text(".noUserIdProvided");
|
|
740
|
+
}
|
|
741
|
+
const caves = await ctx.database.get("echo_cave", id);
|
|
742
|
+
if (caves.length === 0) {
|
|
743
|
+
return session.text("echo-cave.general.noMsgWithId");
|
|
744
|
+
}
|
|
745
|
+
const isAllUsersInGroup = await checkUsersInGroup(ctx, session, userIds);
|
|
746
|
+
if (!isAllUsersInGroup) {
|
|
747
|
+
return session.text(".userNotInGroup");
|
|
748
|
+
}
|
|
749
|
+
await ctx.database.set("echo_cave", id, {
|
|
750
|
+
relatedUsers: userIds
|
|
751
|
+
});
|
|
752
|
+
return session.text(".userBoundSuccess", [id]);
|
|
753
|
+
}
|
|
660
754
|
// Annotate the CommonJS export names for ESM import in node:
|
|
661
755
|
0 && (module.exports = {
|
|
662
756
|
Config,
|
package/lib/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export interface Config {
|
|
|
6
6
|
adminMessageProtection?: boolean;
|
|
7
7
|
allowContributorDelete?: boolean;
|
|
8
8
|
allowSenderDelete?: boolean;
|
|
9
|
+
deleteMediaWhenDeletingMsg?: boolean;
|
|
9
10
|
enableSizeLimit?: boolean;
|
|
10
11
|
maxImageSize?: number;
|
|
11
12
|
maxVideoSize?: number;
|
|
@@ -22,6 +23,7 @@ export interface EchoCave {
|
|
|
22
23
|
originUserId: string;
|
|
23
24
|
type: 'forward' | 'msg';
|
|
24
25
|
content: string;
|
|
26
|
+
relatedUsers: string[];
|
|
25
27
|
}
|
|
26
28
|
declare module 'koishi' {
|
|
27
29
|
interface Tables {
|
package/lib/media-helper.d.ts
CHANGED
|
@@ -4,3 +4,4 @@ export declare function saveMedia(ctx: Context, mediaElement: Record<string, any
|
|
|
4
4
|
export declare function processMediaElement(ctx: Context, element: any, cfg: Config): Promise<any>;
|
|
5
5
|
export declare function convertFileUriToBase64(ctx: Context, element: any): Promise<any>;
|
|
6
6
|
export declare function checkAndCleanMediaFiles(ctx: Context, cfg: Config, type: 'image' | 'video' | 'file' | 'record'): Promise<void>;
|
|
7
|
+
export declare function deleteMediaFilesFromMessage(ctx: Context, content: string): Promise<void>;
|
package/lib/onebot-helper.d.ts
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
import { Context, Session } from 'koishi';
|
|
2
2
|
export declare function getUserName(ctx: Context, session: Session, userId: string): Promise<string>;
|
|
3
|
+
/**
|
|
4
|
+
* 检查用户是否属于指定群组
|
|
5
|
+
*/
|
|
6
|
+
export declare function checkUsersInGroup(ctx: Context, session: Session, userIds: string[]): Promise<boolean>;
|