51 lines
3.5 KiB
Markdown
51 lines
3.5 KiB
Markdown
# ShbDiscordBot contributor guide
|
|
|
|
## Purpose and invariants
|
|
|
|
This repository builds one Paper plugin which embeds a JDA Discord bot. Discord is the entry point for issuing short-lived link codes, Minecraft is the only place where a code can be consumed, and ShbUtils Core API is the source of truth for persistent Discord-to-Minecraft links.
|
|
|
|
- `/auth` is a global Discord slash command intended for bot DMs.
|
|
- `/link <six-digit-code>` is a player-only Paper command.
|
|
- `/sdb reload` is the operator-only full runtime/config reload command. Do not override Paper's built-in `/reload` command.
|
|
- Link codes are process-local, single-use, active for ten minutes by default, and must never be logged.
|
|
- Existing Discord or Minecraft links must not be overwritten.
|
|
- Discord roles only grant LuckPerms nodes. This project deliberately does not revoke them.
|
|
|
|
## Build and verification
|
|
|
|
- Use Java 25 and the checked-in Gradle wrapper.
|
|
- `./gradlew test` runs the automated test suite.
|
|
- `./gradlew shadowJar` creates the deployable plugin JAR; the plain JAR does not include JDA/Jackson.
|
|
- `./gradlew build` must pass before handing work off.
|
|
- LuckPerms and Paper are compile-only/server-provided dependencies. Do not shade either of them.
|
|
|
|
## Architecture rules
|
|
|
|
- Keep configuration parsing, Discord/JDA integration, ShbUtils HTTP transport, link orchestration, Paper commands, and LuckPerms synchronization in separate classes.
|
|
- Do not perform network requests, JDA waits, or LuckPerms user loads on the Paper main thread.
|
|
- Only touch Bukkit player/server state on the Paper main thread. Capture UUIDs and immutable values before crossing thread boundaries.
|
|
- Make scheduled role scans non-overlapping and bound API concurrency.
|
|
- Treat API `401` and validation/conflict responses as permanent failures; treat I/O, timeouts, `429`, and `5xx` as retryable.
|
|
- On disable, cancel tasks and close JDA plus plugin-owned executors.
|
|
- A runtime reload must validate the new config before stopping the current runtime, invalidate pending codes, await JDA shutdown off the Paper thread, recreate all config-bound services, and immediately run role synchronization.
|
|
|
|
## Security and configuration
|
|
|
|
- Never commit real Discord tokens or `X-Internal-Secret` values. The resource `config.yml` contains empty placeholders only.
|
|
- Never include secrets, bearer tokens, full HTTP headers, or active link codes in logs or exceptions shown to players.
|
|
- Parse Discord snowflakes as strings/unsigned IDs and Minecraft identifiers as UUIDs.
|
|
- Generate codes with `SecureRandom`; preserve leading zeroes and enforce rate limiting when consuming invalid codes.
|
|
|
|
## API contract and documentation
|
|
|
|
- The local API reference is `docs/API.md`, based on `https://api.shlakoblock.com/api.json`.
|
|
- Runtime code uses only internal status and Discord-link endpoints. Do not use the API verification-code endpoints for the Discord-to-Minecraft flow: those endpoints implement the reverse direction.
|
|
- When the upstream OpenAPI version changes, compare every path/schema and update `docs/API.md`, DTOs, tests, and the recorded snapshot date together.
|
|
|
|
## Testing expectations
|
|
|
|
- Cover code uniqueness, expiry, replacement, rate limiting, reservation/release, and concurrent single-use behavior.
|
|
- Test HTTP paths, JSON fields, internal-secret headers, status handling, and timeout/error classification without contacting production.
|
|
- Test role-to-permission union, idempotent grants, unlinked users, and grant-only behavior.
|
|
- A feature is incomplete if it can block the Paper main thread or leak a secret/code to logs.
|