feat(sticker): add sticker pack module

Nine commands mirroring the names @Stickers uses: /newpack, /mypack,
/addsticker, /delsticker, /editsticker, /ordersticker, /setpackicon,
/renamepack and /delpack, plus a confirm callback for the destructive
one. Sources are replied stickers, photos or image documents; photos are
downloaded, resampled to 512px and re-uploaded.

One pack per user, keyed by owner id. Creating a pack is the only
operation here that makes a durable, publicly linkable object on a user's
behalf, so it is built around proving ownership rather than assuming it:

- A name is claimed globally and create-only before Telegram is called.
  A pending record alone proves only that a caller *asked* for a name,
  which is exactly what someone naming a victim's public slug also does.
- Adopting an existing set additionally requires that the claim predates
  this invocation. The claim lives in our store and the pack lives at
  Telegram, so a wiped store would otherwise make every pack adoptable.
- Names are released only on positive evidence that no pack stands behind
  them, never on a generic failure, so a transient error cannot hand a
  live name to the next caller.
- Ownership refusals are byte-identical across failure modes, so they
  cannot be used to probe which sets exist.

Error classification is positive-only throughout: "the set is gone" and
"nothing was created" are each proven from a specific Telegram response,
never inferred from an error. Post-action commits run on a context
detached from the request so a shutdown mid-handler cannot lose the
record of something Telegram already did.

Enabled explicitly via MODULES rather than by default.
This commit is contained in:
tiennm99 committed 2026-08-25 15:54:28 +07:00
1 parent e1bf7f1ddb
commit 3751010b8e
35 files changed
+5178 -5

No files matched your search

+5 -2
View File
@@ -12,8 +12,11 @@ MONGO_URL=mongodb+srv://botuser:STRONG_UNIQUE_PASSWORD@cluster0.xxxxx.mongodb.ne
MONGO_DATABASE=miti99bot
# ============================ Operational =========================
# Comma-separated module list. Empty = load every module.
MODULES=
# Comma-separated module list. Empty = load every module, including any module
# added later — so list them explicitly when a deployment should only gain a new
# module deliberately. `sticker` creates real, durable Telegram sticker sets on
# behalf of users, which is worth enabling on purpose rather than by default.
MODULES=util,misc,amlich,wordle,loldle,lol,stock,gold,coin,stats,monkeyd,sticker
# Telegram user id for owner-only commands (renamed from BOT_OWNER_ID).
OWNER_ID=
# Comma-separated admin Telegram user ids (renamed from ADMIN_USER_IDS).