# LTD-ManagerBot Module Documentation ## Table of Contents - [Quick Start](#quick-start) - [Infrastructure Modules](#infrastructure-modules) - [New Modules](#new-modules) - [RCON Command Module](#rcon-command-module) - [Gitea Webhook Module](#gitea-webhook-module) - [Whitelist Audit Module](#whitelist-audit-module) - [Configuration Reference](#configuration-reference) --- ## Quick Start 1. Copy the example configs from `src/main/resources/` to `config/` 2. Edit `config/application.yaml` — set database, API URLs, tokens 3. Edit `config/module.yaml` — uncomment and configure desired modules 4. Place SQL templates in `config/sql/` if using InvitationCodes or WhitelistAudit 5. Launch the bot ### Minimal `application.yaml` additions for new modules ```yaml # Whitelist System API (required by WhitelistAuditModule) whitelist-system: url: "https://whitelist.your-server.top" encrypted-token: "your-api-token-here" ``` --- ## Infrastructure Modules ### GroupMessagePollingModule Polls a QQ group's message history at a fixed interval and emits a `SharedFlow>`. Other modules subscribe to this flow to react to messages. ```yaml - name: "talkGroup" type: "GROUP_MESSAGE_POLLING_MODULE" enabled: true config: target-group-id: 538751386 poll-interval-millis: 5000 # optional, default 5000 msg-history-check: 15 # optional, default 15 ``` ### MailModule Queues and sends emails via SMTP. Used by InvitationCodesModule and WhitelistAuditModule. ```yaml - name: "talkGroup" type: "MAIL_MODULE" enabled: true ``` SMTP settings go in `application.yaml` → `mail:` section. --- ## New Modules ### RCON Command Module **Type:** `RCON_COMMAND_MODULE` Allows specified QQ users to execute arbitrary Minecraft RCON commands via QQ group messages, with a configurable blocklist to prevent dangerous operations. #### Workflow ``` QQ Group: "rcon list" │ ├── User NOT in admin-ids → reply: "no permission" ├── Command matches blocklist → reply: "blocked" └── Execute via RCON binary → reply with output ``` #### Example Config ```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" admin-ids: [2561098830] rcon-timeout-sec: 5 command-blocklist: - "stop" - "restart" - "op" - "deop" - "whitelist" - "ban" - "ban-ip" - "kick" - "debug" - "execute" ``` #### Config Reference | Field | Type | Required | Default | Description | |---|---|---|---|---| | `self-id` | long | yes | — | Bot's QQ ID | | `self-nick-name` | string | yes | — | Bot's display name | | `command-prefix` | string | yes | — | Trigger prefix in QQ group | | `admin-ids` | long[] | yes | — | QQ IDs allowed to execute RCON | | `command-blocklist` | string[] | yes | — | Blocked command prefixes (case-insensitive, `/`-prefix stripped) | | `rcon-timeout-sec` | long | no | `5` | RCON timeout in seconds | The RCON binary path and config path are read from `application.yaml` → `tools.rcon`. #### Blocklist Matching The blocklist uses **prefix matching** after stripping leading `/`: - `"stop"` blocks: `stop`, `stop 10s`, `/stop`, `/minecraft:stop` - `"ban"` blocks: `ban Steve`, `ban-ip`, `/ban`, etc. --- ### Gitea Webhook Module **Type:** `GITEA_WEBHOOK_MODULE` Starts an embedded HTTP server to receive [Gitea webhook](https://docs.gitea.com/usage/webhooks) events and forwards formatted notifications to a QQ group. #### Supported Events | Event | QQ Message Format | |---|---| | `push` | Author, branch, commit count, first 5 commit messages, compare URL | | `issues` | Action (opened/closed/reopened), title, body preview, link | | `pull_request` | Action, branches (head → base), state, link | | `create` | Branch/tag created, author | | `delete` | Branch/tag deleted, author | | `release` | Tag name, release name, body preview, draft/prerelease flags | | `repository` | Action (created/deleted/transferred) | | `fork` | Source repo → forked repo | #### Example Config ```yaml - name: "talkGroup" type: "GITEA_WEBHOOK_MODULE" enabled: true config: webhook-port: 8080 webhook-path: "/gitea-webhook" webhook-secret: "your-webhook-secret" target-group-id: 538751386 events: - "push" - "issues" - "pull_request" - "create" - "delete" - "release" ``` #### Config Reference | Field | Type | Required | Default | Description | |---|---|---|---|---| | `webhook-port` | int | yes | — | HTTP server listen port | | `webhook-path` | string | no | `/gitea-webhook` | Webhook endpoint path | | `webhook-secret` | string | no | `""` | HMAC-SHA256 secret for signature verification | | `target-group-id` | long | yes | — | QQ group to send notifications to | | `events` | string[] | no | all | Event types to listen for | #### Gitea-side Setup In your Gitea repository → **Settings** → **Webhooks** → **Add Webhook** → **Gitea**: - **Target URL**: `http://:8080/gitea-webhook` - **Secret**: Same as `webhook-secret` - **Trigger On**: Select desired events #### Security - Signature verification: `X-Gitea-Signature` header validated via HMAC-SHA256 - Empty `webhook-secret` disables verification (not recommended for production) --- ### Whitelist Audit Module **Type:** `WHITELIST_AUDIT_MODULE` Periodically checks the whitelist group membership against the whitelist API. Automatically rejects users who left the group, with a configurable grace period for re-activation via keywords in the main group. Supports admin-triggered manual audits. #### Lifecycle States ``` In Whitelist Group ───────────────────────────────► OK (no action) │ └── User left group ──► Detected ──► Rejected (grace period starts) │ ├── Keyword in main group ──► Re-Activated ├── Warning threshold ──► Email/Group notification sent └── Grace period expired ──► Permanently Removed ``` #### Two-Trigger System | Trigger | Group | Who | Action | |---|---|---|---| | Keyword (e.g. "重新激活") | Main group | Any pending user | Re-activates whitelist | | Audit command (e.g. "审计") | Whitelist group | `audit-allowed-ids` only | Runs immediate audit + posts results | #### Example Config ```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" # only if 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-prefix: "审计" re-activation-keywords: - "重新激活" - "激活白名单" - "reactivate" grace-period-days: 7 expiry-warning-days: 2 poll-interval-minutes: 60 enable-email: false ``` #### Config Reference | Field | Type | Required | Default | Description | |---|---|---|---|---| | `self-id` | long | yes | — | Bot's QQ ID | | `filter-qq-list` | long[] | yes | — | QQ IDs never auto-rejected | | `audit-allowed-ids` | long[] | yes | — | QQ IDs allowed to trigger manual audit | | `whitelist-group-polling-dep-name` | string | yes | — | Dependency name for the whitelist group polling module | | `audit-command-prefix` | string | no | `"审计"` | Command to trigger manual audit in whitelist group | | `re-activation-keywords` | string[] | yes | — | Keywords to re-activate from main group | | `grace-period-days` | int | yes | — | Days user has to re-activate after being rejected | | `expiry-warning-days` | int | yes | — | Days before expiry to send warning | | `poll-interval-minutes` | long | no | `60` | Auto-audit interval in minutes | | `enable-email` | boolean | no | `false` | Enable email notifications (requires MailModule) | #### Manual Audit Output Example ``` 审计完成 ──────────────── 白名单总数: 42 在群正常: 35 人 新发现不在群(已拒绝): 2 人 宽限期中: Steve(剩5天), Alex(剩2天) 已过期删除: 1 人 过滤列表跳过: 3 人 ``` #### State Persistence Audit state is persisted to `data/whitelist_audit_state.json` with automatic backup. Survives bot restarts without losing pending reject records. #### Dependencies | Dependency | Type | Required | Purpose | |---|---|---|---| | Main group polling | `GROUP_MESSAGE_POLLING_MODULE` | yes | Re-activation keyword monitoring | | Whitelist group polling | `GROUP_MESSAGE_POLLING_MODULE` | yes | Audit command monitoring + member list | | Mail module | `MAIL_MODULE` | if `enable-email: true` | Email notifications | #### Whitetelist API Config API URL and token are in `application.yaml` `whitelist-system:` section for security (auto-encrypted): ```yaml whitelist-system: url: "https://whitelist.your-server.top" encrypted-token: "your-api-token-here" ``` --- ## Configuration Reference ### SQL Templates Some modules (InvitationCodesModule, GroupRequestHandlerModule) use SQL templates stored in `config/sql/`. Templates use `${placeholder}` syntax: ```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}) ``` Usage in code: ```kotlin val sql = SqlTemplate.fromFile("invitation/query_qualification.sql") val result = sql.bind("placeholders" to "?, ?, ?") ``` ### Message Filter Pipeline All message-driven modules use a common `TriggerMessageFilter` pipeline: ``` IgnoreSelfFilter → NewMessageFilter → KeywordFilter → [CooldownFilter] → handler ``` This ensures messages from the bot itself are ignored, only new messages are processed, and only keyword-matching messages reach the handler.