-
-
Save hsmiranda/166d5c0631b2de8c97633514429ca89f to your computer and use it in GitHub Desktop.
Basic Telegram bot implementation using WWW::Telegram::BotAPI
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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