Skip to content

Instantly share code, notes, and snippets.

@hsmiranda
Forked from Robertof/tg-example-bot.pl
Created April 3, 2016 18:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hsmiranda/166d5c0631b2de8c97633514429ca89f to your computer and use it in GitHub Desktop.
Save hsmiranda/166d5c0631b2de8c97633514429ca89f to your computer and use it in GitHub Desktop.
Basic Telegram bot implementation using WWW::Telegram::BotAPI
#!/usr/bin/env perl
# Basic Telegram Bot implementation using WWW::Telegram::BotAPI
use strict;
use warnings;
use WWW::Telegram::BotAPI;
my $api = WWW::Telegram::BotAPI->new (
token => (shift or die "ERROR: a token is required!\n")
);
# Bump up the timeout when Mojo::UserAgent is used (LWP::UserAgent uses 180s by default)
$api->agent->can ("inactivity_timeout") and $api->agent->inactivity_timeout (45);
my $me = $api->getMe or die;
my ($offset, $updates) = 0;
# The commands that this bot supports.
my $pic_id; # file_id of the last sent picture
my $commands = {
"start" => "Hello! Try: /whoami - /say - /lastphoto - /keyboard - /knock",
# Example demonstrating the use of parameters in a command.
"say" => sub { join " ", splice @_, 1 or "Usage: /say something" },
# Example showing how to use the result of an API call.
"whoami" => sub {
sprintf "Hello %s, I am %s! How are you?", shift->{from}{username}, $me->{result}{username}
},
# Example showing how to send multiple lines in a single message.
"knock" => sub {
sprintf "Knock-knock.\n- Who's there?\n@%s!", $me->{result}{username}
},
# Example displaying a keyboard with some simple options.
"keyboard" => sub {
+{
text => "Here's a cool keyboard.",
reply_markup => JSON::MaybeXS::encode_json ({
keyboard => [ [ "a" .. "c" ], [ "d" .. "f" ], [ "g" .. "i" ] ],
one_time_keyboard => JSON::MaybeXS::JSON->true
})
}
},
# Example sending a photo with a known picture ID.
"lastphoto" => sub {
return "You didn't send any picture!" unless $pic_id;
+{
method => "sendPhoto",
photo => $pic_id,
caption => "Here it is!"
}
},
# Internal target called when a photo is received.
"_photo" => sub { $pic_id = shift->{photo}[0]{file_id} },
# Internal target used to handle unknown commands.
"_unknown" => "Unknown command :("
};
printf "Hello! I am %s. Starting...\n", $me->{result}{username};
while (1) {
$updates = $api->getUpdates ({
timeout => 30, # Use long polling
$offset ? (offset => $offset) : ()
});
unless ($updates and ref $updates eq "HASH" and $updates->{ok}) {
warn "WARNING: getUpdates returned a false value - trying again...";
next;
}
for my $u (@{$updates->{result}}) {
$offset = $u->{update_id} + 1 if $u->{update_id} >= $offset;
if (my $text = $u->{message}{text}) { # Text message
printf "Incoming text message from \@%s\n", $u->{message}{from}{username};
printf "Text: %s\n", $text;
next if $text !~ m!^/!; # Not a command
my ($cmd, @params) = split / /, $text;
my $res = $commands->{substr ($cmd, 1)} || $commands->{_unknown};
# Pass to the subroutine the message object, and the parameters passed to the cmd.
$res = $res->($u->{message}, @params) if ref $res eq "CODE";
next unless $res;
my $method = ref $res && $res->{method} ? delete $res->{method} : "sendMessage";
$api->$method ({
chat_id => $u->{message}{chat}{id},
ref $res ? %$res : ( text => $res )
});
print "Reply sent.\n";
} elsif ($u->{message}{photo}) {
print "Incoming picture...\n";
$commands->{_photo}->($u->{message}) if ref $commands->{_photo} eq "CODE";
}
# TODO: other message types...
}
}
sub _sendTextMessage {
$api->sendMessage ({
chat_id => shift->{message}{chat}{id},
%{+shift}
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment