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:
@@ -106,6 +106,13 @@ Telegram `external_id`, language and `notifications_in_app_only` flag) lets the
|
||||
route out-of-app push to the Telegram bot over the gateway bot-link; the Telegram login
|
||||
seeds a new account's language and display name from the launch fields, and the
|
||||
`accounts.notifications_in_app_only` flag (default true).
|
||||
The gateway-only `POST /api/v1/internal/chat-access` resolves a Telegram identity (the
|
||||
bot's join-time query) or an account id (a `chat_access_changed` event) to its
|
||||
**moderated-chat write eligibility** — `registered AND NOT suspended AND NOT chat_muted`.
|
||||
That event is emitted on an admin block/unblock, a `chat_muted` role grant/revoke, or — via
|
||||
the `account.SuspensionSweeper` started in `cmd/backend` — a temporary block lapsing;
|
||||
`chat_muted` is an `account.KnownRoles` entry, a chat-only mute distinct from the game
|
||||
suspension (which dominates it).
|
||||
`accounts.is_guest` marks an ephemeral guest — a durable row
|
||||
with no identity, excluded from statistics. The server-rendered
|
||||
**admin console** at `/_gm` (`internal/adminconsole` + `internal/server/handlers_admin_console.go`;
|
||||
|
||||
Reference in New Issue
Block a user