koishi-plugin-maibot 1.9.7 → 1.9.9

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 +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
@@ -1565,13 +1565,28 @@ function apply(ctx, config) {
1565
1565
  const wl = checkWhitelist(sess, config);
1566
1566
  if (!wl.allowed)
1567
1567
  return;
1568
- const hit = await (0, priority_cooldown_1.checkCommandCooldown)(ctx, sess, priorityCooldownCfg, cmdName, getCooldownPrimaryUserId, async (s) => getSessionBindingKeys(ctx, s));
1568
+ // 获取当前用户绑定的 maiUid(用于共享冷却)
1569
+ let sessionMaiUid;
1570
+ try {
1571
+ const binding = await getBindingBySession(ctx, sess);
1572
+ if (binding?.maiUid)
1573
+ sessionMaiUid = binding.maiUid;
1574
+ }
1575
+ catch { /* 忽略 */ }
1576
+ // 超过2个绑定时拦截有冷却的命令
1577
+ if (sessionMaiUid) {
1578
+ const sameUidBindings = await ctx.database.get('maibot_bindings', { maiUid: sessionMaiUid });
1579
+ if (sameUidBindings.length > 2) {
1580
+ return `❌ 您的游戏账号已被 ${sameUidBindings.length} 个用户绑定,请先解绑多余账号后再使用此功能。\n(使用 /mai解绑 解绑当前账号)`;
1581
+ }
1582
+ }
1583
+ const hit = await (0, priority_cooldown_1.checkCommandCooldown)(ctx, sess, priorityCooldownCfg, cmdName, getCooldownPrimaryUserId, async (s) => getSessionBindingKeys(ctx, s), sessionMaiUid);
1569
1584
  if (hit)
1570
1585
  return hit;
1571
1586
  const uid = await getCooldownPrimaryUserId(sess);
1572
1587
  if (!uid)
1573
1588
  return;
1574
- await (0, priority_cooldown_1.recordCommandCooldown)(ctx, uid, cmdName, priorityCooldownCfg);
1589
+ await (0, priority_cooldown_1.recordCommandCooldown)(ctx, uid, cmdName, priorityCooldownCfg, sessionMaiUid);
1575
1590
  });
1576
1591
  /**
1577
1592
  * 获取上传任务的统计信息(平均处理时长和今日成功率)
@@ -2036,6 +2051,29 @@ function apply(ctx, config) {
2036
2051
  const legacy = await getBindRelatedLegacyUserIdsForTarget(ctx, platform, extracted);
2037
2052
  for (const id of legacy)
2038
2053
  keys.add(id);
2054
+ // 通过 bind 插件反查 aid,补上 koishi:<aid>(实际记录冷却用的统一键)
2055
+ const db = ctx.database;
2056
+ if (db && typeof db.get === 'function') {
2057
+ try {
2058
+ const pidCandidates = platform
2059
+ ? [`${platform}:${extracted}`, extracted]
2060
+ : [extracted];
2061
+ let aid;
2062
+ for (const pid of pidCandidates) {
2063
+ const rows = await db.get('binding', { pid });
2064
+ if (rows?.length) {
2065
+ aid = rows[0]?.aid;
2066
+ break;
2067
+ }
2068
+ }
2069
+ if (aid !== undefined && aid !== null) {
2070
+ keys.add(`koishi:${String(aid)}`);
2071
+ }
2072
+ }
2073
+ catch {
2074
+ // binding 表不存在或结构不一致时忽略
2075
+ }
2076
+ }
2039
2077
  for (const id of [...keys]) {
2040
2078
  const rows = await ctx.database.get('maibot_bindings', { userId: id });
2041
2079
  for (const b of rows)
@@ -2735,6 +2773,14 @@ function apply(ctx, config) {
2735
2773
  const maiUid = String(previewResult.UserID);
2736
2774
  const userName = previewResult.UserName;
2737
2775
  const rating = previewResult.Rating ? String(previewResult.Rating) : undefined;
2776
+ // 检查同一游戏账号是否已被其他 Bot 用户绑定
2777
+ const sameUidBindings = await ctx.database.get('maibot_bindings', { maiUid });
2778
+ const otherBindings = sameUidBindings.filter(b => b.userId !== userId);
2779
+ if (otherBindings.length > 0) {
2780
+ const earliest = otherBindings.sort((a, b) => new Date(a.bindTime).getTime() - new Date(b.bindTime).getTime())[0];
2781
+ await session.send(`⚠️ 此游戏账号已被其他用户绑定(最早绑定时间: ${new Date(earliest.bindTime).toLocaleString('zh-CN')})。\n` +
2782
+ `持有 SGID 即证明账号所有权,继续绑定后进入冷却期。`);
2783
+ }
2738
2784
  // 存储到数据库
2739
2785
  await ctx.database.create('maibot_bindings', {
2740
2786
  userId,
@@ -6665,7 +6711,7 @@ function apply(ctx, config) {
6665
6711
  const n = await (0, priority_cooldown_1.adminRemovePersonalPriorityRows)(ctx, candidates);
6666
6712
  return `✅ 已清除 ${n} 条个人优先记录。\n匹配键:${candidates.join('、')}`;
6667
6713
  });
6668
- ctx.command('mai管理员设置个人优先 <targetUserId:text> <spec:text>', '设置个人优先:永久 / 时长 / clear')
6714
+ ctx.command('mai管理员设置个人优先 [targetUserId:text] [spec:text]', '设置个人优先:永久 / 时长 / clear(无参数走交互式)')
6669
6715
  .userFields(['authority'])
6670
6716
  .action(async ({ session }, targetUserId, spec) => {
6671
6717
  if (!session)
@@ -6673,8 +6719,24 @@ function apply(ctx, config) {
6673
6719
  if ((session.user?.authority ?? 0) < authLevelForCardAdmin) {
6674
6720
  return `❌ 权限不足,需要 auth 等级 ${authLevelForCardAdmin} 以上`;
6675
6721
  }
6676
- if (!targetUserId?.trim() || !spec?.trim()) {
6677
- return '❌ 用法:/mai管理员设置个人优先 <@或ID> <永久|7d|clear>';
6722
+ const promptMs = Math.max(90000, rebindTimeout);
6723
+ // 交互式:未提供目标用户
6724
+ if (!targetUserId?.trim()) {
6725
+ await session.send(`【设置个人优先】请在 ${Math.floor(promptMs / 1000)} 秒内发送目标用户(@用户 或数字ID)\n${INTERACTIVE_CANCEL_HINT}`);
6726
+ const r1 = await waitForUserReply(session, ctx, promptMs);
6727
+ const replyText = r1?.content?.trim() || '';
6728
+ if (!replyText || isInteractiveCancel(replyText))
6729
+ return '操作已取消';
6730
+ targetUserId = replyText;
6731
+ }
6732
+ // 交互式:未提供时长
6733
+ if (!spec?.trim()) {
6734
+ await session.send(`请发送时长规格(永久 / 7d / 30d / clear 等)\n${INTERACTIVE_CANCEL_HINT}`);
6735
+ const r2 = await waitForUserReply(session, ctx, promptMs);
6736
+ const replyText = r2?.content?.trim() || '';
6737
+ if (!replyText || isInteractiveCancel(replyText))
6738
+ return '操作已取消';
6739
+ spec = replyText;
6678
6740
  }
6679
6741
  const sp = (0, priority_cooldown_1.parsePriorityAdminSpec)(spec);
6680
6742
  if (sp === null) {
@@ -6687,11 +6749,11 @@ function apply(ctx, config) {
6687
6749
  const r = await (0, priority_cooldown_1.adminSetPersonalPriorityForUserIds)(ctx, candidates, sp);
6688
6750
  return r.message;
6689
6751
  });
6690
- ctx.command('mai管理员设置群组优先 <spec:text>', '直接设置群组优先(-g 指定群,默认当前群)')
6752
+ ctx.command('mai管理员设置群组优先 [spec:text]', '直接设置群组优先(-g 指定群;无参数走交互式)')
6691
6753
  .userFields(['authority'])
6692
6754
  .usage(' 示例:/mai管理员设置群组优先 clear -g qq:5911013814031454\n' +
6693
6755
  '或:/mai管理员设置群组优先 -g qq:5911013814031454 永久\n' +
6694
- '(仅数字群号时请写 qq:群号;在群内执行可省略 -g)')
6756
+ '无参数:发指令后按提示输入群标识与时长(仅数字群号请写 qq:群号;在群内执行可省略群标识)')
6695
6757
  .option('guild', '-g <guildKey:string> 群标识,如 qq:群号')
6696
6758
  .action(async ({ session, options }, spec) => {
6697
6759
  if (!session)
@@ -6699,15 +6761,43 @@ function apply(ctx, config) {
6699
6761
  if ((session.user?.authority ?? 0) < authLevelForCardAdmin) {
6700
6762
  return `❌ 权限不足,需要 auth 等级 ${authLevelForCardAdmin} 以上`;
6701
6763
  }
6764
+ const promptMs = Math.max(90000, rebindTimeout);
6702
6765
  const { spec: specOnly, guild: guildOpt } = splitGroupPrioritySpecAndGuild(spec, options?.guild);
6703
- if (!specOnly) {
6704
- return '❌ 用法:/mai管理员设置群组优先 <永久|7d|clear> [-g 群标识]';
6766
+ let specFinal = specOnly;
6767
+ let guildFinal = guildOpt;
6768
+ // 无任何参数 → 全交互式
6769
+ if (!specFinal) {
6770
+ // 群标识
6771
+ if (!guildFinal) {
6772
+ const fromSessionGuild = (0, priority_cooldown_1.canonicalGuildPriorityKey)(session);
6773
+ await session.send(`【设置群组优先】请在 ${Math.floor(promptMs / 1000)} 秒内发送群标识(如 qq:123456)${fromSessionGuild ? `\n直接发送 0 则使用当前群 ${fromSessionGuild}` : ''}\n${INTERACTIVE_CANCEL_HINT}`);
6774
+ const r1 = await waitForUserReply(session, ctx, promptMs);
6775
+ const replyText = r1?.content?.trim() || '';
6776
+ if (isInteractiveCancel(replyText))
6777
+ return '操作已取消';
6778
+ if (replyText === '0' && fromSessionGuild) {
6779
+ guildFinal = fromSessionGuild;
6780
+ }
6781
+ else if (replyText) {
6782
+ guildFinal = replyText;
6783
+ }
6784
+ else {
6785
+ return '操作已取消';
6786
+ }
6787
+ }
6788
+ // 时长
6789
+ await session.send(`请发送时长规格(永久 / 7d / 30d / clear 等)\n${INTERACTIVE_CANCEL_HINT}`);
6790
+ const r2 = await waitForUserReply(session, ctx, promptMs);
6791
+ const replyText = r2?.content?.trim() || '';
6792
+ if (!replyText || isInteractiveCancel(replyText))
6793
+ return '操作已取消';
6794
+ specFinal = replyText;
6705
6795
  }
6706
- const sp = (0, priority_cooldown_1.parsePriorityAdminSpec)(specOnly);
6796
+ const sp = (0, priority_cooldown_1.parsePriorityAdminSpec)(specFinal);
6707
6797
  if (sp === null) {
6708
6798
  return '❌ 无效的 spec,示例:永久、7d、clear';
6709
6799
  }
6710
- let gk = (guildOpt.trim() || (0, priority_cooldown_1.canonicalGuildPriorityKey)(session) || '').trim();
6800
+ let gk = (guildFinal.trim() || (0, priority_cooldown_1.canonicalGuildPriorityKey)(session) || '').trim();
6711
6801
  gk = normalizeGuildKeyForPriority(gk, session);
6712
6802
  if (!gk) {
6713
6803
  return '❌ 请使用 -g 指定群标识(platform:guildId),或在群聊内执行。';