diff --git a/plans/261007-1423-rebrand-tiennm99bot/phase-01-code-rebrand.md b/plans/261007-1423-rebrand-tiennm99bot/phase-01-code-rebrand.md new file mode 100644 index 0000000..936184d --- /dev/null +++ b/plans/261007-1423-rebrand-tiennm99bot/phase-01-code-rebrand.md @@ -0,0 +1,85 @@ +--- +phase: 1 +title: "Code rebrand" +status: done +owner: agent +--- + +# Phase 1 — Code rebrand + +## Context + +Every in-repo `miti99bot` occurrence, listed in the +[scout report](../reports/scout-261007-1423-rebrand-tiennm99bot.md). The bot's +own username is already runtime-resolved (`BOT_USERNAME` or getMe), so nothing +here depends on the new Telegram account. + +## Steps + +1. **Go module path.** In `go.mod`, change it to `github.com/tiennm99/tiennm99bot`, + then rewrite every import: + `git ls-files '*.go' | xargs sed -i 's#github.com/tiennm99/miti99bot#github.com/tiennm99/tiennm99bot#g'`. + `util/help.go` `repoURL` and `util/help_test.go` follow from the same sed. +2. **Runtime strings** → `tiennm99bot`: + - `internal/server/health.go` health body, plus the `compose.yml` and + `docs/deploy-coolify-selfhosted.md` text that quotes it. + - `internal/deploynotify/deploy_notify.go` DM text, plus its test. + - User-Agents in `coin/price_providers.go`, `gold/vnappmob_client.go` (×2), + `stock/prices_ssi.go`, `lol/api_client.go` (`userAgentProduct`), plus + `stock/prices_test.go` and `lol/api_client_test.go`. + - `monkeyd/export_job.go` `cacheDirName`. + - `renderer/src/gacha/page/page.js` edition label. +3. **Sticker slug.** Set `sticker/sticker_pack.go` `defaultStickerPackSlug` to the + confirmed slug (proposed `stickers`). Update the comment example and the tests + (`addsticker_command_test.go`, `sticker_pack_test.go`), plus the examples in + `docs/sticker-packs.md`, `.env.example` and `compose.yml`. +4. **Test fixtures.** Change `/cmd@miti99bot` to `@tiennm99bot` in + `modules/dispatcher_test.go` and `alias/fallback_test.go`, and the comment in + `stats/views.go`. Change the test DB prefixes `miti99bot_*` to + `tiennm99bot_*` in four `*_mongo*_test.go` files. Update the + `sticker_pack_test.go` username fixture. Leave `misc/handlers_test.go` + `@miti99` alone, because it is a user handle. +5. **loldle stickers.** Update the `loldle/stickers.go` comment to name + @tiennm99bot. The file_ids are replaced in phase 2, because they need the + new bot. +6. **Build/deploy config.** + - `.github/workflows/ci.yml` image tags `tiennm99bot`, `tiennm99bot-renderer`. + - `compose.yml`: the commented GHCR image and the DB example. + - `.env.example`: the header and `MONGO_DATABASE=tiennm99bot`. + - `renderer/package.json` name `tiennm99bot-renderer`. Regenerate the lock + file with `npm install --package-lock-only` in `renderer/`; do not edit it + by hand. +7. **Docs.** + - `README.md` (title, local mongo container name, `_dev` DB), `AGENTS.md`, + `CLAUDE.md`, `docs/deploy-coolify-selfhosted.md`. + - `renderer/README.md`, `renderer/docs/deployment.md`. + - `git mv renderer/docs/miti99bot-integration.md renderer/docs/tiennm99bot-integration.md`, + then fix its links (`git grep -n miti99bot-integration`). +8. **Sweep.** `git grep -n -i miti99bot -- ':!plans'` must be empty. Review any + remaining `miti99` hits by hand. + +## Validation + +```sh +gofmt -l . && go vet ./... && go test -race -count=1 ./... && go build ./... +(cd renderer && npm ci && npm run lint && npm run typecheck && npm test) +docker build -t tiennm99bot . && docker build -t tiennm99bot-renderer renderer +``` + +## Commit + +Use two focused conventional commits on `main`: +- `feat(config): resolve the bot username from BOT_USERNAME or getMe` (the existing uncommitted change) +- `refactor!: rebrand miti99bot to tiennm99bot` + +The body notes that the default sticker pack and the module path changed. +Delay the push to the cutover in phase 2 if the old bot should keep its old strings. + +## Risk and rollback + +- Go module path change: purely mechanical, and the build and tests catch any miss. +- Pushing deploys to Coolify. If it is pushed before cutover, the only visible + effects are new strings and a new default pack name on the *old* bot, where + `/addsticker` would create `stickers_by_miti99bot`. To avoid that, set + `STICKER_PACK_NAME=miti99_by_miti99bot` in Coolify until cutover, or hold the push. +- Rollback: `git revert` the rebrand commit. diff --git a/plans/261007-1423-rebrand-tiennm99bot/phase-02-cutover-and-manual-steps.md b/plans/261007-1423-rebrand-tiennm99bot/phase-02-cutover-and-manual-steps.md new file mode 100644 index 0000000..e43793f --- /dev/null +++ b/plans/261007-1423-rebrand-tiennm99bot/phase-02-cutover-and-manual-steps.md @@ -0,0 +1,140 @@ +--- +phase: 2 +title: "Cutover and manual steps" +status: in-progress +owner: user + agent +blockedBy: [phase-01] +--- + +# Phase 2 — Cutover and manual steps + +Legend: **[you]** only you can do it (BotFather, Atlas UI, Coolify secrets). +**[agent]** I can run it once you approve that step. + +Verified facts (2026-10-07): +- The Coolify app `miti99bot` is on **miti-sg** (uuid `ofo63lqv73huw1hce24ntg9i`). +- It has no `STICKER_PACK_NAME` and no `BOT_USERNAME` set. +- The name `tiennm99/tiennm99bot` is free on GitHub. +- `mongodump`/`mongorestore` are not installed here, but the local `mongo:8` + image ships them. + +## A. Prepare (no downtime) + +1. **[you] Create the bot.** In BotFather, run `/newbot` → username `tiennm99bot` + and keep the token. Then: + - `/setinline` on @tiennm99bot. The alias inline picker needs it + ([docs/aliases.md](../../docs/aliases.md)). + - Optionally set `/setdescription`, `/setabouttext`, `/setuserpic`, and + `/setjoingroups` (keep enabled). + - The command menu needs nothing here: the bot registers it at startup. +2. **[you] Start the new bot.** Open @tiennm99bot from the `OWNER_ID` account + and press Start. Without that, the deploy DM fails with 403. Admins should + do the same. +3. **[you] Create the Atlas DB user.** Make a user with `readWrite` on database + `tiennm99bot` only, and build the new `MONGO_URL` with it. Keep the old user + until step D. +4. ✅ **Done 2026-10-07.** **[agent] Rename the repo.** Run `gh repo rename tiennm99bot -R tiennm99/miti99bot`. + GitHub keeps a redirect from the old URL. Then set the local `origin` to + `https://github.com/tiennm99/tiennm99bot.git`. +5. ✅ **Done 2026-10-07.** **[agent] Move the checkout.** Move `/workspace/tiennm99/miti99bot` to + `/workspace/tiennm99/tiennm99bot`. `/tiennm99/` is already ignored at the + workspace root. Restart the Claude session from the new path, because + project memory is keyed by path. + +## B. Cutover window (bot offline about 10–15 min) + +1. **[agent] Stop the app.** Use `control stop` on the Coolify app (confirm + required) so nothing writes during the copy. +2. **[agent] Back up and copy the database**, using the `mongo:8` image, with + the URL passed via env and never echoed: + - `mongodump --uri "$OLD_URL" --db miti99bot --archive=miti99bot-.archive --gzip` + Keep this archive outside the repo as the backup. + - `mongorestore --uri "$NEW_URL" --archive=... --gzip --nsFrom 'miti99bot.*' --nsTo 'tiennm99bot.*'` + This restores indexes too. + - Compare `countDocuments` for every collection in both DBs with `mongosh`. + Any mismatch means stop and fix before going further. + - A first copy already ran on 2026-10-07 15:10 from `.env` `OLD_MONGO_URL` + / `OLD_MONGO_DATABASE` (249 docs, counts and indexes match; backup + `~/backups/mongo/miti99bot-20261007-1510.archive.gz`). The old bot kept + writing after it, so at cutover use `--drop` on the restore to re-sync. + - Docker bind mounts land on the daemon host, not this workspace: stream + with `--archive` to stdout/stdin instead of `--out`. +3. **[you] Update the Coolify app env** in the dashboard (the MCP never writes + secret values): + - `TELEGRAM_BOT_TOKEN` = the new token + - `MONGO_URL` = the new user's URL + - `MONGO_DATABASE=tiennm99bot` + - Optionally `BOT_USERNAME=tiennm99bot`, which skips getMe. + - Do **not** set `STICKER_PACK_NAME`, so the default `stickers_by_tiennm99bot` + applies. + - Apply the same values to the preview copies, or delete those. +4. **[you] Rename and repoint the app.** Rename the Coolify app to `tiennm99bot` + and set its git repository to `tiennm99/tiennm99bot`, branch `main`. Check + that the GitHub App source still sees the repo after the rename. +5. **[agent] Deploy.** Push the phase 1 commits to `main` if they are held, or + trigger `deploy`. Then watch `get_deployment` until it is running:healthy. + +## C. Verify (agent checks plus you in Telegram) + +1. **[agent]** The logs show `bot username ... source getMe|BOT_USERNAME` = `tiennm99bot`, + `webhook cleared`, `telegram long polling started`, and no Mongo errors. +2. **[you]** The owner receives "🚀 tiennm99bot deployed: " from @tiennm99bot. +3. **[you]** Smoke-test in DM and in one group: + - `/help` + - `/stats` (old counts present, which proves the data moved) + - `/lol`, `/stock`, `/gold`, `/coin` + - `@tiennm99bot` inline + - `/wheelofnames` +4. **[you]** Run `/addsticker` replying to a sticker. It creates + `stickers_by_tiennm99bot`. The old `miti99_by_miti99bot` pack stays with the + old bot. Re-adding its stickers to the new pack is manual, one `/addsticker` + each. +5. **[you] Recapture the loldle stickers.** Send each wanted sticker to + @tiennm99bot and capture its file_id with `/stickerid`. **[agent]** puts + them in `internal/modules/loldle/stickers.go`, then commits and deploys. + Until then, loldle simply sends no sticker, because the errors are already + ignored. + +## D. Migration window and cleanup + +1. **[you] Move users and groups:** + - Add @tiennm99bot to every group that used @miti99bot. + - Users must Start the new bot in DM. + - Stored subscriptions (lol daily push and others) are keyed by chat ID, so + they stay valid. They deliver once the new bot is in that chat; until + then, the fan-out logs 403s for those chats. + - Announce the move from @miti99bot. Since its token is unused, send the + announcement manually from your account, or post a message in each group. +2. **[you] Retire the old bot** after the window (suggested 2–4 weeks). + Options: `/revoke` the old token in BotFather, `/deletebot`, or keep the + name parked to stop impersonation (recommended: keep it parked and revoke + the token). +3. **[agent] Drop the old database** after verification and the window. Run + `db.getSiblingDB('miti99bot').dropDatabase()` only after a fresh count + check, and keep the dump archive. **[you]** then delete the old Atlas user. +4. **[agent] Clean up.** Delete the local `miti99bot` and `miti99bot-renderer` + docker images if any remain. Update workspace memory or notes that mention + the old name. + +## Rollback + +Before D.3, rollback is quick: +1. Restore the old `TELEGRAM_BOT_TOKEN`, `MONGO_URL` and `MONGO_DATABASE`. +2. `git revert` the rebrand commit. +3. Redeploy. + +The old DB is untouched until D.3. Any writes made to the new DB after cutover +would be lost on rollback. + +## File_id migration (done 2026-10-07 16:10) + +- Sticker file_ids turned out to work across bots: the 6 sticker aliases and + all 6 loldle stickers send from @tiennm99bot unchanged, so C.5 needs no code + change. Photo and animation file_ids do not transfer. +- The 9 photo/animation aliases were downloaded with the old token, re-uploaded + through the new bot to the owner DM (messages deleted), send-tested, and + their `fileId` updated only where unchanged. Three GIFs were stored without + a file extension and had to be uploaded as `.mp4` to stay animations. +- The 8 stickers of `miti99_by_miti99bot` were added to + `stickers_by_tiennm99bot` by file_id (pack now 9 with the /addsticker test). +- Backup before the update: `~/backups/mongo/tiennm99bot-20261007-pre-fileid-migration.archive.gz`. diff --git a/plans/261007-1423-rebrand-tiennm99bot/plan.md b/plans/261007-1423-rebrand-tiennm99bot/plan.md new file mode 100644 index 0000000..e4f21be --- /dev/null +++ b/plans/261007-1423-rebrand-tiennm99bot/plan.md @@ -0,0 +1,73 @@ +--- +title: "Rebrand miti99bot to tiennm99bot" +description: "Rename the code, repo, image, Coolify app, Mongo database and Telegram bot from miti99bot to tiennm99bot." +status: in-progress +priority: P2 +effort: 1d (2h code, rest is a cutover window plus manual Telegram/Atlas steps) +branch: main +tags: [rebrand, deploy, mongo, telegram] +blockedBy: [] +blocks: [] +created: 2026-10-07 +--- + +# Rebrand miti99bot → tiennm99bot + +## Outcome + +The project, the GitHub repo, the Coolify app, the Mongo database and the +Telegram bot are all named `tiennm99bot`. The bot runs as the new @tiennm99bot +account with all existing data. Old @miti99bot is retired after a migration +window. + +Scout: [scout report](../reports/scout-261007-1423-rebrand-tiennm99bot.md). + +## Decisions (user, 2026-10-07) + +| Topic | Decision | +|---|---| +| Telegram bot | New @tiennm99bot account (new token). Bot usernames cannot be renamed. | +| Mongo database | Rename `miti99bot` → `tiennm99bot` by dump/restore, with a backup kept. | +| Sticker pack | New slug `stickers` → `stickers_by_tiennm99bot` (confirmed). | +| Push timing | Hold every push to `main` until the phase 2 cutover window. | +| Local checkout | Move to `/workspace/tiennm99/tiennm99bot`. | +| Coolify app | Rename the app on miti-sg and repoint it to the new repo. | + +## Constraints and non-goals + +- `plans/**` stays untouched: those are historical records. +- `@miti99` in `misc/handlers_test.go` is a user handle in a fixture, not the brand. +- Owner/admin IDs are Telegram *user* IDs and do not change. +- No data model changes. Chat IDs stored in Mongo stay valid under the new bot. +- Prerequisite: the uncommitted `BOT_USERNAME` change lands first as its own commit. + +## Phases + +| # | Phase | Who | Status | +|---|---|---|---| +| 1 | [Code rebrand](phase-01-code-rebrand.md) | agent | done (79104ef, 7008a57; not pushed) | +| 2 | [Cutover and manual steps](phase-02-cutover-and-manual-steps.md) | user + agent | B, C done 2026-10-07; D (retire old bot, drop old DB) after the migration window | + +Phase 1 can merge to `main` any time, because nothing in it depends on the new +bot, repo or DB. Its deploy only changes branding strings and the default +sticker pack name, though. Hold the push until the phase 2 cutover window if +the old bot should keep its old strings until the switch. + +## Acceptance criteria + +- `git grep -i miti99bot -- ':!plans'` returns nothing. +- `go vet ./...`, `go test -race ./...`, `go build ./...`, the renderer + `npm run lint && npm run typecheck && npm test`, and both docker builds pass. +- Coolify app `tiennm99bot` is running:healthy from `github.com/tiennm99/tiennm99bot`. +- The logs show `bot username ... tiennm99bot`, and the owner receives + "🚀 tiennm99bot deployed: " from @tiennm99bot. +- Every collection in DB `tiennm99bot` has the same document count as in `miti99bot` at cutover. +- `/addsticker` creates or extends `stickers_by_tiennm99bot`, the loldle win/lose + stickers send, and the inline `@tiennm99bot` alias picker works. + +## Open questions + +- Should old @miti99bot stay alive during the migration window to answer + "moved to @tiennm99bot"? That would need a tiny separate process, so this + plan leaves it idle instead. Telegram allows only one `getUpdates` consumer + per token, so the old token is simply unused. diff --git a/plans/journals/2026-10-07-plan-rebrand-to-tiennm99bot.md b/plans/journals/2026-10-07-plan-rebrand-to-tiennm99bot.md new file mode 100644 index 0000000..a91f620 --- /dev/null +++ b/plans/journals/2026-10-07-plan-rebrand-to-tiennm99bot.md @@ -0,0 +1,18 @@ +--- +title: Plan rebrand to tiennm99bot +date: 2026-10-07 +summary: "Scouted and planned the miti99bot to tiennm99bot rebrand across code, repo, Coolify, Mongo and Telegram" +--- + +# Plan rebrand to tiennm99bot + +## What happened +Scouted 159 files with `miti99bot`; most are the Go module path (315 import lines). External surfaces: GitHub repo, Coolify app on miti-sg (uuid ofo63lqv73huw1hce24ntg9i), Atlas DB, Telegram bot account. + +## Decision +New @tiennm99bot account (bot usernames cannot be renamed), Mongo DB renamed by dump/restore, new sticker slug (proposed `stickers`), checkout moved, Coolify app renamed. Plan: plans/261007-1423-rebrand-tiennm99bot/. + +## Next steps +Commit the pending BOT_USERNAME change, run phase 1 (code), then the phase 2 cutover with the user's BotFather/Atlas/Coolify steps. + +> Historical work record — not durable authority. Prefer docs/specs/ADRs for current decisions. diff --git a/plans/reports/scout-261007-1423-rebrand-tiennm99bot.md b/plans/reports/scout-261007-1423-rebrand-tiennm99bot.md new file mode 100644 index 0000000..75f12a5 --- /dev/null +++ b/plans/reports/scout-261007-1423-rebrand-tiennm99bot.md @@ -0,0 +1,58 @@ +# Scout Report: rebrand miti99bot → tiennm99bot + +Baseline: `main` @ c18006f plus the uncommitted `BOT_USERNAME` change (username +is now runtime-resolved; sticker default = `miti99_by_`). + +## In-repo occurrences (159 files) + +### Go module path — 315 import lines, ~150 files +- `go.mod:1` `module github.com/tiennm99/miti99bot` +- Every `internal/...` import in `cmd/` and `internal/`. Mechanical rewrite. +- `internal/modules/util/help.go:16` `repoURL`; asserted in `util/help_test.go:62,165`. + +### Runtime branding strings +- `internal/server/health.go:20` — `"miti99bot ok\n"` (health body; docs quote it). +- `internal/deploynotify/deploy_notify.go:74` — `"🚀 miti99bot deployed: %s"`; test `deploy_notify_test.go:89`. +- User-Agent `Mozilla/5.0 (miti99bot)`: `coin/price_providers.go:261`, `gold/vnappmob_client.go:127,233`, `stock/prices_ssi.go:152`; asserted in `stock/prices_test.go:66-67`. +- `lol/api_client.go` `userAgentProduct = "miti99bot/0.1"`; asserted in `lol/api_client_test.go` (`TestClientUserAgent`). +- `monkeyd/export_job.go:42` — cache dir `miti99bot-monkeyd-cache` (temp dir; rename is harmless, old dir orphaned). +- `renderer/src/gacha/page/page.js:281` — gacha recap edition label `'miti99bot'`. + +### Sticker pack slug `miti99` +- `sticker/sticker_pack.go:29` `defaultStickerPackSlug = "miti99"`, comment at `:79`. +- Tests: `sticker/addsticker_command_test.go:108,136`, `sticker/sticker_pack_test.go:24`. +- Prod sets no `STICKER_PACK_NAME`, so the live pack is the derived default `miti99_by_miti99bot`. + +### Test fixtures (bot-agnostic, rename for consistency only) +- `/cmd@miti99bot`: `modules/dispatcher_test.go:92,98,110,140`, `alias/fallback_test.go:43,45`, `stats/views.go:82` (comment). +- Test DB names `miti99bot_*_test_%d`: `storage/mongo_doc_store_test.go:38`, `lol/startup_mongo_test.go:32`, `stats/startup_mongo_test.go:129`, `stock/startup_mongo_test.go:79`. +- `sticker/sticker_pack_test.go:22-23`, `sticker/addsticker_command_test.go`. +- `misc/handlers_test.go:257-263` uses `@miti99` as a *user* handle — not the brand; leave. + +### Bot-scoped data +- `loldle/stickers.go` — sticker file_ids valid only for the @miti99bot account (comment line 5). + +### Build / deploy config +- `.github/workflows/ci.yml:65,102` — local image tags `miti99bot`, `miti99bot-renderer`. +- `compose.yml:6` (`ghcr.io/tiennm99/miti99bot:latest`, commented), `:12` DB example, `:53` health text. +- `.env.example:1,12` header and `MONGO_DATABASE=miti99bot`. +- `renderer/package.json:2`, `renderer/package-lock.json:2,8` — `miti99bot-renderer`. + +### Docs +- `README.md:1,289,293,295`, `AGENTS.md:5`, `CLAUDE.md:1`. +- `docs/deploy-coolify-selfhosted.md:3,33,118,184,249`, `docs/sticker-packs.md:27,55`. +- `renderer/README.md:3,180,181`, `renderer/docs/deployment.md:3`, `renderer/docs/miti99bot-integration.md` (file name + 3 lines). +- `plans/**` — historical records; leave untouched. + +## External surfaces (outside the repo) +- GitHub repo `tiennm99/miti99bot` (git `origin`). Renaming keeps a redirect. +- Coolify app `miti99bot` on **miti-sg** (uuid `ofo63lqv73huw1hce24ntg9i`, project "Applications", running:healthy). Env keys: `TELEGRAM_BOT_TOKEN`, `MONGO_URL`, `MONGO_DATABASE`, `OWNER_ID`, `ADMIN_IDS`, `MODULES`, `LOL_PANDASCORE_TOKEN` (+ preview copies). No `STICKER_PACK_NAME`, no `BOT_USERNAME`. +- MongoDB Atlas database (value of `MONGO_DATABASE`; docs suggest `miti99bot`) and its least-privilege user scoped to that DB. +- Telegram bot account @miti99bot. Bot usernames cannot be renamed; a new @tiennm99bot means a new bot + token. +- Local checkout path `/workspace/tiennm99/miti99bot` (workspace rule: `/`). +- No GHCR publish workflow exists; the image ref is only a comment. + +## Unresolved Questions +- Is the Telegram bot itself moving to a new @tiennm99bot account, or only the code/repo? +- Should the Mongo database be renamed (requires dump/restore; Mongo has no DB rename)? +- Should the sticker pack slug change (`tiennm99_by_…`), creating a new pack?