NAME

Langertha::Raider::Hall::Telegram - Internal multi-bot Telegram long-poll adapter for the raider hall

VERSION

version 0.504

DESCRIPTION

Internal module. Its interface may change without notice.

Long-polls every Telegram bot configured for a Langertha::Raider::Hall, routes incoming messages to raiders and sends replies.

Access is fail-closed and checked per message:

telegram:
  bots:
    ops:
      token: '...'
      allowlist:     [1234567890]      # Telegram user ids (message.from.id)
      allowed_chats: [-1001234567890]  # optional: group chats to answer in

A message is accepted only when its sender (from.id) is in allowlist and its chat is either the private chat with that sender or listed in allowed_chats. An empty or missing allowlist accepts nobody. Rejected messages emit a telegram.rejected event and are neither stored nor routed.

A routed message runs in the session bound to its chat -- telegram:BOT:CHAT_ID, with :THREAD for a forum topic -- so the conversation continues across messages (see "session_bindings" in Langertha::Raider::Hall). The raider's telegram_reply answers into the same chat and forum topic.

A mission the hall refuses (raider.refused, see "EVENT BUS" in Langertha::Raider::Hall) -- at once or when it is pulled from a queue -- is answered in its chat and topic with the short mission not started (configuration), see the hall log; the reason stays in the event and the slot log.

/new (or /new@BOTNAME) from an accepted sender is not a mission: the chat's (topic's) next message starts a new session, and the bot confirms with a short message. The old journal stays.

When a module the https connection to the Bot API needs does not load (IO::Async::SSL and what it needs, see Langertha::Raider::ConnectCheck), a bot does not poll: the hall warns and emits telegram.poll_error with the module's name, and a reply is an error result. Nothing is sent, so nothing waits for a connection that cannot open.

Poll errors. Every getUpdates answer that is not a usable result emits telegram.poll_error with the bot, the HTTP status (when there was an answer) and an error of the form HTTP 409: description, and the bot polls again only after a wait, never at once:

  • a non-2xx status, or ok: false in the body, is an error answer;

  • a 2xx answer whose body cannot be read as the Bot API's JSON object (HTTP 200: unreadable response) counts as an error answer as well, and no update of it is handled;

  • a failure of the request itself (network, TLS, timeout) emits the event without a status;

  • 429 waits the retry_after seconds Telegram sent; every other failure waits 5 s, doubling with each consecutive one up to 300 s, and the wait starts over after an answer that was usable;

  • 401 (the token is wrong or revoked) stops the bot with a warning instead of retrying;

  • the bot's token is masked (***) in the reported error.

An update whose handling dies does not stop the loop: it emits telegram.update_error with the bot, the update_id and the error, and polling continues with the offset behind that update.

SUPPORT

Issues

Please report bugs and feature requests at https://github.com/Getty/langertha-raider/issues.

IRC

Join #langertha on irc.perl.org or message Getty directly.

CONTRIBUTING

Contributions are welcome! Please fork the repository and submit a pull request.

AUTHOR

Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Torsten Raudssus.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

https://raudssus.de/