LTD-ManaagerBot/docs/zh/modules.md

376 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# LTD-ManagerBot 模块文档
## 目录
- [快速开始](#快速开始)
- [基础设施模块](#基础设施模块)
- [新模块](#新模块)
- [RCON 命令模块](#rcon-命令模块)
- [Gitea Webhook 模块](#gitea-webhook-模块)
- [白名单审计模块](#白名单审计模块)
- [配置参考](#配置参考)
---
## 快速开始
1. 复制 `src/main/resources/` 下的示例配置到 `config/`
2. 编辑 `config/application.yaml` — 设置数据库、API 地址、密钥
3. 编辑 `config/module.yaml` — 取消注释并配置需要的模块
4. 如需使用邀请码或白名单审计模块,将 SQL 模板放入 `config/sql/`
5. 启动机器人
### 新模块必需的 `application.yaml` 配置
```yaml
# 白名单系统 API (WhitelistAuditModule 必需)
whitelist-system:
url: "https://whitelist.your-server.top"
encrypted-token: "your-api-token-here"
```
---
## 基础设施模块
### GroupMessagePollingModule (群消息轮询模块)
按固定间隔轮询 QQ 群消息历史,通过 `SharedFlow<List<MsgHistorySpecificMsg>>` 向其他模块分发消息。
```yaml
- name: "talkGroup"
type: "GROUP_MESSAGE_POLLING_MODULE"
enabled: true
config:
target-group-id: 538751386 # 目标群号
poll-interval-millis: 5000 # 轮询间隔(毫秒)可选默认5000
msg-history-check: 15 # 每次检查的历史消息数可选默认15
```
### MailModule (邮件模块)
通过 SMTP 发送邮件。InvitationCodesModule 和 WhitelistAuditModule 会使用此模块。
```yaml
- name: "talkGroup"
type: "MAIL_MODULE"
enabled: true
```
SMTP 设置在 `application.yaml``mail:` 段配置。
---
## 新模块
### RCON 命令模块
**类型:** `RCON_COMMAND_MODULE`
允许指定用户在 QQ 群中执行 Minecraft RCON 命令。通过黑名单机制阻止危险操作,非授权用户无法执行。
#### 执行流程
```
QQ群: "rcon list"
├── 用户不在 admin-ids 中 → 回复: "你没有权限执行 RCON 命令"
├── 命令匹配 command-blocklist → 回复: "命令已被阻止"
└── 通过 RCON 二进制执行 → 回复执行结果
```
#### 配置示例
```yaml
- name: "talkGroup"
type: "RCON_COMMAND_MODULE"
enabled: true
dependencies:
- name: "talkGroup"
type: "GROUP_MESSAGE_POLLING_MODULE"
config:
self-id: 3327379836
self-nick-name: "Bot"
command-prefix: "rcon" # QQ群触发前缀
admin-ids: [2561098830] # 允许执行RCON的QQ号
rcon-timeout-sec: 5 # RCON超时(秒)
command-blocklist: # 危险命令黑名单(前缀匹配)
- "stop"
- "restart"
- "op"
- "deop"
- "whitelist"
- "ban"
- "ban-ip"
- "kick"
- "debug"
- "execute"
```
#### 配置项
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| `self-id` | long | 是 | — | 机器人 QQ 号 |
| `self-nick-name` | string | 是 | — | 机器人昵称 |
| `command-prefix` | string | 是 | — | QQ 群触发前缀 |
| `admin-ids` | long[] | 是 | — | 允许执行 RCON 的 QQ 号列表 |
| `command-blocklist` | string[] | 是 | — | 危险命令黑名单(不区分大小写,自动去除 `/` 前缀) |
| `rcon-timeout-sec` | long | 否 | `5` | RCON 超时时间(秒) |
RCON 二进制路径和配置文件路径从 `application.yaml``tools.rcon` 读取。
#### 黑名单匹配规则
黑名单使用**前缀匹配**,自动去除前置 `/`
- `"stop"` 阻止: `stop`, `stop 10s`, `/stop`, `/minecraft:stop`
- `"ban"` 阻止: `ban Steve`, `ban-ip`, `/ban`
---
### Gitea Webhook 模块
**类型:** `GITEA_WEBHOOK_MODULE`
启动嵌入式 HTTP 服务器,接收 [Gitea Webhook](https://docs.gitea.com/zh-cn/usage/webhooks) 事件,格式化后推送通知到 QQ 群。
#### 支持的事件类型
| 事件 | QQ 消息格式 |
|---|---|
| `push` | 推送者、分支、提交数、前5条提交摘要、对比链接 |
| `issues` | 操作(已创建/已关闭/已重新打开)、标题、内容预览、链接 |
| `pull_request` | 操作、分支流转(head → base)、状态、链接 |
| `create` | 创建的分支/标签、创建者 |
| `delete` | 删除的分支/标签、操作者 |
| `release` | 标签名、版本名、内容预览、草稿/预发布标记 |
| `repository` | 仓库操作(已创建/已删除/已转移) |
| `fork` | 源仓库 → Fork 仓库 |
#### 配置示例
```yaml
- name: "talkGroup"
type: "GITEA_WEBHOOK_MODULE"
enabled: true
config:
webhook-port: 8080 # 监听端口
webhook-path: "/gitea-webhook" # Webhook 路径
webhook-secret: "your-webhook-secret" # HMAC-SHA256 密钥
target-group-id: 538751386 # 推送 QQ 群号
events: # 监听事件列表(空=全部)
- "push"
- "issues"
- "pull_request"
- "create"
- "delete"
- "release"
```
#### 配置项
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| `webhook-port` | int | 是 | — | HTTP 服务器监听端口 |
| `webhook-path` | string | 否 | `/gitea-webhook` | Webhook 端点路径 |
| `webhook-secret` | string | 否 | `""` | HMAC-SHA256 签名验证密钥,为空则跳过验证 |
| `target-group-id` | long | 是 | — | 推送通知的目标 QQ 群号 |
| `events` | string[] | 否 | 全部 | 监听的事件类型列表 |
#### Gitea 端设置
在 Gitea 仓库 → **设置****Webhooks****添加 Webhook****Gitea**
- **目标 URL**: `http://<服务器IP>:8080/gitea-webhook`
- **密钥**: 与 `webhook-secret` 一致
- **触发条件**: 勾选需要的事件
#### 安全性
- 签名验证: 通过 HMAC-SHA256 验证 `X-Gitea-Signature` 请求头
- 生产环境建议务必设置 `webhook-secret`
---
### 白名单审计模块
**类型:** `WHITELIST_AUDIT_MODULE`
定期检查白名单群成员与白名单 API 的一致性。自动拒绝已离开白名单群的用户,设置宽限期供用户通过主群关键词重新激活。支持管理员手动触发审计,输出详细逐人报告。
**存储:** MySQL `ltd_manager_bot.whitelist_audit` 表(首次加载自动建表)。
#### 自动 vs 手动审计
| | 自动审计 | 手动审计 |
|---|---|---|
| 触发 | 每 N 分钟自动轮询 | 管理员在白名单群发关键词 |
| 群消息 | 不发送(安静) | 发送完整统计摘要 + 逐人详情 |
| 邮件 | 所有操作始终发送 | 所有操作始终发送 |
| 日志前缀 | `[自动]` | `[手动审计]` |
#### 生命周期状态
```
在白名单群中 ───────────────────────────────► 正常(无操作)
└── 用户退出群 ──► 检测到离群 ──► 已被拒绝(宽限期开始)
├── 主群发关键词 ──► 已重新激活
├── 进入警告窗口 ──► 邮件通知(仅一次)
└── 宽限期过 ──► 永久删除
```
#### 配置示例
```yaml
- name: "talkGroup"
type: "WHITELIST_AUDIT_MODULE"
enabled: true
dependencies:
- name: "talkGroup" # 主群轮询 (重新激活关键词)
type: "GROUP_MESSAGE_POLLING_MODULE"
- name: "whitelistGroup" # 白名单群轮询 (审计命令)
type: "GROUP_MESSAGE_POLLING_MODULE"
- name: "talkGroup" # 邮件模块 (enable-email:true 时)
type: "MAIL_MODULE"
config:
self-id: 3327379836
filter-qq-list: [2561098830, 3327379836]
audit-allowed-ids: [2561098830]
whitelist-group-polling-dep-name: "whitelistGroup"
audit-command-prefixes: # 支持多个关键词
- "审计"
- "audit"
re-activation-keywords:
- "重新激活"
- "激活白名单"
grace-period-days: 7
expiry-warning-days: 2
poll-interval-minutes: 60
enable-email: false
# 邮件模板 (空=使用内置默认,支持占位符)
email-reject-template: ""
email-warning-template: ""
email-removed-template: ""
email-reactivated-template: ""
```
#### 配置项
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| `self-id` | long | 是 | — | 机器人 QQ 号 |
| `filter-qq-list` | long[] | 是 | — | 保护列表,永不自动拒绝 |
| `audit-allowed-ids` | long[] | 是 | — | 允许执行手动审计的 QQ |
| `whitelist-group-polling-dep-name` | string | 是 | — | 白名单群轮询模块的依赖名 |
| `audit-command-prefixes` | string[] | 否 | `["审计"]` | 白名单群触发手动审计的关键词(支持多个) |
| `re-activation-keywords` | string[] | 是 | — | 主群中触发重新激活的关键词列表 |
| `grace-period-days` | int | 是 | — | 被拒绝后允许重新激活的天数 |
| `expiry-warning-days` | int | 是 | — | 宽限期到期前多少天发送警告 |
| `poll-interval-minutes` | long | 否 | `60` | 自动审计间隔(分钟) |
| `enable-email` | boolean | 否 | `false` | 是否启用邮件通知(需 MailModule 依赖) |
| `email-reject-template` | string | 否 | `""` | 拒绝邮件正文。占位符:`${playerName}` `${graceDays}` `${keywords}` |
| `email-warning-template` | string | 否 | `""` | 过期警告邮件正文。占位符:`${playerName}` `${remainDays}` `${keywords}` |
| `email-removed-template` | string | 否 | `""` | 删除邮件正文。占位符:`${playerName}` |
| `email-reactivated-template` | string | 否 | `""` | 重新激活邮件正文。占位符:`${playerName}` `${graceDays}` |
#### 手动审计输出示例
```
审计完成
────────────────
白名单总数: 42
在群正常: 35 人
新发现不在群(已拒绝): 2 人
• Steve(123456789)
• Alex(987654321)
宽限期中: Notch(111222333, 剩5天)
已过期删除: 1 人
• Hero(444555666)
过滤列表跳过: 3 人
```
#### 邮件去重
每类邮件只发送一次:
| 邮件 | 去重方式 |
|---|---|
| 拒绝 | 仅首次检测到离群时发送(`existing == null` |
| 重新拒绝 | 仅之前已重新激活的用户再次离群时发送 |
| 即将过期警告 | `warningSentTime == 0L` 守卫,仅发一次 |
| 已删除 | 发送后立即从 DB 删除记录,不再匹配 |
| 重新激活 | 仅在宽限期内关键词触发成功时发送 |
#### 状态持久化
审计状态存储在 **MySQL** `ltd_manager_bot.whitelist_audit` 表中自动建表零配置。Bot 重启不丢失已标记的待处理记录。原先基于 JSON 文件的状态持久化已移除。
SQL 模板位于 `config/sql/whitelist/`:
- `create_audit_table.sql` — 建表 DDL
- `query_all_audit.sql` — 查全表
- `query_audit_by_qq.sql` — 按 QQ 查询
- `upsert_audit.sql` — 新增或更新
- `delete_audit.sql` — 删除记录
#### 依赖关系
| 依赖模块 | 类型 | 是否必需 | 用途 |
|---|---|---|---|
| 主群轮询 | `GROUP_MESSAGE_POLLING_MODULE` | 是 | 监听主群重新激活关键词 |
| 白名单群轮询 | `GROUP_MESSAGE_POLLING_MODULE` | 是 | 监听审计命令 + 获取群成员列表 |
| 邮件模块 | `MAIL_MODULE` | `enable-email: true` 时 | 发送邮件通知 |
#### 白名单 API 配置
API 地址和密钥在 `application.yaml``whitelist-system:` 段配置(启动后自动加密):
```yaml
whitelist-system:
url: "https://whitelist.your-server.top"
encrypted-token: "your-api-token-here"
```
#### 邮件通知时机
| 触发条件 | 邮件主题 |
|---|---|
| 首次检测离群 → 被拒绝 | `白名单已被拒绝` — 含宽限期和关键词提示 |
| 重新激活后再离群 → 再次拒绝 | `白名单已被拒绝` — 同上 |
| 进入警告窗口 | `白名单即将过期` — 剩余天数 |
| 宽限期过 → 永久删除 | `白名单已删除` |
| 关键词重新激活成功 | `白名单已重新激活` — 提醒加群 |
---
## 配置参考
### SQL 模板
部分模块(InvitationCodesModule、GroupRequestHandlerModule)使用 `config/sql/` 下的 SQL 模板文件。模板使用 `${placeholder}` 语法:
```sql
-- config/sql/invitation/query_qualification.sql
SELECT q.player_id, q.effective, q.is_used, q.qq, q.status
FROM ltd_manager_bot.qualified_user_info q
WHERE q.qq IN (${placeholders})
```
代码中使用:
```kotlin
val sql = SqlTemplate.fromFile("invitation/query_qualification.sql")
val result = sql.bind("placeholders" to "?, ?, ?")
```
### 消息过滤管道
所有消息驱动的模块使用统一的 `TriggerMessageFilter` 管道:
```
IgnoreSelfFilter → NewMessageFilter → KeywordFilter → [CooldownFilter] → handler
```
管道确保:机器人自己的消息被忽略、只处理新消息、只有匹配关键词的消息才会到达业务处理器。