Commit Graph
298 Commits
Author SHA1 Message Date
tiennm99 275c83b8a6 feat(lol): make match cache fallback-only 2026-07-01 16:41:59 +07:00
tiennm99 2fb10ff632 refactor: remove completed migration logic 2026-07-01 16:20:30 +07:00
tiennm99 3049af2800 perf(stats): simplify username lookup index 2026-07-01 16:06:03 +07:00
tiennm99 b0b4321fa1 feat(lol): expire match cache 2026-07-01 13:40:37 +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 ad153d8e6c fix(stats): merge legacy trade command counts 2026-07-01 11:21:11 +07:00
tiennm99 364ddee285 feat(stats): migrate command history 2026-07-01 11:10:36 +07:00
tiennm99 b4f6265688 docs: add project agent guidance 2026-07-01 11:10:24 +07:00
tiennm99 788f1015b5 feat(commands): simplify portfolio command names 2026-07-01 10:53:52 +07:00
tiennm99 c362732951 feat: rename wc schedule commands 2026-07-01 10:42:56 +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 034252b2ea fix(cron): claim daily pushes by ict day 2026-07-01 09:31:58 +07:00
tiennm99 7f16ccf668 fix(lolschedule): silence empty daily push 2026-06-30 09:01:40 +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 20dc03c6d2 refactor(config): remove price URL env overrides 2026-06-29 09:23:20 +07:00
tiennm99 d9c7421c7e chore(plans): remove completed planning artifacts 2026-06-29 09:15:29 +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 5dcf94a652 fix(config): remove claude settings 2026-06-29 00:24:07 +07:00
tiennm99 9c8387bf3a fix(deploynotify): preserve coolify source commit 2026-06-29 00:20:04 +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
tiennm99andGitHub 4d0613fd0e Merge pull request #1 from tiennm99/feature/selfhosted
Self-host on Coolify + MongoDB Atlas; decommission AWS
2026-06-28 23:55:12 +07:00
tiennm99 98a5cea386 docs(reports): add AWS footprint and cleanup audit 2026-06-28 23:53:12 +07:00
tiennm99 893e072101 docs(deploy): mark AWS decommission complete, record teardown deviations 2026-06-28 23:44:12 +07:00
tiennm99 35850d6e7f fix(deploynotify): reference SOURCE_COMMIT in compose so it reaches container
Coolify passes predefined vars to Docker Compose via --env-file for
interpolation only; a var reaches the container solely if the compose file
references it. Removing the reference left SOURCE_COMMIT unset, so deploynotify
reported "unknown". Re-add SOURCE_COMMIT: ${SOURCE_COMMIT:-} per Coolify docs.
2026-06-28 23:30:03 +07:00
tiennm99 ed867f33f0 feat(deploynotify): notify owner on every startup, no SHA dedup
Match the store-scraper-bot behaviour: DM the owner once per boot regardless of
commit, and report an unknown SHA rather than staying silent. Drop the store-
based dedup and the empty-SHA skip; resolveCommitSHA defaults to "unknown".
2026-06-28 23:25:07 +07:00
tiennm99 035149f600 fix(deploynotify): stop clobbering Coolify-injected SOURCE_COMMIT
Declaring SOURCE_COMMIT: ${SOURCE_COMMIT:-} in compose resolved to an empty
string at parse time and overrode the value Coolify auto-injects into the
container at runtime, so gitSHA stayed empty and the owner DM was skipped.
Remove the declaration; the bot already reads SOURCE_COMMIT from the container
env at startup.
2026-06-28 23:17:27 +07:00
tiennm99 0abd33cb42 fix(deploynotify): read commit SHA from Coolify SOURCE_COMMIT runtime env
Baking SOURCE_COMMIT as a Docker build arg never worked: Coolify exposes it
as a runtime env var, not a build arg, so gitSHA was always empty and the owner
DM was skipped. Read SOURCE_COMMIT from the container env at startup (falling
back to the ldflags-baked gitSHA for local builds), forward it via the compose
environment, and drop the dead build-arg baking.
2026-06-28 23:08:17 +07:00
tiennm99 1fa549fa18 feat(modules): log every command with input, sender, chat, result
Emit one structured line per authorized command: input text, sender id +
username, chat type/id/title (DM vs group), and outcome (INFO ok / ERROR with
err). Replaces the prior error-only log; denied commands stay silent.
2026-06-28 22:52:55 +07:00
tiennm99 9d5b774846 refactor(server): delete webhook once on startup, no retry
The Bot API GET reliably clears the webhook, so the retry loop added for the
empty-body POST is no longer needed. One best-effort call; log on failure.
2026-06-28 22:52:55 +07:00
tiennm99 36cb5750e6 fix(telegram): clear webhook via Bot API GET to avoid empty-body POST
go-telegram's DeleteWebhook posts an empty multipart form (DropPendingUpdates
is omitempty); some networks answer that bodyless POST with an empty response,
failing to parse and leaving the webhook active so getUpdates 409s forever.
Replace it with a plain GET /deleteWebhook, which sends no body and parses the
JSON reliably. Keeps pending updates for a lossless cutover.
2026-06-28 22:41:49 +07:00
tiennm99 60a7aa5836 fix(server): retry webhook clear on startup past transient empty-body error
Telegram's edge can return an empty body on the first request after a cold
container start, failing the single best-effort DeleteWebhook with 'unexpected
end of JSON input' and leaving a stale webhook that 409s getUpdates. Retry up
to 5 times with a 1s backoff so long polling is reliably unblocked.
2026-06-28 22:33:34 +07:00
tiennm99 d4f1bbfc83 fix(server): clear Telegram webhook at startup before owner DM
Move DeleteWebhook ahead of the deploynotify owner DM and polling so the
webhook is cleared first thing once the bot is ready, instead of just before
getUpdates. DropPendingUpdates=false keeps the lossless cutover.
2026-06-28 22:18:28 +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 cc547136b7 refactor(server): drop HTTP /cron route; run crons in-process only
The in-process scheduler is the sole cron trigger on self-host, so the
/cron/{name} HTTP endpoint and its CRON_SHARED_SECRET are dead surface.
Reduce the HTTP server to GET / (health) and remove the cron secret config,
SSM binding, and now-unused timeout.
2026-06-28 22:15:04 +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 b4910c2289 docs(plan): native mongo value documents + version CAS plan
Brainstorm decision record (Option A) + validated 2-phase TDD plan for
storing mongo values as native BSON and switching CAS to a version field.
2026-06-28 12:53:20 +07:00
tiennm99 e8a6dbb4de feat(storage): store mongo values as native BSON documents
Implement mongodb_value_codec to encode portfolio/gold/stock values as native
BSON documents instead of JSON-serialized byte strings. Reduces storage size,
improves query efficiency, and eliminates unmarshal overhead. Native BSON
encoding preserves int64 fidelity and enables future native-format queries.
Add NativeValueRepresentation and Int64Fidelity tests validating lossless
encoding. Update migration tool comments. Document native-value behavior
in deploy guide. Update phase-01 plan with implementation notes.
2026-06-28 12:52:48 +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 cd82abbb0c refactor(storage): replace value-bytes CAS with version-field optimistic lock
Replace content-addressed storage versioning (CAS) with explicit version fields
on documents. Versions are managed via optimistic locking pattern: Get returns
version, Put increments atomically and fails if version mismatch detected.
Callers (portfolio, lolschedule) updated to use GetVersioned/PutVersioned,
simplifying concurrency handling and eliminating CAS overhead.
2026-06-28 12:52:32 +07:00
tiennm99 ab7a597541 refactor(storage): store mongo value as JSON string, not BinData
Persist the KV value field as a BSON string so it is directly readable in
the Atlas/Compass UI, matching DynamoDB's String storage. Reads still accept
BSON binary as a backward-compat fallback. Non-UTF-8 callers must encode
upstream, same constraint as DynamoDB; all current callers write JSON.
2026-06-28 10:50:41 +07:00
tiennm99 a83582f79d docs(plan): update self-host phases with completion status and implementation details
Mark phases 1–5 (MongoDB, cron, polling, migration, decommission) as completed.
Update phase files with finalized implementation notes and test coverage summaries.
2026-06-28 09:58:41 +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 4a8466db5b feat(selfhost): containerize for Coolify + decommission AWS deploy
Add multi-stage Dockerfile, docker-compose.yml for local dev, .env.example template,
and Makefile helpers. Disable GitHub Actions AWS deploy workflow. Supports Coolify
container orchestration for self-hosted deployments.
2026-06-28 09:58:32 +07:00
tiennm99 b27d2b3b87 feat(migrate): add DynamoDB-to-MongoDB data migrator
Add standalone migrator tool with scan-and-transform logic for moving persisted
state from DynamoDB to MongoDB. Includes tests and README with usage instructions.
2026-06-28 09:58:28 +07:00
tiennm99 f399717613 refactor(stock): remove FireAnt income-events command
Drop FireAnt-based /income command per AWS decommission plan. Simplifies
stock module and reduces third-party dependencies. Updates telegram-commands.json.
2026-06-28 09:58:25 +07:00