mirror of
https://github.com/tiennm99/tiennm99bot.git
synced 2026-10-11 03:13:46 +00:00
docs: describe the bundled renderer service
This commit is contained in:
1 parent
2bb5108151
commit
3130f5ec36
5 files changed
+37
-31
No files matched your search
+6
-5
@@ -38,12 +38,13 @@ STICKER_PACK_NAME=miti99_by_miti99bot
|
||||
# Without it every /lol* fetch fails; the stale cache covers ≤60 min.
|
||||
LOL_PANDASCORE_TOKEN=
|
||||
|
||||
# Optional /wheelofnames GIF and /gacha MP4 renderer. Standard deployment:
|
||||
# https://github.com/tiennm99/wheelofnames. Set the full /api/gif endpoint;
|
||||
# /gacha calls /api/gacha on the same service. Leave blank to fall back to text
|
||||
# selection.
|
||||
# Optional /wheelofnames GIF and /gacha MP4 renderer: the renderer/ service in
|
||||
# this repository. compose.yml fixes this to http://renderer:3000/api/gif, so
|
||||
# set it only when running the bot outside compose. /gacha calls /api/gacha on
|
||||
# the same service. Leave blank to fall back to text selection.
|
||||
WHEELOFNAMES_API_URL=
|
||||
# Bearer token matching the wheelofnames service API_TOKEN when URL is set.
|
||||
# Bearer token shared with the renderer; compose passes it to the renderer as
|
||||
# API_TOKEN. Required for the renderer to start.
|
||||
WHEELOFNAMES_API_TOKEN=
|
||||
|
||||
# ====================== Leave UNSET on self-host ==================
|
||||
|
||||
@@ -12,6 +12,11 @@ port of `tiennm99/mttools/monkeyd-crawler` under
|
||||
`internal/modules/monkeyd/{crawler,pdf,export}`. Change them here; they no
|
||||
longer track the mttools copy.
|
||||
|
||||
`renderer/` is a separate Node 24 service (JavaScript + JSDoc, Remotion) that
|
||||
draws the `random` module's animations. It has its own `package.json`, tests,
|
||||
and `renderer/AGENTS.md`; run its npm commands from that folder. `compose.yml`
|
||||
deploys it next to the bot.
|
||||
|
||||
## Development Rules
|
||||
|
||||
- Keep changes scoped to the requested module or shared contract.
|
||||
|
||||
@@ -9,7 +9,7 @@ Atlas via long polling and an in-process cron scheduler.
|
||||
|---|---|
|
||||
| `util` | `/help`, `/info` (admin), `/stickerid` (owner) |
|
||||
| `misc` | `/ping`, `/ping_stats` (admin), `/ff` (admin), `/xlt1`, `/giaxang` (Petrolimex retail fuel prices), `/the_answer` (owner), `/trongtruonghop` + `/tth`, `/trongtruonghopvng` + `/tthvng` disclaimers |
|
||||
| `random` | Pick one comma-separated option at random: `/random` (text), `/wheelofnames` (wheel GIF), `/gacha` (card-pack wish MP4; options are 5★ by default, prefix `4*` or `3*`), `/genshin` (unlisted; the same wish as a Genshin-style meteor). The animations use the optional wheelofnames renderer |
|
||||
| `random` | Pick one comma-separated option at random: `/random` (text), `/wheelofnames` (wheel GIF), `/gacha` (card-pack wish MP4; options are 5★ by default, prefix `4*` or `3*`), `/genshin` (unlisted; the same wish as a Genshin-style meteor). The animations use the bundled [renderer](renderer/README.md) service |
|
||||
| `amlich` | Vietnamese lunar calendar: `/amlich` (dương lịch → âm lịch, defaults to today), `/duonglich` (âm lịch → dương lịch, `nhuan` flag for leap months); dates accept `d`, `d/m`, or `d/m/yyyy` — missing parts fill from today in the input's calendar. Years 1800–2199 only |
|
||||
| `wordle` | Daily Wordle game: `/wordle [word]`, `/wordle_new`, `/wordle_giveup`, `/wordle_stats` |
|
||||
| `loldle` | League-of-Legends "guess the champion": `/loldle [champion]`, `/loldle_giveup`, `/loldle_stats`, `/loldle_setmax` (owner) |
|
||||
@@ -240,7 +240,8 @@ internal/modules/ Module framework, registry, dispatchers, modules
|
||||
internal/storage/ typed DocStore[T] (Provider + Typed); mongodb runtime + memory (tests). Values persist as flattened native BSON root documents
|
||||
internal/systemstate/ shared `system` collection helper for startup migration records
|
||||
internal/log/, metrics/ JSON logging (LOG_LEVEL) and periodic metrics flush
|
||||
compose.yml Coolify self-host stack (single bot service)
|
||||
renderer/ Node animation renderer for /wheelofnames, /gacha, /genshin
|
||||
compose.yml Coolify self-host stack (bot + renderer services)
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -36,8 +36,8 @@ Copy [`.env.example`](../.env.example) → `.env` (gitignored) and fill in.
|
||||
| `ADMIN_IDS` | optional | CSV of Telegram user ids for admin-only commands |
|
||||
| `STICKER_PACK_NAME` | optional | set `/addsticker` writes to; default `miti99_by_miti99bot`. See [sticker packs](sticker-packs.md) |
|
||||
| `LOL_PANDASCORE_TOKEN` | ✅ for lol module | PandaScore API token (free tier) — secret, never logged; without it every `/lol*` fetch fails (stale cache may still serve briefly) |
|
||||
| `WHEELOFNAMES_API_URL` | optional | full `/api/gif` endpoint for remote `/wheelofnames` GIF rendering |
|
||||
| `WHEELOFNAMES_API_TOKEN` | optional | bearer token matching the wheelofnames service `API_TOKEN` |
|
||||
| `WHEELOFNAMES_API_URL` | leave unset | fixed by `compose.yml` to the bundled renderer (`http://renderer:3000/api/gif`); a Coolify value is ignored |
|
||||
| `WHEELOFNAMES_API_TOKEN` | ✅ for animations | bearer token shared by the bot and the bundled renderer (its `API_TOKEN`) — secret; unset = the renderer refuses to start and the animated commands reply with text |
|
||||
| `LOG_LEVEL` | optional | `debug`, `info` (default), `warn`, or `error`; logs are JSON on stdout |
|
||||
| `GOLD_VNAPP_API_KEY` | leave unset | VNAppMob key; unset = the gold module fetches one and caches it in MongoDB |
|
||||
| `KV_PROVIDER` | leave unset | `memory` or `mongodb`; unset = `mongodb` when `MONGO_URL` is set, otherwise `memory` |
|
||||
@@ -51,31 +51,30 @@ has no webhook.
|
||||
> Cron runs in-process (`internal/cron`) — there is no `/cron` HTTP route and no
|
||||
> `CRON_SHARED_SECRET`. The scheduler is the sole trigger; nothing inbound.
|
||||
|
||||
### Optional wheelofnames renderer
|
||||
### Animation renderer
|
||||
|
||||
`/wheelofnames` uses a remote GIF renderer when `WHEELOFNAMES_API_URL` is set.
|
||||
The standard renderer is a deployment of
|
||||
[`tiennm99/wheelofnames`](https://github.com/tiennm99/wheelofnames), but any
|
||||
service that implements the same `/api/gif` contract can be used. Set the URL
|
||||
to the full GIF endpoint and set the token to the same value as the service
|
||||
`API_TOKEN`:
|
||||
`/wheelofnames`, `/gacha`, and `/genshin` are drawn by the Node renderer in
|
||||
[`renderer/`](../renderer/README.md) (Remotion and headless Chrome).
|
||||
`compose.yml` deploys it as a second service, `renderer`, next to the bot. It
|
||||
is internal only: the bot reaches it at `http://renderer:3000/api/gif` over the
|
||||
compose network, so it needs no domain and publishes no port. The only setting
|
||||
is the shared token:
|
||||
|
||||
```env
|
||||
WHEELOFNAMES_API_URL=http://wheelofnames:3000/api/gif
|
||||
WHEELOFNAMES_API_TOKEN=<same value as wheelofnames API_TOKEN>
|
||||
WHEELOFNAMES_API_TOKEN=<random secret>
|
||||
```
|
||||
|
||||
Use a public HTTPS URL instead when the bot cannot reach the service on a
|
||||
private Coolify/Docker network:
|
||||
Renderer tuning (`MAX_CONCURRENT_RENDERS`, `RENDER_TIMEOUT_MS`, `MAX_OPTIONS`,
|
||||
`MAX_OPTION_CHARS`) can be set in Coolify too; the defaults are in
|
||||
[`renderer/docs/deployment.md`](../renderer/docs/deployment.md). Give the host
|
||||
1-2 GB of headroom for the renderer's Chrome.
|
||||
|
||||
```env
|
||||
WHEELOFNAMES_API_URL=https://wheelofnames.example.com/api/gif
|
||||
WHEELOFNAMES_API_TOKEN=<same value as wheelofnames API_TOKEN>
|
||||
```
|
||||
Outside compose, `WHEELOFNAMES_API_URL` can point the bot at any service that
|
||||
implements the same `/api/gif` contract.
|
||||
|
||||
The bot sends outbound HTTP only; no public bot ingress is required. Remote
|
||||
renders use `512px`, `20fps`, and `7` seconds total by default. If the remote
|
||||
service is unset, unavailable, unauthorized, or returns a non-GIF response,
|
||||
renders use `512px`, `20fps`, and `7` seconds total by default. If the renderer
|
||||
is unset, unavailable, unauthorized, or returns a non-GIF response,
|
||||
`/wheelofnames` falls back to the same plain text winner reply as `/random`.
|
||||
Successful GIF replies include the result behind Telegram spoiler formatting.
|
||||
|
||||
@@ -146,8 +145,8 @@ MP4, with the same text fallback.
|
||||
## 2. Coolify
|
||||
|
||||
1. New resource → from this Git repo (Docker Compose), or a prebuilt image.
|
||||
The committed [`compose.yml`](../compose.yml) defines the single
|
||||
`bot` service.
|
||||
The committed [`compose.yml`](../compose.yml) defines the `bot` service
|
||||
and the internal `renderer` service.
|
||||
2. Set the env vars above in Coolify.
|
||||
3. **No public domain / port** is needed — polling is outbound-only. Do not
|
||||
publish a port or attach a domain. `expose: 8080` keeps the health endpoint
|
||||
|
||||
@@ -16,9 +16,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// The standard renderer is a deployment of
|
||||
// https://github.com/tiennm99/wheelofnames. Operators may point this to any
|
||||
// service that implements the same /api/gif contract.
|
||||
// The standard renderer is the renderer/ service in this repository, wired
|
||||
// in by compose.yml. Operators may point this to any service that
|
||||
// implements the same /api/gif contract.
|
||||
wheelOfNamesAPIURLEnv = "WHEELOFNAMES_API_URL"
|
||||
wheelOfNamesAPITokenEnv = "WHEELOFNAMES_API_TOKEN"
|
||||
|
||||
|
||||
Reference in new issue
Block a user