koishi-plugin-maibot 1.7.67 → 1.7.69

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.
@@ -1,26 +1,12 @@
1
1
  import type { UserBinding } from './database';
2
2
  export declare function normalizePreviewUserId(userId: string | number): string;
3
- /** 与插件配置 bindingPlayerNameMatch 对应 */
4
- export interface BindingPlayerNameMatchConfig {
5
- /** 0–100:规范化后玩家名相似度下限(编辑距离比值×100)。100 须完全一致 */
6
- minSimilarityPercent?: number;
7
- }
8
- export interface BindingNameMatchOptions {
9
- minSimilarityPercent: number;
10
- }
11
- export declare function resolveBindingNameMatchOptions(cfg?: BindingPlayerNameMatchConfig): BindingNameMatchOptions;
12
- /** 玩家名规范化:去首尾空白 + Unicode NFKC(全角英数、兼容字符等与半角统一) */
13
- export declare function normalizePlayerNameForMatch(name: string): string;
14
- /** 0–1,分母为 max(len);用于短玩家名 */
15
- export declare function playerNameSimilarityRatio(a: string, b: string): number;
16
3
  /**
17
- * 校验 preview 与绑定是否为同一街机账号(加密 UserID + 可选绑定时的玩家名)
18
- * @param nameMatch 玩家名:先 NFKC 规范化,再按 minSimilarityPercent 比较编辑距离比值
4
+ * 校验 preview 与绑定是否为同一街机账号:仅比较绑定记录的 maiUid 与二维码 preview 的 UserID。
19
5
  */
20
6
  export declare function verifyPreviewMatchesBinding(binding: UserBinding, preview: {
21
7
  UserID: string | number;
22
8
  UserName?: string;
23
- }, nameMatch?: BindingNameMatchOptions): string | null;
9
+ }): string | null;
24
10
  /** lastStateAt:maibot_user_rebind_state.lastBindChangeAt;bindTime:当前绑定记录的 bindTime(无绑定则 0) */
25
11
  export declare function msUntilBindChangeAllowed(lastStateAtMs: number, bindTimeMs: number, minIntervalDays: number): number;
26
12
  export declare function formatBindChangeWaitHuman(ms: number): string;
@@ -1 +1 @@
1
- {"version":3,"file":"binding-verify.d.ts","sourceRoot":"","sources":["../src/binding-verify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAEtE;AAED,sCAAsC;AACtC,MAAM,WAAW,4BAA4B;IAC3C,+CAA+C;IAC/C,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED,MAAM,WAAW,uBAAuB;IACtC,oBAAoB,EAAE,MAAM,CAAA;CAC7B;AAID,wBAAgB,8BAA8B,CAC5C,GAAG,CAAC,EAAE,4BAA4B,GACjC,uBAAuB,CAKzB;AAED,mDAAmD;AACnD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhE;AAsBD,8BAA8B;AAC9B,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAKtE;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,EACvD,SAAS,GAAE,uBAA0D,GACpE,MAAM,GAAG,IAAI,CAgCf;AAED,8FAA8F;AAC9F,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,MAAM,GACtB,MAAM,CAMR;AAED,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAS5D"}
1
+ {"version":3,"file":"binding-verify.d.ts","sourceRoot":"","sources":["../src/binding-verify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAEtE;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACtD,MAAM,GAAG,IAAI,CAcf;AAED,8FAA8F;AAC9F,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,MAAM,GACtB,MAAM,CAMR;AAED,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAS5D"}
@@ -1,94 +1,27 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.normalizePreviewUserId = normalizePreviewUserId;
4
- exports.resolveBindingNameMatchOptions = resolveBindingNameMatchOptions;
5
- exports.normalizePlayerNameForMatch = normalizePlayerNameForMatch;
6
- exports.playerNameSimilarityRatio = playerNameSimilarityRatio;
7
4
  exports.verifyPreviewMatchesBinding = verifyPreviewMatchesBinding;
8
5
  exports.msUntilBindChangeAllowed = msUntilBindChangeAllowed;
9
6
  exports.formatBindChangeWaitHuman = formatBindChangeWaitHuman;
10
7
  function normalizePreviewUserId(userId) {
11
8
  return String(userId);
12
9
  }
13
- const DEFAULT_MIN_SIMILARITY = 100;
14
- function resolveBindingNameMatchOptions(cfg) {
15
- let p = cfg?.minSimilarityPercent;
16
- if (typeof p !== 'number' || Number.isNaN(p))
17
- p = DEFAULT_MIN_SIMILARITY;
18
- p = Math.min(100, Math.max(0, p));
19
- return { minSimilarityPercent: p };
20
- }
21
- /** 玩家名规范化:去首尾空白 + Unicode NFKC(全角英数、兼容字符等与半角统一) */
22
- function normalizePlayerNameForMatch(name) {
23
- return name.normalize('NFKC').trim();
24
- }
25
- function levenshtein(a, b) {
26
- const m = a.length;
27
- const n = b.length;
28
- if (m === 0)
29
- return n;
30
- if (n === 0)
31
- return m;
32
- const dp = new Uint32Array(n + 1);
33
- for (let j = 0; j <= n; j++)
34
- dp[j] = j;
35
- for (let i = 1; i <= m; i++) {
36
- let prev = dp[0];
37
- dp[0] = i;
38
- for (let j = 1; j <= n; j++) {
39
- const tmp = dp[j];
40
- const cost = a[i - 1] === b[j - 1] ? 0 : 1;
41
- dp[j] = Math.min(dp[j] + 1, dp[j - 1] + 1, prev + cost);
42
- prev = tmp;
43
- }
44
- }
45
- return dp[n];
46
- }
47
- /** 0–1,分母为 max(len);用于短玩家名 */
48
- function playerNameSimilarityRatio(a, b) {
49
- if (a === b)
50
- return 1;
51
- const maxLen = Math.max(a.length, b.length);
52
- if (maxLen === 0)
53
- return 1;
54
- return Math.max(0, 1 - levenshtein(a, b) / maxLen);
55
- }
56
10
  /**
57
- * 校验 preview 与绑定是否为同一街机账号(加密 UserID + 可选绑定时的玩家名)
58
- * @param nameMatch 玩家名:先 NFKC 规范化,再按 minSimilarityPercent 比较编辑距离比值
11
+ * 校验 preview 与绑定是否为同一街机账号:仅比较绑定记录的 maiUid 与二维码 preview 的 UserID。
59
12
  */
60
- function verifyPreviewMatchesBinding(binding, preview, nameMatch = resolveBindingNameMatchOptions()) {
13
+ function verifyPreviewMatchesBinding(binding, preview) {
61
14
  const pid = normalizePreviewUserId(preview.UserID);
62
15
  if (pid === '-1' || preview.UserID === -1) {
63
- return '❌ 无效或过期的二维码,无法完成验证。';
16
+ return '❌ 无效或过期的二维码,无法完成验证。请重新获取玩家二维码后重试。';
64
17
  }
65
18
  if (String(binding.maiUid) !== pid) {
66
- return '❌ 当前二维码对应的街机账号与绑定不一致,请使用已绑定账号本人微信获取的二维码。';
67
- }
68
- const boundName = binding.boundPlayerName?.trim();
69
- if (!boundName || preview.UserName === undefined) {
70
- return null;
71
- }
72
- const current = String(preview.UserName).trim();
73
- const na = normalizePlayerNameForMatch(boundName);
74
- const nb = normalizePlayerNameForMatch(current);
75
- if (!na) {
76
- return null;
77
- }
78
- if (!nb) {
79
- return `❌ 玩家名与绑定记录不一致(绑定为「${boundName}」,当前玩家名为空)。如已改名请使用解绑卡流程后重新绑定。`;
80
- }
81
- const min = nameMatch.minSimilarityPercent;
82
- const ratio = playerNameSimilarityRatio(na, nb);
83
- const pct = ratio * 100;
84
- if (pct + 1e-9 >= min) {
85
- return null;
86
- }
87
- const minDisp = Number.isInteger(min) ? String(min) : min.toFixed(1);
88
- if (min >= 100) {
89
- return `❌ 玩家名与绑定记录不一致(绑定为「${boundName}」,当前为「${current}」)。如已改名请使用解绑卡流程后重新绑定。`;
19
+ return (`❌ 街机账号 UID 不一致:\n` +
20
+ `• 当前绑定记录的 UID:${binding.maiUid}\n` +
21
+ `• 当前二维码对应的 UID:${pid}\n` +
22
+ `若您已更换游戏账号,请使用 /mai解绑 后重新绑定(换绑冷却期内请使用 /mai解绑卡)。`);
90
23
  }
91
- return `❌ 玩家名与绑定记录不一致(绑定为「${boundName}」,当前为「${current}」)。规范化后相似度约 ${pct.toFixed(0)}%(要求≥${minDisp}%)。可在插件配置中调低「玩家名最低相似度」或解绑后重新绑定。`;
24
+ return null;
92
25
  }
93
26
  /** lastStateAt:maibot_user_rebind_state.lastBindChangeAt;bindTime:当前绑定记录的 bindTime(无绑定则 0) */
94
27
  function msUntilBindChangeAllowed(lastStateAtMs, bindTimeMs, minIntervalDays) {
@@ -1 +1 @@
1
- {"version":3,"file":"binding-verify.js","sourceRoot":"","sources":["../src/binding-verify.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"binding-verify.js","sourceRoot":"","sources":["../src/binding-verify.ts"],"names":[],"mappings":";;AAEA,wDAEC;AAKD,kEAiBC;AAGD,4DAUC;AAED,8DASC;AAhDD,SAAgB,sBAAsB,CAAC,MAAuB;IAC5D,OAAO,MAAM,CAAC,MAAM,CAAC,CAAA;AACvB,CAAC;AAED;;GAEG;AACH,SAAgB,2BAA2B,CACzC,OAAoB,EACpB,OAAuD;IAEvD,MAAM,GAAG,GAAG,sBAAsB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAClD,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;QAC1C,OAAO,mCAAmC,CAAA;IAC5C,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC;QACnC,OAAO,CACL,mBAAmB;YACnB,iBAAiB,OAAO,CAAC,MAAM,IAAI;YACnC,kBAAkB,GAAG,IAAI;YACzB,gDAAgD,CACjD,CAAA;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,8FAA8F;AAC9F,SAAgB,wBAAwB,CACtC,aAAqB,EACrB,UAAkB,EAClB,eAAuB;IAEvB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,IAAI,CAAC,EAAE,UAAU,IAAI,CAAC,CAAC,CAAA;IAC1D,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,CAAA;IACnB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;IAChE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA;IACjC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,CAAA;AACrC,CAAC;AAED,SAAgB,yBAAyB,CAAC,EAAU;IAClD,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,GAAG,CAAA;IACvB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAA;IAChD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAA;IACrE,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;IACpD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAA;IAC3D,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;IACrD,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAA;IAC9B,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAA;AAC9B,CAAC"}
package/lib/index.d.ts CHANGED
@@ -69,11 +69,6 @@ export interface Config {
69
69
  minDaysBetweenBindChange: number;
70
70
  shopUrl?: string;
71
71
  };
72
- /** SGID / preview 校验时:绑定快照玩家名与当前玩家名的匹配(含 /mai状态、mymai 等) */
73
- bindingPlayerNameMatch?: {
74
- /** 0–100:NFKC 规范化后,编辑距离相似度下限;100 为须完全一致。全角如 Milk 与半角 Milk 在 100 下通常视为一致 */
75
- minSimilarityPercent: number;
76
- };
77
72
  }
78
73
  export declare const Config: Schema<Config>;
79
74
  export declare function apply(ctx: Context, config: Config): void;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/lib/index.js CHANGED
@@ -88,7 +88,7 @@ exports.Config = koishi_1.Schema.object({
88
88
  autoRecallProcessingMessages: koishi_1.Schema.boolean().default(true).description('B50任务完成后自动撤回"正在处理"和"已提交"消息'),
89
89
  authLevelForCardAdmin: koishi_1.Schema.number().default(4).description('卡密管理指令(生成/删除/导出)需要的 Koishi authority,默认 4'),
90
90
  priorityCooldown: koishi_1.Schema.object({
91
- enabled: koishi_1.Schema.boolean().default(false).description('开启后,非管理员、非优先用户执行功能指令需等待冷却'),
91
+ enabled: koishi_1.Schema.boolean().default(false).description('开启后,对参与冷却槽的 mai 指令在指令执行前统一检查间隔(见插件内 commandToCooldownSlot:含发票/B50/状态等分槽,其余多数为 default 槽;帮助、绑定类、maialert、管理员指令等不参与)'),
92
92
  adminBypassAuthority: koishi_1.Schema.number()
93
93
  .default(4)
94
94
  .description('仅当用户 Koishi authority 大于该数值时视为管理员:绕过冷却,并自动写入永久个人优先(带标记,权限回落时自动删除);卡密兑换的优先记录不会被删除。'),
@@ -123,15 +123,6 @@ exports.Config = koishi_1.Schema.object({
123
123
  minDaysBetweenBindChange: 30,
124
124
  shopUrl: '',
125
125
  }),
126
- bindingPlayerNameMatch: koishi_1.Schema.object({
127
- minSimilarityPercent: koishi_1.Schema.number()
128
- .default(100)
129
- .min(0)
130
- .max(100)
131
- .description('玩家名最低相似度(0–100)。先进行 Unicode NFKC 规范化(全角/半角英数字统一)再按编辑距离计算;100 表示须完全一致。略低于 100 可容忍少量字符差异(改名、显示差异等)。'),
132
- })
133
- .description('绑定记录中的玩家名与 preview 的校验(maiUid 一致时的第二道校验)')
134
- .default({ minSimilarityPercent: 100 }),
135
126
  });
136
127
  // 我认识了很多朋友 以下是我认识的好朋友们!
137
128
  // Fracture_Hikaritsu
@@ -210,6 +201,36 @@ function getSessionCommandUsageHint(session) {
210
201
  function isMaiPluginCommandName(name) {
211
202
  return name.trim().startsWith('mai');
212
203
  }
204
+ /**
205
+ * <spec:text> 会把「clear -g 群号」整段吃成一个参数;从首尾拆出 -g 群标识,并与 .option('-g') 合并(优先已解析的 -g)。
206
+ */
207
+ function splitGroupPrioritySpecAndGuild(specRaw, optionGuild) {
208
+ let specStr = (specRaw ?? '').trim();
209
+ let guild = String(optionGuild ?? '').trim();
210
+ const lead = specStr.match(/^\s*-g\s+(\S+)\s+([\s\S]+)$/i);
211
+ if (lead) {
212
+ if (!guild)
213
+ guild = lead[1];
214
+ specStr = lead[2].trim();
215
+ }
216
+ const tail = specStr.match(/^([\s\S]+?)\s+-g\s+(\S+)\s*$/i);
217
+ if (tail) {
218
+ specStr = tail[1].trim();
219
+ if (!guild)
220
+ guild = tail[2];
221
+ }
222
+ return { spec: specStr, guild };
223
+ }
224
+ /** 群优先表里的 guildKey 多为 platform:guildId;仅填数字时按当前会话平台补前缀 */
225
+ function normalizeGuildKeyForPriority(gk, session) {
226
+ const t = gk.trim();
227
+ if (!t)
228
+ return t;
229
+ if (!/^\d+$/.test(t))
230
+ return t;
231
+ const p = String(session.platform || '').trim().toLowerCase();
232
+ return p ? `${p}:${t}` : t;
233
+ }
213
234
  async function computeMaiCommandUsageHint(command, session) {
214
235
  if (!command || !isMaiPluginCommandName(String(command.name || '')))
215
236
  return '';
@@ -1174,7 +1195,7 @@ async function getQrText(session, ctx, api, binding, config, timeout = 60000, pr
1174
1195
  if (cacheAge < cacheValidDuration && binding.lastQrCode.startsWith('SGWCMAID')) {
1175
1196
  try {
1176
1197
  const previewCached = await api.getPreview(config.machineInfo.clientId, binding.lastQrCode);
1177
- const vErr = (0, binding_verify_1.verifyPreviewMatchesBinding)(binding, previewCached, (0, binding_verify_1.resolveBindingNameMatchOptions)(config.bindingPlayerNameMatch));
1198
+ const vErr = (0, binding_verify_1.verifyPreviewMatchesBinding)(binding, previewCached);
1178
1199
  if (!vErr) {
1179
1200
  if (previewCached.UserName != null && !binding.boundPlayerName?.trim()) {
1180
1201
  await ctx.database.set('maibot_bindings', { userId: binding.userId }, {
@@ -1288,7 +1309,7 @@ async function getQrText(session, ctx, api, binding, config, timeout = 60000, pr
1288
1309
  return { qrText: '', error: '无效或过期的二维码' };
1289
1310
  }
1290
1311
  if (binding) {
1291
- const vErr = (0, binding_verify_1.verifyPreviewMatchesBinding)(binding, preview, (0, binding_verify_1.resolveBindingNameMatchOptions)(config.bindingPlayerNameMatch));
1312
+ const vErr = (0, binding_verify_1.verifyPreviewMatchesBinding)(binding, preview);
1292
1313
  if (vErr) {
1293
1314
  await session.send(vErr);
1294
1315
  return { qrText: '', error: vErr };
@@ -1426,20 +1447,29 @@ function apply(ctx, config) {
1426
1447
  const keys = await getSessionBindingKeys(ctx, session);
1427
1448
  return keys[0] || String(session.userId || '');
1428
1449
  }
1429
- async function gateUserCooldown(session, commandName) {
1430
- if (!session)
1431
- return undefined;
1432
- const hit = await (0, priority_cooldown_1.checkCommandCooldown)(ctx, session, priorityCooldownCfg, commandName, getCooldownPrimaryUserId, async (s) => getSessionBindingKeys(ctx, s));
1433
- return hit ?? undefined;
1434
- }
1435
- async function markUserCooldown(session, commandName) {
1436
- if (!session)
1450
+ ctx.on('command/before-execute', async (argv) => {
1451
+ const sess = argv.session;
1452
+ const cmd = argv.command;
1453
+ if (!sess || !cmd)
1454
+ return;
1455
+ const cmdName = String(cmd.name || '');
1456
+ if (!priorityCooldownCfg?.enabled)
1457
+ return;
1458
+ if (!isMaiPluginCommandName(cmdName))
1459
+ return;
1460
+ if ((0, priority_cooldown_1.commandToCooldownSlot)(cmdName) === null)
1437
1461
  return;
1438
- const uid = await getCooldownPrimaryUserId(session);
1462
+ const wl = checkWhitelist(sess, config);
1463
+ if (!wl.allowed)
1464
+ return;
1465
+ const hit = await (0, priority_cooldown_1.checkCommandCooldown)(ctx, sess, priorityCooldownCfg, cmdName, getCooldownPrimaryUserId, async (s) => getSessionBindingKeys(ctx, s));
1466
+ if (hit)
1467
+ return hit;
1468
+ const uid = await getCooldownPrimaryUserId(sess);
1439
1469
  if (!uid)
1440
1470
  return;
1441
- await (0, priority_cooldown_1.recordCommandCooldown)(ctx, uid, commandName, priorityCooldownCfg);
1442
- }
1471
+ await (0, priority_cooldown_1.recordCommandCooldown)(ctx, uid, cmdName, priorityCooldownCfg);
1472
+ });
1443
1473
  /**
1444
1474
  * 获取上传任务的统计信息(平均处理时长和今日成功率)
1445
1475
  * @param commandPrefix 命令前缀,用于筛选日志(如 'mai上传B50' 或 'mai上传落雪b50')
@@ -2249,7 +2279,7 @@ function apply(ctx, config) {
2249
2279
  /mai管理员取消群组优先 [群标识] — 取消群组优先;省略时在群内则针对当前群
2250
2280
  /mai管理员取消个人优先 <@或ID> — 清除个人优先记录
2251
2281
  /mai管理员设置个人优先 <@或ID> <spec> — spec:永久、7d、clear 等
2252
- /mai管理员设置群组优先 <spec> [-g 群标识] — 直接改群组优先;spec:永久、7d、clear;-g 省略且群内则当前群
2282
+ /mai管理员设置群组优先 <spec> [-g 群标识] — spec 与 -g 可同一段输入(如 clear -g qq:群号);纯数字 -g 会按当前平台补前缀;-g 省略且在群内则当前群
2253
2283
  /maibypass <@用户|用户ID> — 清除该用户当前全部指令冷却(别名 /mai管理员清除冷却)`;
2254
2284
  }
2255
2285
  helpText += `
@@ -2685,9 +2715,6 @@ function apply(ctx, config) {
2685
2715
  if (!whitelistCheck.allowed) {
2686
2716
  return whitelistCheck.message || '本群暂时没有被授权使用本Bot的功能,请添加官方群聊1072033605。';
2687
2717
  }
2688
- const cdStatus = await gateUserCooldown(session, 'mai状态');
2689
- if (cdStatus)
2690
- return cdStatus;
2691
2718
  try {
2692
2719
  // 获取目标用户绑定
2693
2720
  const { binding, isProxy, error } = await getTargetBinding(session, targetUserId);
@@ -2904,7 +2931,6 @@ function apply(ctx, config) {
2904
2931
  status: 'success',
2905
2932
  result: statusInfo,
2906
2933
  });
2907
- await markUserCooldown(session, 'mai状态');
2908
2934
  return appendRefId(statusInfo, refId);
2909
2935
  }
2910
2936
  catch (error) {
@@ -3326,9 +3352,6 @@ function apply(ctx, config) {
3326
3352
  if (!whitelistCheck.allowed) {
3327
3353
  return whitelistCheck.message || '本群暂时没有被授权使用本Bot的功能,请添加官方群聊1072033605。';
3328
3354
  }
3329
- const cdInv = await gateUserCooldown(session, 'mai发票');
3330
- if (cdInv)
3331
- return cdInv;
3332
3355
  const multiple = multipleInput ? Number(multipleInput) : 2;
3333
3356
  if (!Number.isInteger(multiple) || multiple < 2 || multiple > 6) {
3334
3357
  return '❌ 倍数必须是2-6之间的整数\n例如:/mai发票 3\n例如:/mai发票 6 @userid';
@@ -3427,7 +3450,6 @@ function apply(ctx, config) {
3427
3450
  status: 'success',
3428
3451
  result: successMessage,
3429
3452
  });
3430
- await markUserCooldown(session, 'mai发票');
3431
3453
  return appendRefId(successMessage, refId);
3432
3454
  }
3433
3455
  catch (error) {
@@ -3552,9 +3574,6 @@ function apply(ctx, config) {
3552
3574
  if (!whitelistCheck.allowed) {
3553
3575
  return whitelistCheck.message || '本群暂时没有被授权使用本Bot的功能,请添加官方群聊1072033605。';
3554
3576
  }
3555
- const cdB50u = await gateUserCooldown(session, 'mai上传B50');
3556
- if (cdB50u)
3557
- return cdB50u;
3558
3577
  try {
3559
3578
  // 解析参数:可能是SGID或targetUserId
3560
3579
  let qrCode;
@@ -3595,7 +3614,7 @@ function apply(ctx, config) {
3595
3614
  if (preview.UserID === -1 || (typeof preview.UserID === 'string' && preview.UserID === '-1')) {
3596
3615
  return '❌ 无效或过期的二维码,请重新发送';
3597
3616
  }
3598
- const vErr = (0, binding_verify_1.verifyPreviewMatchesBinding)(binding, preview, (0, binding_verify_1.resolveBindingNameMatchOptions)(config.bindingPlayerNameMatch));
3617
+ const vErr = (0, binding_verify_1.verifyPreviewMatchesBinding)(binding, preview);
3599
3618
  if (vErr) {
3600
3619
  return vErr;
3601
3620
  }
@@ -3690,7 +3709,6 @@ function apply(ctx, config) {
3690
3709
  result: successMessage,
3691
3710
  apiResponse: result,
3692
3711
  });
3693
- await markUserCooldown(session, 'mai上传B50');
3694
3712
  // 发送成功消息并获取消息ID(用于后续撤回)
3695
3713
  const successMsgIds = await sendAndGetMessageIds(session, appendRefId(successMessage, refId));
3696
3714
  // 合并处理中消息ID和成功消息ID
@@ -3734,9 +3752,6 @@ function apply(ctx, config) {
3734
3752
  if (!whitelistCheck.allowed) {
3735
3753
  return whitelistCheck.message || '本群暂时没有被授权使用本Bot的功能,请添加官方群聊1072033605。';
3736
3754
  }
3737
- const cdUa = await gateUserCooldown(session, 'maiua');
3738
- if (cdUa)
3739
- return cdUa;
3740
3755
  try {
3741
3756
  // 解析参数:可能是SGID/URL或落雪代码或目标用户
3742
3757
  let qrCode;
@@ -3784,7 +3799,7 @@ function apply(ctx, config) {
3784
3799
  if (preview.UserID === -1 || (typeof preview.UserID === 'string' && preview.UserID === '-1')) {
3785
3800
  return '❌ 无效或过期的二维码,请重新发送';
3786
3801
  }
3787
- const vErr = (0, binding_verify_1.verifyPreviewMatchesBinding)(binding, preview, (0, binding_verify_1.resolveBindingNameMatchOptions)(config.bindingPlayerNameMatch));
3802
+ const vErr = (0, binding_verify_1.verifyPreviewMatchesBinding)(binding, preview);
3788
3803
  if (vErr) {
3789
3804
  return vErr;
3790
3805
  }
@@ -4008,9 +4023,6 @@ function apply(ctx, config) {
4008
4023
  if (results.length === 0) {
4009
4024
  return `⚠️ 未能发起上传请求${proxyTip}`;
4010
4025
  }
4011
- if (results.some(r => /B50任务已提交/.test(r) && r.includes('✅'))) {
4012
- await markUserCooldown(session, 'maiua');
4013
- }
4014
4026
  return `${results.join('\n\n')}${proxyTip ? `\n${proxyTip}` : ''}`;
4015
4027
  }
4016
4028
  catch (error) {
@@ -4152,9 +4164,6 @@ function apply(ctx, config) {
4152
4164
  if (!whitelistCheck.allowed) {
4153
4165
  return whitelistCheck.message || '本群暂时没有被授权使用本Bot的功能,请添加官方群聊1072033605。';
4154
4166
  }
4155
- const cdItem = await gateUserCooldown(session, 'mai获取收藏品');
4156
- if (cdItem)
4157
- return cdItem;
4158
4167
  try {
4159
4168
  // 解析首参:可为 SGID/链接 或 目标用户(代操作)
4160
4169
  let qrCode;
@@ -4220,7 +4229,7 @@ function apply(ctx, config) {
4220
4229
  if (preview.UserID === -1 || (typeof preview.UserID === 'string' && preview.UserID === '-1')) {
4221
4230
  return '❌ 无效或过期的二维码,请重新发送';
4222
4231
  }
4223
- const vErr = (0, binding_verify_1.verifyPreviewMatchesBinding)(binding, preview, (0, binding_verify_1.resolveBindingNameMatchOptions)(config.bindingPlayerNameMatch));
4232
+ const vErr = (0, binding_verify_1.verifyPreviewMatchesBinding)(binding, preview);
4224
4233
  if (vErr) {
4225
4234
  return vErr;
4226
4235
  }
@@ -4290,7 +4299,6 @@ function apply(ctx, config) {
4290
4299
  return '❌ 获取收藏品失败:服务器返回未成功,请稍后再试或刷新二维码后再试。';
4291
4300
  }
4292
4301
  }
4293
- await markUserCooldown(session, 'mai获取收藏品');
4294
4302
  return `✅ 已为 ${maskUserId(binding.maiUid)} 获取收藏品${proxyTip}\n类型: ${selectedType?.label}\nID: ${itemId}\n数量: ${stockFinal}`;
4295
4303
  }
4296
4304
  catch (error) {
@@ -4319,9 +4327,6 @@ function apply(ctx, config) {
4319
4327
  if (!whitelistCheck.allowed) {
4320
4328
  return whitelistCheck.message || '本群暂时没有被授权使用本Bot的功能,请添加官方群聊1072033605。';
4321
4329
  }
4322
- const cdVer = await gateUserCooldown(session, 'mai修改版本号');
4323
- if (cdVer)
4324
- return cdVer;
4325
4330
  try {
4326
4331
  let qrCode;
4327
4332
  let targetUserId;
@@ -4347,7 +4352,7 @@ function apply(ctx, config) {
4347
4352
  if (preview.UserID === -1 || (typeof preview.UserID === 'string' && preview.UserID === '-1')) {
4348
4353
  return '❌ 无效或过期的二维码,请重新发送';
4349
4354
  }
4350
- const vErr = (0, binding_verify_1.verifyPreviewMatchesBinding)(binding, preview, (0, binding_verify_1.resolveBindingNameMatchOptions)(config.bindingPlayerNameMatch));
4355
+ const vErr = (0, binding_verify_1.verifyPreviewMatchesBinding)(binding, preview);
4351
4356
  if (vErr) {
4352
4357
  return vErr;
4353
4358
  }
@@ -4420,7 +4425,6 @@ function apply(ctx, config) {
4420
4425
  }
4421
4426
  return '❌ 修改版本号失败:服务器返回未成功,请稍后再试或刷新二维码后再试。';
4422
4427
  }
4423
- await markUserCooldown(session, 'mai修改版本号');
4424
4428
  return `✅ 已为 ${maskUserId(binding.maiUid)} 修改版本号${proxyTip}\n机台版本: ${romVer}\n数据版本: ${dataVer}`;
4425
4429
  }
4426
4430
  catch (error) {
@@ -4695,9 +4699,6 @@ function apply(ctx, config) {
4695
4699
  if (!whitelistCheck.allowed) {
4696
4700
  return whitelistCheck.message || '本群暂时没有被授权使用本Bot的功能,请添加官方群聊1072033605。';
4697
4701
  }
4698
- const cdLx = await gateUserCooldown(session, 'mai上传落雪b50');
4699
- if (cdLx)
4700
- return cdLx;
4701
4702
  // 解析参数:第一个参数可能是SGID/URL或落雪代码
4702
4703
  let qrCode;
4703
4704
  let lxnsCode;
@@ -4752,7 +4753,7 @@ function apply(ctx, config) {
4752
4753
  if (preview.UserID === -1 || (typeof preview.UserID === 'string' && preview.UserID === '-1')) {
4753
4754
  return '❌ 无效或过期的二维码,请重新发送';
4754
4755
  }
4755
- const vErr = (0, binding_verify_1.verifyPreviewMatchesBinding)(binding, preview, (0, binding_verify_1.resolveBindingNameMatchOptions)(config.bindingPlayerNameMatch));
4756
+ const vErr = (0, binding_verify_1.verifyPreviewMatchesBinding)(binding, preview);
4756
4757
  if (vErr) {
4757
4758
  return vErr;
4758
4759
  }
@@ -4843,7 +4844,6 @@ function apply(ctx, config) {
4843
4844
  result: successMessage,
4844
4845
  apiResponse: result,
4845
4846
  });
4846
- await markUserCooldown(session, 'mai上传落雪b50');
4847
4847
  // 发送成功消息并获取消息ID(用于后续撤回)
4848
4848
  const successMsgIds = await sendAndGetMessageIds(session, appendRefId(successMessage, refId));
4849
4849
  // 合并处理中消息ID和成功消息ID
@@ -6320,6 +6320,9 @@ function apply(ctx, config) {
6320
6320
  });
6321
6321
  ctx.command('mai管理员设置群组优先 <spec:text>', '直接设置群组优先(-g 指定群,默认当前群)')
6322
6322
  .userFields(['authority'])
6323
+ .usage(' 示例:/mai管理员设置群组优先 clear -g qq:5911013814031454\n' +
6324
+ '或:/mai管理员设置群组优先 -g qq:5911013814031454 永久\n' +
6325
+ '(仅数字群号时请写 qq:群号;在群内执行可省略 -g)')
6323
6326
  .option('guild', '-g <guildKey:string> 群标识,如 qq:群号')
6324
6327
  .action(async ({ session, options }, spec) => {
6325
6328
  if (!session)
@@ -6327,14 +6330,16 @@ function apply(ctx, config) {
6327
6330
  if ((session.user?.authority ?? 0) < authLevelForCardAdmin) {
6328
6331
  return `❌ 权限不足,需要 auth 等级 ${authLevelForCardAdmin} 以上`;
6329
6332
  }
6330
- if (!spec?.trim()) {
6333
+ const { spec: specOnly, guild: guildOpt } = splitGroupPrioritySpecAndGuild(spec, options?.guild);
6334
+ if (!specOnly) {
6331
6335
  return '❌ 用法:/mai管理员设置群组优先 <永久|7d|clear> [-g 群标识]';
6332
6336
  }
6333
- const sp = (0, priority_cooldown_1.parsePriorityAdminSpec)(spec);
6337
+ const sp = (0, priority_cooldown_1.parsePriorityAdminSpec)(specOnly);
6334
6338
  if (sp === null) {
6335
6339
  return '❌ 无效的 spec,示例:永久、7d、clear';
6336
6340
  }
6337
- const gk = (String(options?.guild ?? '').trim() || (0, priority_cooldown_1.canonicalGuildPriorityKey)(session) || '').trim();
6341
+ let gk = (guildOpt.trim() || (0, priority_cooldown_1.canonicalGuildPriorityKey)(session) || '').trim();
6342
+ gk = normalizeGuildKeyForPriority(gk, session);
6338
6343
  if (!gk) {
6339
6344
  return '❌ 请使用 -g 指定群标识(platform:guildId),或在群聊内执行。';
6340
6345
  }