Skip to content

Ephemeral commands + vahter confirmations (Bot API 10.2)#212

Merged
Szer merged 1 commit into
mainfrom
ephemeral-commands
Jul 16, 2026
Merged

Ephemeral commands + vahter confirmations (Bot API 10.2)#212
Szer merged 1 commit into
mainfrom
ephemeral-commands

Conversation

@Szer

@Szer Szer commented Jul 16, 2026

Copy link
Copy Markdown
Owner

What

Makes the public-chat moderation commands invisible and gives vahters in-chat feedback, using the ephemeral messages/commands feature from Bot API 10.2 (supported since Funogram.Telegram 10.2.0, #211). Everything is behind two DB-backed flags (bot_setting, hot-reloadable via /reload-settings), default off in code; ops seeds them ON manually via SQL:

Flag Effect
EPHEMERAL_COMMANDS_ENABLED New BotCommandsSetupService registers /ban, /sban, /unban with is_ephemeral = true in the all_group_chats scope at startup, so clients send them invisibly to other chat members. When off, deletes the registration (revert requires a restart).
EPHEMERAL_CONFIRMATION_ENABLED After /ban, /sban, /unban the issuing vahter gets a short self-dismissing ephemeral confirmation in the same chat (✅ Banned @user(id), ✅ Soft-banned … for 12h, ✅ Unbanned …, ⚠️ User <id> not found). Applies instantly on reload.

How

  • Confirmations are sent with Req.SendMessage.Make(chatId, text, receiverUserId = vahter.Id) via CallIgnore — ephemeral delivery is best-effort by design (may not arrive if the vahter is offline) and must never fail the command itself. Placed in the AdminCommand dispatch, so ML auto-bans never confirm; logs-channel reporting is unchanged.
  • Ephemeral messages auto-expire on Telegram's side ("may disappear automatically after some time, or if the app is restarted") — no tracking/cleanup machinery needed.
  • TgMessage exposes IsEphemeral/EphemeralMessageId; deleteCmdTask skips DeleteMessage for ephemeral command messages (nothing visible to delete). The delete path stays for old clients that keep sending regular commands.
  • Ephemeral /ban ping answers with an ephemeral pong instead of a public one.
  • Extracted softBanDuration helper so SoftBanMsg and the confirmation text share the /sban [hours] parsing.

Tests

tests/VahterBanBot.Tests/EphemeralTests.fs (6 tests on the fake-Telegram infra): confirmation sent/suppressed per flag, unban/softban confirmation content, ephemeral command not deleted while the ban still lands, ephemeral ping/pong. Tg.quickMsg/Tg.replyMsg gained ?ephemeralMessageId. Flag is restored in DisposeAsync per the AdminCommandTests precedent.

Rollout & accepted risk

Flags are seeded ON in prod via a manual bot_setting upsert (no migration), so both features go live with the deploy. Unverified: Telegram docs don't say whether an ephemeral command can be a reply to a regular message, which /ban//sban require — after deploy, verify /ban-as-reply from an updated client actually reaches the bot with a usable reply target. Kill switches: flip EPHEMERAL_CONFIRMATION_ENABLED off (+ /reload-settings, instant) and/or EPHEMERAL_COMMANDS_ENABLED off (+ restart to re-register plain commands).

🤖 Generated with Claude Code

https://claude.ai/code/session_019QJX5JAiRcLoPsyK7naF8E

Public-chat moderation commands (/ban, /sban, /unban) can now be
registered with is_ephemeral so clients send them invisibly to other
chat members, and the issuing vahter can get a short self-dismissing
ephemeral confirmation in the same chat. Both behind default-off
DB-backed flags:

- EPHEMERAL_COMMANDS_ENABLED: new BotCommandsSetupService registers
  the commands with is_ephemeral in the all_group_chats scope on
  startup; when off, deletes the registration so clients revert to
  plain visible commands.
- EPHEMERAL_CONFIRMATION_ENABLED: after /ban, /sban, /unban the
  issuing vahter receives an ephemeral confirmation (receiver_user_id,
  CallIgnore — best-effort, never fails the command). Lives in the
  AdminCommand dispatch so ML auto-bans never confirm; logs-channel
  reporting unchanged.

Incoming ephemeral commands (TgMessage.IsEphemeral) skip the
delete-command-message step — they are invisible and auto-expire;
the delete path stays for old clients. Ephemeral /ban ping gets an
ephemeral pong.

Known risk (accepted): Telegram docs don't say whether an ephemeral
command can be a reply (required by /ban and /sban). If broken in
practice, flip EPHEMERAL_COMMANDS_ENABLED off.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QJX5JAiRcLoPsyK7naF8E
@Szer
Szer force-pushed the ephemeral-commands branch from 92636ae to e3d3bea Compare July 16, 2026 20:55
@Szer
Szer enabled auto-merge (squash) July 16, 2026 20:56
@Szer
Szer merged commit f9d934e into main Jul 16, 2026
5 checks passed
@Szer
Szer deleted the ephemeral-commands branch July 16, 2026 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant