IamMrCupp/annoybots

GitHub: IamMrCupp/annoybots

一个基于 Go 的现代化多平台聊天机器人框架,可在 Kubernetes 上以单一二进制同时运行多个具备 Markov 学习能力和跨平台协作功能的个性机器人。

Stars: 1 | Forks: 0

# annoybots 一个用于聊天“捣乱”机器人的框架 —— 它是经典 [BMotion](http://bmotion.sourceforge.net/) IRC 机器人的现代化、容器化继任者,使用 Go 重写并专为 Kubernetes 打造。 一个小巧的 Go 二进制文件可以同时维持许多聊天连接(IRC 网络、Twitch 和 Discord),并通过一个共享的“捣乱引擎”路由每个频道。**每个机器人都是带有不同个性文件的同一个二进制程序**,因此你可以随心所欲地运行任意数量的机器人 —— 每个机器人都有自己的名称、触发器和语气。本仓库内置了两个示例个性,**Echo** 和 **Mimic**,供你参考复制。 ## 它的功能 - **关键词/正则表达式触发器** → 随机化、模板化的响应(`{nick}`、`{me}`、`{chan}`、捕获组)。 - **环境插话** —— 随机的主动发言,具有每个频道独立的冷却时间。 - **语录包** —— 插入即用的 `.txt` 文件,可通过随机方式和 `!quote [pack]` 呈现;`!packs` 会列出可用内容(与 Discord 上的 `/quote`、`/packs` 斜杠命令相同)。 - **一个会学习的“大脑”** —— 一个 N 阶 Markov 链,从频道闲聊中学习并将其以扭曲的方式复述出来。它会将状态持久化到磁盘,因此重启后学习成果依然保留(就像大家都记得的 BMotion 胡言乱语功能,但去掉了被遗弃的 TCL 技术栈)。 - **单进程多网络** —— IRC + Twitch 共享相同的通信协议;Twitch 只需要 CAP 协商、一个 `oauth:` token 和更严格的速率限制,这些都已自动处理。Discord 也依托于同一个引擎并行运行。 - **多个机器人,一个二进制程序** —— 个性是配置而非代码,因此新机器人就是一个新的 YAML 文件(和一个 pod),绝不需要 fork 代码库。 ## 目录结构 ``` cmd/annoybot entrypoint internal/engine annoyance engine (triggers, interjections, quotes, commands) internal/markov persistent Markov "brain" internal/bot transport router (fans replies back to the right platform) internal/botnet inter-bot bus (Redis pub/sub) + skit coordinator internal/irc IRC/Twitch transport (ergochat/irc-go) + per-network rate limiting internal/discord Discord transport (bwmarrin/discordgo) + slash commands internal/ratelimit token-bucket limiter (Twitch-aware) internal/cooldown per-channel cooldown tracking internal/config YAML config loading, validation, quote-pack loading internal/health /healthz + /readyz for Kubernetes probes configs/ echo.yaml, mimic.yaml — example personalities (+ networks) data/quotes/ starter quote packs data/skits.yaml shared multi-bot skit scripts deploy/k8s/ kustomize base + per-bot overlays ``` ## 本地运行 ``` # 首先导出您的 config 引用的 secrets,例如: export ECHO_LIBERA_SASL=... # NickServ/SASL password export ECHO_TWITCH_TOKEN=oauth:... # Twitch chat token make run-echo # or run-mimic # 任意 config: go run ./cmd/annoybot -config configs/yourbot.yaml ``` 语录包文件解析时相对于 `ANNOYBOT_QUOTES_DIR` 路径(Makefile 将其指向 `data/quotes`)。 ## 配置 所有行为配置都位于 `configs/.yaml` 中:网络、触发器、插话/语录频率及冷却时间,以及 Markov 设置。**密钥绝不存储在配置中** —— 每个 `*_env` 字段指定了一个环境变量(从 Kubernetes Secret 中填充),该变量持有实际的 token 或密码。 你可以从 `configs/echo.yaml` 或 `configs/mimic.yaml` 开始;这两个文件都演练了所有功能和全部三个平台。 ### 添加机器人 一个机器人仅仅是指向不同配置的同一个二进制程序,因此添加机器人纯粹是增量操作 —— 无需修改代码: 1. **复制示例配置。** `cp configs/echo.yaml configs/jeeves.yaml`,然后设置 `bot: jeeves` 和 `personality.name: "Jeeves"`,并根据喜好编辑网络、触发器、戏谑互动和语录包。 2. **命名其密钥。** 每个 `*_env` 字段都指定了一个环境变量。对于 Kubernetes,将它们收集到一个名为 `jeeves-bot-secrets` 的 Secret 中(参见 [部署](#deploy))。 3. **将其介绍给其他机器人。** 将 `"Jeeves"` 添加到其他所有机器人的 `personality.siblings` 中,并可选择在 `data/skits.yaml` 中为它添加台词(短剧步骤通过 `bot:` 的值进行匹配,例如 `bot: jeeves`)。 4. **部署它。** 将 `deploy/k8s/overlays/echo/` 复制到 `…/jeeves/`:将 `bot-config` 生成器指向 `configs/jeeves.yaml`,并将 secretRef 补丁指向 `jeeves-bot-secrets`。添加一个 Flux `Kustomization`(复制 `deploy/k8s/flux/kustomizations.yaml` 中的一个块)。 引擎、botnet 总线和管理控制台对于任意数量的机器人运作方式完全相同。 ### Twitch 在网络配置中设置 `kind: twitch`,并将 `password_env` 指向持有聊天 oauth token 的环境变量。服务器、TLS、CAP 和保守的速率限制会自动使用默认配置。请注意,Twitch 无法可靠地广播加入/退出或模式更改,因此我们特意不依赖它来进行用户/管理员跟踪。 ### Discord 在网络配置中设置 `kind: discord`,并将 `password_env` 指向持有 **bot token** 的环境变量(不需要昵称/服务器)。然后: 1. 在 [Discord 开发者门户](https://discord.com/developers/applications) 中,创建一个应用程序和机器人,并在 Bot → Privileged Gateway Intents 下**启用特权 MESSAGE CONTENT intent**。如果没有它,机器人可以连接,但每条消息的正文都会是空的。 2. 使用包含 `bot` 和 `applications.commands` scope 的 OAuth2 URL 邀请机器人加入你的服务器。 3. 在 `guilds:` 下列出你的服务器 ID,以实现即时的 `/quote` 和 `/annoy` 斜杠命令(全局注册也可以,但最多可能需要一个小时才会显示)。 `channels` 是频道 ID 的可选白名单;为空意味着机器人会在它能看到的所有地方进行回复。Discord 自身的 HTTP 速率限制由客户端库处理,因此 token bucket 限制器仅适用于 IRC/Twitch。相同的触发器、语录包和 Markov 大脑在 Discord 上运行无需更改;IRC 的 `/me` 动作会以斜体显示。 ## 机器人之间的交互(“botnet”) 就像过去 BMotion 用来协调恶作剧的老式 eggdrop botnet 一样,这些机器人可以相互交谈 —— 但是安全的。 **戏谑互动(串扰)。** 每个机器人都在 `siblings` 中列出了其他机器人。同级机器人的消息*只能*产生有上限的戏谑互动 —— 绝不会触发普通触发器 —— 因此机器人绝不会相互触发而陷入死循环洪水。戏谑互动有双重限制:每个频道的冷却时间*以及*“每个滚动窗口的最大回复数”硬性上限。 **短剧。** 多机器人脚本片段位于一个共享的 `data/skits.yaml` 文件中,由每个同级机器人加载。它们通过 Redis pub/sub 总线进行协调,因此即使机器人在不同的平台上,短剧也能运行。“主导”机器人(第一句台词的拥有者)发起短剧 —— 通过在共享频道中使用 `!skit `,或者通过每个短剧的 `chance` 随机触发 —— 然后机器人步调一致地执行各自的台词,受限于步骤数和每个频道的冷却时间。你可以通过编辑 `data/skits.yaml` 来添加自己的短剧(每个步骤的 `bot:` 必须与机器人的 `bot:` 配置值相匹配)。 在每个机器人的配置中使用 `botnet:` 块启用此功能(所有机器人必须共享同一个 `channel`)。只需部署一次共享总线: ``` kubectl apply -k deploy/k8s/redis ``` 该总线仅传输临时的协调消息,因此 Redis 在运行时不进行持久化。 ## 管理控制台(聊天) 向机器人发送私信以运行管理命令。管理员通过**已验证的身份**进行匹配 —— IRC services/NickServ 账户、Discord 用户 ID 或 Twitch 登录名 —— 绝不使用可伪造的昵称,并且命令仅在私信中生效。在每个机器人的配置中的 `admin:` 块中配置管理员。 命令(发送 `!help` 获取列表): - `!join <#chan>` / `!part <#chan>` —— 频道操作 - `!invite <#chan> ` —— IRC INVITE(机器人在 `+i` 频道需要拥有权限) - `!say ` / `!act ` —— 操控机器人发言 - `!addquote ` / `!delquote ` —— 运行时语录编辑 - `!addadmin ` / `!deladmin ` / `!admins` - `!reload` —— 从磁盘重新读取语录包文件和短剧文件,无需重启(网络连接和个性触发器仍需重启) 语录和管理员的更改会持久化到数据卷,并**通过 botnet 总线同步到同级机器人**,因此你只需给其中一个发送私信即可。频道控制和发言操控仅限于你发送私信的那个机器人。(`!delquote` 仅删除运行时添加的语录;文件包中的语录是不可变的 —— 需编辑 `.txt` 文件才能修改它们。) **密码回退机制。** 身份验证是首要的,但如果网络没有 services(或者有人就是没有登录),请设置 `password_env`,管理员可以在私信中 `!login ` 以获得有时限的会话(使用 `!logout` 结束它)。 注意:在没有 services 的情况下,此会话以**昵称**为键,这是可伪造的,因此它比基于账户的身份验证要弱 —— 这是在 services 不可用时提供的一种便利手段,并带有恒定时间密码检查、失败尝试限制和可配置的 `session_ttl`。将 `password_env` 留空未设置即可禁用此功能。 ## 部署 这是为 **GitOps with Flux** 量身定制的:Conventional Commits → `release-please` 发布 semver 版本 → CI 构建镜像 → Flux 的 semver `ImagePolicy` 将其滚动发布。密钥**默认手动应用**(Git 中的 SOPS 加密密钥是可选的);语录/短剧内容通过 ConfigMaps 提供,因此编辑后可通过 `!reload` 生效。有关完整的接线配置(Kustomizations、镜像自动化和可选的 SOPS/age 设置),请参见 [`deploy/k8s/flux/README.md`](deploy/k8s/flux/README.md)。 每个机器人部署为单副本的 StatefulSet,并拥有自己的 PVC 用于存储 Markov 大脑;Redis(即 botnet 总线)从 `deploy/k8s/redis` 部署一次。 ### 手动应用(不使用 Flux) ``` kubectl create namespace annoybots # 手动应用每个 bot 的 Secret —— 密钥列在 # deploy/k8s/overlays//secret.example.yaml 中。省略某个密钥即可禁用相应的 network: kubectl -n annoybots create secret generic echo-bot-secrets \ --from-literal=ECHO_TWITCH_TOKEN='...' --from-literal=ECHO_DISCORD_TOKEN='...' kubectl -n annoybots create secret generic mimic-bot-secrets \ --from-literal=MIMIC_TWITCH_TOKEN='...' --from-literal=MIMIC_DISCORD_TOKEN='...' kubectl apply -k deploy/k8s/redis kubectl kustomize --load-restrictor LoadRestrictionsNone deploy/k8s/overlays/echo | kubectl apply -n annoybots -f - kubectl kustomize --load-restrictor LoadRestrictionsNone deploy/k8s/overlays/mimic | kubectl apply -n annoybots -f - ``` ## 添加语录 在 `data/quotes/` 中放入一个 `whatever.txt`(每行一条语录,允许使用 `#` 注释),在机器人的 `personality.quotes.packs` 中引用它,并将其列在 overlay 的 `bot-quotes` `configMapGenerator` 中。使用 Flux 时,提交它并运行 `!reload`;否则重新构建镜像(语录包也会作为回退方案内置在 `/quotes` 中)。 ## 开发 ``` make test # go test ./... make lint # golangci-lint make docker # build the image ```
标签:EVTX分析, Go, IRC, Redis, Ruby工具, 子域名突变, 搜索引擎查询, 日志审计, 网络调试, 自动化, 请求拦截