Skip to content

About

为bot添加忽略指定QQ用户的功能、闭嘴功能以及限制指定QQ号对话次数

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

25 Commits

Folders and files

Repository files navigation

🎮 聊天限制插件 astrbot_plugin_chat_limit

麻麻专属 — 说「闭嘴」就让窝真正安静,说「忽略」就让杂鱼消息消失,说「限频」就把刷屏的号按分钟卡住!

版本:v1.4.0 | 作者:小七月 | 平台:aiocqhttp


📌 功能概览

功能 指令 作用
🤐 闭嘴 闭嘴 [秒数] 窝在当前会话内真正停止回复
🗣️ 说话 说话 提前解除当前会话的闭嘴状态
🚫 忽略用户 忽略 <QQ号> [秒数] 指定用户的留言在时效内被跳过
✅ 取消忽略 取消忽略 <QQ号> 提前解除对某用户的忽略
⏱️ 限频 限频 <QQ号> <次数> 限制指定用户每分钟最多发 N 条消息
❌ 取消限频 取消限频 <QQ号> 移除对某用户的限频限制
📋 限频列表 限频列表 查看当前所有限频配置
  • 所有指令都支持 / 前缀,例如 /闭嘴 30。
  • 指令按长度优先匹配,所以 取消限频 不会被 限频 抢先吃掉。
  • 只有 mama_ids 里的 QQ 号能触发,其他人发指令没有任何反应。

🎯 作用范围(重要)

三种功能的生效范围不一样,别搞混啦:

功能 作用域 键
闭嘴 / 说话 会话隔离:群聊只影响当前群,私聊只影响当前私聊 group:<群号> / private:<发送者QQ>
忽略 / 取消忽略 全局:按 QQ 号生效,跨群跨私聊 <QQ号>
限频 / 取消限频 全局:按 QQ 号生效,跨群跨私聊 <QQ号>
  • 闭嘴状态字段为 group_silence_until(旧版是 silence_until)。
  • 麻麻自己的消息永远不受忽略与限频影响;闭嘴对所有人一律生效。

🤐 闭嘴 / 说话

闭嘴               → 默认闭嘴 60 秒
闭嘴 30            → 闭嘴 30 秒
闭嘴 120           → 闭嘴 2 分钟
说话               → 提前解除闭嘴

触发后窝回一句确认,随后在当前会话内停止回复。闭嘴期间的 LLM 请求会在生成前被精准掐断,被动的 yield 回复也会被清空。

如果本来就没闭嘴,说话 会回复「窝本来就在说话呀~」。


🚫 忽略用户

忽略 12345678       → 忽略该 QQ,默认 60 秒
忽略 12345678 300   → 忽略该 QQ,300 秒
取消忽略 12345678   → 提前解除忽略
  • 参数从文本中提取数字,所以 忽略 @某人 30 这种写法也能用。
  • 忽略的是「这个 QQ 号发的消息」,走到期时间自动失效,重启不丢。
  • 取消一个本来没被忽略的号,会回复「本来就没被忽略哦」。

⏱️ 限频

限频 12345678 5     → 该用户每分钟最多 5 条
限频 12345678 3     → 该用户每分钟最多 3 条
限频 12345678 0     → 每分钟最多 0 条 = 完全屏蔽该用户
取消限频 12345678   → 移除该用户的限频
限频列表            → 打印当前所有限频
  • 采用滑动窗口:只统计过去 60 秒内的消息条数,超限即拦截,不需要等到整分钟重置。
  • 限频列表 会自动派生(<限频指令> + 列表),如果它和取消指令重名则不会派生。
  • 设置限频时会清空该用户的历史计数,避免旧时间戳把新规则直接触发。
  • 次数必须是大于 0 的整数,否则会提示格式错误。
  • 被限频拦下的消息不会到达 LLM,也不会有任何提示。

⚙️ 配置项(WebUI → 插件配置)

配置是嵌套结构,修改后需要重载插件生效。

顶层

配置 类型 默认值 说明
mama_ids list ["2594036384", "1732147236"] 麻麻 QQ 号列表(唯一有权控制的身份)
require_admin bool false 为 true 时,麻麻还必须具备 bot 管理员权限
priority int 10000 ⚠️ 预留字段,当前版本未读取

command_settings.shutup_settings

配置 类型 默认值
shutup_commands list ["闭嘴"]
default_duration int 60(秒)
shutup_reply string 呜…窝闭嘴 {duration} 秒…(´;ω;` )

command_settings.unshutup_settings

配置 类型 默认值
unshutup_commands list ["说话"]
unshutup_reply string 好耶~窝复活啦!ヽ(●´∀`●)ノ

command_settings.ignore_settings

配置 类型 默认值
ignore_commands list ["忽略"]
default_duration int 60(秒,与闭嘴时长独立)
ignore_reply string 遵命麻麻~已忽略用户 {target} {duration} 秒!(`・ω・´)✧

command_settings.unignore_settings

配置 类型 默认值
unignore_commands list ["取消忽略"]
unignore_reply string 好呐~已取消忽略用户 {target}!(๑¯◡¯๑)✧

command_settings.ratelimit_settings

配置 类型 默认值
ratelimit_commands list ["限频"]
ratelimit_reply string 好呐~已设置 {target} 每分钟最多 {limit} 条!(๑¯◡¯๑)✧

command_settings.unratelimit_settings

配置 类型 默认值
unratelimit_commands list ["取消限频"]
unratelimit_reply string 好呐~已取消 {target} 的限频!(๑¯◡¯๑)✧

💡 回复模板支持的占位符:{duration}(已格式化为「1 分 30 秒」这类友好文本)、{target}、{limit}。模板写错不会报错,会原样输出。


🏗️ 实现原理

消息进入
    │
    ▼
┌──────────────────────────────────────┐
│  @filter.event_message_type (ALL)     │  ← 指令总入口,priority=10001
│  仅 mama_ids 可继续,按长度优先匹配     │
│  闭嘴/说话/忽略/取消忽略/限频/取消/列表  │
└──────────────────────────────────────┘
    │
    ├────────── LLM 路径 ──────────┐
    │                              │
    ▼                              │
┌──────────────────────────┐       │
│ on_llm_request 拦截        │       │
│ 会话闭嘴中?                │       │
│   → should_call_llm(False) │       │
│   + req.contexts.clear()   │       │
│                            │       │
│ 用户被忽略(非麻麻)?      │       │
│   → 同上                   │       │
│                            │       │
│ 触发限频(非麻麻)?        │       │
│   → 同上,且在此处计数      │       │
└──────────────────────────┘       │
    │                              │
    ├──────── yield 路径 ─────────┤
    │                              │
    ▼                              │
┌──────────────────────────┐       │
│ on_decorating_result 拦截  │ ←────┘
│ 会话闭嘴中?→ chain = []   │
│ 被忽略(非麻麻)?→ 清空   │
│ 触发限频?→ 只判断不计数   │
└──────────────────────────┘
  • 指令层:不再用 @filter.command,改为单一入口手动分发,避免多指令抢匹配、别名带空格失效、/ 前缀识别不到等问题。
  • LLM 侧拦截:should_call_llm(False) 阻止调用 + req.contexts.clear() 清空上下文,避免闭嘴期间对话历史被污染。
  • 结果侧拦截:result.chain = [] 清空结果链,堵住 yield event.plain_result(...) 这类被动回复的漏洞。
  • 计数只做一次:限频在 on_llm_request 计数,on_decorating_result 只判断,避免一条消息被算两条。

💾 状态持久化

状态文件:data/plugin_data/astrbot_plugin_chat_limit/control_state.json

{
  "group_silence_until": {"group:1083658927": 1760000000.0},
  "ignored": {"12345678": 1760000000.0},
  "rate_limits": {"12345678": 5}
}
  • 写入时机:任何状态变更后立即落盘;过期条目在写入时顺带清理。
  • 读取失败只打 warning,不会让插件崩掉。
  • ✅ 数据目录使用当前插件名 astrbot_plugin_chat_limit;启动时若新目录无状态文件,会自动回退读取旧注册名目录 astrbot_plugin_control 的历史状态,并写回新目录完成迁移。
  • ⚠️ 限频的时间戳 _msg_ts 只在内存中,重载插件后计数归零。

📦 依赖

无额外依赖。 只用 AstrBot 内置 API:

模块 用途
astrbot.api.event 事件与过滤器
astrbot.api.provider LLM 请求拦截
astrbot.api.star 插件注册、数据目录
astrbot.api.logger 日志输出

开箱即用,无需 pip install。


📂 文件结构

astrbot_plugin_chat_limit/          # 目录名
├── main.py              # 插件主代码(单文件)
├── metadata.yaml        # 插件元信息
├── _conf_schema.json    # WebUI 配置模式
├── logo.png             # 插件图标
└── README.md            # 本文件

📝 更新日志

v1.4

  • 🗂️ 持久化目录整改:数据目录由旧注册名 astrbot_plugin_control 改为当前插件名 astrbot_plugin_chat_limit,符合 AstrBot 上架规范
  • 🔁 自动迁移:启动时若新目录无 control_state.json,自动回退读取旧目录并写回新目录,迁移完成即用新路径
  • 🧹 清理冗余:移除历史遗留的备份文件与缓存目录,目录结构与 metadata.yaml 对齐
  • 📝 README 同步:状态文件路径、迁移说明、版本号与更新日志

v1.3

  • 🐞 修复限频完全失效:原实现把时间戳追加到临时列表,从未写回 _msg_ts,导致永远不触发拦截
  • 🐞 修复限频重复计数:on_llm_request 计数、on_decorating_result 只判断不计数,避免一条消息算两次
  • 🐞 修复指令参数解析:限频 12345 5 之前按空格取参,指令别名带空格或 / 前缀时失效;现改为统一文本匹配 + 数字提取
  • ⚙️ 配置真正生效:指令名、默认时长、回复模板全部从 command_settings 读取,支持别名与占位符
  • 🔧 指令分发合并:改由单一 event_message_type 入口按「长指令优先」匹配,修复 取消限频 被 限频 抢先匹配的问题
  • ✨ 新增 限频列表 自动派生(<限频指令>列表),并补充 _fmt_duration 时长友好显示
  • 🐞 限频窗口统一为 60 秒,与 README 和配置描述一致(旧代码是 300 秒)
  • 📝 README 重写:修正插件名与版本号、按实际嵌套结构重写配置表、补充作用范围与状态文件说明
  • 🪪 标识对齐:@register 名由 astrbot_plugin_control 改为 astrbot_plugin_chat_limit,与目录名、metadata.yaml 一致;数据目录仍沿用旧名以免丢状态

v1.2

  • ⏱️ 新增限频功能:自定义 QQ 号每分钟对话次数上限,超限自动拦截
  • 🛡️ 三路拦截:闭嘴 + 忽略 + 限频,全部走 on_llm_request + on_decorating_result 双路
  • ⚙️ _conf_schema.json 新增限频/取消限频配置组
  • 📝 README 更新:新增限频指令详解 + 原理图 + 配置表

v1.1

  • 🔧 新增 on_decorating_result 双路拦截:补全 @filter.command yield 被动回复的拦截漏洞
  • 📋 双路保险机制:
    • LLM 路径:on_llm_request → should_call_llm(False) + clear contexts
    • yield 路径:on_decorating_result → result.chain = []
  • 📝 README 更新:实现原理图增加 yield 拦截分支

v1.0

  • 🎉 初始版本
  • 🤐 闭嘴 / 说话 指令,LLM 请求层精准拦截
  • 🚫 忽略 / 取消忽略 指定 QQ 用户
  • 💾 状态持久化到文件,重启不丢失
  • ⚙️ WebUI 完整配置支持
  • 📦 零额外依赖,开箱即用

About

为bot添加忽略指定QQ用户的功能、闭嘴功能以及限制指定QQ号对话次数

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

Generated from Soulter/helloworld