Bot::ChatBots::Telegram::LongPoll - Telegram updates receiver, long-poll


   use Bot::ChatBots::Telegram::LongPoll;
   my $lp = Bot::ChatBots::Telegram::LongPoll->new(
      token     => $ENV{TOKEN},
      processor => \&processor,
      start     => 1,
   sub processor { # tube-compliant
      my $record = shift;

      # ... your business logic goes here...
      my $message = 'Howdy!';

      if (automatic_via_sender()) { # same as WebHook
         $record->{send_response} = $message;
      elsif (do_it_yourself_via_sender()) { # same as WebHook
         my $sender = $record->{source}{refs}{sender};
         $sender->send_response($message, record => $record);
      # else nothing is sent back, just a HTTP 204 by default

      return $record; # follow on..


This is an updates receiver and dispatcher for the Telegram infrastructure. It connects to Telegram's API for long-poll style (i.e. pulling updates continuously), so it's somehow inefficient but should let you get started in all conditions in which you can at least browse the Internet (webhook require that your endpoint lives in a routable place).

At the base, you have to provide at least the "token" and the "processor". The former is needed to connect to Telegram and get updates, the latter is what will be invoked for each update that is received.

When you have an object, you have to "start" to get the ball rolling. You can also pass start in the constructor, this will start the Mojo::IOLoop directly (so you can use it in case you don't have other stuff to do).

When invoked, the "processor" tube can return a record with the send_response field set. In this case, this update receiver can act also on the other way around, and send the response towards Telegram using a Bot::ChatBots::Telegram::Sender.

 .                            ..Bot Application.....
                              :                    :
   __________________         :     ____________   :
  /                  \        :    /            \  :
  |                  |<----------1-|            |  :
  |  Telegram Server |        :    |  LongPoll  |  :
  |                  |-2---------->|            |  :
  \__________________/        :    \____________/  :
              |  ^            :        |           :
              5  |            :        3 "send_response"
              |  |            :        |           :
              |  |            :     ___v______     :
              |  |            :    /          \    :
              |  +---------------4-|          |    :
              |               :    |  Sender  |    :
              +------------------->|          |    :
                              :    \__________/    :
                              :                    :

   1, 2: Poll for new Update(s)
   3   : internal call
   4, 5: Telegram API Request/Response


This class consumes roles Bot::ChatBots::Telegram::Role::Source and Bot::ChatBots::Role::Source and all its accessors.


   my $to = $obj->connect_timeout;

Acccessor for the connection timeout for Bot::ChatBots::Telegram::Sender's user agent (this is Mojo::UserAgent).


   $secs = $obj->interval;
   $obj->interval(0.2); # secs

Accessor for the interval of scheduling calls to getUpdates. You can set this to a pretty low value (default is 0.1 seconds) because there is a flag that prevents calls from being sent if another one is ongoing.


   my $n = $obj->max_redirects;
   $obj->max_redirects(7); # default is 5

Accessors for maximum number of redirects acceptable for the underlying Mojo::UserAgent. Defaults to 5.


   my $to = $obj->update_timeout;

Accessor to set/get the update_timeout set in the getUpdates call to the Telegram API. Defaults to 300 seconds, i.e. you should get at least one update every 5 minutes.


This class consumes roles Bot::ChatBots::Telegram::Role::Source and Bot::ChatBots::Role::Source and all its methods.


Method called upon construction. It checks for the presence of a start parameter set to true and in case calls "start".


   my @pairs = $obj->class_custom_pairs;

Returns custom pairs, used by role Bot::ChatBots::Role::Source. It adds a token to the parameters put in the source key inside the record passed to the process method, when invoked.


   my @updates = $obj->parse_response($res, $threshold_id);

Parse the response to the polling request ($res is a Mojo::Message::Result object) and filters all updates whose identifier (according to field update_id) are greater than, or equal to, the $threshold_id. It takes care to check the return values and the rest.


   my $subref = $obj->poller(%args);
      $subref = $obj->poller(\%args);

Build a polling sub reference suitable for being installed as a repetitive task in "start". This poller sends one single request to the Telegram endpoint for the longpoll and processes one single response.

In particular, it extracts the list of updates from the response and calls "process_updates" in Bot::ChatBots::Role::Source on them.

The source key in the record that is eventually generated contains:

  • refs with sender, tx and ua

  • an additional item in source that is a hash reference associated to the key query. Inside this you can find a key offset that you can use to increase the offset to be used in following calls. This is done automatically in "process".


   my $retval = $self->process($record);

Wrapper around "process" in Bot::ChatBots::Role::Source to cope with the need to increase the offset for each incoming update (see "poller" for additional details).


   $obj->start(%args); # OR

Start polling Telegram for new updates. "poller" is called to retrieve a sub reference that is then installed as a recurring job according to "interval".

This method is called automatically upon object construction if option start is present and set to a true value.


Bot::ChatBots, Bot::ChatBots::Telegram::WebHooks.


Flavio Poletti <>


Copyright (C) 2016, 2018 by Flavio Poletti <>

This module is free software. You can redistribute it and/or modify it under the terms of the Artistic License 2.0.

This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose.