mioku-plugin-admin 2.3.5 → 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 +463 -473
- package/commands/notice.ts +3 -3
- package/commands/personal.ts +234 -276
- package/commands/verify.ts +325 -308
- package/config.ts +29 -17
- package/index.ts +5 -7
- package/notify/index.ts +110 -140
- package/notify/welcome.ts +52 -44
- package/package.json +4 -283
- package/skills/group.ts +87 -143
- package/skills/message-image.ts +8 -9
- package/skills/personal.ts +72 -98
- package/verify/chiral.ts +4 -4
- package/verify/index.ts +59 -45
- package/verify/number.ts +4 -4
- package/verify/reaction.ts +62 -14
- package/verify/state.ts +1 -1
- package/verify/types.ts +18 -8
package/commands/group.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
Bot,
|
|
3
|
+
CommandDefinition,
|
|
4
|
+
CommandExecutionContext,
|
|
5
|
+
MiokuContext,
|
|
6
|
+
} from "mioku";
|
|
7
|
+
|
|
2
8
|
import {
|
|
3
9
|
extractImageUrl,
|
|
4
10
|
getAtUserId,
|
|
@@ -13,518 +19,502 @@ function formatGroupRole(role: string): string {
|
|
|
13
19
|
return "群成员";
|
|
14
20
|
}
|
|
15
21
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"/改群头像",
|
|
44
|
-
"/撤回",
|
|
45
|
-
"撤回",
|
|
46
|
-
].some((prefix) => text.startsWith(prefix));
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
const selfId = event.self_id;
|
|
50
|
-
const bot = ctx.pickBot(selfId);
|
|
51
|
-
if (!bot) return;
|
|
52
|
-
|
|
53
|
-
const isGroup = event.message_type === "group";
|
|
54
|
-
const groupId: number | undefined = isGroup ? event.group_id : undefined;
|
|
55
|
-
if (!isGroup || !groupId) return;
|
|
56
|
-
|
|
57
|
-
const isMaster = ctx.isOwner?.(event) ?? false;
|
|
58
|
-
const senderRole = await getMemberRole(bot, groupId, event.user_id);
|
|
59
|
-
const hasAdminPermission =
|
|
60
|
-
isMaster || senderRole === "owner" || senderRole === "admin";
|
|
61
|
-
|
|
62
|
-
const replyDone = async () => {
|
|
63
|
-
await event.reply("done");
|
|
64
|
-
};
|
|
65
|
-
const ensureAdminPermission = async (instruction?: string) => {
|
|
66
|
-
if (hasAdminPermission) return true;
|
|
67
|
-
await replyAdminErrorNotice({
|
|
68
|
-
ctx,
|
|
69
|
-
event,
|
|
70
|
-
instruction:
|
|
71
|
-
instruction ||
|
|
72
|
-
"用户想让你执行群管操作但用户不是群主或管理员,无权限让操作",
|
|
73
|
-
fallbackMessage: "你得是群主或管理员才行哦~",
|
|
74
|
-
});
|
|
75
|
-
return false;
|
|
76
|
-
};
|
|
77
|
-
const ensureDangerousTargetPermission = async (
|
|
78
|
-
targetUserId: number,
|
|
79
|
-
actionName: string,
|
|
80
|
-
) => {
|
|
81
|
-
const targetRole = await getMemberRole(bot, groupId, targetUserId);
|
|
82
|
-
if (senderRole !== targetRole) return true;
|
|
83
|
-
|
|
84
|
-
await replyAdminErrorNotice({
|
|
85
|
-
ctx,
|
|
86
|
-
event,
|
|
87
|
-
instruction: `用户想${actionName}目标成员,但操作人与被操作人群身份相同,均为${formatGroupRole(senderRole)},群管危险操作无权操作同等级成员。请明确告诉用户无权操作同级成员。`,
|
|
88
|
-
fallbackMessage: "无权操作同级成员哦~",
|
|
89
|
-
});
|
|
90
|
-
return false;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
// 普通群员只能给自己设置头衔。
|
|
94
|
-
if (text.startsWith("我要头衔")) {
|
|
95
|
-
const atUser = getAtUserId(event.message);
|
|
96
|
-
if (atUser && atUser !== event.user_id) {
|
|
97
|
-
await event.reply("管好自己呗~", true);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const title = text.replace(/^我要头衔\s*/, "").trim();
|
|
102
|
-
if (!title) {
|
|
103
|
-
await event.reply("想要什么头衔呀~", true);
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
22
|
+
type GroupContext = CommandExecutionContext & {
|
|
23
|
+
bot: Bot;
|
|
24
|
+
groupIdNum: number;
|
|
25
|
+
senderRole: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export function registerGroupAdminCommands(ctx: MiokuContext) {
|
|
29
|
+
const register = (
|
|
30
|
+
def: Omit<CommandDefinition, "handler">,
|
|
31
|
+
run: (c: GroupContext) => Promise<void>,
|
|
32
|
+
) => {
|
|
33
|
+
ctx.command({
|
|
34
|
+
...def,
|
|
35
|
+
prefixes: false,
|
|
36
|
+
handler: async (c) => {
|
|
37
|
+
const event = c.event;
|
|
38
|
+
if (event.user_id === event.self_id) return;
|
|
39
|
+
if (event.message_type !== "group") return;
|
|
40
|
+
const bot = event.bot;
|
|
41
|
+
if (!bot) return;
|
|
42
|
+
const groupIdNum = event.group_id ? Number(event.group_id) : 0;
|
|
43
|
+
if (!groupIdNum) return;
|
|
44
|
+
const senderRole = await getMemberRole(
|
|
45
|
+
bot,
|
|
46
|
+
groupIdNum,
|
|
47
|
+
Number(event.user_id),
|
|
48
|
+
);
|
|
107
49
|
try {
|
|
108
|
-
await (bot
|
|
109
|
-
groupId,
|
|
110
|
-
event.user_id,
|
|
111
|
-
title,
|
|
112
|
-
);
|
|
113
|
-
await replyDone();
|
|
50
|
+
await run({ ...c, bot, groupIdNum, senderRole });
|
|
114
51
|
} catch (err) {
|
|
52
|
+
ctx.logger.error(`[admin group] 未捕获异常: ${String(err)}`);
|
|
115
53
|
await replyAdminErrorNotice({
|
|
116
54
|
ctx,
|
|
117
55
|
event,
|
|
118
|
-
instruction:
|
|
56
|
+
instruction: `群管理指令执行时发生未捕获异常:${String(err)},请简要说明失败并建议稍后重试`,
|
|
119
57
|
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
120
58
|
error: err,
|
|
121
59
|
});
|
|
122
60
|
}
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const ensureDangerousTargetPermission = async (
|
|
66
|
+
c: GroupContext,
|
|
67
|
+
targetUserId: number,
|
|
68
|
+
actionName: string,
|
|
69
|
+
): Promise<boolean> => {
|
|
70
|
+
const { bot, groupIdNum, senderRole, event } = c;
|
|
71
|
+
const targetRole = await getMemberRole(bot, groupIdNum, targetUserId);
|
|
72
|
+
if (senderRole !== targetRole) return true;
|
|
73
|
+
await replyAdminErrorNotice({
|
|
74
|
+
ctx,
|
|
75
|
+
event,
|
|
76
|
+
instruction: `用户想${actionName}目标成员,但操作人与被操作人群身份相同,均为${formatGroupRole(senderRole)},群管危险操作无权操作同等级成员。请明确告诉用户无权操作同级成员。`,
|
|
77
|
+
fallbackMessage: "无权操作同级成员哦~",
|
|
78
|
+
});
|
|
79
|
+
return false;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
register(
|
|
83
|
+
{
|
|
84
|
+
name: "我要头衔",
|
|
85
|
+
match: /^我要头衔/,
|
|
86
|
+
description: "普通群员给自己设置专属头衔",
|
|
87
|
+
usage: "我要头衔 头衔内容",
|
|
88
|
+
},
|
|
89
|
+
async (c) => {
|
|
90
|
+
const { ctx, event, bot, groupIdNum, body } = c;
|
|
91
|
+
const atUser = getAtUserId(event.message);
|
|
92
|
+
if (atUser != null && atUser !== Number(event.user_id)) {
|
|
93
|
+
await event.reply("管好自己呗~", true);
|
|
123
94
|
return;
|
|
124
95
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
96
|
+
const title = body.replace(/^我要头衔\s*/, "").trim();
|
|
97
|
+
if (!title) {
|
|
98
|
+
await event.reply("想要什么头衔呀~", true);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
await bot.setMemberTitle(groupIdNum, event.user_id!, title);
|
|
103
|
+
await event.reply("done");
|
|
104
|
+
} catch (err) {
|
|
105
|
+
await replyAdminErrorNotice({
|
|
106
|
+
ctx,
|
|
107
|
+
event,
|
|
108
|
+
instruction: `为用户设置个人头衔执行失败:${String(err)},请简要说明失败并建议稍后重试`,
|
|
109
|
+
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
110
|
+
error: err,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
register(
|
|
117
|
+
{
|
|
118
|
+
name: "/改头衔",
|
|
119
|
+
match: /^\/?改头衔(?:\s|$)/,
|
|
120
|
+
permission: "admin",
|
|
121
|
+
description: "设置群成员专属头衔",
|
|
122
|
+
usage: "/改头衔 qq号或@人 头衔",
|
|
123
|
+
},
|
|
124
|
+
async (c) => {
|
|
125
|
+
const { ctx, event, bot, groupIdNum, body } = c;
|
|
126
|
+
const rest = body.replace(/^\/?改头衔\s*/, "").trim();
|
|
127
|
+
const atUser = getAtUserId(event.message);
|
|
128
|
+
let targetUser: number | undefined = atUser;
|
|
129
|
+
let title: string;
|
|
130
|
+
|
|
131
|
+
const isSlashCommand = body.startsWith("/");
|
|
132
|
+
|
|
133
|
+
if (atUser) {
|
|
134
|
+
title = rest.replace(/@\d+\s*/, "").trim();
|
|
135
|
+
} else {
|
|
136
|
+
const parts = rest.split(/\s+/);
|
|
137
|
+
if (parts.length < 2) {
|
|
157
138
|
if (!isSlashCommand) return;
|
|
158
139
|
await replyAdminErrorNotice({
|
|
159
140
|
ctx,
|
|
160
141
|
event,
|
|
161
142
|
instruction:
|
|
162
|
-
"
|
|
143
|
+
"用户在让你修改别人的头衔时缺少参数,请提示用户命令后需要加qq号或@人",
|
|
163
144
|
fallbackMessage: "想改谁的头衔呀~",
|
|
164
145
|
});
|
|
165
146
|
return;
|
|
166
147
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
await (bot as any).setGroupSpecialTitle(groupId, targetUser, title);
|
|
170
|
-
await replyDone();
|
|
171
|
-
} catch (err) {
|
|
172
|
-
await replyAdminErrorNotice({
|
|
173
|
-
ctx,
|
|
174
|
-
event,
|
|
175
|
-
instruction: `改头衔执行失败: ${String(err)},请简要说明失败并建议稍后重试`,
|
|
176
|
-
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
177
|
-
error: err,
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
return;
|
|
148
|
+
targetUser = parseInt(parts[0], 10);
|
|
149
|
+
title = parts.slice(1).join(" ");
|
|
181
150
|
}
|
|
182
151
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
if (!atUser) {
|
|
193
|
-
await replyAdminErrorNotice({
|
|
194
|
-
ctx,
|
|
195
|
-
event,
|
|
196
|
-
instruction:
|
|
197
|
-
"用户希望从群聊中踢出一个人,请提醒要在命令后@要踢出的人",
|
|
198
|
-
fallbackMessage: "你想踢掉谁呀~",
|
|
199
|
-
});
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
if (!(await ensureDangerousTargetPermission(atUser, "踢出"))) return;
|
|
203
|
-
try {
|
|
204
|
-
await bot.api("set_group_kick", {
|
|
205
|
-
group_id: groupId,
|
|
206
|
-
user_id: atUser,
|
|
207
|
-
});
|
|
208
|
-
await replyDone();
|
|
209
|
-
} catch (err) {
|
|
210
|
-
await replyAdminErrorNotice({
|
|
211
|
-
ctx,
|
|
212
|
-
event,
|
|
213
|
-
instruction: `踢执行失败${String(err)},请简要说明失败`,
|
|
214
|
-
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
215
|
-
error: err,
|
|
216
|
-
});
|
|
217
|
-
}
|
|
152
|
+
if (!targetUser || !title) {
|
|
153
|
+
if (!isSlashCommand) return;
|
|
154
|
+
await replyAdminErrorNotice({
|
|
155
|
+
ctx,
|
|
156
|
+
event,
|
|
157
|
+
instruction:
|
|
158
|
+
"用户触发改头衔时参数无效,请提示用户命令后需要加qq号或@人",
|
|
159
|
+
fallbackMessage: "想改谁的头衔呀~",
|
|
160
|
+
});
|
|
218
161
|
return;
|
|
219
162
|
}
|
|
220
163
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
const atUser = getAtUserId(event.message);
|
|
233
|
-
|
|
234
|
-
// 不带 / 的命令必须有@才触发,否则静默忽略
|
|
235
|
-
const isSlashCommand = text.startsWith("/");
|
|
236
|
-
if (!atUser && !isSlashCommand) {
|
|
237
|
-
return; // 静默忽略,不走 chat runtime
|
|
238
|
-
}
|
|
239
|
-
if (!atUser) {
|
|
240
|
-
await replyAdminErrorNotice({
|
|
241
|
-
ctx,
|
|
242
|
-
event,
|
|
243
|
-
instruction:
|
|
244
|
-
"用户希望禁言一个人,但是没有目标,请提醒要在命令后@要禁言的人",
|
|
245
|
-
fallbackMessage: "想把谁关小黑屋呀~",
|
|
246
|
-
});
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
if (!(await ensureDangerousTargetPermission(atUser, "禁言"))) return;
|
|
250
|
-
const rest = text.replace(/^\/?禁言\s*/, "").trim();
|
|
251
|
-
const durationStr = rest.replace(/@\d+\s*/, "").trim();
|
|
252
|
-
const durationSec = parseDuration(durationStr) || 10 * 60;
|
|
253
|
-
try {
|
|
254
|
-
await bot.setGroupBan(groupId, atUser, durationSec);
|
|
255
|
-
await replyDone();
|
|
256
|
-
} catch (err) {
|
|
257
|
-
await replyAdminErrorNotice({
|
|
258
|
-
ctx,
|
|
259
|
-
event,
|
|
260
|
-
instruction: `禁言执行失败:${String(err)},请简要说明失败并建议稍后重试`,
|
|
261
|
-
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
262
|
-
error: err,
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
return;
|
|
164
|
+
try {
|
|
165
|
+
await bot.setMemberTitle(groupIdNum, targetUser, title);
|
|
166
|
+
await event.reply("done");
|
|
167
|
+
} catch (err) {
|
|
168
|
+
await replyAdminErrorNotice({
|
|
169
|
+
ctx,
|
|
170
|
+
event,
|
|
171
|
+
instruction: `改头衔执行失败: ${String(err)},请简要说明失败并建议稍后重试`,
|
|
172
|
+
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
173
|
+
error: err,
|
|
174
|
+
});
|
|
266
175
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
"用户想让你解除一个人的禁言,请提醒要在命令后@要解禁的人",
|
|
291
|
-
fallbackMessage: "你想拉谁出来呀~",
|
|
292
|
-
});
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
try {
|
|
296
|
-
await bot.setGroupBan(groupId, atUser, 0);
|
|
297
|
-
await replyDone();
|
|
298
|
-
} catch (err) {
|
|
299
|
-
await replyAdminErrorNotice({
|
|
300
|
-
ctx,
|
|
301
|
-
event,
|
|
302
|
-
instruction: `解禁执行失败:${String(err)},请简要说明失败`,
|
|
303
|
-
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
304
|
-
error: err,
|
|
305
|
-
});
|
|
306
|
-
}
|
|
176
|
+
},
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
register(
|
|
180
|
+
{
|
|
181
|
+
name: "/踢",
|
|
182
|
+
match: /^\/?踢(?:\s|$)/,
|
|
183
|
+
permission: "admin",
|
|
184
|
+
description: "踢出群成员",
|
|
185
|
+
},
|
|
186
|
+
async (c) => {
|
|
187
|
+
const { ctx, event, bot, groupIdNum, body } = c;
|
|
188
|
+
const atUser = getAtUserId(event.message);
|
|
189
|
+
const isSlashCommand = body.startsWith("/");
|
|
190
|
+
if (!atUser && !isSlashCommand) return;
|
|
191
|
+
if (!atUser) {
|
|
192
|
+
await replyAdminErrorNotice({
|
|
193
|
+
ctx,
|
|
194
|
+
event,
|
|
195
|
+
instruction:
|
|
196
|
+
"用户希望从群聊中踢出一个人,请提醒要在命令后@要踢出的人",
|
|
197
|
+
fallbackMessage: "你想踢掉谁呀~",
|
|
198
|
+
});
|
|
307
199
|
return;
|
|
308
200
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
201
|
+
if (!(await ensureDangerousTargetPermission(c, atUser, "踢出"))) return;
|
|
202
|
+
try {
|
|
203
|
+
await bot.kickMember(groupIdNum, atUser);
|
|
204
|
+
await event.reply("done");
|
|
205
|
+
} catch (err) {
|
|
206
|
+
await replyAdminErrorNotice({
|
|
207
|
+
ctx,
|
|
208
|
+
event,
|
|
209
|
+
instruction: `踢执行失败${String(err)},请简要说明失败`,
|
|
210
|
+
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
211
|
+
error: err,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
register(
|
|
218
|
+
{
|
|
219
|
+
name: "/禁言",
|
|
220
|
+
match: /^\/?禁(?:言)?(?:\s|$)/,
|
|
221
|
+
permission: "admin",
|
|
222
|
+
description: "禁言群成员(支持分钟/小时/天)",
|
|
223
|
+
usage: "/禁言 @人 10分钟",
|
|
224
|
+
},
|
|
225
|
+
async (c) => {
|
|
226
|
+
const { ctx, event, bot, groupIdNum, body } = c;
|
|
227
|
+
const atUser = getAtUserId(event.message);
|
|
228
|
+
const isSlashCommand = body.startsWith("/");
|
|
229
|
+
if (!atUser && !isSlashCommand) return;
|
|
230
|
+
if (!atUser) {
|
|
231
|
+
await replyAdminErrorNotice({
|
|
232
|
+
ctx,
|
|
233
|
+
event,
|
|
234
|
+
instruction:
|
|
235
|
+
"用户希望禁言一个人,但是没有目标,请提醒要在命令后@要禁言的人",
|
|
236
|
+
fallbackMessage: "想把谁关小黑屋呀~",
|
|
237
|
+
});
|
|
344
238
|
return;
|
|
345
239
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
240
|
+
if (!(await ensureDangerousTargetPermission(c, atUser, "禁言"))) return;
|
|
241
|
+
const rest = body.replace(/^\/?禁言\s*/, "").trim();
|
|
242
|
+
const durationStr = rest.replace(/@\d+\s*/, "").trim();
|
|
243
|
+
const durationSec = parseDuration(durationStr) || 10 * 60;
|
|
244
|
+
try {
|
|
245
|
+
await bot.banMember(groupIdNum, atUser, durationSec);
|
|
246
|
+
await event.reply("done");
|
|
247
|
+
} catch (err) {
|
|
248
|
+
await replyAdminErrorNotice({
|
|
249
|
+
ctx,
|
|
250
|
+
event,
|
|
251
|
+
instruction: `禁言执行失败:${String(err)},请简要说明失败并建议稍后重试`,
|
|
252
|
+
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
253
|
+
error: err,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
register(
|
|
260
|
+
{
|
|
261
|
+
name: "/解禁",
|
|
262
|
+
match: /^\/?解(?:禁)?(?:\s|$)/,
|
|
263
|
+
permission: "admin",
|
|
264
|
+
description: "解除群成员禁言",
|
|
265
|
+
},
|
|
266
|
+
async (c) => {
|
|
267
|
+
const { ctx, event, bot, groupIdNum, body } = c;
|
|
268
|
+
const atUser = getAtUserId(event.message);
|
|
269
|
+
const isSlashCommand = body.startsWith("/");
|
|
270
|
+
if (!atUser && !isSlashCommand) return;
|
|
271
|
+
if (!atUser) {
|
|
272
|
+
await replyAdminErrorNotice({
|
|
273
|
+
ctx,
|
|
274
|
+
event,
|
|
275
|
+
instruction:
|
|
276
|
+
"用户想让你解除一个人的禁言,请提醒要在命令后@要解禁的人",
|
|
277
|
+
fallbackMessage: "你想拉谁出来呀~",
|
|
278
|
+
});
|
|
364
279
|
return;
|
|
365
280
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
281
|
+
try {
|
|
282
|
+
await bot.banMember(groupIdNum, atUser, 0);
|
|
283
|
+
await event.reply("done");
|
|
284
|
+
} catch (err) {
|
|
285
|
+
await replyAdminErrorNotice({
|
|
286
|
+
ctx,
|
|
287
|
+
event,
|
|
288
|
+
instruction: `解禁执行失败:${String(err)},请简要说明失败`,
|
|
289
|
+
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
290
|
+
error: err,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
register(
|
|
297
|
+
{
|
|
298
|
+
name: "/设管理",
|
|
299
|
+
match: /^\/?设管理(?:\s|$)/,
|
|
300
|
+
permission: "admin",
|
|
301
|
+
description: "设置群管理员",
|
|
302
|
+
},
|
|
303
|
+
async (c) => {
|
|
304
|
+
const { ctx, event, bot, groupIdNum, body } = c;
|
|
305
|
+
const atUser = getAtUserId(event.message);
|
|
306
|
+
const isSlashCommand = body.startsWith("/");
|
|
307
|
+
if (!atUser && !isSlashCommand) return;
|
|
308
|
+
if (!atUser) {
|
|
309
|
+
await replyAdminErrorNotice({
|
|
310
|
+
ctx,
|
|
311
|
+
event,
|
|
312
|
+
instruction:
|
|
313
|
+
"用户希望你把一个人设置成群管理员,但是没有目标,请提醒要在命令后@要设为管理的人",
|
|
314
|
+
fallbackMessage: "你想给谁管理呀~",
|
|
315
|
+
});
|
|
384
316
|
return;
|
|
385
317
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
318
|
+
try {
|
|
319
|
+
await bot.setMemberAdmin(groupIdNum, atUser, true);
|
|
320
|
+
await event.reply("done");
|
|
321
|
+
} catch (err) {
|
|
322
|
+
await replyAdminErrorNotice({
|
|
323
|
+
ctx,
|
|
324
|
+
event,
|
|
325
|
+
instruction: `设管理执行失败:${String(err)},请简要说明失败`,
|
|
326
|
+
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
327
|
+
error: err,
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
},
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
register(
|
|
334
|
+
{
|
|
335
|
+
name: "/全体禁言",
|
|
336
|
+
match: /^\/全体禁言$/,
|
|
337
|
+
permission: "admin",
|
|
338
|
+
description: "开启全体禁言",
|
|
339
|
+
},
|
|
340
|
+
async (c) => {
|
|
341
|
+
const { ctx, event, bot, groupIdNum } = c;
|
|
342
|
+
try {
|
|
343
|
+
await bot.setGroupWholeBan(groupIdNum, true);
|
|
344
|
+
await event.reply("done");
|
|
345
|
+
} catch (err) {
|
|
346
|
+
await replyAdminErrorNotice({
|
|
347
|
+
ctx,
|
|
348
|
+
event,
|
|
349
|
+
instruction: `全体禁言执行失败:${String(err)},请简要说明失败`,
|
|
350
|
+
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
351
|
+
error: err,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
register(
|
|
358
|
+
{
|
|
359
|
+
name: "/全体解禁",
|
|
360
|
+
match: /^\/全体解禁$/,
|
|
361
|
+
permission: "admin",
|
|
362
|
+
description: "关闭全体禁言",
|
|
363
|
+
},
|
|
364
|
+
async (c) => {
|
|
365
|
+
const { ctx, event, bot, groupIdNum } = c;
|
|
366
|
+
try {
|
|
367
|
+
await bot.setGroupWholeBan(groupIdNum, false);
|
|
368
|
+
await event.reply("done");
|
|
369
|
+
} catch (err) {
|
|
370
|
+
await replyAdminErrorNotice({
|
|
371
|
+
ctx,
|
|
372
|
+
event,
|
|
373
|
+
instruction: `全体解禁执行失败:${String(err)},请简要说明失败`,
|
|
374
|
+
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
375
|
+
error: err,
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
register(
|
|
382
|
+
{
|
|
383
|
+
name: "/改群名片",
|
|
384
|
+
match: /^\/?改群名片(?:\s|$)/,
|
|
385
|
+
permission: "admin",
|
|
386
|
+
description: "修改Bot在群里的名片",
|
|
387
|
+
},
|
|
388
|
+
async (c) => {
|
|
389
|
+
const { ctx, event, bot, groupIdNum, body } = c;
|
|
390
|
+
const card = body.replace(/^\/?改群名片\s*/, "").trim();
|
|
391
|
+
if (!card) {
|
|
392
|
+
await replyAdminErrorNotice({
|
|
393
|
+
ctx,
|
|
394
|
+
event,
|
|
395
|
+
instruction: "用户希望修改你在群里的昵称,但是没有指定名称。",
|
|
396
|
+
fallbackMessage: "名片内容呢~",
|
|
397
|
+
});
|
|
414
398
|
return;
|
|
415
399
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
400
|
+
try {
|
|
401
|
+
await bot.setMemberCard(groupIdNum, event.self_id ?? "", card);
|
|
402
|
+
await event.reply("done");
|
|
403
|
+
} catch (err) {
|
|
404
|
+
await replyAdminErrorNotice({
|
|
405
|
+
ctx,
|
|
406
|
+
event,
|
|
407
|
+
instruction: `改群名片执行失败,${String(err)}`,
|
|
408
|
+
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
409
|
+
error: err,
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
);
|
|
414
|
+
|
|
415
|
+
register(
|
|
416
|
+
{
|
|
417
|
+
name: "/改群昵称",
|
|
418
|
+
match: /^\/改群昵称/,
|
|
419
|
+
permission: "admin",
|
|
420
|
+
description: "修改群聊名称",
|
|
421
|
+
},
|
|
422
|
+
async (c) => {
|
|
423
|
+
const { ctx, event, bot, groupIdNum, body } = c;
|
|
424
|
+
const groupName = body.replace(/^\/改群昵称\s*/, "").trim();
|
|
425
|
+
if (!groupName) {
|
|
426
|
+
await replyAdminErrorNotice({
|
|
427
|
+
ctx,
|
|
428
|
+
event,
|
|
429
|
+
instruction:
|
|
430
|
+
"用户希望修改群聊的名称,但是没有告诉你新的名称是啥,请提醒输入群聊名称",
|
|
431
|
+
fallbackMessage: "群名想改成什么呀~",
|
|
432
|
+
});
|
|
448
433
|
return;
|
|
449
434
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
435
|
+
try {
|
|
436
|
+
await bot.setGroupName(groupIdNum, groupName);
|
|
437
|
+
await event.reply("done");
|
|
438
|
+
} catch (err) {
|
|
439
|
+
await replyAdminErrorNotice({
|
|
440
|
+
ctx,
|
|
441
|
+
event,
|
|
442
|
+
instruction: `改群昵称执行失败${String(err)}`,
|
|
443
|
+
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
444
|
+
error: err,
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
},
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
register(
|
|
451
|
+
{
|
|
452
|
+
name: "/改群头像",
|
|
453
|
+
match: /^\/改群头像/,
|
|
454
|
+
permission: "admin",
|
|
455
|
+
description: "修改群头像",
|
|
456
|
+
},
|
|
457
|
+
async (c) => {
|
|
458
|
+
const { ctx, event, bot, groupIdNum } = c;
|
|
459
|
+
const imageUrl = extractImageUrl(event.message);
|
|
460
|
+
if (!imageUrl) {
|
|
461
|
+
await replyAdminErrorNotice({
|
|
462
|
+
ctx,
|
|
463
|
+
event,
|
|
464
|
+
instruction:
|
|
465
|
+
"用户希望修改群聊的群头像,但是没有发你图片,请提醒附带图片或引用图片。",
|
|
466
|
+
fallbackMessage: "图片呢图片呢~",
|
|
467
|
+
});
|
|
482
468
|
return;
|
|
483
469
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
470
|
+
try {
|
|
471
|
+
await bot.setGroupPortrait(groupIdNum, imageUrl);
|
|
472
|
+
await event.reply("done");
|
|
473
|
+
} catch (err) {
|
|
474
|
+
await replyAdminErrorNotice({
|
|
475
|
+
ctx,
|
|
476
|
+
event,
|
|
477
|
+
instruction: `改群头像执行失败 ${String(err)}`,
|
|
478
|
+
fallbackMessage: `出错了,笨蛋~ ${String(err)}`,
|
|
479
|
+
error: err,
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
},
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
register(
|
|
486
|
+
{
|
|
487
|
+
name: "/撤回",
|
|
488
|
+
match: /^\/?撤回(?:\s|$)/,
|
|
489
|
+
permission: "admin",
|
|
490
|
+
description: "撤回别人的消息",
|
|
491
|
+
usage: "引用一条消息后输入 /撤回",
|
|
492
|
+
},
|
|
493
|
+
async (c) => {
|
|
494
|
+
const { ctx, event, bot } = c;
|
|
495
|
+
const quotedId = event.quote_id;
|
|
496
|
+
if (!quotedId) {
|
|
497
|
+
await replyAdminErrorNotice({
|
|
498
|
+
ctx,
|
|
499
|
+
event,
|
|
500
|
+
instruction:
|
|
501
|
+
"用户希望撤回一条消息,但命令中没有引用具体消息,请提醒用户引用要撤回的消息后输入 /撤回",
|
|
502
|
+
fallbackMessage: "要撤回哪条消息呀~先引用一下~",
|
|
503
|
+
});
|
|
516
504
|
return;
|
|
517
505
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
506
|
+
try {
|
|
507
|
+
await bot.recallMessage(quotedId);
|
|
508
|
+
await event.reply("done");
|
|
509
|
+
} catch (err) {
|
|
510
|
+
await replyAdminErrorNotice({
|
|
511
|
+
ctx,
|
|
512
|
+
event,
|
|
513
|
+
instruction: `撤回消息执行失败:${String(err)}。失败原因通常是Bot没有该消息的撤回权限(需要Bot为群主或管理员,且消息发出不超过2分钟),管理员无法撤回管理员的消息或群主的消息。`,
|
|
514
|
+
fallbackMessage: `撤回失败啦~可能是没权限或消息超过2分钟了:${String(err)}`,
|
|
515
|
+
error: err,
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
},
|
|
519
|
+
);
|
|
530
520
|
}
|