Skip to content

自动禁言 level 0 的随机时长可能为 0,按 OneBot v11 语义等于解除禁言而非处罚 #151

Open

Description

@SuellenQwQ

描述 bug

内容安全(违禁词)自动处罚路径中,首次违规(level 0)的用户有约 1/301 的概率被禁言 0 秒——按 OneBot v11 规范,set_group_ban 的 duration=0 表示取消禁言,也就是说处罚实际效果是解禁,而 bot 仍向群里发送「已执行处罚」。

问题逻辑

core/path.py 的等级-时长映射把 level 0 的下界设为 0:

time_scop_map = {
    0: [0, 5 * TIME_MINUS],   # 下界 0
    1: [5 * TIME_MINUS, 10 * TIME_MINUS],
    ...
}

core/utils.py 的 mute_sb 在被动检测路径用 randint 取值:

if time is None:
    if scope is None:
        time = random.randint(...)
    else:
        time = random.randint(scope[0], scope[1])   # 可取到 0
...
yield bot.set_group_ban(group_id=gid, user_id=qq, duration=time)

content_guard/auto_ban.py 的调用:

level = await get_user_violation(gid, event.user_id, "Text", matched)   # 首次违规返回 0
baning = mute_sb(bot, gid, lst=uid, scope=time_scop_map[level])          # scope=[0, 300]

OneBot v11 规范原文(set_group_ban 参数表):

duration | number | 30 * 60 | 禁言时长,单位秒,0 表示取消禁言

插件自身也依赖这一语义——basic_group_admin/admin.py 的解禁命令就是显式 mute_sb(..., time=0) 来解禁的。所以 duration=0 在本插件支持的实现栈上就是解禁,而非无效操作。

影响

  • 首次违规(level 0)触发自动处罚时,约 1/301 概率实际执行的是「解除禁言」:若该用户此前已被其他方式禁言,会被当场放出;无论如何处罚都没有生效,但群里收到的是「已执行处罚」。
  • 模拟验证:randint(0, 300) 取 20000 次,出现 0 共 60 次(0.30%)。

修复建议

将 level 0 的下界改为正数(例如 [60, 5 * TIME_MINUS],保证处罚至少有意义),或在 mute_sb 的 scope 分支钳制:

else:
    time = max(1, random.randint(scope[0], scope[1]))

注意不要在 time 为显式传入时钳制——admin.py 的解禁命令合法使用 time=0。

环境

  • OS: Windows 11
  • Version: main 分支最新代码

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions