Skip to content

反垃圾 (antispam)

基于 on_message 事件的频道级反垃圾模块,无指令。为指定频道配置捕获规则,自动对触发者执行踢出 / 封禁 / 超时,并可清理其近期消息、公开通知、写入审计日志。

  • 配置键antispam
  • 源文件cogs/antispam.py(复用 modules/clear_message.py 的清理能力)

判定流程

对配置了规则的频道内的每条非机器人消息:

  1. 忽略机器人消息、私信。
  2. 命中该频道的 spam_catcher 规则后开始判定。
  3. 若作者拥有 ignored_roles 中任一角色 → 跳过
  4. 判断作者类别:
    • 陌生账号(spammer):没有任何身份组, 其全部身份组都属于 stranger_roles
    • 正常账号(hacked,疑似被盗):其余情况。
  5. 按类别执行对应动作(spammer / hacked)。
  6. 可选:清理该用户近期消息(clear_message)、在频道公开通知(public_log)。
  7. 将结果(成功 / 失败)写入审计日志antispam-auto-catch,标记为自动操作)。

动作与所需权限

动作含义机器人所需 Discord 权限
kick踢出成员踢出成员(Kick Members)
ban封禁成员封禁成员(Ban Members)
mute / 分钟数超时(默认 60 分钟,或指定分钟数)超时成员(Moderate Members / Timeout)

身份组层级

若机器人已拥有对应权限但操作仍被拒绝,几乎可以确定是身份组层级问题:目标的最高身份组不低于机器人最高身份组。此时需将机器人身份组拖到目标之上。这类失败会以「自动操作失败」记录到审计日志并说明原因。

处理结果通知

  • 疑似被盗(mute):会 @ 该用户,提示账号疑似被盗、已临时禁言、请联系管理员(中英双语)。
  • 陌生账号(kick/ban):公开记录触发的 antispam 动作(中英双语)。由于成员被踢出 / 封禁后 @ 提及会随时间显示为「未知用户」,通知中会在提及后附上 (`用户名`) 以便日后辨认。
  • 是否公开通知由 public_log 控制。
  • 通知末尾会附带一条形如 -# *(antispam-action/{user_id}/{action})* 的标签,用于后续定位和撤销操作。

消息快照(审计)

写入审计日志时,会将触发消息转发到审计频道并回复一条 处理中... 占位消息;待清理等处理完成后,再把该占位消息编辑为最终的「自动化操作日志」(含撤销按钮,上方附带固定格式标签)。消息内容形如:

-# *(antispam-action/992995849946804304/ban)*
[自动化操作日志 embed]
  • 采用转发而非自建 snapshot:转发会在审计频道保留一份内容副本,即使原消息随后被清理删除,图片 / 附件也不会 404。
  • 转发必须在清理删除原消息之前完成;若转发失败,则回退为自建 snapshot embed。

撤销操作(解封 / 解禁)

审计日志卡片的按钮上,Mod/Admin 可以一键撤销 antispam 动作。撤销流程是无状态的(stateless),不依赖数据库记录,仅通过标签搜索来实现。

自动封禁 (ban) 的解除

  1. 点击 取消封禁 按钮 → bot 先检查该用户是否仍处于封禁状态。
  2. 若已被手动解封 → 按钮变为 已过期(灰色禁用),不再做其他操作。
  3. 若仍被封禁 → 执行解封,按钮变为 已由 {mod} 取消封禁

禁言 (mute) 的解除

  1. 点击 解除禁言 按钮 → bot 先检查该用户是否仍处于超时状态。
  2. 若禁言已过期/已被手动解除 → 按钮变为 已过期(灰色禁用),不再做其他操作。
  3. 若仍在禁言中 → 清除超时,按钮变为 已由 {mod} 解除禁言

跨频道同步

撤销操作后,bot 会在所有审计日志频道(全局 + 按服务器)中搜索包含相同标签的消息,自动禁用其按钮并标记为已完成。若 public_log 启用,还会同时编辑公开通知,格式变为:

🚨 Antispam triggered: <@user> (`name`) -> ~~Spammer/ban~~ -> **[Unban by moderator](audit-log-link)**
-# *(antispam-action/xxx/ban)*
  • 公开日志中的 **Unban by moderator** 不显示具体是哪位 mod 操作的。
  • unban_link 启用且服务器配置了审计频道,挂载到审计消息的跳转链接;否则仅显示文本。

注意

  • 踢出 (kick) 动作无法撤销,其审计卡片不显示撤销按钮。
  • 涉及跨频道同步时会静默跳过权限不足/找不到频道的异常,不会向操作者报错。

消息清理

clear_message 指定分钟数时,会清理该用户在服务器范围内最近 N 分钟的消息(内部复用批量清理服务,不额外写审计,结果并入本次记录)。设为 null / false 则禁用。

清理会一并作用于论坛帖子:既删除该用户在论坛帖子内发的消息,也会删除由该用户所作的整个帖子delete_threads,会连带删除帖内其它人的消息)。

配置

yaml
antispam:
  enabled: false
  spam_catcher: {}        # 按频道配置的捕获规则
  # 示例:
  # 1514685631316496615:
  #   spammer: ban              # 陌生人处理: kick | ban
  #   hacked: mute              # 疑似被盗处理: kick | ban | mute | 分钟数
  #   clear_message: 3          # 自动清理窗口 (分钟, null/false 禁用)
  #   public_log: true          # 是否在频道公开通知
  #   unban_link: false         # 公开日志撤销时是否附加审计日志链接(需配置服务器审计频道)
  #   stranger_roles: [1318980288046698506, "新成员"]
  #   ignored_roles: ["管理员", "成员"]

顶层字段

字段类型默认值说明
enabledboolfalse是否启用反垃圾模块
spam_catcherdict[频道ID, 规则]{}按频道配置的捕获规则

每条规则字段

字段类型默认值说明
spammerkick / banban陌生账号处理方式
hackedkick / ban / mute / 分钟数(int)mute疑似被盗账号处理方式
clear_messageint / null / false3清理消息窗口(分钟),null/false 禁用
public_logbooltrue是否在频道公开通知处理结果
unban_linkboolfalse公开日志撤销时是否附加审计日志消息链接(需要服务器配置了审计频道)
stranger_roleslist[int | str][]视为陌生账号的角色列表(身份组 ID 或名称)
ignored_roleslist[int | str][]忽略处理的角色列表(拥有任一即跳过)
  • spam_catcher 的 key 为频道 ID(数字或字符串均可)。
  • 角色列表项支持身份组 ID身份组名称(同名身份组会全部匹配)。

基于 MIT 许可发布