view release on metacpan or search on metacpan
examples/webhook.pl view on Meta::CPAN
262728293031323334353637383940414243444546
return
app ->
log
->
warn
(
'invalid secret'
)
unless
$c
-> req
-> headers
-> header(
'X-Telegram-Bot-Api-Secret-Token'
)
eq
$secret
;
}
$bot
-> process_update(
$c
-> req -> json);
};
$bot
-> set_callbacks(
message
=>
sub
{
my
(
undef
,
$update
) =
@_
;
my
$chat_id
=
$$update
{message}{from}{id};
my
$text
=
$$update
{message}{text};
eval
{
$bot
-> api -> sendMessage({
chat_id
=>
$chat_id
,
text
=>
$text
eq
'/start'
?
'Hey there!'
:
"You said: $text"
,
});
};
lib/Bot/Telegram.pm view on Meta::CPAN
424344454647484950515253545556575859606162
$self
->
log
->
warn
(
"Update processing failed: $err"
);
};
has
[
qw/api current_update polling_config/
];
has
[
qw/_polling
_polling_timer
_polling_interval
_polling_request_id/
];
has
callbacks
=>
sub
{ {} };
has
ioloop
=>
sub
{ Mojo::IOLoop -> new };
has
log
=>
sub
{ Mojo::Log -> new -> level(
'info'
) };
sub
new {
my
$self
=
shift
-> SUPER::new(
@_
);
$self
-> on(
polling_error
=> DEFAULT_POLLING_ERROR_CB);
$self
-> on(
callback_error
=> DEFAULT_CALLBACK_ERROR_CB);
$self
lib/Bot/Telegram.pm view on Meta::CPAN
105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
?
$resolve
:
$reject
) -> (
$ua
,
$tx
);
})
});
}
################################################################################
# Callbacks
################################################################################
sub
set_callbacks {
my
(
$self
,
%cbs
) =
@_
;
while
(
my
(
$key
,
$val
) =
each
%cbs
) {
$self
-> callbacks -> {
$key
} =
$val
;
}
return
$self
;
}
sub
remove_callbacks {
my
(
$self
,
@events
) =
@_
;
foreach
my
$event
(
@events
) {
delete
$self
-> callbacks -> {
$event
};
}
return
$self
;
}
################################################################################
# Updates
################################################################################
sub
shift_offset {
lib/Bot/Telegram.pm view on Meta::CPAN
149150151152153154155156157158159160161162163164165166167168169sub
process_update {
my
(
$self
,
$update
) =
@_
;
$self
-> current_update(
$update
);
my
$type
=
$self
-> _get_update_type(
$update
);
eval
{
# If update type is recognized, call the appropriate callback
if
(
$type
) {
$self
-> callbacks
-> {
$type
}
-> (
$self
,
$update
);
}
# Otherwise report an unknown update
else
{
$self
-> emit(
unknown_update
=>
$update
) }
};
# Report a callback error if we failed to handle the update
$self
-> emit(
callback_error
=>
$update
, $@)
if
$@;
lib/Bot/Telegram.pm view on Meta::CPAN
171172173174175176177178179180181182183184185186187188189190191
return
$self
;
}
# Return the update type if we have a callback for it
# Or just return zero, if we don't
sub
_get_update_type {
my
(
$self
,
$update
) =
@_
;
exists
$$update
{
$_
}
and
return
$_
for
keys
%{
$self
-> callbacks };
return
0;
}
################################################################################
# Webhook
################################################################################
sub
set_webhook {
my
(
$self
,
$config
,
$cb
) =
@_
;
lib/Bot/Telegram.pm view on Meta::CPAN
385386387388389390391392393394395396397398399400401402403404405#!/usr/bin/env perl
use
Mojo::Base -strict;
use
Bot::Telegram;
my
$bot
= Bot::Telegram
-> new
-> init_api(
token
=> YOUR_TOKEN_HERE);
$bot
-> set_callbacks(
message
=>
sub
{
my
(
$bot
,
$update
) =
@_
;
my
$chat
=
$$update
{message}{chat}{id};
my
$user
=
$$update
{message}{from}{username};
my
$text
=
$$update
{message}{text};
say
"> User $user says: $text"
;
$bot
-> api -> sendMessage(
{
chat_id
=>
$chat
,
text
=>
"Hello there, $user!"
},
lib/Bot/Telegram.pm view on Meta::CPAN
532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
my
(
$bot
,
$update
) =
@_
;
say
"> No callback defined for this kind of updates. Anyway, here's the update object:"
;
Data::Dump::dd(
$update
);
});
Emitted
when
an update of an unregistered type is received.
The type is considered
"unregistered"
if
there is
no
matching callback configured
(i.e. C<
$self
-E<gt> callbacks -E<gt> {
$update_type
}> is not a coderef).
Exists mostly
for
debugging purposes.
There are
no
default
subscribers to this event.
=head1 PROPERTIES
L<Bot::Telegram> inherits all properties from L<Mojo::EventEmitter> and implements the following new ones.
=head2 api
my $api = $bot -> api;
$bot -> api($api);
L<WWW::Telegram::BotAPI> instance used by the bot. Can be initialized via the L</"init_api"> method, or set directly.
=head2 callbacks
my $callbacks = $bot -> callbacks;
$bot -> callbacks($callbacks);
Hash reference containing callbacks for different update types.
While you can manipulate it directly, L</"set_callbacks"> and L</"remove_callbacks"> methods provide a more convinient interface.
=head2 current_update
my $update = $bot -> current_update;
say "User $$update{message}{from}{username} says: $$update{message}{text}";
Update that is currently being processed.
=head2 ioloop
lib/Bot/Telegram.pm view on Meta::CPAN
679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719=head2 process_update
$bot = $bot -> process_update($update);
Process a single update and store it in L</"current_update">.
This function will not C<die> regardless of the operation success.
Instead, the L</"callback_error"> event is emitted if things go bad.
=head2 remove_callbacks
$bot = $bot -> remove_callbacks(qw/message edited_message/);
# From now on, bot considers 'message' and 'edited_message' unknown updates
Remove callbacks for given update types, if set.
=head2 set_callbacks
$bot -> set_callbacks(
message => sub {
my ($bot, $update) = @_;
handle_message $update;
},
edited_message => sub {
my ($bot, $update) = @_;
handle_edited_message $update;
}
);
Set callbacks to match specified update types.
=head2 set_webhook
$bot = $bot -> set_webhook($config);
$bot = $bot -> set_webhook($config, $cb);
Set a webhook. All arguments will be proxied to L<WWW::Telegram::BotAPI/"api_request">.
This function ensures that actual C<setWebhook> request will not be made as long as the polling loop is active:
t/01-polling.t view on Meta::CPAN
162163164165166167168169170171172173174175176177178179180181my
$messages
=
$bot
->
log
-> capture(
'info'
);
my
$polling_interval_after_rate_limit
;
my
$stop
=
sub
{
$bot
-> stop_polling;
Mojo::IOLoop -> stop;
};
my
$t
= Mojo::IOLoop -> timer(3,
$stop
);
$bot
-> set_callbacks(
message
=>
sub
{
return
unless
pop
-> {update_id} == 2;
$polling_interval_after_rate_limit
=
$bot
-> _polling_interval;
$stop
-> ();
Mojo::IOLoop -> remove(
$t
);
});
my
$time_before
= steady_time;
t/04-events.t view on Meta::CPAN
495051525354555657585960616263646566676869
result
=> [
map
{ state
$i
= 0 ; update
$_
=>
$i
++ }
qw/message edited_message callback_query/
]
};
my
$messages
=
$log
-> capture(
'warn'
);
my
$upd_counter
= 0;
my
$count_update
=
sub
{ ++
$upd_counter
};
$bot
-> api(bot_api
$res
)
-> set_callbacks(
message
=>
sub
{
die
'failed to process message'
},
edited_message
=>
$count_update
,
callback_query
=>
$count_update
)
-> start_polling;
Mojo::IOLoop -> start;
is
scalar
@$messages
, 1,
'got 1 failure as expected'
;
is
$upd_counter
, 2,
'processed 2 updates as expected'
;
like
$$messages
[0],
qr/Update processing failed: failed to process message/
,
t/04-events.t view on Meta::CPAN
717273747576777879808182838485868788899091
};
};
subtest
callback_error
=>
sub
{
plan
tests
=> 2;
my
$bot
= Bot::Telegram -> new;
my
$res
= json_response {
ok
=> \1,
result
=> [update
message
=> 1] };
$bot
-> api(bot_api
$res
);
$bot
-> set_callbacks(
message
=>
sub
{ This shit will definitely
die
});
my
(
$pass
,
@args
) = 0;
$bot
-> unsubscribe(
'callback_error'
);
$bot
-> on(
callback_error
=>
sub
{
@args
=
@_
});
$bot
-> start_polling;
Mojo::IOLoop -> one_tick;
$bot
-> stop_polling;
subtest
arguments
=>
sub
{
t/04-events.t view on Meta::CPAN
109110111112113114115116117118119120121122123124125126127128129my
$res
= json_response {
ok
=> \1,
result
=> [
(update
message
=> 1),
(update
thing
=> 2),
],
};
$bot
-> api(bot_api
$res
);
# $bot -> unsubscribe('unknown_update'); # there's nothing by default
$bot
-> set_callbacks(
message
=>
sub
{ 0 });
# make 'message' a "known" update
my
(
$pass
,
@args
) = 0;
$bot
-> on(
unknown_update
=>
sub
{
@args
=
@_
});
$bot
-> start_polling;
Mojo::IOLoop -> one_tick;
$bot
-> stop_polling;
subtest
arguments
=>
sub
{
plan
tests
=> 2;
t/05-updates.t view on Meta::CPAN
101112131415161718192021222324252627282930313233343536373839404142subtest
'on/off'
=>
sub
{
plan
tests
=> 3;
my
$bot
= Bot::Telegram -> new;
my
$api
= bot_api;
my
$message
=
sub
{
'this is a callback for message'
};
my
$edited_message
=
sub
{
'this is a callback for edited_message'
};
$bot
-> set_callbacks(
message
=>
$message
,
edited_message
=>
$edited_message
);
is_deeply [
sort
keys
%{
$bot
-> callbacks} ], [
qw/edited_message message/
],
'set callbacks'
;
subtest
subs
=>
sub
{
is
$bot
-> callbacks -> {message},
$message
;
is
$bot
-> callbacks -> {edited_message},
$edited_message
;
};
$bot
-> remove_callbacks(
qw/message edited_message/
);
is_deeply [
keys
%{
$bot
-> callbacks} ], [],
'remove callbacks'
;
};
subtest
'update types recognition'
=>
sub
{
my
$upds
= [];
my
@list
=
qw/message callback_query inline_query foobar/
;
my
$update_id
= 0;
plan
tests
=> 4;
push
@$upds
, (update
$_
=>
$update_id
++)
for
@list
;
t/05-updates.t view on Meta::CPAN
454647484950515253545556575859606162
my
$api
= bot_api
json_response {
ok
=> \1,
result
=>
$upds
,
};
$bot
-> api(
$api
);
my
$correctly_recognized
= [];
$bot
-> set_callbacks(
$_
=> updcheck
$_
)
for
@list
;
$bot
-> start_polling;
Mojo::IOLoop -> one_tick;
$bot
-> stop_polling;
};
done_testing;
t/06-sync.t view on Meta::CPAN
4748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
result
=> [
map
{update
$_
=>
$update_id
++}
@UPDATES
]
}), json_response({
ok
=> \1,
result
=> [update
something
=> 0]
}),
sub
{ ++
$req_counter
};
$bot
-> api(
$api
) -> api -> {async} = 0;
my
@processed
;
# let's make ourselves a callbacks generator to simplify things a little bit
my
$push
=
sub
{
my
$name
=
shift
;
sub
{
shift
;
# discard $bot reference
note
"(callback) $name"
;
push
@processed
,
$name
if
ref
shift
-> {
$name
} eq
'HASH'
}
};
$bot
-> set_callbacks(
(
map
{
$_
=>
$_
->
$push
}
qw/message callback_query something/
),
edited_message
=>
sub
{
(
'edited_message'
->
$push
) -> (
@_
);
# This will disable the polling loop once the second update is processed.
# 'callback_query' will still get processed since it's already retrieved,
# but 'something' should never be reached.
$bot
-> stop_polling;
}
);
$bot
-> start_polling(
interval
=> 3);
is
$req_counter
, 1,
'made 1 request'
;
is_deeply \
@processed
, \
@UPDATES
,
'processed all updates received during the first iteration'
;
};
subtest
'Events'
,
sub
{
my
$bot
= Bot::Telegram -> new;
$bot
-> api(bot_api json_response {
ok
=> \1,
result
=> [update
message
=> 1] });
$bot
-> set_callbacks(
message
=>
sub
{
die
'catch me if you can'
});
$bot
-> api -> {async} = 0;
my
$passed
;
$bot
-> unsubscribe(
'callback_error'
);
$bot
-> on(
callback_error
=>
sub
{
note
'inside the callback'
;
$bot
-> stop_polling;
$passed
= 1;
});