Commit Graph
58 Commits
Author SHA1 Message Date
tiennm99 ee2c520944 docs(stock): document dividend event buttons 2026-07-21 18:20:14 +07:00
tiennm99 96ba34384a refactor(portfolio): retire completed migrations 2026-07-21 17:13:19 +07:00
tiennm99 7083079b39 feat(portfolio): nest asset positions 2026-07-21 16:42:33 +07:00
tiennm99 7711029f4c docs(portfolio): document cost basis and P&L 2026-07-21 15:52:30 +07:00
tiennm99 d2c3129d41 refactor(commands): standardize parameter conventions 2026-07-21 14:51:28 +07:00
tiennm99 a211b7f8b7 fix(commands): remove examples from command discovery 2026-07-21 13:52:53 +07:00
tiennm99 b5c7427520 fix(commands): render examples conditionally with inline help code 2026-07-21 13:21:01 +07:00
tiennm99 f5ba9d4032 feat(commands): improve discovery and normalize parameters 2026-07-21 11:45:20 +07:00
tiennm99 3316eec74c test: provision MongoDB 8 with Testcontainers 2026-07-21 09:39:06 +07:00
tiennm99 f0d361eab5 refactor: adopt cross-platform Go development workflow 2026-07-21 09:05:20 +07:00
tiennm99 6ceb7aff02 docs(stock): document dividend commands 2026-07-20 17:33:10 +07:00
tiennm99 6c934f6807 feat(modules): remove world cup module
The 2026 tournament has ended, so the schedule and daily digest commands
have no upcoming matches to report. Drops the module, its catalog entry,
command menu entries, and the WC_FOOTBALL_DATA_TOKEN env var.

Stored subscriber and match-cache documents are left in place.
2026-07-20 11:03:59 +07:00
tiennm99 15c383d6f1 feat(misc): add protected /ff giving-up template
Replies with a fixed Vietnamese copypasta for when T1 starts losing, built
from the local community's running jokes. Protected, so it stays out of the
public command menu like the other gated commands.
2026-07-19 20:09:22 +07:00
tiennm99 3646f9c02c feat(misc): promote wheelofnames gif command 2026-07-09 13:14:11 +07:00
tiennm99 5c5fc5c168 feat(misc): add VNG disclaimer aliases 2026-07-07 11:19:27 +07:00
tiennm99 194caf17eb fix(lol): rename next week command 2026-07-06 20:46:10 +07:00
tiennm99 00a5ff1c0b feat(lol): add tomorrow and next-week schedules 2026-07-06 20:20:07 +07:00
tiennm99 3763b293d6 feat(misc): add wheelofnames beta animation 2026-07-06 11:41:20 +07:00
tiennm99 079d506695 feat(misc): add random command and wheel draft streaming 2026-07-06 11:26:50 +07:00
tiennm99 d375029214 feat(misc): add wheelofnames command 2026-07-03 11:12:34 +07:00
tiennm99 e6d5bc3cc9 feat: refine command names and behavior 2026-07-01 13:19:42 +07:00
tiennm99 5254ab4c8e refactor: remove completed startup migrations 2026-07-01 11:42:59 +07:00
tiennm99 ccaa34336d feat: rename lol schedule module 2026-07-01 10:38:49 +07:00
tiennm99 8f0286e54f feat(stats): use queryable Mongo usage records 2026-07-01 10:22:03 +07:00
tiennm99 ef2f70b49b fix(wc): send silent daily push at midnight ict 2026-06-30 08:56:01 +07:00
tiennm99 9c998a0e2f refactor(modules): remove twentyq genai integration 2026-06-29 10:07:21 +07:00
tiennm99 5aa538be96 feat(server): register command menu on startup 2026-06-29 01:08:51 +07:00
tiennm99 5971347a6b feat(wc): add world cup schedule module 2026-06-29 00:59:30 +07:00
tiennm99 b0586903f5 refactor(deploy): remove retired aws support 2026-06-29 00:11:42 +07:00
tiennm99 d56c95cff2 build(coolify): rename compose file 2026-06-29 00:00:22 +07:00
tiennm99 8edd0f8c27 build(coolify): use SOURCE_COMMIT build arg for deploynotify
Coolify sets SOURCE_COMMIT automatically; consume it as the build arg
feeding the baked commit SHA instead of a manually-passed GIT_SHA.
2026-06-28 22:15:12 +07:00
tiennm99 15a3239ab1 refactor(storage): replace KVStore with generic typed DocStore[T]
Delete the byte-oriented KVStore/VersionedStore abstraction and the
DynamoDB/memory KV backends. Add a generic typed store (DocStore[T] with
Provider/Collection/Typed) persisting each value as a flattened native
Mongo document (storedDoc[T] via bson inline) — no value envelope.

- MongoDB is the only runtime backend; memory kept for tests/local.
- All modules + deploynotify use typed stores; persisted structs carry
  bson tags == json names (incl. nested lolschedule/wordle types).
- lolschedule wraps its array/scalar values in named structs.
- migrate-dynamo-to-mongo writes the flattened shape via Typed[bson.M]
  with wrap rules; Scan/--dry-run/--verify retained.

Verified: go vet/build clean; full go test green hermetically and
in-container vs real Mongo 7 + DynamoDB Local (storage integration +
migrator e2e).
2026-06-28 18:02:11 +07:00
tiennm99 6bc5f334bb refactor(storage): remove legacy firestore backend
Delete Firestore provider implementation and tests (5 files). Extract shared
key helpers to new internal/storage/keys.go module. Remove Firestore case
from server bootstrap and storage factory. Drop cloud.google.com/go/firestore
and related dependencies from go.mod. Remove firestore-emulator test targets
from Makefile. Update README storage section to reflect MongoDB-only backend.
2026-06-28 12:52:40 +07:00
tiennm99 6d1bb5d925 docs(selfhost): add Coolify deploy + AWS decommission guides; retire AWS docs
Add comprehensive Coolify deployment guide with MongoDB Atlas + networking setup.
Add AWS decommission runbook for safe teardown. Update AWS guides to note
deprecation. Update main README with self-hosted quickstart and architecture overview.
2026-06-28 09:58:37 +07:00
tiennm99 ae92539043 docs(gold): document VNAppMob SJC pricing and env vars 2026-06-15 10:49:19 +07:00
tiennm99 32417e4196 refactor(stock): rename trading module to stock
Rename the `trading` module to `stock` across code, config, and docs for
naming consistency with the sibling coin/gold modules.

- Module: internal/modules/trading -> internal/modules/stock (package,
  factory, registry key in cmd/server)
- Commands: trade_* -> stock_* (telegram-commands.json)
- Env/SAM params: TRADING_INCOME_EVENTS_* -> STOCK_INCOME_EVENTS_*
- ModulesCSV updated in template.yaml, samconfig.toml, deploy.yml
- Add cmd/migrate-stock-key: idempotent, non-destructive DynamoDB
  partition copy (pk=trading -> pk=stock) with dry-run default

Production DynamoDB data already migrated (8 keys: 2 portfolios + 6
symbol-cache rows); old trading partition retained as rollback snapshot.
2026-06-12 14:52:12 +07:00
tiennm99 9b379b3d6b feat(coin): add crypto paper trading 2026-06-12 10:47:02 +07:00
tiennm99 d1a01830ae feat(gold): add gold paper trading module
Opt-in module for gold paper trading with VND currency.
Commands: /gold_topup, /gold_buy, /gold_sell, /gold_stats.
Pricing: spot XAU USD converted to VND per luong via GoldPrice.org + ExchangeRate-API.
Features: FX caching, dust normalization (1e-9), HTTPS-only URL validation,
per-user key locking, namespace isolation from trading module.
2026-06-11 17:13:02 +07:00
tiennm99 1c50023261 feat(stats): add per-user analytics with /stats subcommands
Extend the stats module to track per-user counts in addition to the
existing per-command totals. CommandHook now receives the originating
*models.Update so the hook can attribute invocations to a user; only
the stats module consumes this hook today.

Schema (sort keys under pk="stats"):
  count:<cmd>            existing, per-command total
  user:<id>              new, per-user total with cached username
  pair:<cmd>:<id>        new, per (command, user) pair

Subcommands (all public):
  /stats                 top commands (unchanged)
  /stats users           top users overall
  /stats user <name>     top commands for that user
  /stats cmd <name>      top users of that command

When the sender has no Telegram username the per-user/pair writes are
skipped — the global per-command counter still increments. View helpers
fan out KV reads in parallel to stay inside the webhook deadline. The
existing read-modify-write race is unchanged; closing it would need
atomic UpdateItem ADD on the KV interface.
2026-05-22 18:01:12 +07:00
tiennm99 ee5a0cc954 feat(misc): add /trongtruonghop disclaimer command
Vietnamese disclaimer one-liner. Interpolates a target name (default "VNG")
and the sender — @username when set, else tg://user?id link with the display
name. User-supplied text HTML-escaped; reply routed through ReplyHTML to keep
forum-topic threading.
2026-05-16 14:51:26 +07:00
tiennm99 642fccb7b7 refactor: rename module to miti99bot, canonicalize AWS deploy path
Rename:
- Go module github.com/tiennm99/miti99bot-go → github.com/tiennm99/miti99bot
- CloudFormation stack miti99bot-aws-port → miti99bot
- Drop "port", "Cloud Run", "GCP", "cutover", "Phase NN" framing from
  active code and docs — project reads as canonical AWS-Lambda from now on.

AWS deploy guide + flow fix:
- New docs/deploy-aws-free-tier-guide.md — Ubuntu 24.04 ARM64 onboarding
  with project-local venv (pip awscli + sam-cli), SSM secrets via read -s,
  idempotent OIDC provider + role creation, $1 budget alarm.
- Drop sam build from the pipeline — provided.al2023 + makefile builder
  expects a Makefile in CodeUri (build/lambda/, the output dir), so the
  step always fails. sam deploy --template-file template.yaml now reads
  the raw template and zips build/lambda/ directly.
- Rollback section rewritten — use continue-update-rollback /
  cancel-update-stack / git-SHA redeploy. Drop the broken
  --use-previous-template recipe.
- DynamoDB free-tier row corrected (on-demand is 2.5M read / 1M write
  request units, not 25 RCU/WCU).

Updated:
- README.md fully rewritten (drops port/legacy framing, lists modules,
  points new users at the free-tier guide).
- aws/README.md retitled "AWS account setup", phase numbers stripped.
- Makefile / .github/workflows/deploy.yml — sam deploy flow.
- samconfig.toml — stack_name = "miti99bot".
- Go comments — Cloud Run → Lambda, Cloud Scheduler → EventBridge
  Scheduler, Cloud Logging → CloudWatch Logs.
- Struct field GCPProject → FirestoreProject (env GOOGLE_CLOUD_PROJECT
  unchanged).

Plus advisory reports under plans/reports/ from the code-reviewer +
researcher passes that informed the fixes.

Verified: go vet ./..., go build ./..., go test ./... all green.
2026-05-13 22:05:38 +07:00
tiennm99 e29d7afa0e refactor(modules): drop loldle variants, semantle, doantu and dead framework surface
Removes six modules (loldle-ability/emoji/quote/splash, semantle, doantu)
and prunes the framework deps that were only there to serve them:

  - ai.Embedder + Client.Embed + embeddingModel const (semantle only)
  - Deps.Embedder + BuildOptions.Embedder
  - Deps.Env + Build(env) param + ModuleEnv config field + PHOW2SIM allowlist (doantu only)
  - internal/champname package (loldle now owns its lookup helpers directly)
  - template.yaml: Phow2simAPIURL parameter + PHOW2SIM_API_URL Lambda env

Active catalog: util, misc, wordle, loldle, lolschedule, twentyq, trading.

go build / vet / test all pass.
2026-05-11 16:02:06 +07:00
tiennm99 6ab49a379d docs(plans): pre-deploy wrap-up status + AWS-port phase sync + code-review report
- Rewrite README.md for AWS-default deploy architecture
- Sync AWS-port plan.md phases 01-07 statuses to reflect shipped code (trading, lolschedule, gemini modules)
- Include code-reviewer report: cron-and-trading feedback addressed (gofmt, price-fetch reordering, senderInfo validation, ticker regex, typo fixes)
2026-05-10 03:05:56 +07:00
tiennm99 b387a6ea42 feat(modules): port new command modules + update registry
- Add new modules: doantu, semantle, twentyq, ai (Gemini integration)
- Update module registry with new command registration
- Update tests and documentation for module system
- Update README with new module references
2026-05-10 02:29:58 +07:00
tiennm99 35ad4cb997 feat(server,modules): bootstrap server and module framework
Implements Phases 02 (partial) and 03 of the go-port-cloud-run plan.
Introduces module framework with per-module KV prefix isolation,
health check endpoint, request timeout protection, and comprehensive
test coverage. Cloud Run deployment deferred to Phase 01.

Security hardening: constant-time secret comparison, cron auth bridge,
and secrets stripped from dependency environment exports. Includes
Dockerfile, GitHub CI workflow (vet + race + build), and integration
tests for module lifecycle.
2026-05-08 23:27:12 +07:00
tiennm99 ab617ade63 Initial commit 2026-05-08 22:44:45 +07:00
tiennm99 9eb1c527af Clear and rewrite
Retire the JavaScript/Cloudflare implementation; history continues from the Go rewrite (miti99bot).
2026-08-04 23:21:19 +07:00
tiennm99 b52fa7094e feat(loldle): tunable max guesses per subject + retuned defaults
Drop classic loldle from 8 → 6 (7-axis grid leaks too much per guess for 8
to feel earned) and emoji from 5 → 4 (3 emojis are usually unmistakable).
Add a hidden /<module>_setmax <n> command per loldle module so a chat can
override its own round length (1-10). Override stored at config:<subject>
in each module's KV; getMaxGuesses() falls back to the default when unset.
2026-05-07 14:10:01 +07:00
tiennm99 b660692eb2 feat(db): finalize MongoDB Atlas migration documentation
Phase 08: Complete documentation pass for MongoDB Atlas migration.

- Create docs/cost-tracking.md: Cost monitoring, upgrade triggers, monthly checklist
- Create docs/project-changelog.md: Full migration summary with phase breakdown
- Update docs/architecture.md section 8: Describe dual-write era, MongoDB store layers
- Update docs/code-standards.md: Add Persistence section for storage factory patterns
- Update docs/codebase-summary.md: Reflect MongoDB as primary, update test count (733)
- Update README.md: Storage section now describes MongoDB + dual-write during migration
- Update CLAUDE.md: Architecture section references MongoDB instead of KV/D1
- Update tests/fakes/fake-mongo.js: Document frozen surface (Phase 02-08 API)

Verified:
- All 733 tests passing
- Lint + secret-leak check pass
- npm run register:dry succeeds
- Auto-pause concern satisfied: trading (17:00), lolschedule (01:00), drift-verifier (hourly) all write to Mongo
- Roadmap verified migration NOT listed (future-only per user feedback)

Post-Phase-07 cutover: dual-write collapses, KV/D1 deleted, MongoDB becomes sole backend.
2026-04-26 09:34:25 +07:00
tiennm99 434b0cc35b feat(loldle): add ability and splash champion-guessing modules
Closes deferred phases 04 + 05 of loldle-new-modes plan.

- loldle-ability: 5 guesses, DDragon ability icon as photo. State pins
  slot (P/Q/W/E/R) so the same icon shows every turn. Abilities pulled
  from DDragon per-champion — same source loldle.net uses at runtime.
- loldle-splash: 4 guesses, random skin splash as photo. Skin pool
  scraped from loldle.net bundle (var Ad=[…] — 172 champs × 1939 skins,
  non-chroma, matches their splash mode exactly). URLs from Riot
  DDragon CDN (no version segment, stable across patches).
- fetch-ddragon-data.js: extended to write all four JSONs in one run.
  Shares a single DDragon per-champion fetch cycle (concurrency 10).
- Credits loldle.net + Riot Games in all loldle-family READMEs.

19 new tests (503 total). Lint clean. register:dry reports 12 loldle_*
commands with no conflicts.
2026-04-24 23:58:42 +07:00