反垃圾 (antispam)
基于 on_message 事件的频道级反垃圾模块,无指令。为指定频道配置捕获规则,自动对触发者执行踢出 / 封禁 / 超时,并可清理其近期消息、公开通知、写入审计日志。
- 配置键:
antispam - 源文件:
cogs/antispam.py(复用modules/clear_message.py的清理能力)
判定流程
对配置了规则的频道内的每条非机器人消息:
- 忽略机器人消息、私信。
- 命中该频道的
spam_catcher规则后开始判定。 - 若作者拥有
ignored_roles中任一角色 → 跳过。 - 判断作者类别:
- 陌生账号(spammer):没有任何身份组,或 其全部身份组都属于
stranger_roles。 - 正常账号(hacked,疑似被盗):其余情况。
- 陌生账号(spammer):没有任何身份组,或 其全部身份组都属于
- 按类别执行对应动作(
spammer/hacked)。 - 可选:清理该用户近期消息(
clear_message)、在频道公开通知(public_log)。 - 将结果(成功 / 失败)写入审计日志(
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) 的解除
- 点击 取消封禁 按钮 → bot 先检查该用户是否仍处于封禁状态。
- 若已被手动解封 → 按钮变为 已过期(灰色禁用),不再做其他操作。
- 若仍被封禁 → 执行解封,按钮变为 已由 {mod} 取消封禁。
禁言 (mute) 的解除
- 点击 解除禁言 按钮 → bot 先检查该用户是否仍处于超时状态。
- 若禁言已过期/已被手动解除 → 按钮变为 已过期(灰色禁用),不再做其他操作。
- 若仍在禁言中 → 清除超时,按钮变为 已由 {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: ["管理员", "成员"]顶层字段
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled | bool | false | 是否启用反垃圾模块 |
spam_catcher | dict[频道ID, 规则] | {} | 按频道配置的捕获规则 |
每条规则字段
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
spammer | kick / ban | ban | 陌生账号处理方式 |
hacked | kick / ban / mute / 分钟数(int) | mute | 疑似被盗账号处理方式 |
clear_message | int / null / false | 3 | 清理消息窗口(分钟),null/false 禁用 |
public_log | bool | true | 是否在频道公开通知处理结果 |
unban_link | bool | false | 公开日志撤销时是否附加审计日志消息链接(需要服务器配置了审计频道) |
stranger_roles | list[int | str] | [] | 视为陌生账号的角色列表(身份组 ID 或名称) |
ignored_roles | list[int | str] | [] | 忽略处理的角色列表(拥有任一即跳过) |
spam_catcher的 key 为频道 ID(数字或字符串均可)。- 角色列表项支持身份组 ID 或身份组名称(同名身份组会全部匹配)。