Skip to content

Add interactive commands to Telegram bot #138

Description

@rvalitov

WIP, I will provide screenshots after I finish all the tests and improvements

No way to inspect or manage users from the bot without typing commands

Type: enhancement
Area: Telegram bot
Addressed by: PR 3 of 4 (feat(telegram): interactive inline-keyboard menus)

Summary

The bot is entirely text-driven. Every action requires typing a command with
hand-supplied arguments, and there is no way to browse — you cannot see a list
of users and then act on one; you have to know the label, remember the command
and type both correctly.

There are currently zero inline keyboards in the codebase (reply_markup,
callback_query and answerCallbackQuery do not appear anywhere).

Impact

  • Managing users from a phone keyboard is error-prone. /mp_setlimit alice 5 2 10G
    is a lot of typing on mobile, and a typo silently targets the wrong thing or
    fails.
  • Discovery requires memorisation. To disable a user you must already know
    that /mp_disable <label> exists and what the label is. /mp_secrets prints
    labels, but they must then be retyped by hand.
  • Per-user state is scattered. Live connections come from /mp_secrets,
    quota and expiry from /mp_limits, traffic from /mp_traffic — three commands
    to answer "how is alice doing?", and none of them shows all of it at once.

Proposal

Add inline keyboards so the common operations are reachable by tapping:

  1. A hub with buttons for the main views.
  2. A paginated user list — tap a user to open their card.
  3. A per-user card showing status, live connections, unique IPs, quota bar,
    expiry countdown and traffic, with actions attached.
  4. A confirmation step before anything destructive.
  5. Button bars on existing replies (/start, /mp_status, /mp_secrets,
    /mp_traffic, /mp_help) so the views are reachable without typing.

Security requirements (important)

callback_data is entirely attacker-controlled — any user can send any payload
from any client. Therefore:

  • Every tap must be re-authorised against the same rules _process_cmd
    applies
    . A button must never grant more than typing the equivalent command
    would.
  • Public actions run before any role check, exactly as public commands do.
  • An unauthenticated chatter is answered but ignored silently (no edit, no
    audit entry), mirroring the existing role == none behaviour.
  • A recognised-but-underprivileged role is refused loudly, with a SECURITY
    line in audit.log.
  • An unrecognised role string must fail closed to public-only. admins.conf
    is a plain file an operator can edit, so anything that is not exactly
    superadmin or reseller must never exceed public.
  • No chat id may travel in callback_data — identity must come from
    callback_query.message.chat.id, which Telegram authenticates. A chat id in
    the payload would be an attacker-controlled privilege token.
  • The payload must be treated as data, never a command, and the target
    re-validated against secrets.conf before anything runs.
  • Every tap must be acknowledged (answerCallbackQuery) on every path,
    including denial and error, or the client spinner hangs forever.

Destructive actions

⏸ Disable, ♻️ Rotate and 🗑 Remove must require an explicit second tap on a
confirmation button. Nothing destructive should be one mis-tap away.

Acceptance criteria

  • Tapping / hub buttons opens the corresponding view in place.
  • The user list paginates and taps through to a per-user card.
  • Back returns to the page the user came from.
  • A reseller's menus contain no button it cannot use, and a forged
    callback_data from a reseller is refused and audited.
  • An unauthenticated user's taps change nothing and are not audited.
  • Destructive actions require confirmation and are never executed by the
    first tap.
  • Every tap is acknowledged exactly once, on all paths.
  • Every callback_data stays within Telegram's 64-byte limit.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions