feat(telegram): promo bot + channel-chat moderation gate
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 19s
CI / ui (pull_request) Successful in 57s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m39s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 19s
CI / ui (pull_request) Successful in 57s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m39s
Add a second standalone promo bot to the bot container (answers /start with a localized message + a URL button into the main bot's Mini App) and gate write access in a channel's linked discussion chat: grant on join when the Telegram user is registered and neither admin-suspended nor holding a new chat_muted role, and revoke/grant on the matching moderation change for a member currently in the chat. Eligibility (registered AND NOT suspended AND NOT chat_muted; the game suspension dominates) is resolved once in the backend and reached two ways: the bot's join-time unary ResolveChatEligibility over the existing mTLS bot-link, and a backend chat_access_changed event -> gateway -> ChatGate command (idempotent; a temporary-block-expiry sweeper may over-emit). The bot guards the block/unblock path with getChatMember, since bots cannot list members. A web_app button cannot open another bot's Mini App (it signs initData with the sending bot's token), so the promo button is a t.me ?startapp URL reusing the UI's VITE_TELEGRAM_LINK. The bot must be a chat admin with the restrict-members right and chat_member in its allowed updates. No schema change: chat_muted reuses the data-driven account_roles table.
This commit is contained in:
+12
-1
@@ -33,7 +33,10 @@ App** launch authenticates from the platform's signed `initData`, themes the UI
|
||||
the Telegram colours, and — on first contact — seeds the new account's interface
|
||||
language from the Telegram client. Telegram runs a **single bot**: every player uses
|
||||
the same bot, and all of its chat and out-of-app notifications are written in the
|
||||
player's own **interface language** (en/ru). Guests are session-only with restricted features
|
||||
player's own **interface language** (en/ru). A separate optional **promo bot** can run alongside the
|
||||
main one — its only job is to answer `/start` with a short message and a button that opens the
|
||||
**main** bot's app, where the player picks their game variant; it is an onboarding entry point that
|
||||
touches nothing else. Guests are session-only with restricted features
|
||||
(auto-match only; no friends, stats or history); an abandoned guest that never
|
||||
joined a game and has been idle past the retention window is garbage-collected. While the app is open the client
|
||||
keeps a live stream and receives in-app updates in real time — the opponent's move,
|
||||
@@ -320,6 +323,14 @@ plus the reason when one was given, and the app stops all background traffic wit
|
||||
temporary block lifts itself when it expires; the operator can also **unblock** from the user card
|
||||
at any time (games already lost stay lost).
|
||||
|
||||
Where the bot manages a channel's **linked discussion chat**, only a **registered** player who is
|
||||
**not blocked** may write there: the bot grants the right to write when such a player joins, while an
|
||||
unregistered or blocked one stays muted (the promo bot points newcomers at the game so they register).
|
||||
An operator can also **mute a player in the chat only** — a `chat_muted` role on the user card —
|
||||
without a full account block; an account block mutes them in the chat regardless. Muting/unmuting and
|
||||
blocking/unblocking take effect for a player already in the chat; one who is not in it is unaffected
|
||||
until they next join.
|
||||
|
||||
From the user card the operator can also **top up a player's hint wallet**: an additive grant
|
||||
(1–100 hints per action) that raises the balance shown on the card. Grants are **raise-only** —
|
||||
the console can never lower a wallet (a player only loses hints by spending them in a game), so an
|
||||
|
||||
Reference in New Issue
Block a user