12 KiB
LTD-ManagerBot Module Documentation
Table of Contents
Quick Start
- Copy the example configs from
src/main/resources/toconfig/ - Edit
config/application.yaml— set database, API URLs, tokens - Edit
config/module.yaml— uncomment and configure desired modules - Place SQL templates in
config/sql/if using InvitationCodes or WhitelistAudit - Launch the bot
Minimal application.yaml additions for new modules
# 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<List<MsgHistorySpecificMsg>>. Other modules subscribe to this flow to react to messages.
- 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.
- 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
- 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 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
- 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://<server-ip>:8080/gitea-webhook - Secret: Same as
webhook-secret - Trigger On: Select desired events
Security
- Signature verification:
X-Gitea-Signatureheader validated via HMAC-SHA256 - Empty
webhook-secretdisables 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 with detailed per-user reporting.
Storage: MySQL ltd_manager_bot.whitelist_audit table (auto-created on first load).
Auto vs Manual Audit
| Auto Audit | Manual Audit | |
|---|---|---|
| Trigger | Every N minutes (poll-interval) | Admin sends keyword in whitelist group |
| Group messages | Silent (none) | Full summary with per-user detail |
| Always sent for every action | Always sent for every action | |
| Log prefix | [自动] |
[手动审计] |
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 sent (once)
└── Grace period expired ──► Permanently Removed
Example Config
- 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-prefixes:
- "审计"
- "audit"
re-activation-keywords:
- "重新激活"
- "激活白名单"
grace-period-days: 7
expiry-warning-days: 2
poll-interval-minutes: 60
enable-email: false
# Email templates (omit = use built-in defaults)
email-reject-template: ""
email-warning-template: ""
email-removed-template: ""
email-reactivated-template: ""
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-prefixes |
string[] | no | ["审计"] |
Keywords to trigger manual audit (multiple) |
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) |
email-reject-template |
string | no | "" |
Rejection email body. Placeholders: ${playerName} ${graceDays} ${keywords} |
email-warning-template |
string | no | "" |
Expiry warning email body. Placeholders: ${playerName} ${remainDays} ${keywords} |
email-removed-template |
string | no | "" |
Removal email body. Placeholders: ${playerName} |
email-reactivated-template |
string | no | "" |
Re-activation email body. Placeholders: ${playerName} ${graceDays} |
Manual Audit Output Example
审计完成
────────────────
白名单总数: 42
在群正常: 35 人
新发现不在群(已拒绝): 2 人
• Steve(123456789)
• Alex(987654321)
宽限期中: Notch(111222333, 剩5天)
已过期删除: 1 人
• Hero(444555666)
过滤列表跳过: 3 人
Email Deduplication
Emails are sent exactly once per event:
| Guard | |
|---|---|
| Rejection | Only on first detection (existing == null) |
| Re-rejection | Only when previously-reactivated user leaves again |
| Expiry warning | warningSentTime == 0L — sent once |
| Removal | Record deleted from DB after send — never repeats |
| Re-activation | Only on successful keyword-triggered approve |
State Persistence
Audit state is stored in MySQL ltd_manager_bot.whitelist_audit table (auto-created, zero config). Survives bot restarts. Historical JSON file-based state is no longer used.
SQL templates are in config/sql/whitelist/:
create_audit_table.sql— DDLquery_all_audit.sql— fetch all recordsquery_audit_by_qq.sql— fetch by QQupsert_audit.sql— insert or updatedelete_audit.sql— remove record
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):
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:
-- 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:
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.