diff --git a/src/modules/loldle/README.md b/src/modules/loldle/README.md new file mode 100644 index 0000000..e157e61 --- /dev/null +++ b/src/modules/loldle/README.md @@ -0,0 +1,20 @@ +# Loldle Module + +League of Legends guessing game — currently a stub proving the plugin system. + +## Commands + +| Command | Visibility | Description | +|---------|-----------|-------------| +| `/loldle` | public | Start a loldle game (stub) | +| `/lstats` | protected | Show loldle stats (stub) | +| `/ggwp` | private | Easter egg — "gg well played" | + +## Architecture + +- All commands return stub responses. Real game logic is not yet implemented. +- No `init()` hook — this module does not use KV storage yet. + +## Database + +**No KV usage currently.** When game logic is implemented, it will use KV namespace prefix `loldle:`. diff --git a/src/modules/misc/README.md b/src/modules/misc/README.md new file mode 100644 index 0000000..b3f50db --- /dev/null +++ b/src/modules/misc/README.md @@ -0,0 +1,35 @@ +# Misc Module + +Health check and DB demonstration. Exercises all three visibility levels. + +## Commands + +| Command | Visibility | Description | +|---------|-----------|-------------| +| `/ping` | public | Health check — replies "pong" and records timestamp | +| `/mstats` | protected | Shows last `/ping` timestamp | +| `/fortytwo` | private | Easter egg — replies "The answer." | + +## Architecture + +- `/ping` writes a timestamp to KV on every call (best-effort — KV failure doesn't block the reply). +- `/mstats` reads the last ping timestamp and formats it as ISO string. +- `/fortytwo` is a hidden command demonstrating private visibility. + +## Database + +KV namespace prefix: `misc:` + +| Key | Type | Description | Example | +|-----|------|-------------|---------| +| `last_ping` | JSON | Timestamp of the most recent `/ping` call | `{ "at": 1713100000000 }` | + +### Schema: `last_ping` + +```json +{ + "at": 1713100000000 +} +``` + +- `at` — Unix epoch milliseconds (`Date.now()`) diff --git a/src/modules/trading/README.md b/src/modules/trading/README.md index fffb6bf..50c92c3 100644 --- a/src/modules/trading/README.md +++ b/src/modules/trading/README.md @@ -28,16 +28,48 @@ Paper-trading system where each Telegram user manages a virtual portfolio. Currencies: VND, USD. -## Data Model +## Database -Per-user portfolio stored as a single KV object at key `user:`: +KV namespace prefix: `trading:` -```js -{ currency: { VND, USD }, stock: {}, crypto: {}, others: {}, totalvnd: 0 } +| Key | Type | Description | +|-----|------|-------------| +| `user:` | JSON | Per-user portfolio (balances + holdings) | +| `prices:latest` | JSON | Cached merged prices from all APIs | + +### Schema: `user:` + +```json +{ + "currency": { "VND": 5000000, "USD": 100 }, + "stock": { "TCB": 10, "FPT": 5 }, + "crypto": { "BTC": 0.005, "ETH": 1.2 }, + "others": { "GOLD": 0.1 }, + "totalvnd": 10000000 +} ``` -- `totalvnd` tracks cumulative VND value of all top-ups (cost basis for P&L) +- `currency` — fiat balances (VND, USD) +- `stock` / `crypto` / `others` — asset quantities keyed by symbol +- `totalvnd` — cumulative VND value of all top-ups (cost basis for P&L) - VND is the sole settlement currency — buy/sell deducts/adds VND +- Empty categories are `{}`, not absent — migration-safe loading fills missing keys + +### Schema: `prices:latest` + +```json +{ + "ts": 1713100000000, + "crypto": { "BTC": 1500000000, "ETH": 50000000, "SOL": 3000000 }, + "stock": { "TCB": 25000, "VPB": 18000, "FPT": 120000, "VNM": 70000, "HPG": 28000 }, + "forex": { "USD": 25400 }, + "others": { "GOLD": 72000000 } +} +``` + +- `ts` — Unix epoch milliseconds of last fetch +- All prices in VND per unit +- Cache TTL: 60 seconds (stale fallback up to 5 minutes) ## Price Sources diff --git a/src/modules/util/README.md b/src/modules/util/README.md new file mode 100644 index 0000000..4f2b5b8 --- /dev/null +++ b/src/modules/util/README.md @@ -0,0 +1,20 @@ +# Util Module + +Core bot utilities — informational commands that read framework metadata. + +## Commands + +| Command | Visibility | Description | +|---------|-----------|-------------| +| `/info` | public | Echoes chat id, thread id, sender id (debug helper) | +| `/help` | public | Renders all public + protected commands grouped by module | + +## Architecture + +- `/help` is a pure renderer over `getCurrentRegistry()` — it reads the registry's command maps and formats them as Telegram HTML. Modules with zero visible commands are omitted. Private commands are always excluded. +- `/info` reads grammY context fields (`ctx.chat.id`, `ctx.message.message_thread_id`, `ctx.from.id`). No external state. +- HTML injection is prevented via `escapeHtml()` on all user-influenced strings. + +## Database + +**No KV usage.** This module has no `init()` hook and does not store any data. diff --git a/src/modules/wordle/README.md b/src/modules/wordle/README.md new file mode 100644 index 0000000..b9c3d2e --- /dev/null +++ b/src/modules/wordle/README.md @@ -0,0 +1,35 @@ +# Wordle Module + +Word guessing game — currently a stub proving the plugin system. + +## Commands + +| Command | Visibility | Description | +|---------|-----------|-------------| +| `/wordle` | public | Start a wordle game (stub) | +| `/wstats` | protected | Show wordle stats | +| `/konami` | private | Easter egg — "secret wordle mode" | + +## Architecture + +- All commands return stub responses. Real game logic is not yet implemented. +- `/wstats` reads a `stats` key from KV (returns 0 games played when empty). +- Module captures `db` in closure via `init()` for future game state persistence. + +## Database + +KV namespace prefix: `wordle:` + +| Key | Type | Description | Example | +|-----|------|-------------|---------| +| `stats` | JSON | Aggregate game statistics (planned) | `{ "gamesPlayed": 0 }` | + +### Schema: `stats` (planned) + +```json +{ + "gamesPlayed": 0 +} +``` + +No data is currently written — the module only reads this key defensively.