koishi-plugin-group-verification 1.0.36 → 1.0.38
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 +55 -26
- package/package.json +1 -1
- package/src/index.ts +73 -28
package/lib/index.js
CHANGED
|
@@ -60,19 +60,23 @@ function clogV(msg, ...args) {
|
|
|
60
60
|
if (pluginLogLevel === "详细") logger.debug(msg, ...args);
|
|
61
61
|
}
|
|
62
62
|
__name(clogV, "clogV");
|
|
63
|
+
function renderMsg(tmpl) {
|
|
64
|
+
return tmpl.replace(/\\\\n/g, "").replace(/\\n/g, "\n").replace(/\x01/g, "\\n");
|
|
65
|
+
}
|
|
66
|
+
__name(renderMsg, "renderMsg");
|
|
63
67
|
var Config = import_koishi.Schema.object({
|
|
64
68
|
defaultReminderMessage: import_koishi.Schema.string().description("默认提醒消息模板(使用 \\n 表示换行,可包含下方变量)").default("{user}({id}) 申请入群\\n申请理由: {question}\\n匹配情况: {answer}/{threshold}\\n使用 gva 同意或 gvr 拒绝申请"),
|
|
65
69
|
enableStrictGroupCheck: import_koishi.Schema.boolean().description("是否启用严格的群号检查(检查群号长度)").default(false),
|
|
66
70
|
logLevel: import_koishi.Schema.union(["debug", "info", "warn"]).description("日志详细程度").default("info"),
|
|
67
71
|
// debug=详细, info=中等, warn=简洁
|
|
68
|
-
permissionDeniedMessage: import_koishi.Schema.string().description("
|
|
69
|
-
invalidGroupMessage: import_koishi.Schema.string().description("
|
|
70
|
-
parameterConflictMessage: import_koishi.Schema.string().description("
|
|
71
|
-
noKeywordsMessage: import_koishi.Schema.string().description("
|
|
72
|
-
blacklistAddSuccess: import_koishi.Schema.string().description(
|
|
73
|
-
blacklistRemoveSuccess: import_koishi.Schema.string().description(
|
|
74
|
-
blacklistListEmpty: import_koishi.Schema.string().description("
|
|
75
|
-
blacklistInfoTemplate: import_koishi.Schema.string().description("查询指定用户状态时的模板,可用 {global},{group}").default("全局黑名单: {global}
|
|
72
|
+
permissionDeniedMessage: import_koishi.Schema.string().description("权限不足时返回给调用者的提示,支持 \\n 换行").default("权限不足: 需要群主/管理员权限或koishi三级以上权限"),
|
|
73
|
+
invalidGroupMessage: import_koishi.Schema.string().description("无效群号或机器人未在该群时的提示,可用 {group},支持 \\n 换行").default("群号 {group} 格式不合法或机器人不在该群中"),
|
|
74
|
+
parameterConflictMessage: import_koishi.Schema.string().description("参数冲突时提示,支持 \\n 换行").default("参数冲突: -? 或 -r 不能与其他参数或关键词一起使用(仅可搭配 -i)"),
|
|
75
|
+
noKeywordsMessage: import_koishi.Schema.string().description("未提供关键词且无法从现有配置继承时的提示,支持 \\n 换行").default("请先提供关键词创建配置,或使用 -? 查询配置,-r 删除配置"),
|
|
76
|
+
blacklistAddSuccess: import_koishi.Schema.string().description('将用户加入黑名单后的提示,可用 {user},{group},{reason};{group} 含"群"前缀(all时为"全局"),支持 \\n 换行').default("已将用户 {user} 加入{group}黑名单{reason}"),
|
|
77
|
+
blacklistRemoveSuccess: import_koishi.Schema.string().description('从黑名单移除用户后的提示,可用 {user},{group};{group} 含"群"前缀,支持 \\n 换行').default("已从{group}的黑名单中移除用户 {user}"),
|
|
78
|
+
blacklistListEmpty: import_koishi.Schema.string().description('黑名单为空时提示,可用 {group};{group} 含"群"前缀,支持 \\n 换行').default("{group}的黑名单为空"),
|
|
79
|
+
blacklistInfoTemplate: import_koishi.Schema.string().description("查询指定用户状态时的模板,可用 {global},{group},支持 \\n 换行").default("全局黑名单: {global}\\n本群黑名单: {group}")
|
|
76
80
|
}).description("群组验证插件配置");
|
|
77
81
|
var inject = ["database"];
|
|
78
82
|
var ESC_QUOTE = "\0";
|
|
@@ -442,6 +446,31 @@ async function handleGuildMemberRequestEvent(ctx, session) {
|
|
|
442
446
|
} catch (e) {
|
|
443
447
|
logger.warn("黑名单检查失败", e);
|
|
444
448
|
}
|
|
449
|
+
{
|
|
450
|
+
const isId = /* @__PURE__ */ __name((s) => !s || s === userId, "isId");
|
|
451
|
+
let resolvedName;
|
|
452
|
+
const evUser = session.event?.user;
|
|
453
|
+
if (!isId(evUser?.name)) resolvedName = evUser.name;
|
|
454
|
+
else if (!isId(evUser?.nick)) resolvedName = evUser.nick;
|
|
455
|
+
if (!resolvedName) {
|
|
456
|
+
const author = session.author;
|
|
457
|
+
if (!isId(author?.name)) resolvedName = author.name;
|
|
458
|
+
else if (!isId(author?.nick)) resolvedName = author.nick;
|
|
459
|
+
}
|
|
460
|
+
if (!resolvedName && !isId(session.username)) {
|
|
461
|
+
resolvedName = session.username;
|
|
462
|
+
}
|
|
463
|
+
if (!resolvedName) {
|
|
464
|
+
try {
|
|
465
|
+
const userInfo = await session.bot.getUser(userId);
|
|
466
|
+
const n = userInfo?.name || userInfo?.nickname;
|
|
467
|
+
if (!isId(n)) resolvedName = n;
|
|
468
|
+
} catch (_) {
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
session.username = resolvedName || userId;
|
|
472
|
+
clogV(`昵称解析: userId=${userId} resolved="${session.username}" evUser=${JSON.stringify(evUser)} author=${JSON.stringify(session.author)}`);
|
|
473
|
+
}
|
|
445
474
|
const { isValid, matchedCount, requiredThreshold } = await verifyApplication(config, message, session);
|
|
446
475
|
clogV(`验证结果 guild=${guildId} user=${userId} msg="${message}" matched=${matchedCount} threshold=${requiredThreshold} valid=${isValid}`);
|
|
447
476
|
if (isValid) {
|
|
@@ -604,7 +633,7 @@ async function handleFailedVerification(ctx, session, config, matchedCount, requ
|
|
|
604
633
|
logger.warn("handleFailedVerification invoked without guildId, aborting");
|
|
605
634
|
return;
|
|
606
635
|
}
|
|
607
|
-
const username = session.username ||
|
|
636
|
+
const username = session.username || userId;
|
|
608
637
|
const message = session.content || "";
|
|
609
638
|
clog(
|
|
610
639
|
"debug",
|
|
@@ -716,7 +745,7 @@ async function processBlacklistCommand(ctx, session, rawArgs, config) {
|
|
|
716
745
|
} else {
|
|
717
746
|
if (config?.enableStrictGroupCheck) {
|
|
718
747
|
if (!/^\d{5,15}$/.test(group)) {
|
|
719
|
-
return (config.invalidGroupMessage || "群号 {group} 格式不合法或机器人不在该群中").replace("{group}", group);
|
|
748
|
+
return renderMsg((config.invalidGroupMessage || "群号 {group} 格式不合法或机器人不在该群中").replace("{group}", group));
|
|
720
749
|
}
|
|
721
750
|
}
|
|
722
751
|
const [ok, err] = await checkPermission(session, group);
|
|
@@ -746,8 +775,9 @@ async function processBlacklistCommand(ctx, session, rawArgs, config) {
|
|
|
746
775
|
logger.warn(`踢出用户 ${targetUser} 失败`, e);
|
|
747
776
|
}
|
|
748
777
|
}
|
|
749
|
-
const tmpl = config && config.blacklistAddSuccess || "已将用户 {user}
|
|
750
|
-
|
|
778
|
+
const tmpl = config && config.blacklistAddSuccess || "已将用户 {user} 加入{group}黑名单{reason}";
|
|
779
|
+
const groupLabelA = group.toLowerCase() === "all" ? "全局" : "群 " + group;
|
|
780
|
+
return renderMsg(tmpl.replace("{user}", targetUser).replace("{group}", groupLabelA).replace("{reason}", reason ? `,原因: ${reason}` : ""));
|
|
751
781
|
}
|
|
752
782
|
if (op === "r") {
|
|
753
783
|
targetUser = parts[1];
|
|
@@ -760,7 +790,7 @@ async function processBlacklistCommand(ctx, session, rawArgs, config) {
|
|
|
760
790
|
} else {
|
|
761
791
|
if (config?.enableStrictGroupCheck) {
|
|
762
792
|
if (!/^\d{5,15}$/.test(group)) {
|
|
763
|
-
return (config.invalidGroupMessage || "群号 {group} 格式不合法或机器人不在该群中").replace("{group}", group);
|
|
793
|
+
return renderMsg((config.invalidGroupMessage || "群号 {group} 格式不合法或机器人不在该群中").replace("{group}", group));
|
|
764
794
|
}
|
|
765
795
|
}
|
|
766
796
|
const [ok, err] = await checkPermission(session, group);
|
|
@@ -773,8 +803,9 @@ async function processBlacklistCommand(ctx, session, rawArgs, config) {
|
|
|
773
803
|
delete entries[targetUser];
|
|
774
804
|
await ctx.database.set("group_verification_blacklist", { id: row.id }, { entries });
|
|
775
805
|
}
|
|
776
|
-
const tmpl = config && config.blacklistRemoveSuccess || "
|
|
777
|
-
|
|
806
|
+
const tmpl = config && config.blacklistRemoveSuccess || "已从{group}的黑名单中移除用户 {user}";
|
|
807
|
+
const groupLabelR = group.toLowerCase() === "all" ? "全局" : "群 " + group;
|
|
808
|
+
return renderMsg(tmpl.replace("{user}", targetUser).replace("{group}", groupLabelR));
|
|
778
809
|
}
|
|
779
810
|
if (op === "l") {
|
|
780
811
|
group = parts[1] || getCurrentGroup();
|
|
@@ -785,7 +816,7 @@ async function processBlacklistCommand(ctx, session, rawArgs, config) {
|
|
|
785
816
|
} else {
|
|
786
817
|
if (config?.enableStrictGroupCheck) {
|
|
787
818
|
if (!/^\d{5,15}$/.test(group)) {
|
|
788
|
-
return (config.invalidGroupMessage || "群号 {group} 格式不合法或机器人不在该群中").replace("{group}", group);
|
|
819
|
+
return renderMsg((config.invalidGroupMessage || "群号 {group} 格式不合法或机器人不在该群中").replace("{group}", group));
|
|
789
820
|
}
|
|
790
821
|
}
|
|
791
822
|
const [ok, err] = await checkPermission(session, group);
|
|
@@ -793,11 +824,9 @@ async function processBlacklistCommand(ctx, session, rawArgs, config) {
|
|
|
793
824
|
}
|
|
794
825
|
const rows = await ctx.database.get("group_verification_blacklist", { groupId: group });
|
|
795
826
|
if (rows.length === 0) {
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
}
|
|
799
|
-
const tmpl = config && config.blacklistListEmpty || "群 {group} 的黑名单为空";
|
|
800
|
-
return tmpl.replace("{group}", group);
|
|
827
|
+
const tmpl = config && config.blacklistListEmpty || "{group}的黑名单为空";
|
|
828
|
+
const groupLabelL = group && group.toLowerCase() === "all" ? "全局" : "群 " + group;
|
|
829
|
+
return renderMsg(tmpl.replace("{group}", groupLabelL));
|
|
801
830
|
}
|
|
802
831
|
const entries = rows[0].entries || {};
|
|
803
832
|
let prefix = group && group.toLowerCase() === "all" ? "全局黑名单: \n" : `群 ${group} 黑名单:
|
|
@@ -815,7 +844,7 @@ async function processBlacklistCommand(ctx, session, rawArgs, config) {
|
|
|
815
844
|
const groupArg = parts[2];
|
|
816
845
|
const globalRows = await ctx.database.get("group_verification_blacklist", { groupId: "all" });
|
|
817
846
|
const globalHit = globalRows.length > 0 && (globalRows[0].entries || {})[targetUser] !== void 0;
|
|
818
|
-
const tmpl = config && config.blacklistInfoTemplate || "全局黑名单: {global}
|
|
847
|
+
const tmpl = (config && config.blacklistInfoTemplate || "全局黑名单: {global}\\n本群黑名单: {group}").replace(/\\\\n/g, "").replace(/\\n/g, "\n").replace(/\x01/g, "\\n");
|
|
819
848
|
const formatReply = /* @__PURE__ */ __name((localHit, groupsList) => {
|
|
820
849
|
if (groupsList) {
|
|
821
850
|
return tmpl.replace("{global}", globalHit ? "有" : "无").replace(
|
|
@@ -860,7 +889,7 @@ async function processBlacklistCommand(ctx, session, rawArgs, config) {
|
|
|
860
889
|
const groupId = groupArg;
|
|
861
890
|
if (config?.enableStrictGroupCheck && groupId.toLowerCase() !== "all") {
|
|
862
891
|
if (!/^\d{5,15}$/.test(groupId)) {
|
|
863
|
-
return (config.invalidGroupMessage || "群号 {group} 格式不合法或机器人不在该群中").replace("{group}", groupId);
|
|
892
|
+
return renderMsg((config.invalidGroupMessage || "群号 {group} 格式不合法或机器人不在该群中").replace("{group}", groupId));
|
|
864
893
|
}
|
|
865
894
|
}
|
|
866
895
|
const [ok, err] = await checkPermission(session, groupId);
|
|
@@ -1008,7 +1037,7 @@ function apply(ctx, config) {
|
|
|
1008
1037
|
return [false, `无法获取群 ${groupId} 的成员信息,请确认机器人已在该群中`];
|
|
1009
1038
|
}
|
|
1010
1039
|
clogV(`权限检查 - 权限不足`);
|
|
1011
|
-
return [false, config.permissionDeniedMessage || "权限不足: 需要群主/管理员权限或koishi三级以上权限"];
|
|
1040
|
+
return [false, renderMsg(config.permissionDeniedMessage || "权限不足: 需要群主/管理员权限或koishi三级以上权限")];
|
|
1012
1041
|
}
|
|
1013
1042
|
__name(checkPermission2, "checkPermission");
|
|
1014
1043
|
const groupVerify = ctx.command("group-verify", "群组验证管理命令").alias("gv", "gverify");
|
|
@@ -1046,7 +1075,7 @@ function apply(ctx, config) {
|
|
|
1046
1075
|
clogV(`合并后options: ${JSON.stringify(cleanedOptions, null, 2)}
|
|
1047
1076
|
`);
|
|
1048
1077
|
if ((cleanedOptions.query || cleanedOptions.remove) && (parsedKeywords.length > 0 || cleanedOptions.method !== void 0 || cleanedOptions.threshold !== void 0 || cleanedOptions.message !== void 0 || cleanedOptions.enableMessage || cleanedOptions.disableMessage)) {
|
|
1049
|
-
return config.parameterConflictMessage || "参数冲突: -? 或 -r 不能与其他参数或关键词一起使用(仅可搭配 -i)";
|
|
1078
|
+
return renderMsg(config.parameterConflictMessage || "参数冲突: -? 或 -r 不能与其他参数或关键词一起使用(仅可搭配 -i)");
|
|
1050
1079
|
}
|
|
1051
1080
|
const hasRealMessageParam = cleanedOptions.message !== void 0;
|
|
1052
1081
|
const hasRealEnableMessageParam = cleanedOptions.enableMessage === true;
|
|
@@ -1160,7 +1189,7 @@ ${displayMsg}
|
|
|
1160
1189
|
}
|
|
1161
1190
|
if (keywordList.length === 0 && !cleanedOptions.query && !cleanedOptions.remove) {
|
|
1162
1191
|
if (!existingConfig) {
|
|
1163
|
-
return config.noKeywordsMessage || "请先提供关键词创建配置,或使用 -? 查询配置,-r 删除配置";
|
|
1192
|
+
return renderMsg(config.noKeywordsMessage || "请先提供关键词创建配置,或使用 -? 查询配置,-r 删除配置");
|
|
1164
1193
|
}
|
|
1165
1194
|
keywordList = existingConfig.keywords;
|
|
1166
1195
|
}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -35,6 +35,11 @@ function clogV(msg: string, ...args: any[]): void {
|
|
|
35
35
|
if (pluginLogLevel === '详细') logger.debug(msg, ...args)
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/** 处理配置文本中的换行转义:\n→换行,\\n→字面量 \n */
|
|
39
|
+
function renderMsg(tmpl: string): string {
|
|
40
|
+
return tmpl.replace(/\\\\n/g, '\x01').replace(/\\n/g, '\n').replace(/\x01/g, '\\n')
|
|
41
|
+
}
|
|
42
|
+
|
|
38
43
|
// 数据库模型定义
|
|
39
44
|
declare module 'koishi' {
|
|
40
45
|
interface Tables {
|
|
@@ -114,14 +119,14 @@ export const Config: Schema<Config> = Schema.object({
|
|
|
114
119
|
.default('{user}({id}) 申请入群\\n申请理由: {question}\\n匹配情况: {answer}/{threshold}\\n使用 gva 同意或 gvr 拒绝申请'),
|
|
115
120
|
enableStrictGroupCheck: Schema.boolean().description('是否启用严格的群号检查(检查群号长度)').default(false),
|
|
116
121
|
logLevel: Schema.union(['debug', 'info', 'warn']).description('日志详细程度').default('info'), // debug=详细, info=中等, warn=简洁
|
|
117
|
-
permissionDeniedMessage: Schema.string().description('
|
|
118
|
-
invalidGroupMessage: Schema.string().description('
|
|
119
|
-
parameterConflictMessage: Schema.string().description('
|
|
120
|
-
noKeywordsMessage: Schema.string().description('
|
|
121
|
-
blacklistAddSuccess: Schema.string().description('
|
|
122
|
-
blacklistRemoveSuccess: Schema.string().description('
|
|
123
|
-
blacklistListEmpty: Schema.string().description('
|
|
124
|
-
blacklistInfoTemplate: Schema.string().description('查询指定用户状态时的模板,可用 {global},{group}').default('全局黑名单: {global}
|
|
122
|
+
permissionDeniedMessage: Schema.string().description('权限不足时返回给调用者的提示,支持 \\n 换行').default('权限不足: 需要群主/管理员权限或koishi三级以上权限'),
|
|
123
|
+
invalidGroupMessage: Schema.string().description('无效群号或机器人未在该群时的提示,可用 {group},支持 \\n 换行').default('群号 {group} 格式不合法或机器人不在该群中'),
|
|
124
|
+
parameterConflictMessage: Schema.string().description('参数冲突时提示,支持 \\n 换行').default('参数冲突: -? 或 -r 不能与其他参数或关键词一起使用(仅可搭配 -i)'),
|
|
125
|
+
noKeywordsMessage: Schema.string().description('未提供关键词且无法从现有配置继承时的提示,支持 \\n 换行').default('请先提供关键词创建配置,或使用 -? 查询配置,-r 删除配置'),
|
|
126
|
+
blacklistAddSuccess: Schema.string().description('将用户加入黑名单后的提示,可用 {user},{group},{reason};{group} 含"群"前缀(all时为"全局"),支持 \\n 换行').default('已将用户 {user} 加入{group}黑名单{reason}'),
|
|
127
|
+
blacklistRemoveSuccess: Schema.string().description('从黑名单移除用户后的提示,可用 {user},{group};{group} 含"群"前缀,支持 \\n 换行').default('已从{group}的黑名单中移除用户 {user}'),
|
|
128
|
+
blacklistListEmpty: Schema.string().description('黑名单为空时提示,可用 {group};{group} 含"群"前缀,支持 \\n 换行').default('{group}的黑名单为空'),
|
|
129
|
+
blacklistInfoTemplate: Schema.string().description('查询指定用户状态时的模板,可用 {global},{group},支持 \\n 换行').default('全局黑名单: {global}\\n本群黑名单: {group}')
|
|
125
130
|
})
|
|
126
131
|
.description('群组验证插件配置')
|
|
127
132
|
|
|
@@ -604,6 +609,47 @@ export async function handleGuildMemberRequestEvent(ctx: Context, session: any)
|
|
|
604
609
|
logger.warn('黑名单检查失败', e);
|
|
605
610
|
}
|
|
606
611
|
|
|
612
|
+
// 解析用户昵称优先级:
|
|
613
|
+
// 1) event 原始数据(NapCat/OneBot 入群申请事件本身携带昵称)
|
|
614
|
+
// 2) session.author.name / session.author.nick
|
|
615
|
+
// 3) session.username(若非 userId)
|
|
616
|
+
// 4) getUser() API
|
|
617
|
+
// 5) 最终 fallback:userId
|
|
618
|
+
{
|
|
619
|
+
const isId = (s: string | undefined) => !s || s === userId
|
|
620
|
+
|
|
621
|
+
let resolvedName: string | undefined
|
|
622
|
+
|
|
623
|
+
// 优先级1:event 原始数据
|
|
624
|
+
const evUser = (session.event as any)?.user
|
|
625
|
+
if (!isId(evUser?.name)) resolvedName = evUser.name
|
|
626
|
+
else if (!isId(evUser?.nick)) resolvedName = evUser.nick
|
|
627
|
+
|
|
628
|
+
// 优先级2:author 字段
|
|
629
|
+
if (!resolvedName) {
|
|
630
|
+
const author = session.author as any
|
|
631
|
+
if (!isId(author?.name)) resolvedName = author.name
|
|
632
|
+
else if (!isId(author?.nick)) resolvedName = author.nick
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// 优先级3:session.username
|
|
636
|
+
if (!resolvedName && !isId(session.username)) {
|
|
637
|
+
resolvedName = session.username
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// 优先级4:API 拉取(get_stranger_info)
|
|
641
|
+
if (!resolvedName) {
|
|
642
|
+
try {
|
|
643
|
+
const userInfo = await session.bot.getUser(userId)
|
|
644
|
+
const n = (userInfo as any)?.name || (userInfo as any)?.nickname
|
|
645
|
+
if (!isId(n)) resolvedName = n
|
|
646
|
+
} catch (_) {}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
session.username = resolvedName || userId
|
|
650
|
+
clogV(`昵称解析: userId=${userId} resolved="${session.username}" evUser=${JSON.stringify(evUser)} author=${JSON.stringify((session as any).author)}`)
|
|
651
|
+
}
|
|
652
|
+
|
|
607
653
|
const { isValid, matchedCount, requiredThreshold } = await verifyApplication(config, message, session);
|
|
608
654
|
clogV(`验证结果 guild=${guildId} user=${userId} msg="${message}" matched=${matchedCount} threshold=${requiredThreshold} valid=${isValid}`);
|
|
609
655
|
|
|
@@ -803,7 +849,7 @@ export async function handleFailedVerification(
|
|
|
803
849
|
logger.warn('handleFailedVerification invoked without guildId, aborting')
|
|
804
850
|
return
|
|
805
851
|
}
|
|
806
|
-
const username = session.username ||
|
|
852
|
+
const username = session.username || userId
|
|
807
853
|
const message = session.content || ''
|
|
808
854
|
clog('debug', `待审核: guild=${guildId} user=${userId} matched=${matchedCount}/${requiredThreshold}`,
|
|
809
855
|
`处理失败验证 guild=${guildId} user=${userId} msg="${session.content || ''}" matched=${matchedCount} threshold=${requiredThreshold}`)
|
|
@@ -955,7 +1001,7 @@ export async function processBlacklistCommand(ctx: Context, session: any, rawArg
|
|
|
955
1001
|
// 严格群号检查(若开启)
|
|
956
1002
|
if (config?.enableStrictGroupCheck) {
|
|
957
1003
|
if (!/^\d{5,15}$/.test(group)) {
|
|
958
|
-
return (config.invalidGroupMessage || '群号 {group} 格式不合法或机器人不在该群中').replace('{group}', group)
|
|
1004
|
+
return renderMsg((config.invalidGroupMessage || '群号 {group} 格式不合法或机器人不在该群中').replace('{group}', group))
|
|
959
1005
|
}
|
|
960
1006
|
}
|
|
961
1007
|
const [ok, err] = await checkPermission(session, group)
|
|
@@ -988,8 +1034,9 @@ export async function processBlacklistCommand(ctx: Context, session: any, rawArg
|
|
|
988
1034
|
logger.warn(`踢出用户 ${targetUser} 失败`, e)
|
|
989
1035
|
}
|
|
990
1036
|
}
|
|
991
|
-
const tmpl = (config && config.blacklistAddSuccess) || '已将用户 {user}
|
|
992
|
-
|
|
1037
|
+
const tmpl = (config && config.blacklistAddSuccess) || '已将用户 {user} 加入{group}黑名单{reason}'
|
|
1038
|
+
const groupLabelA = group.toLowerCase() === 'all' ? '全局' : '群 ' + group
|
|
1039
|
+
return renderMsg(tmpl.replace('{user}', targetUser).replace('{group}', groupLabelA).replace('{reason}', reason ? `,原因: ${reason}` : ''))
|
|
993
1040
|
}
|
|
994
1041
|
if (op === 'r') {
|
|
995
1042
|
targetUser = parts[1]
|
|
@@ -1002,7 +1049,7 @@ export async function processBlacklistCommand(ctx: Context, session: any, rawArg
|
|
|
1002
1049
|
} else {
|
|
1003
1050
|
if (config?.enableStrictGroupCheck) {
|
|
1004
1051
|
if (!/^\d{5,15}$/.test(group)) {
|
|
1005
|
-
return (config.invalidGroupMessage || '群号 {group} 格式不合法或机器人不在该群中').replace('{group}', group)
|
|
1052
|
+
return renderMsg((config.invalidGroupMessage || '群号 {group} 格式不合法或机器人不在该群中').replace('{group}', group))
|
|
1006
1053
|
}
|
|
1007
1054
|
}
|
|
1008
1055
|
const [ok, err] = await checkPermission(session, group)
|
|
@@ -1015,8 +1062,9 @@ export async function processBlacklistCommand(ctx: Context, session: any, rawArg
|
|
|
1015
1062
|
delete entries[targetUser]
|
|
1016
1063
|
await ctx.database.set('group_verification_blacklist', { id: row.id }, { entries })
|
|
1017
1064
|
}
|
|
1018
|
-
const tmpl = (config && config.blacklistRemoveSuccess) || '
|
|
1019
|
-
|
|
1065
|
+
const tmpl = (config && config.blacklistRemoveSuccess) || '已从{group}的黑名单中移除用户 {user}'
|
|
1066
|
+
const groupLabelR = group.toLowerCase() === 'all' ? '全局' : '群 ' + group
|
|
1067
|
+
return renderMsg(tmpl.replace('{user}', targetUser).replace('{group}', groupLabelR))
|
|
1020
1068
|
}
|
|
1021
1069
|
if (op === 'l') {
|
|
1022
1070
|
group = parts[1] || getCurrentGroup()
|
|
@@ -1027,7 +1075,7 @@ export async function processBlacklistCommand(ctx: Context, session: any, rawArg
|
|
|
1027
1075
|
} else {
|
|
1028
1076
|
if (config?.enableStrictGroupCheck) {
|
|
1029
1077
|
if (!/^\d{5,15}$/.test(group)) {
|
|
1030
|
-
return (config.invalidGroupMessage || '群号 {group} 格式不合法或机器人不在该群中').replace('{group}', group)
|
|
1078
|
+
return renderMsg((config.invalidGroupMessage || '群号 {group} 格式不合法或机器人不在该群中').replace('{group}', group))
|
|
1031
1079
|
}
|
|
1032
1080
|
}
|
|
1033
1081
|
const [ok, err] = await checkPermission(session, group)
|
|
@@ -1035,13 +1083,9 @@ export async function processBlacklistCommand(ctx: Context, session: any, rawArg
|
|
|
1035
1083
|
}
|
|
1036
1084
|
const rows = await ctx.database.get('group_verification_blacklist', { groupId: group })
|
|
1037
1085
|
if (rows.length === 0) {
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
return '全局黑名单为空'
|
|
1042
|
-
}
|
|
1043
|
-
const tmpl = (config && config.blacklistListEmpty) || '群 {group} 的黑名单为空'
|
|
1044
|
-
return tmpl.replace('{group}', group)
|
|
1086
|
+
const tmpl = (config && config.blacklistListEmpty) || '{group}的黑名单为空'
|
|
1087
|
+
const groupLabelL = group && group.toLowerCase() === 'all' ? '全局' : '群 ' + group
|
|
1088
|
+
return renderMsg(tmpl.replace('{group}', groupLabelL))
|
|
1045
1089
|
}
|
|
1046
1090
|
const entries = rows[0].entries || {}
|
|
1047
1091
|
// 构造列表消息,all 也是专用前缀
|
|
@@ -1060,7 +1104,8 @@ export async function processBlacklistCommand(ctx: Context, session: any, rawArg
|
|
|
1060
1104
|
const globalHit = globalRows.length > 0 && (globalRows[0].entries || {})[targetUser] !== undefined
|
|
1061
1105
|
|
|
1062
1106
|
// 使用模板格式化回复的辅助函数
|
|
1063
|
-
const tmpl = (config && config.blacklistInfoTemplate) || '全局黑名单: {global}
|
|
1107
|
+
const tmpl = ((config && config.blacklistInfoTemplate) || '全局黑名单: {global}\\n本群黑名单: {group}')
|
|
1108
|
+
.replace(/\\\\n/g, '\x01').replace(/\\n/g, '\n').replace(/\x01/g, '\\n')
|
|
1064
1109
|
const formatReply = (localHit: boolean, groupsList?: string[]) => {
|
|
1065
1110
|
if (groupsList) {
|
|
1066
1111
|
return tmpl.replace('{global}', globalHit ? '有' : '无').replace(
|
|
@@ -1109,7 +1154,7 @@ export async function processBlacklistCommand(ctx: Context, session: any, rawArg
|
|
|
1109
1154
|
const groupId = groupArg
|
|
1110
1155
|
if (config?.enableStrictGroupCheck && groupId.toLowerCase() !== 'all') {
|
|
1111
1156
|
if (!/^\d{5,15}$/.test(groupId)) {
|
|
1112
|
-
return (config.invalidGroupMessage || '群号 {group} 格式不合法或机器人不在该群中').replace('{group}', groupId)
|
|
1157
|
+
return renderMsg((config.invalidGroupMessage || '群号 {group} 格式不合法或机器人不在该群中').replace('{group}', groupId))
|
|
1113
1158
|
}
|
|
1114
1159
|
}
|
|
1115
1160
|
const [ok, err] = await checkPermission(session, groupId)
|
|
@@ -1294,7 +1339,7 @@ export function apply(ctx: Context, config: Config) {
|
|
|
1294
1339
|
}
|
|
1295
1340
|
|
|
1296
1341
|
clogV(`权限检查 - 权限不足`)
|
|
1297
|
-
return [false, config.permissionDeniedMessage || '权限不足: 需要群主/管理员权限或koishi三级以上权限']
|
|
1342
|
+
return [false, renderMsg(config.permissionDeniedMessage || '权限不足: 需要群主/管理员权限或koishi三级以上权限')]
|
|
1298
1343
|
}
|
|
1299
1344
|
|
|
1300
1345
|
// 创建主命令及别名
|
|
@@ -1355,7 +1400,7 @@ export function apply(ctx: Context, config: Config) {
|
|
|
1355
1400
|
if ((cleanedOptions.query || cleanedOptions.remove) &&
|
|
1356
1401
|
(parsedKeywords.length > 0 || cleanedOptions.method !== undefined || cleanedOptions.threshold !== undefined ||
|
|
1357
1402
|
cleanedOptions.message !== undefined || cleanedOptions.enableMessage || cleanedOptions.disableMessage)) {
|
|
1358
|
-
return config.parameterConflictMessage || '参数冲突: -? 或 -r 不能与其他参数或关键词一起使用(仅可搭配 -i)'
|
|
1403
|
+
return renderMsg(config.parameterConflictMessage || '参数冲突: -? 或 -r 不能与其他参数或关键词一起使用(仅可搭配 -i)')
|
|
1359
1404
|
}
|
|
1360
1405
|
|
|
1361
1406
|
// 检查消息参数冲突
|
|
@@ -1511,7 +1556,7 @@ export function apply(ctx: Context, config: Config) {
|
|
|
1511
1556
|
// 处理关键词: 如果没有关键词但有其他参数,从现有配置中获取
|
|
1512
1557
|
if (keywordList.length === 0 && !cleanedOptions.query && !cleanedOptions.remove) {
|
|
1513
1558
|
if (!existingConfig) {
|
|
1514
|
-
return config.noKeywordsMessage || '请先提供关键词创建配置,或使用 -? 查询配置,-r 删除配置'
|
|
1559
|
+
return renderMsg(config.noKeywordsMessage || '请先提供关键词创建配置,或使用 -? 查询配置,-r 删除配置')
|
|
1515
1560
|
}
|
|
1516
1561
|
keywordList = existingConfig.keywords
|
|
1517
1562
|
}
|