mioku-plugin-admin 3.0.0 → 3.0.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/commands/group.ts +461 -451
- package/commands/personal.ts +129 -99
- package/commands/verify.ts +315 -306
- package/index.ts +0 -2
- package/notify/index.ts +2 -2
- package/package.json +2 -279
package/commands/verify.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
Bot,
|
|
3
|
+
CommandDefinition,
|
|
4
|
+
CommandExecutionContext,
|
|
5
|
+
MessageEvent,
|
|
6
|
+
MiokuContext,
|
|
7
|
+
} from "mioku";
|
|
2
8
|
import { extractImageUrls, getAtUserId, getMemberRole } from "../config";
|
|
3
9
|
import {
|
|
4
10
|
getGroupVerifyConfig,
|
|
@@ -29,7 +35,12 @@ const VERIFY_MODE_LABELS: Record<string, string> = {
|
|
|
29
35
|
chiral: "手性碳",
|
|
30
36
|
};
|
|
31
37
|
|
|
32
|
-
|
|
38
|
+
type VerifyContext = CommandExecutionContext & {
|
|
39
|
+
bot: Bot;
|
|
40
|
+
groupIdNum: number;
|
|
41
|
+
groupName: string;
|
|
42
|
+
selfId: number;
|
|
43
|
+
};
|
|
33
44
|
|
|
34
45
|
async function extractQuoteImageUrls(event: MessageEvent): Promise<string[]> {
|
|
35
46
|
const eventAny = event as MessageEvent & {
|
|
@@ -44,345 +55,343 @@ async function extractQuoteImageUrls(event: MessageEvent): Promise<string[]> {
|
|
|
44
55
|
export function registerVerifyCommands(options: VerifyCommandOptions) {
|
|
45
56
|
const { ctx, getVerifyConfig, setVerifyConfig, verifyController } = options;
|
|
46
57
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const bot = event.bot;
|
|
73
|
-
if (!bot) return;
|
|
74
|
-
|
|
75
|
-
const isMaster = ctx.isOwner?.(event) ?? false;
|
|
76
|
-
const senderRole = await getMemberRole(bot, groupIdNum, Number(event.user_id));
|
|
77
|
-
const hasAdminPermission =
|
|
78
|
-
isMaster || senderRole === "owner" || senderRole === "admin";
|
|
79
|
-
|
|
80
|
-
const ensureAdminPermission = async (instruction?: string) => {
|
|
81
|
-
if (hasAdminPermission) return true;
|
|
82
|
-
await replyAdminErrorNotice({
|
|
83
|
-
ctx,
|
|
84
|
-
event,
|
|
85
|
-
instruction:
|
|
86
|
-
instruction ||
|
|
87
|
-
"用户想使用入群验证相关指令,但不是群主或管理员,无权限。请告诉用户需要管理权限。",
|
|
88
|
-
fallbackMessage: "你得是群主或管理员才行哦~",
|
|
89
|
-
});
|
|
90
|
-
return false;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const groupName =
|
|
94
|
-
String(event?.group?.group_name || "").trim() || String(groupIdNum);
|
|
95
|
-
|
|
96
|
-
// /开启验证 | #开启验证
|
|
97
|
-
if (text === "/开启验证" || text === "#开启验证") {
|
|
98
|
-
if (!(await ensureAdminPermission())) return;
|
|
99
|
-
|
|
100
|
-
const botRole = await getMemberRole(bot, groupIdNum, selfId);
|
|
101
|
-
if (botRole !== "owner" && botRole !== "admin") {
|
|
58
|
+
const register = (
|
|
59
|
+
def: Omit<CommandDefinition, "handler">,
|
|
60
|
+
run: (c: VerifyContext) => Promise<void>,
|
|
61
|
+
) => {
|
|
62
|
+
ctx.command({
|
|
63
|
+
...def,
|
|
64
|
+
prefixes: false,
|
|
65
|
+
handler: async (c) => {
|
|
66
|
+
const event = c.event;
|
|
67
|
+
if (event.user_id === event.self_id) return;
|
|
68
|
+
if (event.message_type !== "group") return;
|
|
69
|
+
const bot = event.bot;
|
|
70
|
+
if (!bot) return;
|
|
71
|
+
const groupIdNum = event.group_id ? Number(event.group_id) : 0;
|
|
72
|
+
if (!groupIdNum) return;
|
|
73
|
+
try {
|
|
74
|
+
await run({
|
|
75
|
+
...c,
|
|
76
|
+
bot,
|
|
77
|
+
groupIdNum,
|
|
78
|
+
groupName: String(event?.group?.group_name || "").trim() || String(groupIdNum),
|
|
79
|
+
selfId: Number(event.self_id),
|
|
80
|
+
});
|
|
81
|
+
} catch (err) {
|
|
82
|
+
ctx.logger.error(`[admin verify] 未捕获异常: ${String(err)}`);
|
|
102
83
|
await replyAdminErrorNotice({
|
|
103
84
|
ctx,
|
|
104
85
|
event,
|
|
105
|
-
instruction:
|
|
106
|
-
|
|
107
|
-
|
|
86
|
+
instruction: `入群验证指令执行时发生未捕获异常:${String(err)},请简要说明失败并建议稍后重试。`,
|
|
87
|
+
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
88
|
+
error: err,
|
|
108
89
|
});
|
|
109
|
-
return;
|
|
110
90
|
}
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
};
|
|
111
94
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
95
|
+
register(
|
|
96
|
+
{
|
|
97
|
+
name: "/开启验证",
|
|
98
|
+
match: /^[/#]开启验证$/,
|
|
99
|
+
permission: "admin",
|
|
100
|
+
description: "开启本群入群验证",
|
|
101
|
+
},
|
|
102
|
+
async (c) => {
|
|
103
|
+
const { ctx, event, bot, groupIdNum, selfId } = c;
|
|
104
|
+
const botRole = await getMemberRole(bot, groupIdNum, selfId);
|
|
105
|
+
if (botRole !== "owner" && botRole !== "admin") {
|
|
106
|
+
await replyAdminErrorNotice({
|
|
107
|
+
ctx,
|
|
108
|
+
event,
|
|
109
|
+
instruction:
|
|
110
|
+
"用户想开启入群验证,但Bot在群内不是群主或管理员,无法执行撤回/踢人等验证操作。请告诉用户需要先把Bot设为群主或管理员。",
|
|
111
|
+
fallbackMessage: "我得是群主或管理员才能开验证哦~",
|
|
120
112
|
});
|
|
121
|
-
await setVerifyConfig(next);
|
|
122
|
-
await event.reply("已开启入群验证~", true);
|
|
123
113
|
return;
|
|
124
114
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
115
|
+
const current = getVerifyConfig();
|
|
116
|
+
const groupCfg = getGroupVerifyConfig(current, groupIdNum);
|
|
117
|
+
if (groupCfg.enabled) {
|
|
118
|
+
await event.reply("本群已经开启验证啦~", true);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const next = upsertGroupVerifyConfig(current, groupIdNum, {
|
|
122
|
+
enabled: true,
|
|
123
|
+
});
|
|
124
|
+
await setVerifyConfig(next);
|
|
125
|
+
await event.reply("已开启入群验证~", true);
|
|
126
|
+
},
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
register(
|
|
130
|
+
{
|
|
131
|
+
name: "/关闭验证",
|
|
132
|
+
match: /^[/#]关闭验证$/,
|
|
133
|
+
permission: "admin",
|
|
134
|
+
description: "关闭本群入群验证",
|
|
135
|
+
},
|
|
136
|
+
async (c) => {
|
|
137
|
+
const { event, groupIdNum } = c;
|
|
138
|
+
const current = getVerifyConfig();
|
|
139
|
+
const groupCfg = getGroupVerifyConfig(current, groupIdNum);
|
|
140
|
+
if (!groupCfg.enabled) {
|
|
141
|
+
await event.reply("本群还没开启验证哦~", true);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const next = upsertGroupVerifyConfig(current, groupIdNum, {
|
|
145
|
+
enabled: false,
|
|
146
|
+
});
|
|
147
|
+
await setVerifyConfig(next);
|
|
148
|
+
await event.reply("已关闭入群验证~", true);
|
|
149
|
+
},
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
register(
|
|
153
|
+
{
|
|
154
|
+
name: "/切换验证模式",
|
|
155
|
+
match: /^[/#]切换验证模式(?:\s|$)/,
|
|
156
|
+
permission: "admin",
|
|
157
|
+
description: "切换验证模式:回应/数字/手性碳",
|
|
158
|
+
usage: "/切换验证模式 回应",
|
|
159
|
+
},
|
|
160
|
+
async (c) => {
|
|
161
|
+
const { ctx, event, groupIdNum, body } = c;
|
|
162
|
+
const arg = body.replace(/^[/#]切换验证模式\s*/, "").trim();
|
|
163
|
+
const mode = normalizeVerifyMode(arg);
|
|
164
|
+
if (!arg) {
|
|
165
|
+
await replyAdminErrorNotice({
|
|
166
|
+
ctx,
|
|
167
|
+
event,
|
|
168
|
+
instruction:
|
|
169
|
+
"用户想切换验证模式但没指定模式。请告诉用户可用模式:回应、数字、手性碳,用法:/切换验证模式 回应。",
|
|
170
|
+
fallbackMessage: "想切换成哪种模式呀~回应/数字/手性碳",
|
|
138
171
|
});
|
|
139
|
-
await setVerifyConfig(next);
|
|
140
|
-
await event.reply("已关闭入群验证~", true);
|
|
141
172
|
return;
|
|
142
173
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
);
|
|
174
|
+
const current = getVerifyConfig();
|
|
175
|
+
const next = upsertGroupVerifyConfig(current, groupIdNum, { mode });
|
|
176
|
+
await setVerifyConfig(next);
|
|
177
|
+
await event.reply(
|
|
178
|
+
`验证模式已切换为:${VERIFY_MODE_LABELS[mode]}~`,
|
|
179
|
+
true,
|
|
180
|
+
);
|
|
181
|
+
},
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
register(
|
|
185
|
+
{
|
|
186
|
+
name: "/绕过验证",
|
|
187
|
+
match: /^[/#]绕过验证(?:\s|$)/,
|
|
188
|
+
permission: "admin",
|
|
189
|
+
description: "绕过指定新成员的验证直接欢迎",
|
|
190
|
+
usage: "/绕过验证 @新成员",
|
|
191
|
+
},
|
|
192
|
+
async (c) => {
|
|
193
|
+
const { ctx, event, groupIdNum, groupName, selfId } = c;
|
|
194
|
+
const atUser = getAtUserId(event.message);
|
|
195
|
+
if (!atUser) {
|
|
196
|
+
await replyAdminErrorNotice({
|
|
197
|
+
ctx,
|
|
198
|
+
event,
|
|
199
|
+
instruction:
|
|
200
|
+
"用户想绕过某位新成员的验证,但没有@目标成员。请提醒用户在命令后@要绕过验证的新成员。",
|
|
201
|
+
fallbackMessage: "要绕过谁呀~先@一下~",
|
|
202
|
+
});
|
|
173
203
|
return;
|
|
174
204
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
205
|
+
try {
|
|
206
|
+
await verifyController.bypassVerification({
|
|
207
|
+
selfId,
|
|
208
|
+
groupId: groupIdNum,
|
|
209
|
+
userId: atUser,
|
|
210
|
+
groupName,
|
|
211
|
+
});
|
|
212
|
+
await event.reply("done");
|
|
213
|
+
} catch (err) {
|
|
214
|
+
await replyAdminErrorNotice({
|
|
215
|
+
ctx,
|
|
216
|
+
event,
|
|
217
|
+
instruction: `绕过验证执行失败:${String(err)},请简要说明失败并建议稍后重试。`,
|
|
218
|
+
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
219
|
+
error: err,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
register(
|
|
226
|
+
{
|
|
227
|
+
name: "/重新验证",
|
|
228
|
+
match: /^[/#]重新验证(?:\s|$)/,
|
|
229
|
+
permission: "admin",
|
|
230
|
+
description: "让指定成员重新进行入群验证",
|
|
231
|
+
usage: "/重新验证 @成员",
|
|
232
|
+
},
|
|
233
|
+
async (c) => {
|
|
234
|
+
const { ctx, event, bot, groupIdNum, groupName, selfId } = c;
|
|
235
|
+
const atUser = getAtUserId(event.message);
|
|
236
|
+
if (!atUser) {
|
|
237
|
+
await replyAdminErrorNotice({
|
|
238
|
+
ctx,
|
|
239
|
+
event,
|
|
240
|
+
instruction:
|
|
241
|
+
"用户想让某人重新进行入群验证,但没有@目标成员。请提醒用户在命令后@要重新验证的成员。",
|
|
242
|
+
fallbackMessage: "要重新验证谁呀~先@一下~",
|
|
243
|
+
});
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
const isTargetMaster = ctx.isMaster?.(atUser) ?? false;
|
|
247
|
+
const targetRole = await getMemberRole(bot, groupIdNum, atUser);
|
|
248
|
+
if (isTargetMaster || targetRole === "owner" || targetRole === "admin") {
|
|
249
|
+
await replyAdminErrorNotice({
|
|
250
|
+
ctx,
|
|
251
|
+
event,
|
|
252
|
+
instruction:
|
|
253
|
+
"用户想让一位群主/管理员/主人重新验证,但这些成员无需验证。请告诉用户该成员是管理/群主或主人,不能对其重新验证。",
|
|
254
|
+
fallbackMessage: "管理/群主或主人可不用验证哦~",
|
|
255
|
+
});
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
const started = await verifyController.restartVerification(
|
|
260
|
+
{
|
|
194
261
|
selfId,
|
|
195
262
|
groupId: groupIdNum,
|
|
196
263
|
userId: atUser,
|
|
197
264
|
groupName,
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
event,
|
|
204
|
-
instruction: `绕过验证执行失败:${String(err)},请简要说明失败并建议稍后重试。`,
|
|
205
|
-
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
206
|
-
error: err,
|
|
207
|
-
});
|
|
265
|
+
},
|
|
266
|
+
bot,
|
|
267
|
+
);
|
|
268
|
+
if (!started) {
|
|
269
|
+
await event.reply("本群还没开启验证哦~", true);
|
|
208
270
|
}
|
|
209
|
-
|
|
271
|
+
} catch (err) {
|
|
272
|
+
await replyAdminErrorNotice({
|
|
273
|
+
ctx,
|
|
274
|
+
event,
|
|
275
|
+
instruction: `重新验证执行失败:${String(err)},请简要说明失败并建议稍后重试。`,
|
|
276
|
+
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
277
|
+
error: err,
|
|
278
|
+
});
|
|
210
279
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
280
|
+
},
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
register(
|
|
284
|
+
{
|
|
285
|
+
name: "/入群提示",
|
|
286
|
+
match: /^[/#]入群提示(?:\s|$)/,
|
|
287
|
+
permission: "admin",
|
|
288
|
+
description: "设置本群自定义入群提示,可附带文字+图片",
|
|
289
|
+
usage: "/入群提示 xxx;/入群提示 关闭",
|
|
290
|
+
},
|
|
291
|
+
async (c) => {
|
|
292
|
+
const { ctx, event, groupIdNum, body } = c;
|
|
293
|
+
const rawArg = body.replace(/^[/#]入群提示\s*/, "").trim();
|
|
294
|
+
const current = getVerifyConfig();
|
|
295
|
+
const groupCfg = getGroupVerifyConfig(current, groupIdNum);
|
|
296
|
+
const directImageUrls = extractImageUrls(event.message);
|
|
297
|
+
const quoteImageUrls = await extractQuoteImageUrls(event).catch(() => []);
|
|
298
|
+
const imageUrls =
|
|
299
|
+
directImageUrls.length > 0 ? directImageUrls : quoteImageUrls;
|
|
300
|
+
|
|
301
|
+
if (rawArg === "关闭" || rawArg === "清空" || rawArg === "关") {
|
|
302
|
+
if (!hasCustomPrompt(groupCfg)) {
|
|
303
|
+
await event.reply("本群还没设置自定义入群提示哦~", true);
|
|
225
304
|
return;
|
|
226
305
|
}
|
|
306
|
+
const removedFile = groupCfg.promptImage;
|
|
307
|
+
const next = upsertGroupVerifyConfig(current, groupIdNum, {
|
|
308
|
+
customPrompt: "",
|
|
309
|
+
promptImage: "",
|
|
310
|
+
});
|
|
311
|
+
await setVerifyConfig(next);
|
|
312
|
+
await pruneGroupPromptImages(groupIdNum, []).catch(() => {});
|
|
313
|
+
ctx.logger.info(
|
|
314
|
+
`admin verify 关闭群 ${groupIdNum} 自定义入群提示,清理图片 ${removedFile}`,
|
|
315
|
+
);
|
|
316
|
+
await event.reply("已关闭本群自定义入群提示~", true);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
227
319
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
instruction:
|
|
235
|
-
"用户想让一位群主/管理员/主人重新验证,但这些成员无需验证。请告诉用户该成员是管理/群主或主人,不能对其重新验证。",
|
|
236
|
-
fallbackMessage: "管理/群主或主人可不用验证哦~",
|
|
237
|
-
});
|
|
320
|
+
if (!rawArg && !imageUrls.length) {
|
|
321
|
+
if (!hasCustomPrompt(groupCfg)) {
|
|
322
|
+
await event.reply(
|
|
323
|
+
"用法:/入群提示 xxx(最多 50 字),可附带图片(当前消息或引用消息中的图片)一起发送;/入群提示 关闭 关闭自定义提示~",
|
|
324
|
+
true,
|
|
325
|
+
);
|
|
238
326
|
return;
|
|
239
327
|
}
|
|
328
|
+
const lines = ["已开启本群自定义入群提示"];
|
|
329
|
+
lines.push(
|
|
330
|
+
groupCfg.customPrompt
|
|
331
|
+
? `文字:${groupCfg.customPrompt}`
|
|
332
|
+
: "文字:(未设置)",
|
|
333
|
+
);
|
|
334
|
+
lines.push(
|
|
335
|
+
groupCfg.promptImage
|
|
336
|
+
? `图片:已设置(filename=${groupCfg.promptImage})`
|
|
337
|
+
: "图片:(未设置)",
|
|
338
|
+
);
|
|
339
|
+
await event.reply(lines.join("\n"), true);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
240
342
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
selfId,
|
|
245
|
-
groupId: groupIdNum,
|
|
246
|
-
userId: atUser,
|
|
247
|
-
groupName,
|
|
248
|
-
},
|
|
249
|
-
bot,
|
|
250
|
-
);
|
|
251
|
-
if (!started) {
|
|
252
|
-
await event.reply("本群还没开启验证哦~", true);
|
|
253
|
-
}
|
|
254
|
-
} catch (err) {
|
|
343
|
+
if (rawArg) {
|
|
344
|
+
const argLength = Array.from(rawArg).length;
|
|
345
|
+
if (argLength > MAX_CUSTOM_PROMPT_LENGTH) {
|
|
255
346
|
await replyAdminErrorNotice({
|
|
256
347
|
ctx,
|
|
257
348
|
event,
|
|
258
|
-
instruction:
|
|
259
|
-
fallbackMessage:
|
|
260
|
-
error: err,
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// /入群提示 xxx
|
|
267
|
-
// /入群提示 关闭
|
|
268
|
-
// /入群提示(带图片,可来自当前消息或引用消息)— 仅图片也可
|
|
269
|
-
if (text.startsWith("/入群提示") || text.startsWith("#入群提示")) {
|
|
270
|
-
if (!(await ensureAdminPermission())) return;
|
|
271
|
-
|
|
272
|
-
const rawArg = text.replace(/^[/#]入群提示\s*/, "").trim();
|
|
273
|
-
const current = getVerifyConfig();
|
|
274
|
-
const groupCfg = getGroupVerifyConfig(current, groupIdNum);
|
|
275
|
-
const directImageUrls = extractImageUrls(event.message);
|
|
276
|
-
const quoteImageUrls = await extractQuoteImageUrls(event).catch(() => []);
|
|
277
|
-
const imageUrls =
|
|
278
|
-
directImageUrls.length > 0 ? directImageUrls : quoteImageUrls;
|
|
279
|
-
|
|
280
|
-
if (rawArg === "关闭" || rawArg === "清空" || rawArg === "关") {
|
|
281
|
-
if (!hasCustomPrompt(groupCfg)) {
|
|
282
|
-
await event.reply("本群还没设置自定义入群提示哦~", true);
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
const removedFile = groupCfg.promptImage;
|
|
286
|
-
const next = upsertGroupVerifyConfig(current, groupIdNum, {
|
|
287
|
-
customPrompt: "",
|
|
288
|
-
promptImage: "",
|
|
349
|
+
instruction: `用户想设置本群入群提示,但内容长度 ${argLength} 超过了上限 ${MAX_CUSTOM_PROMPT_LENGTH} 字,请明确告诉用户最多 ${MAX_CUSTOM_PROMPT_LENGTH} 字。`,
|
|
350
|
+
fallbackMessage: `最多 ${MAX_CUSTOM_PROMPT_LENGTH} 字哦~当前 ${argLength} 字`,
|
|
289
351
|
});
|
|
290
|
-
await setVerifyConfig(next);
|
|
291
|
-
await pruneGroupPromptImages(groupIdNum, []).catch(() => {});
|
|
292
|
-
ctx.logger.info(
|
|
293
|
-
`admin verify 关闭群 ${groupIdNum} 自定义入群提示,清理图片 ${removedFile}`,
|
|
294
|
-
);
|
|
295
|
-
await event.reply("已关闭本群自定义入群提示~", true);
|
|
296
352
|
return;
|
|
297
353
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
354
|
+
}
|
|
355
|
+
const nextPrompt = rawArg
|
|
356
|
+
? normalizeCustomPrompt(rawArg)
|
|
357
|
+
: groupCfg.customPrompt;
|
|
358
|
+
|
|
359
|
+
let nextImage = groupCfg.promptImage;
|
|
360
|
+
let imageNote = "";
|
|
361
|
+
if (imageUrls.length) {
|
|
362
|
+
const targetUrl = imageUrls[0];
|
|
363
|
+
const savedImage = await saveRemoteImageAsPrompt(groupIdNum, targetUrl);
|
|
364
|
+
if (savedImage) {
|
|
365
|
+
const previousImage = groupCfg.promptImage;
|
|
366
|
+
nextImage = savedImage.filename;
|
|
367
|
+
imageNote = previousImage
|
|
368
|
+
? `图片已替换(旧文件 ${previousImage} 已删除)`
|
|
369
|
+
: `图片已设置(${savedImage.filename})`;
|
|
370
|
+
if (previousImage) {
|
|
371
|
+
ctx.logger.info(
|
|
372
|
+
`admin verify 替换群 ${groupIdNum} 入群提示图片:${previousImage} -> ${savedImage.filename}`,
|
|
304
373
|
);
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
const lines = ["已开启本群自定义入群提示"];
|
|
308
|
-
lines.push(
|
|
309
|
-
groupCfg.customPrompt
|
|
310
|
-
? `文字:${groupCfg.customPrompt}`
|
|
311
|
-
: "文字:(未设置)",
|
|
312
|
-
);
|
|
313
|
-
lines.push(
|
|
314
|
-
groupCfg.promptImage
|
|
315
|
-
? `图片:已设置(filename=${groupCfg.promptImage})`
|
|
316
|
-
: "图片:(未设置)",
|
|
317
|
-
);
|
|
318
|
-
await event.reply(lines.join("\n"), true);
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
if (rawArg) {
|
|
323
|
-
const argLength = Array.from(rawArg).length;
|
|
324
|
-
if (argLength > MAX_CUSTOM_PROMPT_LENGTH) {
|
|
325
|
-
await replyAdminErrorNotice({
|
|
326
|
-
ctx,
|
|
327
|
-
event,
|
|
328
|
-
instruction: `用户想设置本群入群提示,但内容长度 ${argLength} 超过了上限 ${MAX_CUSTOM_PROMPT_LENGTH} 字,请明确告诉用户最多 ${MAX_CUSTOM_PROMPT_LENGTH} 字。`,
|
|
329
|
-
fallbackMessage: `最多 ${MAX_CUSTOM_PROMPT_LENGTH} 字哦~当前 ${argLength} 字`,
|
|
330
|
-
});
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
const nextPrompt = rawArg
|
|
335
|
-
? normalizeCustomPrompt(rawArg)
|
|
336
|
-
: groupCfg.customPrompt;
|
|
337
|
-
|
|
338
|
-
let nextImage = groupCfg.promptImage;
|
|
339
|
-
let imageNote = "";
|
|
340
|
-
if (imageUrls.length) {
|
|
341
|
-
const targetUrl = imageUrls[0];
|
|
342
|
-
const savedImage = await saveRemoteImageAsPrompt(groupIdNum, targetUrl);
|
|
343
|
-
if (savedImage) {
|
|
344
|
-
const previousImage = groupCfg.promptImage;
|
|
345
|
-
nextImage = savedImage.filename;
|
|
346
|
-
imageNote = previousImage
|
|
347
|
-
? `图片已替换(旧文件 ${previousImage} 已删除)`
|
|
348
|
-
: `图片已设置(${savedImage.filename})`;
|
|
349
|
-
if (previousImage) {
|
|
350
|
-
ctx.logger.info(
|
|
351
|
-
`admin verify 替换群 ${groupIdNum} 入群提示图片:${previousImage} -> ${savedImage.filename}`,
|
|
352
|
-
);
|
|
353
|
-
}
|
|
354
|
-
} else {
|
|
355
|
-
imageNote = "图片下载失败,请稍后重试";
|
|
356
374
|
}
|
|
375
|
+
} else {
|
|
376
|
+
imageNote = "图片下载失败,请稍后重试";
|
|
357
377
|
}
|
|
358
|
-
|
|
359
|
-
const next = upsertGroupVerifyConfig(current, groupIdNum, {
|
|
360
|
-
customPrompt: nextPrompt,
|
|
361
|
-
promptImage: nextImage,
|
|
362
|
-
});
|
|
363
|
-
await setVerifyConfig(next);
|
|
364
|
-
await pruneGroupPromptImages(groupIdNum, nextImage ? [nextImage] : []).catch(
|
|
365
|
-
() => {},
|
|
366
|
-
);
|
|
367
|
-
|
|
368
|
-
const lines = ["已更新本群自定义入群提示"];
|
|
369
|
-
if (rawArg) lines.push(`文字:${nextPrompt}`);
|
|
370
|
-
else if (groupCfg.customPrompt)
|
|
371
|
-
lines.push(`文字(保持):${groupCfg.customPrompt}`);
|
|
372
|
-
if (imageUrls.length && imageNote) lines.push(imageNote);
|
|
373
|
-
await event.reply(lines.join("\n"), true);
|
|
374
|
-
return;
|
|
375
378
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
ctx,
|
|
381
|
-
event,
|
|
382
|
-
instruction: `入群验证指令执行时发生未捕获异常:${String(err)},请简要说明失败并建议稍后重试。`,
|
|
383
|
-
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
384
|
-
error: err,
|
|
379
|
+
|
|
380
|
+
const next = upsertGroupVerifyConfig(current, groupIdNum, {
|
|
381
|
+
customPrompt: nextPrompt,
|
|
382
|
+
promptImage: nextImage,
|
|
385
383
|
});
|
|
386
|
-
|
|
387
|
-
|
|
384
|
+
await setVerifyConfig(next);
|
|
385
|
+
await pruneGroupPromptImages(groupIdNum, nextImage ? [nextImage] : []).catch(
|
|
386
|
+
() => {},
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
const lines = ["已更新本群自定义入群提示"];
|
|
390
|
+
if (rawArg) lines.push(`文字:${nextPrompt}`);
|
|
391
|
+
else if (groupCfg.customPrompt)
|
|
392
|
+
lines.push(`文字(保持):${groupCfg.customPrompt}`);
|
|
393
|
+
if (imageUrls.length && imageNote) lines.push(imageNote);
|
|
394
|
+
await event.reply(lines.join("\n"), true);
|
|
395
|
+
},
|
|
396
|
+
);
|
|
388
397
|
}
|