File Coverage

blib/lib/Net/API/Telegram.pm
Criterion Covered Total %
statement 110 1598 6.8
branch 0 992 0.0
condition 0 574 0.0
subroutine 44 184 23.9
pod 78 87 89.6
total 232 3435 6.7


line stmt bran cond sub pod time code
1             # -*- perl -*-
2             ##----------------------------------------------------------------------------
3             ## Telegram API - ~/lib/Net/API/Telegram.pm
4             ## Version 0.6
5             ## Copyright(c) 2020 Jacques Deguest
6             ## Author: Jacques Deguest <jack@deguest.jp>
7             ## Created 2019/05/29
8             ## Modified 2020/03/28
9             ## All rights reserved
10             ##
11             ## This program is free software; you can redistribute it and/or modify it
12             ## under the same terms as Perl itself.
13             ##----------------------------------------------------------------------------
14             package Net::API::Telegram;
15             BEGIN
16 0         0 {
17 1     1   102977 use strict;
  1         3  
  1         34  
18 1     1   467 use parent qw( Module::Generic );
  1         312  
  1         6  
19 1     1   1825536 use HTTP::Daemon;
  1         88908  
  1         12  
20 1     1   1014 use HTTP::Daemon::SSL;
  1         51795  
  1         8  
21 1     1   1034 use File::Temp;
  1         11455  
  1         78  
22 1     1   8 use File::Spec;
  1         2  
  1         22  
23 1     1   10 use File::Basename ();
  1         1  
  1         33  
24 1     1   486 use IO::File;
  1         1021  
  1         140  
25 1     1   488 use Data::UUID;
  1         738  
  1         73  
26 1     1   751 use JSON;
  1         10050  
  1         5  
27 1     1   710 use Encode ();
  1         10294  
  1         43  
28 1     1   9 use TryCatch;
  1         2  
  1         12  
29 1     1   1067 use File::Map;
  1         5464  
  1         4  
30 1     1   671 use Class::Struct qw( struct );
  1         1989  
  1         6  
31 1     1   195 use Devel::StackTrace;
  1         2  
  1         28  
32 1     1   546 use Time::HiRes;
  1         1331  
  1         5  
33 1     1   1056 use DateTime;
  1         442495  
  1         55  
34 1     1   10 use DateTime::TimeZone;
  1         3  
  1         22  
35 1     1   6 use Scalar::Util;
  1         2  
  1         52  
36 1     1   6 use POSIX qw( :sys_wait_h );
  1         2  
  1         11  
37 1     1   990 use Net::IP ();
  1         61492  
  1         43  
38 1     1   11 use Errno qw( EINTR );
  1         3  
  1         66  
39 1     1   919 use LWP::UserAgent;
  1         11772  
  1         34  
40 1     1   24 use HTTP::Headers;
  1         3  
  1         28  
41 1     1   5 use HTTP::Request;
  1         2  
  1         29  
42 1     1   501 use HTTP::Request::Common;
  1         2337  
  1         138  
43 1     1   8 use HTTP::Response;
  1         3  
  1         31  
44             ## We load Net::API::Telegram::Update because we test the existence of its methods for the setup of handlers
45 1     1   505 use Net::API::Telegram::Update;
  1         3  
  1         13  
46 1     1   1165 use Devel::Confess;
  1         7623  
  1         4  
47 1     1   1709 our( $VERSION ) = '0.6';
48 1     1   93 use constant TELEGRAM_BASE_API_URI => 'https://api.telegram.org/bot';
  1         2  
  1         83  
49 1     1   7 use constant TELEGRAM_DL_FILE_URI => 'https://api.telegram.org/file/bot';
  1         2  
  1         51  
50             ## We do not use the port 80 or 880 by default, because they are commonly used for other things
51 1     1   6 use constant DEFAULT_PORT => 8443;
  1         3  
  1         47  
52             ## 50Mb
53 1     1   6 use constant FILE_MAX_SIZE => 52428800;
  1         3  
  1         40  
54             };
55              
56             {
57             our $DEBUG = 0;
58             our $VERBOSE = 0;
59             our $ERROR = '';
60             ## our $BROWSER = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0';
61             our $BROWSER = 'Net::API::Telegram_Bot/' . $VERSION;
62             our $TYPE2CLASS =
63             {
64             'message' => 'Net::API::Telegram::Message',
65             'update' => 'Net::API::Telegram::Update',
66             };
67              
68             struct Net::API::Telegram::Error =>
69             {
70             'type' => '$',
71             'code' => '$',
72             'message' => '$',
73             'file' => '$',
74             'line' => '$',
75             'package' => '$',
76             'sub' => '$',
77             #'trace' => 'Devel::StackTrace',
78             'trace' => '$',
79             'retry_after' => '$',
80             };
81             our $CHILDREN = {};
82             ## Flag set by sig handler
83             our $TIME_TO_DIE = 0;
84             }
85              
86             sub init
87             {
88 0     0 1   my $self = shift( @_ );
89 0           my $token;
90 0 0         $token = shift( @_ ) if( ( scalar( @_ ) % 2 ) );
91 0           $self->{ 'token' } = $token;
92 0           $self->{ 'webhook' } = 0;
93 0           $self->{ 'host' } = '';
94 0           $self->{ 'port' } = DEFAULT_PORT;
95 0           $self->{ 'external_ssl' } = 0;
96 0           $self->{ 'external_host' } = '';
97 0           $self->{ 'external_port' } = '';
98 0           $self->{ 'external_path' } = '';
99 0           $self->{ 'encode_with_json' } = 1;
100 0           $self->{ 'cookie_file' } = '';
101 0           $self->{ 'browser' } = $BROWSER;
102 0           $self->{ 'timeout' } = 5;
103 0           $self->{ 'use_ssl' } = 0;
104 0           $self->{ 'ssl_key' } = '';
105 0           $self->{ 'ssl_cert' } = '';
106 0           $self->{ 'max_connections' } = 1;
107 0           $self->{ 'logging' } = 0;
108 0           $self->{ 'log_file' } = '';
109 0           $self->{ 'debug_log_file' } = '';
110             ## Default timeout to 10 seconds
111 0           $self->{ 'timeout' } = 10;
112             ## A URI object representing the url at which the webhook can be accessed
113 0           $self->{ 'webhook_uri' } = '';
114             ## When receiving message from Telegram either on the webhook or through the getUpdates() method
115             ## if this is on, it will only accept messages older than our start time
116 0           $self->{ 'skip_past_messages' } = 1;
117             ## Time to wait between each getUpdates() polling call
118 0           $self->{ 'poll_interval' } = 10;
119             ## If true, temporary files will be removed
120 0           $self->{ 'cleanup_temp' } = 1;
121 0           $self->{ 'authorised_ips' } = [];
122 0           $self->{temp_dir} = File::Spec->tmpdir;
123             ## Json configuration file
124 0           $self->{conf_file} = '';
125 0           $self->SUPER::init( @_ );
126 0           $self->{conf_data} = {};
127 0 0         if( $self->{conf_file} )
128             {
129 0           my $json = $self->conf_file( $self->{conf_file} );
130 0 0         $self->{token} = $json->{token} if( !$self->{token} );
131             }
132 0 0         $self->debug_log_file( $self->{debug_log_file} ) if( $self->{debug_log_file} );
133 0 0         $self->port( $self->{port} ) if( $self->{port} );
134 0           $self->{ 'ug' } = Data::UUID->new;
135 0           $self->{ 'json' } = JSON->new->allow_nonref;
136 0           $self->{ '_log_io' } = '';
137 0           $self->{ '_handlers' } = {};
138 0           $self->{ '_auth_ips' } = [];
139 0           $self->{ 'start_time' } = '';
140             ## A boolean value that is being checked when getUpdates polling is in service.
141             ## This is set to true by stop()
142 0           $self->{ '_stop_polling' } = 0;
143 0           $self->{ '_stop_daemon' } = 0;
144             ## Used to keep track of the parent pid, which in turn is used to know if it is a child process that triggered the cleanup procedure
145             ## Since when forking the information is hard copied into the child process, this is registered before fork happens
146 0           $self->{ 'pid' } = '';
147 0 0         return( $self->error( "No Telegram authorisation token was provided" ) ) if( !$self->{token} );
148 0           $self->{ 'api_uri' } = URI->new( TELEGRAM_BASE_API_URI . $self->{token} );
149             ## https://api.telegram.org/file/bot<token>/<file_path>
150 0           $self->{ 'dl_uri' } = URI->new( TELEGRAM_DL_FILE_URI . $self->{token} );
151 0           $self->{ 'offset' } = 0;
152 0           $self->{ 'http_request' } = '';
153 0           $self->{ 'http_response' } = '';
154 0 0 0       $self->authorised_ips( $self->{authorised_ips} ) if( $self->{authorised_ips} && ref( $self->{authorised_ips} ) eq 'ARRAY' );
155             ## Customisation
156 0 0         $self->message( 3, "Initialising webhook..." ) if( $self->{webhook} );
157 0           $self->webhook( $self->{webhook} );
158 0           return( $self );
159             }
160              
161             sub agent
162             {
163 0     0 1   my $self = shift( @_ );
164 0           my $cookie_file = $self->cookie_file;
165 0           my $browser = $self->browser;
166 0   0       my $timeout = $self->{timeout} || 3;
167 0           my $ua = LWP::UserAgent->new(
168             agent => $browser,
169             #sleep => '1..3',
170             timeout => $timeout,
171             );
172 0           $ua->default_header( 'Content_Type' => 'multipart/form-data' );
173 0 0         $ua->cookie_jar({ file => $cookie_file }) if( $cookie_file );
174 0           return( $ua );
175             }
176              
177 0     0 1   sub api_uri { return( shift->_set_get( 'api_uri', @_ ) ); }
178              
179             sub authorised_ips
180             {
181 0     0 0   my $self = shift( @_ );
182 0 0         $self->{_auth_ips} = [] if( ref( $self->{_auth_ips} ) ne 'ARRAY' );
183 0           my $ips = $self->{_auth_ips};
184 0 0         if( @_ )
185             {
186 0           my $err = [];
187             local $check = sub
188             {
189 0     0     my $raw = shift( @_ );
190 0           my $ip;
191 0 0 0       if( Scalar::Util::blessed( $raw ) && $raw->isa( 'Net::IP' ) )
192             {
193 0           $ip = $raw;
194             }
195             else
196             {
197             $ip = Net::IP->new( $raw ) || do
198 0   0       {
199             warn( "Warning only: IP '$raw' is not valid: ", Net::IP->Error, "\n" );
200             push( @$err, sprintf( "IP '$raw' is not valid: %s", Net::IP->Error ) );
201             return( '' );
202             };
203             }
204 0           $self->messagef( 3, "IP block provided has %d IP addresses, starts with %s and ends with %s", $ip->size, $ip->ip, $ip->last_ip );
205 0           foreach my $existing_ip ( @$ips )
206             {
207             ## We found an existing ip same as the one we are adding, so we skip
208             ## If we are given a block that has some overlapping elements, we go ahead and add it
209             ## because it would become complicated and risky to only take the ips that do not overalp in the given block
210 0 0         if( $ip->overlaps( $existing_ip ) == $Net::IP::IP_IDENTICAL )
211             {
212 0           return( '' );
213             }
214             }
215 0           return( $ip );
216 0           };
217            
218 0           ARG_RECEIVED: foreach my $this ( @_ )
219             {
220 0 0         if( ref( $this ) eq 'ARRAY' )
    0          
221             {
222 0           RAW_IPS: foreach my $raw ( @$this )
223             {
224 0 0         if( my $new_ip = $check->( $raw ) )
225             {
226 0           push( @$ips, $new_ip );
227             }
228             }
229             }
230             ## a scalar
231             elsif( !ref( $this ) )
232             {
233 0 0         if( my $new_ip = $check->( $this ) )
234             {
235 0           push( @$ips, $new_ip );
236             }
237             }
238             else
239             {
240 0           warn( "Illegal argument provided '$this'. I was expecting an array of string or array reference and each value being a string or a Net::IP object\n" );
241 0           next ARG_RECEIVED;
242             }
243             }
244 0 0         if( scalar( @$err ) )
245             {
246 0           warn( sprintf( "Warning only: the following ip do not seem valid and were skipped: %s\n", join( ', ', @$err ) ) );
247             }
248             }
249 0           return( $ips );
250             }
251              
252 0     0 1   sub browser { return( shift->_set_get_scalar( 'browser', @_ ) ); }
253              
254             sub cleanup
255             {
256 0     0 0   my $self = shift( @_ );
257 0           my( $pack, $file, $line ) = caller;
258 0           $self->message( 3, "Called from package $pack in file $file at line $line" );
259 0           $self->message( 3, "Cleaning up call from pid $$..." );
260 0 0         $self->message( 3, "This is", ( $$ == $self->{pid} ? '' : ' not' ), " the parent process with pid $$." );
261             ## Wrap it up within 5 seconds max
262 0           alarm( 5 );
263             eval
264 0           {
265 0     0     local $SIG{ 'ALRM' } = sub{ die( "Timeout\n" ); };
  0            
266 0           $self->stop;
267             };
268 0           alarm( 0 );
269 0 0         if( $@ =~ /timeout/i )
270             {
271 0           $self->message( 1, "Timeout when cleaning up before exiting." );
272             }
273 0           return( $self );
274             }
275              
276             sub conf_file
277             {
278 0     0 1   my $self = shift( @_ );
279 0 0         if( @_ )
280             {
281 0           my $file = shift( @_ );
282 0 0         if( !-e( $file ) )
    0          
283             {
284 0           return( $self->error( "Configuration file $file does not exist." ) );
285             }
286             elsif( -z( $file ) )
287             {
288 0           return( $self->error( "Configuration file $file is empty." ) );
289             }
290 0   0       my $fh = IO::File->new( "<$file" ) || return( $self->error( "Unable to open configuration file $file: $!" ) );
291 0           $fh->binmode( ':utf8' );
292 0           my $data = join( '', $fh->getlines );
293 0           $fh->close;
294 0           try
295 1     1   321 {
  0            
  0            
  0            
296 0           my $json = JSON->new->relaxed->decode( $data );
297 0           $self->{conf_data} = $json;
298 0           $self->{conf_file} = $file;
299             }
300             catch( $e )
301 1 0   1   24839 {
  0            
  0            
  0            
  0            
302 0           return( $self->error( "An error occured while json decoding configuration file $file: $e" ) );
303             }
304 0           }
305 0           return( $self->{conf_data} );
306             }
307              
308 0     0 1   sub cookie_file { return( shift->_set_get_scalar( 'cookie_file', @_ ) ); }
309              
310             sub data2json
311             {
312 0     0 1   my $self = shift( @_ );
313 0           my $data = shift( @_ );
314 0           my $unescape = shift( @_ );
315 0 0         return( $self->error( "No data provided to decode into json." ) ) if( !length( $data ) );
316 0 0         if( $unescape )
317             {
318 0           $data =~ s/\\\\r\\\\n/\n/gs;
319 0           $data =~ s/^\"|\"$//gs;
320 0           $data =~ s/\"\[|\]\"//gs;
321             }
322 0           my $json;
323 0           try
324 1     1   776 {
  0            
  0            
  0            
325 0           $json = $self->json->decode( $data );
326             }
327             catch( $e )
328 1 0   1   23780 {
  0            
  0            
  0            
  0            
329 0           $self->message( 3, "An error occured while trying to decode json: $e" );
330 0           my $tmpdir = $self->temp_dir;
331 0           my $file = File::Temp::mktemp( "$tmpdir/json-XXXXXXX" );
332 0           $file .= '.js';
333 0   0       my $io = IO::File->new( ">$file" ) || return( $self->error( "Unable to write to file $file: $!" ) );
334 0           $io->binmode( ":utf8" );
335 0           $io->autoflush( 1 );
336 0 0         $io->print( $data ) || return( $self->error( "Unable to write data to json file $file: $!" ) );
337 0           $io->close;
338 0           chmod( 0666, $file );
339 0           return( $self->error( sprintf( "An error occured while attempting to parse %d bytes of data into json: $e\nFailed raw data was saved in file $file", length( $data ) ) ) );
340             }
341 0           return( $json );
  0            
342             }
343              
344             sub debug_log_file
345             {
346 0     0 0   my $self = shift( @_ );
347 0 0         if( @_ )
348             {
349 0           my $file = shift( @_ );
350 0 0 0       return( $self->error( "Debug log file \"$file\" exists, but is not writable. Please check permissions." ) ) if( -e( $file ) && !-w( $file ) );
351 0   0       my $fh = IO::File->new( ">>$file" ) || return( $self->error( "Unable to open debug log file \"$file\" in append mode: $!" ) );
352             ## print( STDERR ref( $self ), "::debug_log_file() opened log file \"$file\" in append mode with io $fh\n" );
353 0           $fh->binmode( ':utf8' );
354 0           $fh->autoflush( 1 );
355 0           $self->log_io( $fh );
356 0           $self->{debug_log_file} = $file;
357             }
358 0           return( $self->{debug_log_file} );
359             }
360              
361 0     0 0   sub download_uri { return( shift->_set_get_uri( 'dl_uri', @_ ) ); }
362              
363             sub generate_uuid
364             {
365 0     0 1   return( shift->{ug}->create_str );
366             }
367              
368             sub handler
369             {
370 0     0 0   my $self = shift( @_ );
371 0           my $handlers = $self->{ '_handlers' };
372 0 0         if( @_ )
373             {
374 0 0         if( scalar( @_ ) == 1 )
    0          
375             {
376 0           my $name = shift( @_ );
377 0 0         return( $self->error( "Handler $name is not a recognised handler." ) ) if( !Net::API::Telegram::Update->can( $name ) );
378 0           return( $handlers->{ $name } );
379             }
380             elsif( scalar( @_ ) % 2 )
381             {
382 0           return( $self->error( sprintf( "Wrong number of parameters (%d) provided to set handlers.", scalar( @_ ) ) ) );
383             }
384             else
385             {
386 0           my $args = { @_ };
387 0           foreach my $name ( keys( %$args ) )
388             {
389 0 0         return( $self->error( "Handler provided for $name is not a subroutine reference. Use something like \&some_routine or sub{ 'some code here' } as handler." ) ) if( ref( $args->{ $name } ) ne 'CODE' );
390 0           $handlers->{ $name } = $args->{ $name };
391             }
392             }
393             }
394 0           return( $handlers );
395             }
396              
397 0     0 0   sub json { return( shift->_set_get_object( 'json', 'JSON', @_ ) ); }
398              
399             sub launch_daemon
400             {
401 0     0 1   my $self = shift( @_ );
402 0           my( $pack, $file, $line ) = caller;
403 0           $self->message( 3, "Called from package $pack in file $file at line $line" );
404             my $params =
405             {
406 0   0       LocalPort => $self->{port} || DEFAULT_PORT,
407             ReuseAddr => 1,
408             };
409 0 0         $params->{LocalAddr} = $self->{host} if( length( $self->{host} ) );
410 0           $params->{Debug} = $self->debug;
411             #$params->{LocalAddr} ||= 'localhost';
412 0           my $httpd;
413 0 0         if( $self->{use_ssl} )
414             {
415 0     0     $self->message( 3, "Launching the HTTP ssl daemon with parameters ", sub{ $self->dumper( $params ) } );
  0            
416 0 0         return( $self->error( "No ssl key specified." ) ) if( !$self->{ssl_key} );
417 0 0         return( $self->error( "No ssl certificate specified." ) ) if( !$self->{ssl_cert} );
418 0 0         return( $self->error( "SSL key specified $self->{ssl_key} does not exist." ) ) if( !-e( $self->{ssl_key} ) );
419 0 0         return( $self->error( "SSL certificate specified $self->{ssl_cert} does not exist." ) ) if( !-e( $self->{ssl_cert} ) );
420 0 0         return( $self->error( "SSL key specified $self->{ssl_key} is not readable." ) ) if( !-e( $self->{ssl_key} ) );
421 0 0         return( $self->error( "SSL certificate specified $self->{ssl_cert} is not readable." ) ) if( !-e( $self->{ssl_cert} ) );
422 0           $params->{SSL_key_file} = $self->{ssl_key};
423 0           $params->{SSL_cert_file} = $self->{ssl_cert};
424 0   0       $httpd = HTTP::Daemon::SSL->new( %$params ) || return( $self->error( "Could not launch the HTTP daemon: $!" ) );
425             }
426             else
427             {
428 0     0     $self->message( 3, "Launching the HTTP daemon with parameters ", sub{ $self->dumper( $params ) } );
  0            
429 0   0       $httpd = HTTP::Daemon->new( %$params ) || return( $self->error( "Could not launch the HTTP daemon: $!" ) );
430             #$httpd = HTTP::Daemon->new( %$params ) || return( $self->error( "Could not launch the HTTP daemon: $!" ) );
431             }
432 0           $self->{httpd} = $httpd;
433             }
434              
435             sub log
436             {
437 0     0 0   my $self = shift( @_ );
438 0 0         if( $_[0] =~ /^\d{1,2}$/ )
439             {
440 0 0         if( $_[0] < $self->{debug} )
441             {
442 0           return;
443             }
444             ## Make sure to remove this arguement
445             else
446             {
447 0           shift( @_ );
448             }
449             }
450 0           my @msg = @_;
451             # $self->message( 1, @msg ) if( -t( STDIN ) );
452 0           my( $pack, $file, $line ) = caller;
453 0           $self->message( 3, "Called from package $pack in file $file at line $line" );
454 0           my @time = localtime();
455 0           my $tz = DateTime::TimeZone->new( 'name' => 'local' );
456 0           my $dt = DateTime->from_epoch( epoch => time(), time_zone => $tz->name );
457 0           my $stamp = $dt->strftime( '[%Y/%m/%d %H:%M:%S]' );
458              
459 0 0 0       if( Scalar::Util::blessed( $msg[0] ) && $msg[0]->isa( 'Net::API::Telegram::Message' ) )
460             {
461 0           my $msg = $msg[0];
462 0   0       my $name = $msg->chat->title
463             || $msg->chat->username
464             || ( $msg->from ? join( ' ', $msg->from->first_name, $msg->from->last_name ) : 'unknown' );
465              
466 0 0 0       if( $self->{logging} && ( $self->{log_file} || $self->{_log_io} ) )
      0        
467             {
468 0           my $log_io;
469 0 0         if( $self->{_log_io} )
470             {
471 0           $log_io = $self->{_log_io};
472             }
473             else
474             {
475 0   0       $log_io = $self->{_log_io} = IO::File->new( ">>$self->{log_file}" ) || return( $self->error( "Unable to open log file $self->{log_file} in append mode: $!" ) );
476 0           $log_io->binmode( ':utf8' );
477             }
478 0 0         $log_io->printf( "${stamp}: %s\n", $msg->text ) || return( $self->error( "Unable to print to log file $self->{log_file}: $!" ) );
479             }
480 0 0         $stamp .= "<$name> " if( $msg->chat->title );
481 0           $self->messagef( 1, "${stamp}: %s", $msg->text );
482             }
483             else
484             {
485 0           my $msg = join( '', @_ );
486 0           $self->message( 1, "${stamp}: $msg" );
487             }
488 0           return( $self );
489             }
490              
491             sub port
492             {
493 0     0 1   my $self = shift( @_ );
494 0 0         if( @_ )
495             {
496 0           my $v = shift( @_ );
497 0 0         if( $v !~ /^(?:443|80|88|8443)$/ )
498             {
499 0           return( $self->error( "Illegal port number. Acceptable port numbers are: 443, 80, 88 or 8443. See https://core.telegram.org/bots/api#setwebhook for more information." ) );
500             }
501 0           $self->{port} = $v;
502             }
503 0           return( $self->{port} );
504             }
505              
506             sub query
507             {
508 0     0 1   my $self = shift( @_ );
509 0           my $opts = shift( @_ );
510 0 0         return( $self->error( "Parameter provided ($opts) is not a hash reference" ) ) if( ref( $opts ) ne 'HASH' );
511 0           my( $uri, $headers, $data, $req, $resp );
512 0 0         if( $opts->{uri} )
    0          
513             {
514 0           $uri = URI->new( $opts->{uri} );
515             }
516             elsif( $opts->{method} )
517             {
518 0           $uri = URI->new( $self->api_uri . "/$opts->{method}" );
519             }
520 0 0         if( !$opts->{headers} )
521             {
522 0           $headers = HTTP::Headers->new;
523             }
524             else
525             {
526 0           $headers = $opts->{headers};
527             }
528 0 0         $data = $opts->{data} if( length( $opts->{data} ) );
529            
530 0 0         if( $data->{certificate} )
    0          
531             {
532 0           my( $baseName, $cert );
533             ## Or possibly application/x-pem-file ?
534 0           my $type = 'application/x-x509-ca-cert';
535 0 0         if( Scalar::Util::blessed( $data->{certificate} ) )
    0          
536             {
537 0           my $obj = $data->{certificate};
538 0 0         return( $self->error( "File object is not an Net::API::Telegram::InputFile object." ) ) if( !$obj->isa( 'Net::API::Telegram::InputFile' ) );
539 0   0       $baseName = $obj->filename || 'certificate.pem';
540 0           $cert = $obj->content;
541             }
542             elsif( -f( $data->{certificate} ) )
543             {
544 0           $baseName = File::Basename::basename( $data->{certificate} );
545 0   0       $cert = $self->_load_file( $data->{certificate} ) || return( $self->error( "Unable to load the ssl certificate $data->{certificate}" ) );
546             }
547             else
548             {
549 0           return( $self->error( "Certificate was provided as parameter, but I am clueless about what do with it. It is not a file nor a Net::API::Telegram::InputFile object." ) );
550             }
551 0           $data->{certificate} = [ undef(), $baseName, 'Content-Type' => $type, 'Content' => $cert ];
552 0           $req = $opts->{request} = HTTP::Request::Common::POST( $uri, 'Content-Type' => 'form-data', 'Content' => $data );
553             }
554             elsif( !$opts->{request} )
555             {
556 0 0         if( $self->{encode_with_json} )
557             {
558 0           $self->message( 3, "Encapsulating query using json payload" );
559 0           my $payload = $self->json->utf8->encode( $data );
560 0           $self->message( 3, "Payload is now: $payload" );
561 0           $headers->header( 'Content-Type' => 'application/json; charset=utf-8' );
562 0           $req = HTTP::Request->new( 'POST', $uri, $headers, $payload );
563             }
564             else
565             {
566 0           my $u = URI->new( $self->api_uri );
567 0           $u->query_form( $data );
568 0           $req = HTTP::Request->new( 'POST', $uri, $headers, $u->query );
569             }
570             }
571             else
572             {
573 0           $req = $opts->{request};
574             }
575             #print( STDERR ref( $self ), "::query(): stopping here for debug\n" );
576             #exit( 0 );
577            
578 0 0         if( !length( $req->header( 'Content-Type' ) ) )
579             {
580 0 0 0       if( $opts->{encode_with_json} || $self->encode_with_json )
581             {
582 0           $req->header( 'Content-Type' => 'application/json' );
583             }
584             else
585             {
586 0           $req->header( 'Content-Type' => 'application/x-www-form-urlencoded' );
587             }
588             }
589 0           $req->header( 'Accept' => 'application/json' );
590 0           $self->message( 3, "Post request is: ", $req->as_string );
591 0           my $agent = $self->agent;
592 0           try
593 1     1   2905 {
  0            
  0            
  0            
594 0           $resp = $agent->request( $req );
595 0           $self->{ 'http_request' } = $req;
596 0           $self->{ 'http_response' } = $resp;
597             ## if( $resp->code == 200 )
598 0 0         if( $resp->is_success )
599             {
600 0           $self->message( 3, "Request successful, decoding its content" );
601 0           my $hash = $self->json->utf8->decode( $resp->decoded_content );
602 0     0     $self->message( 3, "Returning $hash: ", sub{ $self->dumper( $hash ) } );
  0            
603 0           return( $hash );
604             }
605             else
606             {
607 0           $self->messagef( 3, "Request failed with error %s", $resp->message );
608 0 0         if( $resp->header( 'Content_Type' ) =~ m{text/html} )
609             {
610 0           return( $sef->error({
611             code => $resp->code,
612             type => $resp->message,
613             message => $resp->message
614             }) );
615             }
616             else
617             {
618 0           my $hash = $self->json->utf8->decode( $resp->decoded_content );
619 0     0     $self->message( 3, "Error returned by Telegram is: ", sub{ $self->dumper( $hash ) } );
  0            
620 0           $self->message( 3, "Creating error from Telegram error $hash->{description}" );
621 0           $hash->{message} = delete( $hash->{description} );
622 0           $hash->{code} = delete( $hash->{error_code} );
623 0   0       return( $self->error( $hash->{ 'error' } // $hash ) );
624             }
625             }
626             }
627             catch
628 1 0   1   623 {
  0            
  0            
  0            
629 0           $self->message( 3, "Returning error $_" );
630 0 0         return( $self->error({
631             'type' => "Could not decode HTTP response: $_",
632             $resp
633             ? ( 'message' => $resp->status_line . ' - ' . $resp->content )
634             : (),
635             }) );
636 0           };
637             }
638              
639             sub start
640             {
641 0     0 1   my $self = shift( @_ );
642 0           my $httpd = $self->{httpd};
643 0           my $json = $self->{json};
644            
645             local $reaper = sub
646             {
647 0     0     local $!;
648 0           my $child;
649             my $waitedpid;
650             ##while( ( $waitedpid = waitpid( -1, WNOHANG ) ) > 0 && WIFEXITED( $? ) )
651 0           while( ( $waitedpid = waitpid( -1, WNOHANG ) ) > 0 )
652             {
653 0 0         if( my $start = $CHILDREN->{ $waitedpid } )
654             {
655 0           my $interval = Time::HiRes::tv_interval( $start );
656 0           delete( $CHILDREN->{ $waitedpid } );
657 0           my( $user, $system, $cuser, $csystem ) = times();
658 0 0         $self->log( "Child $waitedpid ending", ($? ? " with exit $?" : ''), " with user time $user and system time $system. It took $interval seconds." );
659             }
660             else
661             {
662 0 0         $self->log( "Reaped $waitedpid" . ($? ? " with exit $?" : '') );
663             }
664             }
665             ## loathe sysV
666 0           $SIG{ 'CHLD' } = $reaper;
667 0           return;
668 0           };
669 0           local $SIG{ 'CHLD' } = $reaper;
670            
671             local $SIG{ 'INT' } = sub
672             {
673 0     0     my $sig = @_;
674 0           $self->message( 3, "Called with signal $sig" );
675 0           $self->cleanup;
676 0           exit( 0 );
677 0           };
678 0           local $SIG{ 'TERM' } = $SIG{ 'INT' };
679 0           local $SIG{ 'ABRT' } = $SIG{ 'INT' };
680 0           local $SIG{ 'QUIT' } = $SIG{ 'INT' };
681             local $SIG{ '__DIE__' } = sub
682             {
683 0     0     my( $pack, $file, $line ) = caller;
684 0           $self->message( 3, "Fatal error triggered from package $pack in file $file at line $line" );
685 0           $self->error( join( '', @_ ) );
686 0           my $trace = $self->error->trace;
687 0           $self->log( "Fatal error, terminating. ", @_, "\n$trace\n" );
688 0           $TIME_TO_DIE++;
689 0           $self->cleanup;
690 0           exit( 1 );
691 0           };
692 0           my $start_time = [Time::HiRes::gettimeofday()];
693 0           my $tz = DateTime::TimeZone->new( 'name' => 'local' );
694 0           my $start = $self->{start_time} = DateTime->from_epoch(
695             epoch => $start_time->[0],
696             time_zone => $tz->name,
697             );
698 0           my $check_messages_after;
699 0 0         if( Scalar::Util::blessed( $self->{skip_past_messages} ) )
    0          
700             {
701 0           $check_messages_after = $self->{skip_past_messages};
702             }
703             elsif( $self->{skip_past_messages} < 0 )
704             {
705 0           $check_messages_after = $start->clone->subtract( seconds => abs( $self->{skip_past_messages} ) );
706 0           $self->message( 3, "Will check messages only from $check_messages_after onward" );
707             }
708 0           my $handlers = $self->{ '_handlers' };
709            
710 0           my $out = IO::File->new;
711 0           my $err = IO::File->new;
712 0           my $in = IO::File->new;
713 0           $out->fdopen( fileno( STDOUT ), 'w' );
714 0           $out->binmode( ':utf8' );
715 0           $out->autoflush( 1 );
716 0           $err->fdopen( fileno( STDERR ), 'w' );
717 0           $err->binmode( ':utf8' );
718 0           $err->autoflush( 1 );
719 0           $in->fdopen( fileno( STDIN ), 'r' );
720 0           $in->binmode( ':utf8' );
721 0           my $log_io = $self->{_log_io};
722 0 0         if( $self->{webhook} )
723             {
724 0           $self->message( 3, "Starting the daemon using webhook" );
725 0 0         return( $self->error( "HTTP daemon object is gone!" ) ) if( !$httpd );
726             #my $uri = URI->new( ( $self->{use_ssl} ? 'https' : 'http' ) . '://' . $self->{host} );
727 0           my $uri = URI->new( $httpd->url );
728 0 0 0       $uri->scheme( 'https' ) if( $self->{use_ssl} || $self->{external_ssl} );
729 0           $self->{host} = $uri->host;
730 0 0         if( $self->{external_host} )
731             {
732 0           $uri->host( $self->{external_host} );
733             }
734 0 0         if( $self->{external_port} )
    0          
735             {
736 0           $uri->port( $self->{external_port} );
737             }
738             elsif( $self->port )
739             {
740 0           $uri->port( $self->port );
741             }
742 0           $self->message( 3, "Webhook path is: $self->{webhook_path}" );
743 0 0         $uri->path( ( $self->{external_path} ? $self->{external_path} : '' ) . $self->{webhook_path} );
744 0           $self->{webhook_uri} = $uri;
745 0           $self->{pid} = $$;
746 0           $self->message( 3, "Accepting webhooks connections on port $self->{port} with uri $uri from pid $$" );
747             my $params =
748             {
749             url => $uri,
750             ## Simultaneous connections. Since this is not threaded, we accept only one
751 0   0       max_connections => ( $self->{max_connections} || 1 ),
752             };
753 0 0 0       if( $self->{use_ssl} && $self->{ssl_cert} )
754             {
755 0           $params->{certificate} = $self->{ssl_cert};
756             }
757             ## Inform Telegram of our bot webhook url
758 0 0         $self->setWebhook( $params ) || return( $self->error( "Unable to set the webhook with Telegram: ", $self->error ) );
759             ## For additional security, we should check the remote ip
760             ## Telegram webhook documentation tells us their requests originate from a subnet from either 149.154.160.0/20 or 91.108.4.0/22 and on ports 443, 80, 88, or 8443
761             ## https://core.telegram.org/bots/webhooks
762             ## while( my $client = $httpd->accept )
763 0           my $client;
764 0           my $loopback = Net::IP->new( '127.0.0.1' );
765 0   0       while( !$self->{_stop_daemon} && !$TIME_TO_DIE )
766             {
767             ## Set when we receive signals
768             ## last if( $self->{_stop_daemon} );
769             $client = $httpd->accept || do
770 0   0       {
771             $self->log( "Unable to accept queries on tcp port $self->{port}" );
772             ## https://www.perlmonks.org/bare/?node_id=244384
773             next if( $! == EINTR );
774             warn( "Error on accept: $!\n" );
775             next;
776             };
777             ## XXX Temporary
778             # $client->debug( 3 );
779            
780 0           $client->autoflush( 1 );
781 0           my $pid = POSIX::getpid();
782 0 0         if( !defined( $pid = fork() ) )
    0          
783             {
784 0           $self->log( "Cannot fork child process: $!" );
785             }
786             ## Parent process
787             elsif( $pid )
788             {
789 0           $self->log( "Received an incoming connection, forking to $pid" );
790 0           $CHILDREN->{ $pid } = [Time::HiRes::gettimeofday()];
791 0           $pid = POSIX::getpid();
792 0           $client->close();
793 0           waitpid( $pid, 0 );
794 0           sleep( 0.1 );
795             }
796             ## Child process == 0
797             else
798             {
799             ## Close STDIN, STDOUT and STDERR
800 0           $in->close;
801 0           $out->close;
802 0           $err->close;
803 0 0         $log_io->close if( $log_io );
804             ## Then, re-open them
805 0           $out->fdopen( fileno( STDOUT ), 'w' );
806 0           $out->binmode( ':utf8' );
807 0           $out->autoflush( 1 );
808 0           $err->fdopen( fileno( STDERR ), 'w' );
809 0           $err->binmode( ':utf8' );
810 0           $err->autoflush( 1 );
811 0           $in->fdopen( fileno( STDIN ), 'r' );
812 0           $in->binmode( ':utf8' );
813            
814 0           $httpd->close();
815 0           $pid = POSIX::getpid();
816 0           $self->log( "Child answering on socket with pid $pid" );
817             ## Processing here
818 0           my $req;
819 0           my $ip_check = 0;
820 0           REQUEST: while( $req = $client->get_request )
821             {
822 0           my $remote_addr;
823 0 0         if( $req->header( 'X-Forwarded-For' ) )
824             {
825 0           $remote_addr = Net::IP->new( $req->header( 'X-Forwarded-For' ) );
826             }
827             else
828             {
829 0           $remote_addr = Net::IP->new( Socket::inet_ntoa( $client->peeraddr ) );
830             }
831 0           $self->message( 3, "Connection received from $remote_addr" );
832             ## First Check the IP
833 0 0         if( !$ip_check )
834             {
835 0           $ip_check++;
836 0           $self->messagef( 3, "Remote address is: '%s'.", $remote_addr->ip );
837 0           my $ok_ips = $self->authorised_ips;
838 0 0         if( scalar( @$ok_ips ) )
839             {
840 0           $ip_is_authorised = 0;
841 0 0         if( $remote_addr->overlaps( $loopback ) == $Net::IP::IP_IDENTICAL )
842             {
843 0           $ip_is_authorised++;
844             }
845             else
846             {
847 0           IP_BLOCK_CHECKED: foreach my $block ( @$ok_ips )
848             {
849             ## We found an overlap, we're good.
850 0 0         if( !( $remote_addr->overlaps( $block ) == $Net::IP::IP_NO_OVERLAP ) )
851             {
852 0           $ip_is_authorised++, last IP_BLOCK_CHECKED;
853             }
854             }
855             }
856             }
857             }
858            
859 0           my $uri = $req->uri;
860 0 0         if( $uri->path ne $self->{webhook_path} )
861             {
862 0           $client->send_response( HTTP::Response->new( 404 ) );
863 0           last;
864             }
865             ## We need to send back a reply to Telegram quicly or Telegram will issue a "read timeout" error and will re-send the message
866 0           $self->message( 3, "Returning http code 200 to Telegram." );
867 0           $client->send_response( HTTP::Response->new( 200 ) );
868 0           my $res = $self->data2json( $req->decoded_content );
869 0           $client->close();
870            
871 0     0     $self->message( 3, "Data received: ", sub{ $self->dumper( $res ) } );
  0            
872             my $upd = $self->_response_to_object( 'Net::API::Telegram::Update', $res ) || do
873 0   0       {
874             $self->message( 1, "Error trying to instantiate object Net::API::Telegram::Update: ", $self->error->message );
875             $self->error( "Could not create a Net::API::Telegram::Update with following data: " . $self->dumper( $res ) );
876             $client->send_response( HTTP::Response->new( 500 ) );
877             next;
878             };
879             ## Get the Webhook information for possible error
880 0           my $info = $self->getWebhookInfo;
881 0           $self->messagef( 3, "WebHookInfo returned:\nallowed_updates: %s\nhas_custom_certificate: %s\nlast_error_date: %s\nlast_error_message: %s\nmax_connections: %s\npending_update_count: %s\nurl: %s", $info->allowed_updates, $info->has_custom_certificate, $info->last_error_date, $info->last_error_message, $info->max_connections, $info->pending_update_count, $info->url );
882 0 0         if( length( $info->last_error_message ) )
883             {
884 0           my $err_time = $info->last_error_date;
885 0           $self->error( sprintf( "Warning only: webhook error occured on $err_time: %s", $info->last_error_message ) );
886             }
887 0 0         my $msg_epoch = $upd->message->date if( $upd->message );
888 0 0 0       if( !$self->{skip_past_messages} ||
      0        
      0        
      0        
      0        
889             ( $check_messages_after && $msg_epoch && $msg_epoch > $check_messages_after ) ||
890             ( $msg_epoch && $msg_epoch > $start ) )
891             {
892 0           my $msg = $upd->message;
893 0           $self->log( $msg );
894             ## return( $msg );
895 0           $self->message( 3, "Checking for handler." );
896 0           foreach my $k ( keys( %$res ) )
897             {
898 0 0         next if( !exists( $handlers->{ $k } ) );
899 0           my $v = $upd->$k;
900 0           my $code = $handlers->{ $k };
901 0 0         next if( ref( $code ) ne 'CODE' );
902 0           $self->message( 3, "Calling handler $k" );
903 0           alarm( $self->{timeout} );
904             eval
905 0           {
906             local $SIG{ 'ALRM' } = sub
907             {
908             ## Gateway Timeout
909 0     0     die( "Timeout\n" );
910 0           };
911 0           $code->({
912             'request' => $req,
913             'payload' => $res,
914             ## Overall update object
915             'update' => $upd,
916             ## $v could be empty. This is to the handler to decide what to do with it
917             'object' => $v,
918             ## We send also our Telegram object so the handler can call us like $t->sendMessage
919             'tg' => $self,
920             });
921             };
922 0           alarm( 0 );
923 0 0         if( $@ =~ /timeout/i )
    0          
924             {
925             ## $client->send_response( HTTP::Response->new( 504 ) );
926 0           $self->message( 3, "Timeout while calling handler $k" );
927 0           warn( "Timeout while calling handler $k\n" );
928 0           next REQUEST;
929             }
930             elsif( $@ )
931             {
932 0           $self->error( $@ );
933 0           my $trace = $self->error->trace;
934 0           $self->message( 3, "Error while calling handler $k: $trace" );
935             ## $client->send_response( HTTP::Response->new( 500 ) );
936 0           warn( "Error while calling handler $k: $@\n" );
937 0           next REQUEST;
938             }
939             }
940             ## $client->send_response( HTTP::Response->new( 200 ) );
941             }
942             else
943             {
944             ## $client->send_response( HTTP::Response->new( 200 ) );
945 0           next;
946             }
947             }
948 0           undef( $client );
949 0           exit( 0 );
950             }
951             }
952 0           my $interval = Time::HiRes::tv_interval( $start_time );
953 0           my( $user, $system, $cuser, $csystem ) = CORE::times();
954 0           $self->message( 3, "Webhook http daemon took user time $user and system time $system. It took $interval seconds." );
955             }
956             else
957             {
958 0           $self->message( 3, "Starting the polling." );
959 0           my $start_time = [Time::HiRes::gettimeofday()];
960 0   0       my $poll_interval = ( $self->{poll_interval} || 10 );
961 0           POLL: while( 1 )
962             {
963 0 0         last if( $self->{_stop_polling} );
964 0           $self->message( 3, "Fetching update with office $self->{offset}" );
965             my $all = $self->getUpdates( offset => $self->{offset} ) || do
966 0   0       {
967             $self->error( "Error while trying to get update: ", $self->error->message );
968             sleep( 1 );
969             next;
970             };
971             # my $results = $res->{result};
972             # $self->message( 3, "Result received frm Telegram: ", sub{ $self->dumper( $results ) } );
973             # my $all = $self->_response_array_to_object( 'Net::API::Telegram::Update', $results ) || do
974             # {
975             # $self->error( "Unable to get the objects for data received: ", sub{ $self->dumper( $results ) } );
976             # next;
977             # };
978 0           $self->messagef( 3, "Found %d updates received.", scalar( @$all ) );
979 0           REQUEST: foreach my $upd ( @$all )
980             {
981 0           $self->{offset} = $upd->update_id + 1;
982 0 0         my $msg_epoch = $upd->message->date if( $upd->message );
983 0           $self->messagef( 3, "Checking update id %s with time $msg_epoch", $upd->update_id );
984 0 0 0       if( !$self->{skip_past_messages} ||
      0        
      0        
      0        
      0        
985             ( $check_messages_after && $msg_epoch && $msg_epoch > $check_messages_after ) ||
986             ( $msg_epoch && $msg_epoch > $start ) )
987             {
988 0           my $msg = $upd->message;
989 0           $self->log( $msg );
990             ## return( $msg );
991 0           $self->message( 3, "Checking for handler." );
992 0           foreach my $k ( keys( %$res ) )
993             {
994 0 0         next if( !exists( $handlers->{ $k } ) );
995 0           my $v = $upd->$k;
996 0           my $code = $handlers->{ $k };
997 0 0         next if( ref( $code ) ne 'CODE' );
998 0           $self->message( 3, "Calling handler $k" );
999 0           alarm( $self->{timeout} );
1000             eval
1001 0           {
1002             local $SIG{ 'ALRM' } = sub
1003             {
1004             ## Gateway Timeout
1005 0     0     die( "Timeout\n" );
1006 0           };
1007 0           $code->({
1008             'request' => $req,
1009             'payload' => $res,
1010             ## Overall update object
1011             'update' => $upd,
1012             ## $v could be empty. This is to the handler to decide what to do with it
1013             'object' => $v,
1014             });
1015             };
1016 0           alarm( 0 );
1017 0 0         if( $@ =~ /timeout/i )
    0          
1018             {
1019 0           next REQUEST;
1020             }
1021             elsif( $@ )
1022             {
1023 0           $self->message( 3, "Error while calling handler: $@" );
1024 0           next REQUEST;
1025             }
1026             }
1027             }
1028             }
1029             ## Sleep a few before doing next query
1030 0           $self->message( 3, "Sleeping $poll_interval seconds." );
1031 0           sleep( $poll_interval );
1032             }
1033 0           my $interval = Time::HiRes::tv_interval( $start_time );
1034 0           my( $user, $system, $cuser, $csystem ) = CORE::times();
1035 0           $self->message( 3, "Polling took user time $user and system time $system. It took $interval seconds." );
1036             }
1037 0           return;
1038             }
1039              
1040             sub stop
1041             {
1042 0     0 0   my $self = shift( @_ );
1043 0 0         if( $self->{webhook} )
1044             {
1045 0           foreach my $kid ( keys( %$CHILDREN ) )
1046             {
1047             ## reap them
1048 0 0         $self->log( "Failed to reap child pid: $kid" ) unless( kill(+ 9, $kid ) );
1049             }
1050 0 0         $self->deleteWebhook || return( $self->error( "Unable to remove webhook: ", $self->error ) );
1051 0           $self->{_stop_daemon}++;
1052             }
1053             else
1054             {
1055 0           $self->{_stop_polling}++;
1056             }
1057 0           return( $self );
1058             }
1059              
1060 0     0 0   sub temp_dir { return( shift->_set_get_scalar( 'temp_dir', @_ ) ); }
1061              
1062             sub timeout
1063             {
1064 0     0 1   my $self = shift( @_ );
1065 0 0         if( @_ )
1066             {
1067 0           my $v = shift( @_ );
1068 0 0 0       return( $self->error( "Invalid timeout value '$v'. I was expecting an integer or undefined" ) ) if( defined( $v ) && $v !~ /^\d+$/ );
1069 0 0         $v = 0 if( !defined( $v ) );
1070 0           $self->{timeout} = $v;
1071             }
1072 0           return( $self->{timeout} );
1073             }
1074              
1075 0     0 1   sub verbose { return( shift->_set_get( 'verbose', @_ ) ); }
1076              
1077             sub webhook
1078             {
1079 0     0 1   my $self = shift( @_ );
1080 0 0         if( @_ )
1081             {
1082 0           my $v = shift( @_ );
1083 0           $self->{webhook} = $v;
1084 0 0         if( $v )
1085             {
1086 0           $self->message( 3, "Launching daemon..." );
1087 0 0         $self->launch_daemon if( !$self->{ 'httpd' } );
1088 0           $self->{webhook_path} = '/' . lc( $self->generate_uuid );
1089             }
1090             else
1091             {
1092 0           undef( $self->{ 'httpd' } );
1093             }
1094             }
1095 0           return( $self->{webhook} );
1096             }
1097              
1098             ## DO NOT REMOVE THIS LINE
1099             ## START DYNAMICALLY GENERATED METHODS
1100             sub answerCallbackQuery
1101             {
1102 0     0 1   my $self = shift( @_ );
1103 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1104 0 0         return( $self->error( "Missing parameter callback_query_id" ) ) if( !exists( $opts->{ 'callback_query_id' } ) );
1105 0           my $form = $self->_options2form( $opts );
1106 0   0       my $hash = $self->query({
1107             'method' => 'answerCallbackQuery',
1108             'data' => $form,
1109             }) || return( $self->error( "Unable to make post query for method answerCallbackQuery: ", $self->error->message ) );
1110 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1111             {
1112 0           return( $self->error( $t_error ) );
1113             }
1114             else
1115             {
1116 0           return( $hash->{ok} );
1117             }
1118             }
1119              
1120             sub answerInlineQuery
1121             {
1122 0     0 1   my $self = shift( @_ );
1123 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1124 0 0         return( $self->error( "Missing parameter inline_query_id" ) ) if( !exists( $opts->{ 'inline_query_id' } ) );
1125 0 0         return( $self->error( "Missing parameter results" ) ) if( !exists( $opts->{ 'results' } ) );
1126 0 0         return( $self->error( "Value provided for results is not an array reference." ) ) if( ref( $opts->{ 'results' } ) ne 'ARRAY' );
1127 0 0         return( $self->error( "Value provided is not an array of either of this objects: InlineQueryResult" ) ) if( !$self->_param_check_array_object( qr/^(?:Net::API::Telegram::InlineQueryResult)$/, @_ ) );
1128 0 0         $self->_load( [qw( Net::API::Telegram::InlineQueryResult )] ) || return( undef() );
1129 0           my $form = $self->_options2form( $opts );
1130 0   0       my $hash = $self->query({
1131             'method' => 'answerInlineQuery',
1132             'data' => $form,
1133             }) || return( $self->error( "Unable to make post query for method answerInlineQuery: ", $self->error->message ) );
1134 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1135             {
1136 0           return( $self->error( $t_error ) );
1137             }
1138             else
1139             {
1140 0           return( $hash->{ok} );
1141             }
1142             }
1143              
1144             sub answerPreCheckoutQuery
1145             {
1146 0     0 1   my $self = shift( @_ );
1147 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1148 0 0         return( $self->error( "Missing parameter ok" ) ) if( !exists( $opts->{ 'ok' } ) );
1149 0 0         return( $self->error( "Missing parameter pre_checkout_query_id" ) ) if( !exists( $opts->{ 'pre_checkout_query_id' } ) );
1150 0           my $form = $self->_options2form( $opts );
1151 0   0       my $hash = $self->query({
1152             'method' => 'answerPreCheckoutQuery',
1153             'data' => $form,
1154             }) || return( $self->error( "Unable to make post query for method answerPreCheckoutQuery: ", $self->error->message ) );
1155 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1156             {
1157 0           return( $self->error( $t_error ) );
1158             }
1159             else
1160             {
1161 0           return( $hash->{ok} );
1162             }
1163             }
1164              
1165             sub answerShippingQuery
1166             {
1167 0     0 1   my $self = shift( @_ );
1168 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1169 0 0         return( $self->error( "Missing parameter ok" ) ) if( !exists( $opts->{ 'ok' } ) );
1170 0 0 0       return( $self->error( "Value provided for shipping_options is not an array reference." ) ) if( length( $opts->{ 'shipping_options' } ) && ref( $opts->{ 'shipping_options' } ) ne 'ARRAY' );
1171 0 0 0       return( $self->error( "Value provided is not an array of either of this objects: ShippingOption" ) ) if( length( $opts->{ 'shipping_options' } ) && !$self->_param_check_array_object( qr/^(?:Net::API::Telegram::ShippingOption)$/, @_ ) );
1172 0 0         return( $self->error( "Missing parameter shipping_query_id" ) ) if( !exists( $opts->{ 'shipping_query_id' } ) );
1173 0 0         $self->_load( [qw( Net::API::Telegram::ShippingOption )] ) || return( undef() );
1174 0           my $form = $self->_options2form( $opts );
1175 0   0       my $hash = $self->query({
1176             'method' => 'answerShippingQuery',
1177             'data' => $form,
1178             }) || return( $self->error( "Unable to make post query for method answerShippingQuery: ", $self->error->message ) );
1179 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1180             {
1181 0           return( $self->error( $t_error ) );
1182             }
1183             else
1184             {
1185 0           return( $hash->{ok} );
1186             }
1187             }
1188              
1189             sub createNewStickerSet
1190             {
1191 0     0 1   my $self = shift( @_ );
1192 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1193 0 0         return( $self->error( "Missing parameter emojis" ) ) if( !exists( $opts->{ 'emojis' } ) );
1194 0 0 0       return( $self->error( "Value provided for mask_position is not a Net::API::Telegram::MaskPosition object." ) ) if( length( $opts->{ 'mask_position' } ) && ref( $opts->{ 'mask_position' } ) ne 'Net::API::Telegram::MaskPosition' );
1195 0 0         return( $self->error( "Missing parameter name" ) ) if( !exists( $opts->{ 'name' } ) );
1196 0 0         return( $self->error( "Missing parameter png_sticker" ) ) if( !exists( $opts->{ 'png_sticker' } ) );
1197 0 0         return( $self->error( "Value provided for png_sticker is not a valid object. I was expecting one of the following: InputFile, String" ) ) if( ref( $opts->{ 'png_sticker' } ) !~ /^(?:Net::API::Telegram::InputFile)$/ );
1198 0 0         return( $self->error( "Missing parameter title" ) ) if( !exists( $opts->{ 'title' } ) );
1199 0 0         return( $self->error( "Missing parameter user_id" ) ) if( !exists( $opts->{ 'user_id' } ) );
1200 0 0         $self->_load( [qw( Net::API::Telegram::MaskPosition Net::API::Telegram::InputFile )] ) || return( undef() );
1201 0           my $form = $self->_options2form( $opts );
1202 0   0       my $hash = $self->query({
1203             'method' => 'createNewStickerSet',
1204             'data' => $form,
1205             }) || return( $self->error( "Unable to make post query for method createNewStickerSet: ", $self->error->message ) );
1206 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1207             {
1208 0           return( $self->error( $t_error ) );
1209             }
1210             else
1211             {
1212 0           return( $hash->{ok} );
1213             }
1214             }
1215              
1216             sub deleteChatPhoto
1217             {
1218 0     0 1   my $self = shift( @_ );
1219 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1220 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1221 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1222 0           my $form = $self->_options2form( $opts );
1223 0   0       my $hash = $self->query({
1224             'method' => 'deleteChatPhoto',
1225             'data' => $form,
1226             }) || return( $self->error( "Unable to make post query for method deleteChatPhoto: ", $self->error->message ) );
1227 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1228             {
1229 0           return( $self->error( $t_error ) );
1230             }
1231             else
1232             {
1233 0           return( $hash->{ok} );
1234             }
1235             }
1236              
1237             sub deleteChatStickerSet
1238             {
1239 0     0 1   my $self = shift( @_ );
1240 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1241 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1242 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1243 0           my $form = $self->_options2form( $opts );
1244 0   0       my $hash = $self->query({
1245             'method' => 'deleteChatStickerSet',
1246             'data' => $form,
1247             }) || return( $self->error( "Unable to make post query for method deleteChatStickerSet: ", $self->error->message ) );
1248 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1249             {
1250 0           return( $self->error( $t_error ) );
1251             }
1252             else
1253             {
1254 0           return( $hash->{ok} );
1255             }
1256             }
1257              
1258             sub deleteMessage
1259             {
1260 0     0 1   my $self = shift( @_ );
1261 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1262 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1263 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1264 0 0         return( $self->error( "Missing parameter message_id" ) ) if( !exists( $opts->{ 'message_id' } ) );
1265 0           my $form = $self->_options2form( $opts );
1266 0   0       my $hash = $self->query({
1267             'method' => 'deleteMessage',
1268             'data' => $form,
1269             }) || return( $self->error( "Unable to make post query for method deleteMessage: ", $self->error->message ) );
1270 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1271             {
1272 0           return( $self->error( $t_error ) );
1273             }
1274             else
1275             {
1276 0           return( $hash->{ok} );
1277             }
1278             }
1279              
1280             sub deleteStickerFromSet
1281             {
1282 0     0 1   my $self = shift( @_ );
1283 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1284 0 0         return( $self->error( "Missing parameter sticker" ) ) if( !exists( $opts->{ 'sticker' } ) );
1285 0           my $form = $self->_options2form( $opts );
1286 0   0       my $hash = $self->query({
1287             'method' => 'deleteStickerFromSet',
1288             'data' => $form,
1289             }) || return( $self->error( "Unable to make post query for method deleteStickerFromSet: ", $self->error->message ) );
1290 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1291             {
1292 0           return( $self->error( $t_error ) );
1293             }
1294             else
1295             {
1296 0           return( $hash->{ok} );
1297             }
1298             }
1299              
1300             sub deleteWebhook
1301             {
1302 0     0 1   my $self = shift( @_ );
1303 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1304 0           my $form = $self->_options2form( $opts );
1305 0   0       my $hash = $self->query({
1306             'method' => 'deleteWebhook',
1307             'data' => $form,
1308             }) || return( $self->error( "Unable to make post query for method deleteWebhook: ", $self->error->message ) );
1309 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1310             {
1311 0           return( $self->error( $t_error ) );
1312             }
1313             else
1314             {
1315 0           return( $hash->{ok} );
1316             }
1317             }
1318              
1319             sub editMessageCaption
1320             {
1321 0     0 1   my $self = shift( @_ );
1322 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1323 0 0 0       return( $self->error( "Value provided for reply_markup is not a Net::API::Telegram::InlineKeyboardMarkup object." ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) ne 'Net::API::Telegram::InlineKeyboardMarkup' );
1324 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup )] ) || return( undef() );
1325 0           my $form = $self->_options2form( $opts );
1326 0   0       my $hash = $self->query({
1327             'method' => 'editMessageCaption',
1328             'data' => $form,
1329             }) || return( $self->error( "Unable to make post query for method editMessageCaption: ", $self->error->message ) );
1330 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1331             {
1332 0           return( $self->error( $t_error ) );
1333             }
1334             elsif( $hash->{result} )
1335             {
1336 0   0       my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
1337             return( $self->error( "Error while getting an object out of hash for this message: ", $self->error ) );
1338 0           return( $o );
1339             }
1340             else
1341             {
1342 0           return( $hash->{ok} );
1343             }
1344             }
1345              
1346             sub editMessageLiveLocation
1347             {
1348 0     0 1   my $self = shift( @_ );
1349 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1350 0 0         return( $self->error( "Missing parameter latitude" ) ) if( !exists( $opts->{ 'latitude' } ) );
1351 0 0         return( $self->error( "Missing parameter longitude" ) ) if( !exists( $opts->{ 'longitude' } ) );
1352 0 0 0       return( $self->error( "Value provided for reply_markup is not a Net::API::Telegram::InlineKeyboardMarkup object." ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) ne 'Net::API::Telegram::InlineKeyboardMarkup' );
1353 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup )] ) || return( undef() );
1354 0           my $form = $self->_options2form( $opts );
1355 0   0       my $hash = $self->query({
1356             'method' => 'editMessageLiveLocation',
1357             'data' => $form,
1358             }) || return( $self->error( "Unable to make post query for method editMessageLiveLocation: ", $self->error->message ) );
1359 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1360             {
1361 0           return( $self->error( $t_error ) );
1362             }
1363             elsif( $hash->{result} )
1364             {
1365 0   0       my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
1366             return( $self->error( "Error while getting an object out of hash for this message: ", $self->error ) );
1367 0           return( $o );
1368             }
1369             else
1370             {
1371 0           return( $hash->{ok} );
1372             }
1373             }
1374              
1375             sub editMessageMedia
1376             {
1377 0     0 1   my $self = shift( @_ );
1378 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1379 0 0         return( $self->error( "Missing parameter media" ) ) if( !exists( $opts->{ 'media' } ) );
1380 0 0         return( $self->error( "Value provided for media is not a Net::API::Telegram::InputMedia object." ) ) if( ref( $opts->{ 'media' } ) ne 'Net::API::Telegram::InputMedia' );
1381 0 0 0       return( $self->error( "Value provided for reply_markup is not a Net::API::Telegram::InlineKeyboardMarkup object." ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) ne 'Net::API::Telegram::InlineKeyboardMarkup' );
1382 0 0         $self->_load( [qw( Net::API::Telegram::InputMedia Net::API::Telegram::InlineKeyboardMarkup )] ) || return( undef() );
1383 0           my $form = $self->_options2form( $opts );
1384 0   0       my $hash = $self->query({
1385             'method' => 'editMessageMedia',
1386             'data' => $form,
1387             }) || return( $self->error( "Unable to make post query for method editMessageMedia: ", $self->error->message ) );
1388 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1389             {
1390 0           return( $self->error( $t_error ) );
1391             }
1392             elsif( $hash->{result} )
1393             {
1394 0   0       my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
1395             return( $self->error( "Error while getting an object out of hash for this message: ", $self->error ) );
1396 0           return( $o );
1397             }
1398             else
1399             {
1400 0           return( $hash->{ok} );
1401             }
1402             }
1403              
1404             sub editMessageReplyMarkup
1405             {
1406 0     0 1   my $self = shift( @_ );
1407 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1408 0 0 0       return( $self->error( "Value provided for reply_markup is not a Net::API::Telegram::InlineKeyboardMarkup object." ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) ne 'Net::API::Telegram::InlineKeyboardMarkup' );
1409 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup )] ) || return( undef() );
1410 0           my $form = $self->_options2form( $opts );
1411 0   0       my $hash = $self->query({
1412             'method' => 'editMessageReplyMarkup',
1413             'data' => $form,
1414             }) || return( $self->error( "Unable to make post query for method editMessageReplyMarkup: ", $self->error->message ) );
1415 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1416             {
1417 0           return( $self->error( $t_error ) );
1418             }
1419             elsif( $hash->{result} )
1420             {
1421 0   0       my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
1422             return( $self->error( "Error while getting an object out of hash for this message: ", $self->error ) );
1423 0           return( $o );
1424             }
1425             else
1426             {
1427 0           return( $hash->{ok} );
1428             }
1429             }
1430              
1431             sub editMessageText
1432             {
1433 0     0 1   my $self = shift( @_ );
1434 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1435 0 0 0       return( $self->error( "Value provided for reply_markup is not a Net::API::Telegram::InlineKeyboardMarkup object." ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) ne 'Net::API::Telegram::InlineKeyboardMarkup' );
1436 0 0         return( $self->error( "Missing parameter text" ) ) if( !exists( $opts->{ 'text' } ) );
1437 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup )] ) || return( undef() );
1438 0           my $form = $self->_options2form( $opts );
1439 0   0       my $hash = $self->query({
1440             'method' => 'editMessageText',
1441             'data' => $form,
1442             }) || return( $self->error( "Unable to make post query for method editMessageText: ", $self->error->message ) );
1443 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1444             {
1445 0           return( $self->error( $t_error ) );
1446             }
1447             elsif( $hash->{result} )
1448             {
1449 0   0       my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
1450             return( $self->error( "Error while getting an object out of hash for this message: ", $self->error ) );
1451 0           return( $o );
1452             }
1453             else
1454             {
1455 0           return( $hash->{ok} );
1456             }
1457             }
1458              
1459             sub exportChatInviteLink
1460             {
1461 0     0 1   my $self = shift( @_ );
1462 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1463 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1464 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1465 0           my $form = $self->_options2form( $opts );
1466 0   0       my $hash = $self->query({
1467             'method' => 'exportChatInviteLink',
1468             'data' => $form,
1469             }) || return( $self->error( "Unable to make post query for method exportChatInviteLink: ", $self->error->message ) );
1470 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1471             {
1472 0           return( $self->error( $t_error ) );
1473             }
1474             else
1475             {
1476 0           return( $hash->{result} );
1477             }
1478             }
1479              
1480             sub forwardMessage
1481             {
1482 0     0 1   my $self = shift( @_ );
1483 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1484 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1485 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1486 0 0         return( $self->error( "Missing parameter from_chat_id" ) ) if( !exists( $opts->{ 'from_chat_id' } ) );
1487 0 0         return( $self->error( "Value provided for from_chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'from_chat_id' } ) );
1488 0 0         return( $self->error( "Missing parameter message_id" ) ) if( !exists( $opts->{ 'message_id' } ) );
1489 0           my $form = $self->_options2form( $opts );
1490 0   0       my $hash = $self->query({
1491             'method' => 'forwardMessage',
1492             'data' => $form,
1493             }) || return( $self->error( "Unable to make post query for method forwardMessage: ", $self->error->message ) );
1494 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1495             {
1496 0           return( $self->error( $t_error ) );
1497             }
1498             elsif( $hash->{result} )
1499             {
1500             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
1501 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
1502 0           return( $o );
1503             }
1504             }
1505              
1506             sub getChat
1507             {
1508 0     0 1   my $self = shift( @_ );
1509 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1510 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1511 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1512 0           my $form = $self->_options2form( $opts );
1513 0   0       my $hash = $self->query({
1514             'method' => 'getChat',
1515             'data' => $form,
1516             }) || return( $self->error( "Unable to make post query for method getChat: ", $self->error->message ) );
1517 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1518             {
1519 0           return( $self->error( $t_error ) );
1520             }
1521             elsif( $hash->{result} )
1522             {
1523             my $o = $self->_response_to_object( 'Net::API::Telegram::Chat', $hash->{result} ) ||
1524 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Chat object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
1525 0           return( $o );
1526             }
1527             }
1528              
1529             sub getChatAdministrators
1530             {
1531 0     0 1   my $self = shift( @_ );
1532 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1533 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1534 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1535 0           my $form = $self->_options2form( $opts );
1536 0   0       my $hash = $self->query({
1537             'method' => 'getChatAdministrators',
1538             'data' => $form,
1539             }) || return( $self->error( "Unable to make post query for method getChatAdministrators: ", $self->error->message ) );
1540 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1541             {
1542 0           return( $self->error( $t_error ) );
1543             }
1544             elsif( $hash->{result} )
1545             {
1546 0           my $arr = [];
1547 0           foreach my $h ( @{$hash->{result}} )
  0            
1548             {
1549             my $o = $self->_response_to_object( 'Net::API::Telegram::ChatMember', $h ) ||
1550 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::ChatMember object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
1551 0           push( @$arr, $o );
1552             }
1553 0           return( $arr );
1554             }
1555             }
1556              
1557             sub getChatMember
1558             {
1559 0     0 1   my $self = shift( @_ );
1560 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1561 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1562 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1563 0 0         return( $self->error( "Missing parameter user_id" ) ) if( !exists( $opts->{ 'user_id' } ) );
1564 0           my $form = $self->_options2form( $opts );
1565 0   0       my $hash = $self->query({
1566             'method' => 'getChatMember',
1567             'data' => $form,
1568             }) || return( $self->error( "Unable to make post query for method getChatMember: ", $self->error->message ) );
1569 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1570             {
1571 0           return( $self->error( $t_error ) );
1572             }
1573             elsif( $hash->{result} )
1574             {
1575             my $o = $self->_response_to_object( 'Net::API::Telegram::ChatMember', $hash->{result} ) ||
1576 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::ChatMember object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
1577 0           return( $o );
1578             }
1579             }
1580              
1581             sub getChatMembersCount
1582             {
1583 0     0 1   my $self = shift( @_ );
1584 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1585 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1586 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1587 0           my $form = $self->_options2form( $opts );
1588 0   0       my $hash = $self->query({
1589             'method' => 'getChatMembersCount',
1590             'data' => $form,
1591             }) || return( $self->error( "Unable to make post query for method getChatMembersCount: ", $self->error->message ) );
1592 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1593             {
1594 0           return( $self->error( $t_error ) );
1595             }
1596             else
1597             {
1598 0           return( $hash->{result} );
1599             }
1600             }
1601              
1602             sub getFile
1603             {
1604 0     0 1   my $self = shift( @_ );
1605 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1606 0 0         return( $self->error( "Missing parameter file_id" ) ) if( !exists( $opts->{ 'file_id' } ) );
1607 0           my $form = $self->_options2form( $opts );
1608 0   0       my $hash = $self->query({
1609             'method' => 'getFile',
1610             'data' => $form,
1611             }) || return( $self->error( "Unable to make post query for method getFile: ", $self->error->message ) );
1612 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1613             {
1614 0           return( $self->error( $t_error ) );
1615             }
1616             elsif( $hash->{result} )
1617             {
1618             my $o = $self->_response_to_object( 'Net::API::Telegram::File', $hash->{result} ) ||
1619 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::File object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
1620 0           return( $o );
1621             }
1622             }
1623              
1624             sub getGameHighScores
1625             {
1626 0     0 1   my $self = shift( @_ );
1627 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1628 0 0         return( $self->error( "Missing parameter user_id" ) ) if( !exists( $opts->{ 'user_id' } ) );
1629 0           my $form = $self->_options2form( $opts );
1630 0   0       my $hash = $self->query({
1631             'method' => 'getGameHighScores',
1632             'data' => $form,
1633             }) || return( $self->error( "Unable to make post query for method getGameHighScores: ", $self->error->message ) );
1634 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1635             {
1636 0           return( $self->error( $t_error ) );
1637             }
1638             elsif( $hash->{result} )
1639             {
1640 0           my $arr = [];
1641 0           foreach my $h ( @{$hash->{result}} )
  0            
1642             {
1643             my $o = $self->_response_to_object( 'Net::API::Telegram::GameHighScore', $h ) ||
1644 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::GameHighScore object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
1645 0           push( @$arr, $o );
1646             }
1647 0           return( $arr );
1648             }
1649             }
1650              
1651             sub getMe
1652             {
1653 0     0 1   my $self = shift( @_ );
1654 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1655 0           my $form = $self->_options2form( $opts );
1656 0   0       my $hash = $self->query({
1657             'method' => 'getMe',
1658             'data' => $form,
1659             }) || return( $self->error( "Unable to make post query for method getMe: ", $self->error->message ) );
1660 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1661             {
1662 0           return( $self->error( $t_error ) );
1663             }
1664             elsif( $hash->{result} )
1665             {
1666             my $o = $self->_response_to_object( 'Net::API::Telegram::User', $hash->{result} ) ||
1667 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::User object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
1668 0           return( $o );
1669             }
1670             }
1671              
1672             sub getStickerSet
1673             {
1674 0     0 1   my $self = shift( @_ );
1675 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1676 0 0         return( $self->error( "Missing parameter name" ) ) if( !exists( $opts->{ 'name' } ) );
1677 0           my $form = $self->_options2form( $opts );
1678 0   0       my $hash = $self->query({
1679             'method' => 'getStickerSet',
1680             'data' => $form,
1681             }) || return( $self->error( "Unable to make post query for method getStickerSet: ", $self->error->message ) );
1682 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1683             {
1684 0           return( $self->error( $t_error ) );
1685             }
1686             elsif( $hash->{result} )
1687             {
1688             my $o = $self->_response_to_object( 'Net::API::Telegram::StickerSet', $hash->{result} ) ||
1689 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::StickerSet object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
1690 0           return( $o );
1691             }
1692             }
1693              
1694             sub getUpdates
1695             {
1696 0     0 1   my $self = shift( @_ );
1697 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1698 0 0 0       return( $self->error( "Value provided for allowed_updates is not an array reference." ) ) if( length( $opts->{ 'allowed_updates' } ) && ref( $opts->{ 'allowed_updates' } ) ne 'ARRAY' );
1699 0           my $form = $self->_options2form( $opts );
1700 0   0       my $hash = $self->query({
1701             'method' => 'getUpdates',
1702             'data' => $form,
1703             }) || return( $self->error( "Unable to make post query for method getUpdates: ", $self->error->message ) );
1704 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1705             {
1706 0           return( $self->error( $t_error ) );
1707             }
1708             elsif( $hash->{result} )
1709             {
1710 0           my $arr = [];
1711 0           foreach my $h ( @{$hash->{result}} )
  0            
1712             {
1713             my $o = $self->_response_to_object( 'Net::API::Telegram::Update', $h ) ||
1714 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Update object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
1715 0           push( @$arr, $o );
1716             }
1717 0           return( $arr );
1718             }
1719             }
1720              
1721             sub getUserProfilePhotos
1722             {
1723 0     0 1   my $self = shift( @_ );
1724 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1725 0 0         return( $self->error( "Missing parameter user_id" ) ) if( !exists( $opts->{ 'user_id' } ) );
1726 0           my $form = $self->_options2form( $opts );
1727 0   0       my $hash = $self->query({
1728             'method' => 'getUserProfilePhotos',
1729             'data' => $form,
1730             }) || return( $self->error( "Unable to make post query for method getUserProfilePhotos: ", $self->error->message ) );
1731 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1732             {
1733 0           return( $self->error( $t_error ) );
1734             }
1735             elsif( $hash->{result} )
1736             {
1737             my $o = $self->_response_to_object( 'Net::API::Telegram::UserProfilePhotos', $hash->{result} ) ||
1738 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::UserProfilePhotos object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
1739 0           return( $o );
1740             }
1741             }
1742              
1743             sub getWebhookInfo
1744             {
1745 0     0 1   my $self = shift( @_ );
1746 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1747 0           my $form = $self->_options2form( $opts );
1748 0   0       my $hash = $self->query({
1749             'method' => 'getWebhookInfo',
1750             'data' => $form,
1751             }) || return( $self->error( "Unable to make post query for method getWebhookInfo: ", $self->error->message ) );
1752 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1753             {
1754 0           return( $self->error( $t_error ) );
1755             }
1756             elsif( $hash->{result} )
1757             {
1758             my $o = $self->_response_to_object( 'Net::API::Telegram::WebhookInfo', $hash->{result} ) ||
1759 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::WebhookInfo object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
1760 0           return( $o );
1761             }
1762             }
1763              
1764             sub kickChatMember
1765             {
1766 0     0 1   my $self = shift( @_ );
1767 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1768 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1769 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1770 0 0         return( $self->error( "Missing parameter user_id" ) ) if( !exists( $opts->{ 'user_id' } ) );
1771 0           my $form = $self->_options2form( $opts );
1772 0   0       my $hash = $self->query({
1773             'method' => 'kickChatMember',
1774             'data' => $form,
1775             }) || return( $self->error( "Unable to make post query for method kickChatMember: ", $self->error->message ) );
1776 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1777             {
1778 0           return( $self->error( $t_error ) );
1779             }
1780             else
1781             {
1782 0           return( $hash->{ok} );
1783             }
1784             }
1785              
1786             sub leaveChat
1787             {
1788 0     0 1   my $self = shift( @_ );
1789 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1790 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1791 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1792 0           my $form = $self->_options2form( $opts );
1793 0   0       my $hash = $self->query({
1794             'method' => 'leaveChat',
1795             'data' => $form,
1796             }) || return( $self->error( "Unable to make post query for method leaveChat: ", $self->error->message ) );
1797 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1798             {
1799 0           return( $self->error( $t_error ) );
1800             }
1801             else
1802             {
1803 0           return( $hash->{ok} );
1804             }
1805             }
1806              
1807             sub pinChatMessage
1808             {
1809 0     0 1   my $self = shift( @_ );
1810 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1811 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1812 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1813 0 0         return( $self->error( "Missing parameter message_id" ) ) if( !exists( $opts->{ 'message_id' } ) );
1814 0           my $form = $self->_options2form( $opts );
1815 0   0       my $hash = $self->query({
1816             'method' => 'pinChatMessage',
1817             'data' => $form,
1818             }) || return( $self->error( "Unable to make post query for method pinChatMessage: ", $self->error->message ) );
1819 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1820             {
1821 0           return( $self->error( $t_error ) );
1822             }
1823             else
1824             {
1825 0           return( $hash->{ok} );
1826             }
1827             }
1828              
1829             sub promoteChatMember
1830             {
1831 0     0 1   my $self = shift( @_ );
1832 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1833 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1834 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1835 0 0         return( $self->error( "Missing parameter user_id" ) ) if( !exists( $opts->{ 'user_id' } ) );
1836 0           my $form = $self->_options2form( $opts );
1837 0   0       my $hash = $self->query({
1838             'method' => 'promoteChatMember',
1839             'data' => $form,
1840             }) || return( $self->error( "Unable to make post query for method promoteChatMember: ", $self->error->message ) );
1841 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1842             {
1843 0           return( $self->error( $t_error ) );
1844             }
1845             else
1846             {
1847 0           return( $hash->{ok} );
1848             }
1849             }
1850              
1851             sub restrictChatMember
1852             {
1853 0     0 1   my $self = shift( @_ );
1854 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1855 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1856 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1857 0 0         return( $self->error( "Missing parameter permissions" ) ) if( !exists( $opts->{ 'permissions' } ) );
1858 0 0         return( $self->error( "Value provided for permissions is not a Net::API::Telegram::ChatPermissions object." ) ) if( ref( $opts->{ 'permissions' } ) ne 'Net::API::Telegram::ChatPermissions' );
1859 0 0         return( $self->error( "Missing parameter user_id" ) ) if( !exists( $opts->{ 'user_id' } ) );
1860 0 0         $self->_load( [qw( Net::API::Telegram::ChatPermissions )] ) || return( undef() );
1861 0           my $form = $self->_options2form( $opts );
1862 0   0       my $hash = $self->query({
1863             'method' => 'restrictChatMember',
1864             'data' => $form,
1865             }) || return( $self->error( "Unable to make post query for method restrictChatMember: ", $self->error->message ) );
1866 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1867             {
1868 0           return( $self->error( $t_error ) );
1869             }
1870             else
1871             {
1872 0           return( $hash->{ok} );
1873             }
1874             }
1875              
1876             sub sendAnimation
1877             {
1878 0     0 1   my $self = shift( @_ );
1879 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1880 0 0         return( $self->error( "Missing parameter animation" ) ) if( !exists( $opts->{ 'animation' } ) );
1881 0 0         return( $self->error( "Value provided for animation is not a valid object. I was expecting one of the following: InputFile, String" ) ) if( ref( $opts->{ 'animation' } ) !~ /^(?:Net::API::Telegram::InputFile)$/ );
1882 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1883 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1884 0 0 0       return( $self->error( "Value provided for reply_markup is not a valid object. I was expecting one of the following: InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply" ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) !~ /^(?:Net::API::Telegram::InlineKeyboardMarkup|Net::API::Telegram::ReplyKeyboardMarkup|Net::API::Telegram::ReplyKeyboardRemove|Net::API::Telegram::ForceReply)$/ );
1885 0 0 0       return( $self->error( "Value provided for thumb is not a valid object. I was expecting one of the following: InputFile, String" ) ) if( length( $opts->{ 'thumb' } ) && ref( $opts->{ 'thumb' } ) !~ /^(?:Net::API::Telegram::InputFile)$/ );
1886 0 0         $self->_load( [qw( Net::API::Telegram::InputFile Net::API::Telegram::InlineKeyboardMarkup Net::API::Telegram::ReplyKeyboardMarkup Net::API::Telegram::ReplyKeyboardRemove Net::API::Telegram::ForceReply Net::API::Telegram::InputFile )] ) || return( undef() );
1887 0           my $form = $self->_options2form( $opts );
1888 0   0       my $hash = $self->query({
1889             'method' => 'sendAnimation',
1890             'data' => $form,
1891             }) || return( $self->error( "Unable to make post query for method sendAnimation: ", $self->error->message ) );
1892 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1893             {
1894 0           return( $self->error( $t_error ) );
1895             }
1896             elsif( $hash->{result} )
1897             {
1898             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
1899 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
1900 0           return( $o );
1901             }
1902             }
1903              
1904             sub sendAudio
1905             {
1906 0     0 1   my $self = shift( @_ );
1907 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1908 0 0         return( $self->error( "Missing parameter audio" ) ) if( !exists( $opts->{ 'audio' } ) );
1909 0 0         return( $self->error( "Value provided for audio is not a valid object. I was expecting one of the following: InputFile, String" ) ) if( ref( $opts->{ 'audio' } ) !~ /^(?:Net::API::Telegram::InputFile)$/ );
1910 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1911 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1912 0 0 0       return( $self->error( "Value provided for reply_markup is not a valid object. I was expecting one of the following: InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply" ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) !~ /^(?:Net::API::Telegram::InlineKeyboardMarkup|Net::API::Telegram::ReplyKeyboardMarkup|Net::API::Telegram::ReplyKeyboardRemove|Net::API::Telegram::ForceReply)$/ );
1913 0 0 0       return( $self->error( "Value provided for thumb is not a valid object. I was expecting one of the following: InputFile, String" ) ) if( length( $opts->{ 'thumb' } ) && ref( $opts->{ 'thumb' } ) !~ /^(?:Net::API::Telegram::InputFile)$/ );
1914 0 0         $self->_load( [qw( Net::API::Telegram::InputFile Net::API::Telegram::InlineKeyboardMarkup Net::API::Telegram::ReplyKeyboardMarkup Net::API::Telegram::ReplyKeyboardRemove Net::API::Telegram::ForceReply Net::API::Telegram::InputFile )] ) || return( undef() );
1915 0           my $form = $self->_options2form( $opts );
1916 0   0       my $hash = $self->query({
1917             'method' => 'sendAudio',
1918             'data' => $form,
1919             }) || return( $self->error( "Unable to make post query for method sendAudio: ", $self->error->message ) );
1920 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1921             {
1922 0           return( $self->error( $t_error ) );
1923             }
1924             elsif( $hash->{result} )
1925             {
1926             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
1927 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
1928 0           return( $o );
1929             }
1930             }
1931              
1932             sub sendChatAction
1933             {
1934 0     0 1   my $self = shift( @_ );
1935 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1936 0 0         return( $self->error( "Missing parameter action" ) ) if( !exists( $opts->{ 'action' } ) );
1937 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1938 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1939 0           my $form = $self->_options2form( $opts );
1940 0   0       my $hash = $self->query({
1941             'method' => 'sendChatAction',
1942             'data' => $form,
1943             }) || return( $self->error( "Unable to make post query for method sendChatAction: ", $self->error->message ) );
1944 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
1945             {
1946 0           return( $self->error( $t_error ) );
1947             }
1948             else
1949             {
1950 0           return( $hash->{ok} );
1951             }
1952             }
1953              
1954             sub sendContact
1955             {
1956 0     0 1   my $self = shift( @_ );
1957 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1958 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1959 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1960 0 0         return( $self->error( "Missing parameter first_name" ) ) if( !exists( $opts->{ 'first_name' } ) );
1961 0 0         return( $self->error( "Missing parameter phone_number" ) ) if( !exists( $opts->{ 'phone_number' } ) );
1962 0 0 0       return( $self->error( "Value provided for reply_markup is not a valid object. I was expecting one of the following: InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply" ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) !~ /^(?:Net::API::Telegram::InlineKeyboardMarkup|Net::API::Telegram::ReplyKeyboardMarkup|Net::API::Telegram::ReplyKeyboardRemove|Net::API::Telegram::ForceReply)$/ );
1963 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup Net::API::Telegram::ReplyKeyboardMarkup Net::API::Telegram::ReplyKeyboardRemove Net::API::Telegram::ForceReply )] ) || return( undef() );
1964 0           my $form = $self->_options2form( $opts );
1965 0   0       my $hash = $self->query({
1966             'method' => 'sendContact',
1967             'data' => $form,
1968             }) || return( $self->error( "Unable to make post query for method sendContact: ", $self->error->message ) );
1969 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1970             {
1971 0           return( $self->error( $t_error ) );
1972             }
1973             elsif( $hash->{result} )
1974             {
1975             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
1976 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
1977 0           return( $o );
1978             }
1979             }
1980              
1981             sub sendDocument
1982             {
1983 0     0 1   my $self = shift( @_ );
1984 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
1985 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
1986 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
1987 0 0         return( $self->error( "Missing parameter document" ) ) if( !exists( $opts->{ 'document' } ) );
1988 0 0         return( $self->error( "Value provided for document is not a valid object. I was expecting one of the following: InputFile, String" ) ) if( ref( $opts->{ 'document' } ) !~ /^(?:Net::API::Telegram::InputFile)$/ );
1989 0 0 0       return( $self->error( "Value provided for reply_markup is not a valid object. I was expecting one of the following: InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply" ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) !~ /^(?:Net::API::Telegram::InlineKeyboardMarkup|Net::API::Telegram::ReplyKeyboardMarkup|Net::API::Telegram::ReplyKeyboardRemove|Net::API::Telegram::ForceReply)$/ );
1990 0 0 0       return( $self->error( "Value provided for thumb is not a valid object. I was expecting one of the following: InputFile, String" ) ) if( length( $opts->{ 'thumb' } ) && ref( $opts->{ 'thumb' } ) !~ /^(?:Net::API::Telegram::InputFile)$/ );
1991 0 0         $self->_load( [qw( Net::API::Telegram::InputFile Net::API::Telegram::InlineKeyboardMarkup Net::API::Telegram::ReplyKeyboardMarkup Net::API::Telegram::ReplyKeyboardRemove Net::API::Telegram::ForceReply Net::API::Telegram::InputFile )] ) || return( undef() );
1992 0           my $form = $self->_options2form( $opts );
1993 0   0       my $hash = $self->query({
1994             'method' => 'sendDocument',
1995             'data' => $form,
1996             }) || return( $self->error( "Unable to make post query for method sendDocument: ", $self->error->message ) );
1997 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
1998             {
1999 0           return( $self->error( $t_error ) );
2000             }
2001             elsif( $hash->{result} )
2002             {
2003             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
2004 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
2005 0           return( $o );
2006             }
2007             }
2008              
2009             sub sendGame
2010             {
2011 0     0 1   my $self = shift( @_ );
2012 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2013 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2014 0 0         return( $self->error( "Missing parameter game_short_name" ) ) if( !exists( $opts->{ 'game_short_name' } ) );
2015 0 0 0       return( $self->error( "Value provided for reply_markup is not a Net::API::Telegram::InlineKeyboardMarkup object." ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) ne 'Net::API::Telegram::InlineKeyboardMarkup' );
2016 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup )] ) || return( undef() );
2017 0           my $form = $self->_options2form( $opts );
2018 0   0       my $hash = $self->query({
2019             'method' => 'sendGame',
2020             'data' => $form,
2021             }) || return( $self->error( "Unable to make post query for method sendGame: ", $self->error->message ) );
2022 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2023             {
2024 0           return( $self->error( $t_error ) );
2025             }
2026             elsif( $hash->{result} )
2027             {
2028             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
2029 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
2030 0           return( $o );
2031             }
2032             }
2033              
2034             sub sendInvoice
2035             {
2036 0     0 1   my $self = shift( @_ );
2037 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2038 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2039 0 0         return( $self->error( "Missing parameter currency" ) ) if( !exists( $opts->{ 'currency' } ) );
2040 0 0         return( $self->error( "Missing parameter description" ) ) if( !exists( $opts->{ 'description' } ) );
2041 0 0         return( $self->error( "Missing parameter payload" ) ) if( !exists( $opts->{ 'payload' } ) );
2042 0 0         return( $self->error( "Missing parameter prices" ) ) if( !exists( $opts->{ 'prices' } ) );
2043 0 0         return( $self->error( "Value provided for prices is not an array reference." ) ) if( ref( $opts->{ 'prices' } ) ne 'ARRAY' );
2044 0 0         return( $self->error( "Value provided is not an array of either of this objects: LabeledPrice" ) ) if( !$self->_param_check_array_object( qr/^(?:Net::API::Telegram::LabeledPrice)$/, @_ ) );
2045 0 0         return( $self->error( "Missing parameter provider_token" ) ) if( !exists( $opts->{ 'provider_token' } ) );
2046 0 0 0       return( $self->error( "Value provided for reply_markup is not a Net::API::Telegram::InlineKeyboardMarkup object." ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) ne 'Net::API::Telegram::InlineKeyboardMarkup' );
2047 0 0         return( $self->error( "Missing parameter start_parameter" ) ) if( !exists( $opts->{ 'start_parameter' } ) );
2048 0 0         return( $self->error( "Missing parameter title" ) ) if( !exists( $opts->{ 'title' } ) );
2049 0 0         $self->_load( [qw( Net::API::Telegram::LabeledPrice Net::API::Telegram::InlineKeyboardMarkup )] ) || return( undef() );
2050 0           my $form = $self->_options2form( $opts );
2051 0   0       my $hash = $self->query({
2052             'method' => 'sendInvoice',
2053             'data' => $form,
2054             }) || return( $self->error( "Unable to make post query for method sendInvoice: ", $self->error->message ) );
2055 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2056             {
2057 0           return( $self->error( $t_error ) );
2058             }
2059             elsif( $hash->{result} )
2060             {
2061             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
2062 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
2063 0           return( $o );
2064             }
2065             }
2066              
2067             sub sendLocation
2068             {
2069 0     0 1   my $self = shift( @_ );
2070 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2071 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2072 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2073 0 0         return( $self->error( "Missing parameter latitude" ) ) if( !exists( $opts->{ 'latitude' } ) );
2074 0 0         return( $self->error( "Missing parameter longitude" ) ) if( !exists( $opts->{ 'longitude' } ) );
2075 0 0 0       return( $self->error( "Value provided for reply_markup is not a valid object. I was expecting one of the following: InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply" ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) !~ /^(?:Net::API::Telegram::InlineKeyboardMarkup|Net::API::Telegram::ReplyKeyboardMarkup|Net::API::Telegram::ReplyKeyboardRemove|Net::API::Telegram::ForceReply)$/ );
2076 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup Net::API::Telegram::ReplyKeyboardMarkup Net::API::Telegram::ReplyKeyboardRemove Net::API::Telegram::ForceReply )] ) || return( undef() );
2077 0           my $form = $self->_options2form( $opts );
2078 0   0       my $hash = $self->query({
2079             'method' => 'sendLocation',
2080             'data' => $form,
2081             }) || return( $self->error( "Unable to make post query for method sendLocation: ", $self->error->message ) );
2082 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2083             {
2084 0           return( $self->error( $t_error ) );
2085             }
2086             elsif( $hash->{result} )
2087             {
2088             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
2089 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
2090 0           return( $o );
2091             }
2092             }
2093              
2094             sub sendMediaGroup
2095             {
2096 0     0 1   my $self = shift( @_ );
2097 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2098 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2099 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2100 0 0         return( $self->error( "Missing parameter media" ) ) if( !exists( $opts->{ 'media' } ) );
2101 0 0         return( $self->error( "Value provided for media is not an array reference." ) ) if( ref( $opts->{ 'media' } ) ne 'ARRAY' );
2102 0 0         return( $self->error( "Value provided is not an array of either of this objects: InputMediaPhoto, InputMediaVideo" ) ) if( !$self->_param_check_array_object( qr/^(?:Net::API::Telegram::InputMediaPhoto|Net::API::Telegram::InputMediaVideo)$/, @_ ) );
2103 0 0         $self->_load( [qw( Net::API::Telegram::InputMediaPhoto Net::API::Telegram::InputMediaVideo )] ) || return( undef() );
2104 0           my $form = $self->_options2form( $opts );
2105 0   0       my $hash = $self->query({
2106             'method' => 'sendMediaGroup',
2107             'data' => $form,
2108             }) || return( $self->error( "Unable to make post query for method sendMediaGroup: ", $self->error->message ) );
2109 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2110             {
2111 0           return( $self->error( $t_error ) );
2112             }
2113             elsif( $hash->{result} )
2114             {
2115 0           my $arr = [];
2116 0           foreach my $h ( @{$hash->{result}} )
  0            
2117             {
2118             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $h ) ||
2119 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
2120 0           push( @$arr, $o );
2121             }
2122 0           return( $arr );
2123             }
2124             }
2125              
2126             sub sendMessage
2127             {
2128 0     0 1   my $self = shift( @_ );
2129 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2130 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2131 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2132 0 0 0       return( $self->error( "Value provided for reply_markup is not a valid object. I was expecting one of the following: InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply" ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) !~ /^(?:Net::API::Telegram::InlineKeyboardMarkup|Net::API::Telegram::ReplyKeyboardMarkup|Net::API::Telegram::ReplyKeyboardRemove|Net::API::Telegram::ForceReply)$/ );
2133 0 0         return( $self->error( "Missing parameter text" ) ) if( !exists( $opts->{ 'text' } ) );
2134 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup Net::API::Telegram::ReplyKeyboardMarkup Net::API::Telegram::ReplyKeyboardRemove Net::API::Telegram::ForceReply )] ) || return( undef() );
2135 0           my $form = $self->_options2form( $opts );
2136 0   0       my $hash = $self->query({
2137             'method' => 'sendMessage',
2138             'data' => $form,
2139             }) || return( $self->error( "Unable to make post query for method sendMessage: ", $self->error->message ) );
2140 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2141             {
2142 0           return( $self->error( $t_error ) );
2143             }
2144             elsif( $hash->{result} )
2145             {
2146             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
2147 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
2148 0           return( $o );
2149             }
2150             }
2151              
2152             sub sendPhoto
2153             {
2154 0     0 1   my $self = shift( @_ );
2155 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2156 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2157 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2158 0 0         return( $self->error( "Missing parameter photo" ) ) if( !exists( $opts->{ 'photo' } ) );
2159 0 0         return( $self->error( "Value provided for photo is not a valid object. I was expecting one of the following: InputFile, String" ) ) if( ref( $opts->{ 'photo' } ) !~ /^(?:Net::API::Telegram::InputFile)$/ );
2160 0 0 0       return( $self->error( "Value provided for reply_markup is not a valid object. I was expecting one of the following: InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply" ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) !~ /^(?:Net::API::Telegram::InlineKeyboardMarkup|Net::API::Telegram::ReplyKeyboardMarkup|Net::API::Telegram::ReplyKeyboardRemove|Net::API::Telegram::ForceReply)$/ );
2161 0 0         $self->_load( [qw( Net::API::Telegram::InputFile Net::API::Telegram::InlineKeyboardMarkup Net::API::Telegram::ReplyKeyboardMarkup Net::API::Telegram::ReplyKeyboardRemove Net::API::Telegram::ForceReply )] ) || return( undef() );
2162 0           my $form = $self->_options2form( $opts );
2163 0   0       my $hash = $self->query({
2164             'method' => 'sendPhoto',
2165             'data' => $form,
2166             }) || return( $self->error( "Unable to make post query for method sendPhoto: ", $self->error->message ) );
2167 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2168             {
2169 0           return( $self->error( $t_error ) );
2170             }
2171             elsif( $hash->{result} )
2172             {
2173             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
2174 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
2175 0           return( $o );
2176             }
2177             }
2178              
2179             sub sendPoll
2180             {
2181 0     0 1   my $self = shift( @_ );
2182 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2183 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2184 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2185 0 0         return( $self->error( "Missing parameter options" ) ) if( !exists( $opts->{ 'options' } ) );
2186 0 0         return( $self->error( "Value provided for options is not an array reference." ) ) if( ref( $opts->{ 'options' } ) ne 'ARRAY' );
2187 0 0         return( $self->error( "Missing parameter question" ) ) if( !exists( $opts->{ 'question' } ) );
2188 0 0 0       return( $self->error( "Value provided for reply_markup is not a valid object. I was expecting one of the following: InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply" ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) !~ /^(?:Net::API::Telegram::InlineKeyboardMarkup|Net::API::Telegram::ReplyKeyboardMarkup|Net::API::Telegram::ReplyKeyboardRemove|Net::API::Telegram::ForceReply)$/ );
2189 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup Net::API::Telegram::ReplyKeyboardMarkup Net::API::Telegram::ReplyKeyboardRemove Net::API::Telegram::ForceReply )] ) || return( undef() );
2190 0           my $form = $self->_options2form( $opts );
2191 0   0       my $hash = $self->query({
2192             'method' => 'sendPoll',
2193             'data' => $form,
2194             }) || return( $self->error( "Unable to make post query for method sendPoll: ", $self->error->message ) );
2195 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2196             {
2197 0           return( $self->error( $t_error ) );
2198             }
2199             elsif( $hash->{result} )
2200             {
2201             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
2202 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
2203 0           return( $o );
2204             }
2205             }
2206              
2207             sub sendSticker
2208             {
2209 0     0 1   my $self = shift( @_ );
2210 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2211 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2212 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2213 0 0 0       return( $self->error( "Value provided for reply_markup is not a valid object. I was expecting one of the following: InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply" ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) !~ /^(?:Net::API::Telegram::InlineKeyboardMarkup|Net::API::Telegram::ReplyKeyboardMarkup|Net::API::Telegram::ReplyKeyboardRemove|Net::API::Telegram::ForceReply)$/ );
2214 0 0         return( $self->error( "Missing parameter sticker" ) ) if( !exists( $opts->{ 'sticker' } ) );
2215 0 0         return( $self->error( "Value provided for sticker is not a valid object. I was expecting one of the following: InputFile, String" ) ) if( ref( $opts->{ 'sticker' } ) !~ /^(?:Net::API::Telegram::InputFile)$/ );
2216 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup Net::API::Telegram::ReplyKeyboardMarkup Net::API::Telegram::ReplyKeyboardRemove Net::API::Telegram::ForceReply Net::API::Telegram::InputFile )] ) || return( undef() );
2217 0           my $form = $self->_options2form( $opts );
2218 0   0       my $hash = $self->query({
2219             'method' => 'sendSticker',
2220             'data' => $form,
2221             }) || return( $self->error( "Unable to make post query for method sendSticker: ", $self->error->message ) );
2222 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2223             {
2224 0           return( $self->error( $t_error ) );
2225             }
2226             elsif( $hash->{result} )
2227             {
2228             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
2229 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
2230 0           return( $o );
2231             }
2232             }
2233              
2234             sub sendVenue
2235             {
2236 0     0 1   my $self = shift( @_ );
2237 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2238 0 0         return( $self->error( "Missing parameter address" ) ) if( !exists( $opts->{ 'address' } ) );
2239 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2240 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2241 0 0         return( $self->error( "Missing parameter latitude" ) ) if( !exists( $opts->{ 'latitude' } ) );
2242 0 0         return( $self->error( "Missing parameter longitude" ) ) if( !exists( $opts->{ 'longitude' } ) );
2243 0 0 0       return( $self->error( "Value provided for reply_markup is not a valid object. I was expecting one of the following: InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply" ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) !~ /^(?:Net::API::Telegram::InlineKeyboardMarkup|Net::API::Telegram::ReplyKeyboardMarkup|Net::API::Telegram::ReplyKeyboardRemove|Net::API::Telegram::ForceReply)$/ );
2244 0 0         return( $self->error( "Missing parameter title" ) ) if( !exists( $opts->{ 'title' } ) );
2245 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup Net::API::Telegram::ReplyKeyboardMarkup Net::API::Telegram::ReplyKeyboardRemove Net::API::Telegram::ForceReply )] ) || return( undef() );
2246 0           my $form = $self->_options2form( $opts );
2247 0   0       my $hash = $self->query({
2248             'method' => 'sendVenue',
2249             'data' => $form,
2250             }) || return( $self->error( "Unable to make post query for method sendVenue: ", $self->error->message ) );
2251 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2252             {
2253 0           return( $self->error( $t_error ) );
2254             }
2255             elsif( $hash->{result} )
2256             {
2257             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
2258 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
2259 0           return( $o );
2260             }
2261             }
2262              
2263             sub sendVideo
2264             {
2265 0     0 1   my $self = shift( @_ );
2266 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2267 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2268 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2269 0 0 0       return( $self->error( "Value provided for reply_markup is not a valid object. I was expecting one of the following: InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply" ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) !~ /^(?:Net::API::Telegram::InlineKeyboardMarkup|Net::API::Telegram::ReplyKeyboardMarkup|Net::API::Telegram::ReplyKeyboardRemove|Net::API::Telegram::ForceReply)$/ );
2270 0 0 0       return( $self->error( "Value provided for thumb is not a valid object. I was expecting one of the following: InputFile, String" ) ) if( length( $opts->{ 'thumb' } ) && ref( $opts->{ 'thumb' } ) !~ /^(?:Net::API::Telegram::InputFile)$/ );
2271 0 0         return( $self->error( "Missing parameter video" ) ) if( !exists( $opts->{ 'video' } ) );
2272 0 0         return( $self->error( "Value provided for video is not a valid object. I was expecting one of the following: InputFile, String" ) ) if( ref( $opts->{ 'video' } ) !~ /^(?:Net::API::Telegram::InputFile)$/ );
2273 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup Net::API::Telegram::ReplyKeyboardMarkup Net::API::Telegram::ReplyKeyboardRemove Net::API::Telegram::ForceReply Net::API::Telegram::InputFile Net::API::Telegram::InputFile )] ) || return( undef() );
2274 0           my $form = $self->_options2form( $opts );
2275 0   0       my $hash = $self->query({
2276             'method' => 'sendVideo',
2277             'data' => $form,
2278             }) || return( $self->error( "Unable to make post query for method sendVideo: ", $self->error->message ) );
2279 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2280             {
2281 0           return( $self->error( $t_error ) );
2282             }
2283             elsif( $hash->{result} )
2284             {
2285             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
2286 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
2287 0           return( $o );
2288             }
2289             }
2290              
2291             sub sendVideoNote
2292             {
2293 0     0 1   my $self = shift( @_ );
2294 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2295 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2296 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2297 0 0 0       return( $self->error( "Value provided for reply_markup is not a valid object. I was expecting one of the following: InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply" ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) !~ /^(?:Net::API::Telegram::InlineKeyboardMarkup|Net::API::Telegram::ReplyKeyboardMarkup|Net::API::Telegram::ReplyKeyboardRemove|Net::API::Telegram::ForceReply)$/ );
2298 0 0 0       return( $self->error( "Value provided for thumb is not a valid object. I was expecting one of the following: InputFile, String" ) ) if( length( $opts->{ 'thumb' } ) && ref( $opts->{ 'thumb' } ) !~ /^(?:Net::API::Telegram::InputFile)$/ );
2299 0 0         return( $self->error( "Missing parameter video_note" ) ) if( !exists( $opts->{ 'video_note' } ) );
2300 0 0         return( $self->error( "Value provided for video_note is not a valid object. I was expecting one of the following: InputFile, String" ) ) if( ref( $opts->{ 'video_note' } ) !~ /^(?:Net::API::Telegram::InputFile)$/ );
2301 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup Net::API::Telegram::ReplyKeyboardMarkup Net::API::Telegram::ReplyKeyboardRemove Net::API::Telegram::ForceReply Net::API::Telegram::InputFile Net::API::Telegram::InputFile )] ) || return( undef() );
2302 0           my $form = $self->_options2form( $opts );
2303 0   0       my $hash = $self->query({
2304             'method' => 'sendVideoNote',
2305             'data' => $form,
2306             }) || return( $self->error( "Unable to make post query for method sendVideoNote: ", $self->error->message ) );
2307 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2308             {
2309 0           return( $self->error( $t_error ) );
2310             }
2311             elsif( $hash->{result} )
2312             {
2313             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
2314 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
2315 0           return( $o );
2316             }
2317             }
2318              
2319             sub sendVoice
2320             {
2321 0     0 1   my $self = shift( @_ );
2322 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2323 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2324 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2325 0 0 0       return( $self->error( "Value provided for reply_markup is not a valid object. I was expecting one of the following: InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply" ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) !~ /^(?:Net::API::Telegram::InlineKeyboardMarkup|Net::API::Telegram::ReplyKeyboardMarkup|Net::API::Telegram::ReplyKeyboardRemove|Net::API::Telegram::ForceReply)$/ );
2326 0 0         return( $self->error( "Missing parameter voice" ) ) if( !exists( $opts->{ 'voice' } ) );
2327 0 0         return( $self->error( "Value provided for voice is not a valid object. I was expecting one of the following: InputFile, String" ) ) if( ref( $opts->{ 'voice' } ) !~ /^(?:Net::API::Telegram::InputFile)$/ );
2328 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup Net::API::Telegram::ReplyKeyboardMarkup Net::API::Telegram::ReplyKeyboardRemove Net::API::Telegram::ForceReply Net::API::Telegram::InputFile )] ) || return( undef() );
2329 0           my $form = $self->_options2form( $opts );
2330 0   0       my $hash = $self->query({
2331             'method' => 'sendVoice',
2332             'data' => $form,
2333             }) || return( $self->error( "Unable to make post query for method sendVoice: ", $self->error->message ) );
2334 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2335             {
2336 0           return( $self->error( $t_error ) );
2337             }
2338             elsif( $hash->{result} )
2339             {
2340             my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
2341 0   0 0     return( $self->error( "Unable to create an Net::API::Telegram::Message object with this data returned: ", sub{ $self->dumper( $h ) } ) );
  0            
2342 0           return( $o );
2343             }
2344             }
2345              
2346             sub setChatDescription
2347             {
2348 0     0 1   my $self = shift( @_ );
2349 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2350 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2351 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2352 0           my $form = $self->_options2form( $opts );
2353 0   0       my $hash = $self->query({
2354             'method' => 'setChatDescription',
2355             'data' => $form,
2356             }) || return( $self->error( "Unable to make post query for method setChatDescription: ", $self->error->message ) );
2357 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
2358             {
2359 0           return( $self->error( $t_error ) );
2360             }
2361             else
2362             {
2363 0           return( $hash->{ok} );
2364             }
2365             }
2366              
2367             sub setChatPermissions
2368             {
2369 0     0 1   my $self = shift( @_ );
2370 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2371 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2372 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2373 0 0         return( $self->error( "Missing parameter permissions" ) ) if( !exists( $opts->{ 'permissions' } ) );
2374 0 0         return( $self->error( "Value provided for permissions is not a Net::API::Telegram::ChatPermissions object." ) ) if( ref( $opts->{ 'permissions' } ) ne 'Net::API::Telegram::ChatPermissions' );
2375 0 0         $self->_load( [qw( Net::API::Telegram::ChatPermissions )] ) || return( undef() );
2376 0           my $form = $self->_options2form( $opts );
2377 0   0       my $hash = $self->query({
2378             'method' => 'setChatPermissions',
2379             'data' => $form,
2380             }) || return( $self->error( "Unable to make post query for method setChatPermissions: ", $self->error->message ) );
2381 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
2382             {
2383 0           return( $self->error( $t_error ) );
2384             }
2385             else
2386             {
2387 0           return( $hash->{ok} );
2388             }
2389             }
2390              
2391             sub setChatPhoto
2392             {
2393 0     0 1   my $self = shift( @_ );
2394 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2395 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2396 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2397 0 0         return( $self->error( "Missing parameter photo" ) ) if( !exists( $opts->{ 'photo' } ) );
2398 0 0         return( $self->error( "Value provided for photo is not a Net::API::Telegram::InputFile object." ) ) if( ref( $opts->{ 'photo' } ) ne 'Net::API::Telegram::InputFile' );
2399 0 0         $self->_load( [qw( Net::API::Telegram::InputFile )] ) || return( undef() );
2400 0           my $form = $self->_options2form( $opts );
2401 0   0       my $hash = $self->query({
2402             'method' => 'setChatPhoto',
2403             'data' => $form,
2404             }) || return( $self->error( "Unable to make post query for method setChatPhoto: ", $self->error->message ) );
2405 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
2406             {
2407 0           return( $self->error( $t_error ) );
2408             }
2409             else
2410             {
2411 0           return( $hash->{ok} );
2412             }
2413             }
2414              
2415             sub setChatStickerSet
2416             {
2417 0     0 1   my $self = shift( @_ );
2418 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2419 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2420 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2421 0 0         return( $self->error( "Missing parameter sticker_set_name" ) ) if( !exists( $opts->{ 'sticker_set_name' } ) );
2422 0           my $form = $self->_options2form( $opts );
2423 0   0       my $hash = $self->query({
2424             'method' => 'setChatStickerSet',
2425             'data' => $form,
2426             }) || return( $self->error( "Unable to make post query for method setChatStickerSet: ", $self->error->message ) );
2427 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
2428             {
2429 0           return( $self->error( $t_error ) );
2430             }
2431             else
2432             {
2433 0           return( $hash->{ok} );
2434             }
2435             }
2436              
2437             sub setChatTitle
2438             {
2439 0     0 1   my $self = shift( @_ );
2440 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2441 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2442 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2443 0 0         return( $self->error( "Missing parameter title" ) ) if( !exists( $opts->{ 'title' } ) );
2444 0           my $form = $self->_options2form( $opts );
2445 0   0       my $hash = $self->query({
2446             'method' => 'setChatTitle',
2447             'data' => $form,
2448             }) || return( $self->error( "Unable to make post query for method setChatTitle: ", $self->error->message ) );
2449 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
2450             {
2451 0           return( $self->error( $t_error ) );
2452             }
2453             else
2454             {
2455 0           return( $hash->{ok} );
2456             }
2457             }
2458              
2459             sub setGameScore
2460             {
2461 0     0 1   my $self = shift( @_ );
2462 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2463 0 0         return( $self->error( "Missing parameter score" ) ) if( !exists( $opts->{ 'score' } ) );
2464 0 0         return( $self->error( "Missing parameter user_id" ) ) if( !exists( $opts->{ 'user_id' } ) );
2465 0           my $form = $self->_options2form( $opts );
2466 0   0       my $hash = $self->query({
2467             'method' => 'setGameScore',
2468             'data' => $form,
2469             }) || return( $self->error( "Unable to make post query for method setGameScore: ", $self->error->message ) );
2470 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2471             {
2472 0           return( $self->error( $t_error ) );
2473             }
2474             elsif( $hash->{result} )
2475             {
2476 0   0       my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
2477             return( $self->error( "Error while getting an object out of hash for this message: ", $self->error ) );
2478 0           return( $o );
2479             }
2480             else
2481             {
2482 0           return( $hash->{ok} );
2483             }
2484             }
2485              
2486             sub setPassportDataErrors
2487             {
2488 0     0 1   my $self = shift( @_ );
2489 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2490 0 0         return( $self->error( "Missing parameter errors" ) ) if( !exists( $opts->{ 'errors' } ) );
2491 0 0         return( $self->error( "Value provided for errors is not an array reference." ) ) if( ref( $opts->{ 'errors' } ) ne 'ARRAY' );
2492 0 0         return( $self->error( "Value provided is not an array of either of this objects: PassportElementError" ) ) if( !$self->_param_check_array_object( qr/^(?:Net::API::Telegram::PassportElementError)$/, @_ ) );
2493 0 0         return( $self->error( "Missing parameter user_id" ) ) if( !exists( $opts->{ 'user_id' } ) );
2494 0 0         $self->_load( [qw( Net::API::Telegram::PassportElementError )] ) || return( undef() );
2495 0           my $form = $self->_options2form( $opts );
2496 0   0       my $hash = $self->query({
2497             'method' => 'setPassportDataErrors',
2498             'data' => $form,
2499             }) || return( $self->error( "Unable to make post query for method setPassportDataErrors: ", $self->error->message ) );
2500 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
2501             {
2502 0           return( $self->error( $t_error ) );
2503             }
2504             else
2505             {
2506 0           return( $hash->{ok} );
2507             }
2508             }
2509              
2510             sub setWebhook
2511             {
2512 0     0 1   my $self = shift( @_ );
2513 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2514 0 0 0       $opts->{certificate} = Net::API::Telegram::InputFile->new( $self->{ssl_cert} ) if( $opts->{certificate} && $self->{ssl_cert} );
2515 0 0 0       return( $self->error( "Value provided for allowed_updates is not an array reference." ) ) if( length( $opts->{ 'allowed_updates' } ) && ref( $opts->{ 'allowed_updates' } ) ne 'ARRAY' );
2516 0 0 0       return( $self->error( "Value provided for certificate is not a Net::API::Telegram::InputFile object." ) ) if( length( $opts->{ 'certificate' } ) && ref( $opts->{ 'certificate' } ) ne 'Net::API::Telegram::InputFile' );
2517 0 0         return( $self->error( "Missing parameter url" ) ) if( !exists( $opts->{ 'url' } ) );
2518 0 0         $self->_load( [qw( Net::API::Telegram::InputFile )] ) || return( undef() );
2519 0           my $form = $self->_options2form( $opts );
2520 0   0       my $hash = $self->query({
2521             'method' => 'setWebhook',
2522             'data' => $form,
2523             }) || return( $self->error( "Unable to make post query for method setWebhook: ", $self->error->message ) );
2524 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
2525             {
2526 0           return( $self->error( $t_error ) );
2527             }
2528             else
2529             {
2530 0           return( $hash->{ok} );
2531             }
2532             }
2533              
2534             sub stopMessageLiveLocation
2535             {
2536 0     0 1   my $self = shift( @_ );
2537 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2538 0 0 0       return( $self->error( "Value provided for reply_markup is not a Net::API::Telegram::InlineKeyboardMarkup object." ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) ne 'Net::API::Telegram::InlineKeyboardMarkup' );
2539 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup )] ) || return( undef() );
2540 0           my $form = $self->_options2form( $opts );
2541 0   0       my $hash = $self->query({
2542             'method' => 'stopMessageLiveLocation',
2543             'data' => $form,
2544             }) || return( $self->error( "Unable to make post query for method stopMessageLiveLocation: ", $self->error->message ) );
2545 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2546             {
2547 0           return( $self->error( $t_error ) );
2548             }
2549             elsif( $hash->{result} )
2550             {
2551 0   0       my $o = $self->_response_to_object( 'Net::API::Telegram::Message', $hash->{result} ) ||
2552             return( $self->error( "Error while getting an object out of hash for this message: ", $self->error ) );
2553 0           return( $o );
2554             }
2555             else
2556             {
2557 0           return( $hash->{ok} );
2558             }
2559             }
2560              
2561             sub stopPoll
2562             {
2563 0     0 1   my $self = shift( @_ );
2564 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2565 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2566 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2567 0 0         return( $self->error( "Missing parameter message_id" ) ) if( !exists( $opts->{ 'message_id' } ) );
2568 0 0 0       return( $self->error( "Value provided for reply_markup is not a Net::API::Telegram::InlineKeyboardMarkup object." ) ) if( length( $opts->{ 'reply_markup' } ) && ref( $opts->{ 'reply_markup' } ) ne 'Net::API::Telegram::InlineKeyboardMarkup' );
2569 0 0         $self->_load( [qw( Net::API::Telegram::InlineKeyboardMarkup )] ) || return( undef() );
2570 0           my $form = $self->_options2form( $opts );
2571 0   0       my $hash = $self->query({
2572             'method' => 'stopPoll',
2573             'data' => $form,
2574             }) || return( $self->error( "Unable to make post query for method stopPoll: ", $self->error->message ) );
2575 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2576             {
2577 0           return( $self->error( $t_error ) );
2578             }
2579             elsif( $hash->{result} )
2580             {
2581 0   0       my $o = $self->_response_to_object( 'Net::API::Telegram::Poll', $hash->{result} ) ||
2582             return( $self->error( "Error while getting a Poll object out of hash for this message: ", $self->error ) );
2583 0           return( $o );
2584             }
2585             }
2586              
2587             sub unbanChatMember
2588             {
2589 0     0 1   my $self = shift( @_ );
2590 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2591 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2592 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2593 0 0         return( $self->error( "Missing parameter user_id" ) ) if( !exists( $opts->{ 'user_id' } ) );
2594 0           my $form = $self->_options2form( $opts );
2595 0   0       my $hash = $self->query({
2596             'method' => 'unbanChatMember',
2597             'data' => $form,
2598             }) || return( $self->error( "Unable to make post query for method unbanChatMember: ", $self->error->message ) );
2599 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
2600             {
2601 0           return( $self->error( $t_error ) );
2602             }
2603             else
2604             {
2605 0           return( $hash->{ok} );
2606             }
2607             }
2608              
2609             sub unpinChatMessage
2610             {
2611 0     0 1   my $self = shift( @_ );
2612 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2613 0 0         return( $self->error( "Missing parameter chat_id" ) ) if( !exists( $opts->{ 'chat_id' } ) );
2614 0 0         return( $self->error( "Value provided for chat_id is not a valid value. I was expecting one of the following: Integer, String" ) ) if( !length( $opts->{ 'chat_id' } ) );
2615 0           my $form = $self->_options2form( $opts );
2616 0   0       my $hash = $self->query({
2617             'method' => 'unpinChatMessage',
2618             'data' => $form,
2619             }) || return( $self->error( "Unable to make post query for method unpinChatMessage: ", $self->error->message ) );
2620 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
2621             {
2622 0           return( $self->error( $t_error ) );
2623             }
2624             else
2625             {
2626 0           return( $hash->{ok} );
2627             }
2628             }
2629              
2630             sub uploadStickerFile
2631             {
2632 0     0 1   my $self = shift( @_ );
2633 0   0       my $opts = $self->_param2hash( @_ ) || return( undef() );
2634 0 0         return( $self->error( "Missing parameter png_sticker" ) ) if( !exists( $opts->{ 'png_sticker' } ) );
2635 0 0         return( $self->error( "Value provided for png_sticker is not a Net::API::Telegram::InputFile object." ) ) if( ref( $opts->{ 'png_sticker' } ) ne 'Net::API::Telegram::InputFile' );
2636 0 0         return( $self->error( "Missing parameter user_id" ) ) if( !exists( $opts->{ 'user_id' } ) );
2637 0 0         $self->_load( [qw( Net::API::Telegram::InputFile )] ) || return( undef() );
2638 0           my $form = $self->_options2form( $opts );
2639 0   0       my $hash = $self->query({
2640             'method' => 'uploadStickerFile',
2641             'data' => $form,
2642             }) || return( $self->error( "Unable to make post query for method uploadStickerFile: ", $self->error->message ) );
2643 0 0         if( my $t_error = $self->_has_telegram_error( $hash ) )
    0          
2644             {
2645 0           return( $self->error( $t_error ) );
2646             }
2647             elsif( $hash->{result} )
2648             {
2649 0   0       my $o = $self->_response_to_object( 'Net::API::Telegram::File', $hash->{result} ) ||
2650             return( $self->error( "Error while getting a File object out of hash for this message: ", $self->error ) );
2651 0           return( $o );
2652             }
2653             }
2654              
2655             ## END DYNAMICALLY GENERATED METHODS
2656              
2657             ## Private methods
2658             sub _encode_params
2659             {
2660 0     0     my $self = shift( @_ );
2661 0           my $args = shift( @_ );
2662 0 0         if( $self->{ '_encode_with_json' } )
2663             {
2664 0           return( $self->json->utf8->encode( $args ) );
2665             }
2666 0           my @components;
2667 0           foreach my $key ( keys( %$args ) )
2668             {
2669 0           my $ek = URI::Escape::uri_escape( $key );
2670 0           my $value = $args->{ $key };
2671 0           my $pkg = Scalar::Util::blessed( $value );
2672 0 0 0       if( $pkg && $pkg =~ /^AI::Net::Stripe/ && exists( $value->{ 'id' } ) )
      0        
2673             {
2674 0           push( @components, $ek . '=' . $value->{ 'id' } );
2675 0           next;
2676             }
2677              
2678 0           my $ref = ref( $value );
2679 0 0         if( $ref eq 'HASH' )
    0          
2680             {
2681 0           foreach my $sk ( keys( %$value ) )
2682             {
2683 0           my $sv = $value->{ $sk };
2684             ## don't think this PHP convention goes deeper
2685 0 0 0       next if( ref( $sv ) || !length( $sv ) );
2686 0           push( @components, sprintf( '%s[%s]=%s', $ek, URI::Escape::uri_escape( $sk ), URI::Escape::uri_escape_utf8( $sv ) ) );
2687             }
2688             }
2689             elsif( $ref eq 'ARRAY' )
2690             {
2691 0           foreach my $sv ( @$value )
2692             {
2693             ## again, I think we can't go deeper
2694 0 0         next if( ref( $sv ) );
2695 0           push( @components, sprintf( '%s[]=%s', $ek, URI::Escape::uri_escape_utf8( $sv ) ) );
2696             }
2697             }
2698             else
2699             {
2700             ## JSON boolean stringification magic has been erased
2701 0 0         $value = ref( $value ) eq 'JSON::PP::Boolean'
    0          
2702             ? $value
2703             ? 'true'
2704             : 'false'
2705             : URI::Escape::uri_escape_utf8( $value );
2706 0           push( @components, "${ek}=${value}" );
2707             }
2708             }
2709 0           return( join( '&', @components ) );
2710             }
2711              
2712             sub _has_telegram_error
2713             {
2714 0     0     my $self = shift( @_ );
2715 0   0       my $hash = shift( @_ ) || return( $self->error( "No hash reference was provided to check if it contains a Telegram api error." ) );
2716             ## "The response contains a JSON object, which always has a Boolean field ‘ok’ and may have an optional String field ‘description’ with a human-readable description of the result. If ‘ok’ equals true, the request was successful and the result of the query can be found in the ‘result’ field.
2717             ## In case of an unsuccessful request, ‘ok’ equals false and the error is explained in the ‘description’. An Integer ‘error_code’ field is also returned, but its contents are subject to change in the future. Some errors may also have an optional field ‘parameters’ of the type ResponseParameters, which can help to automatically handle the error."
2718             ## https://core.telegram.org/bots/api#making-requests
2719 0 0         return if( !exists( $hash->{ok} ) );
2720 0 0         return if( $hash->{ok} );
2721 0           my $desc = $hash->{description};
2722 0           my $code = $hash->{error_code};
2723 0           my $o = Net::API::Telegram::Error->new;
2724 0           $o->message( $desc );
2725 0           $o->code( $code );
2726 0 0 0       if( exists( $hash->{parameters} ) && ref( $hash->{parameters} ) eq 'HASH' )
2727             {
2728 0 0         if( $hash->{parameters}->{retry_after} )
2729             {
2730 0 0         $desc .= ' ' if( length( $desc ) );
2731 0           $desc .= sprintf( 'Retry after %d seconds', $hash->{parameters}->{retry_after} );
2732 0           $o->message( $desc );
2733 0           $o->retry_after( $hash->{parameters}->{retry_after} );
2734             }
2735             }
2736 0           return( $o );
2737             }
2738              
2739             sub _instantiate
2740             {
2741 0     0     my $self = shift( @_ );
2742 0           my $name = shift( @_ );
2743 0 0 0       return( $self->{ $name } ) if( exists( $self->{ $name } ) && Scalar::Util::blessed( $self->{ $name } ) );
2744 0           my $class = shift( @_ );
2745 0   0       my $this = $class->new(
2746             'debug' => $self->debug,
2747             'verbose' => $self->verbose,
2748             ) || return( $self->error( $class->error ) );
2749 0           $this->{ 'parent' } = $self;
2750 0           return( $this );
2751             }
2752              
2753             sub _load
2754             {
2755 0     0     my $self = shift( @_ );
2756 0           my $arr = shift( @_ );
2757 0 0         return( $self->error( "Parameter provided is not an array. I am expecting an array of package name like this [qw( Some::Thing Some::Else )]" ) ) if( ref( $arr ) ne 'ARRAY' );
2758 0           foreach my $pkg ( @$arr )
2759             {
2760             ## eval( "require $pkg;" ) unless( defined( *{"${pkg}::"} ) );
2761 0           my $rc = eval{ $self->_load_class( $pkg ); };
  0            
2762 0 0         return( $self->error( "An error occured while trying to load the module $pkg: $@" ) ) if( $@ );
2763             }
2764 0           return( 1 );
2765             }
2766              
2767             sub _load_file
2768             {
2769 0     0     my $self = shift( @_ );
2770 0   0       my $fpath = shift( @_ ) || return( $self->error( "No file path to load into memory was provided" ) );
2771 0 0         return( $self->error( "File '$fpath' provided does not exist." ) ) if( !-e( $fpath ) );
2772 0 0         return( $self->error( "File '$fpath' provided is not readable." ) ) if( !-r( $fpath ) );
2773 0 0         return( $self->error( "File '$fpath' size of %d bytes exceeds maximum %d bytes" ) ) if( -s( $fpath ) > FILE_MAX_SIZE );
2774 0           my $data;
2775 0           File::Map::map_file( $data, $fpath );
2776 0           return( $data );
2777             }
2778              
2779             sub _make_error
2780             {
2781 0     0     my $self = shift( @_ );
2782 0           my $args = shift( @_ );
2783 0 0 0       if( !exists( $args->{ 'file' } ) || !exists( $args->{ 'line' } ) )
2784             {
2785 0           my( $pack, $file, $line ) = caller;
2786 0           my $sub = ( caller( 1 ) )[ 3 ];
2787 0           my $sub2 = substr( $sub, rindex( $sub, '::' ) + 2 );
2788 0           @$args{ qw( package file line sub ) } = ( $pack, $file, $line, $sub2 );
2789             }
2790             ## my $o = AI::Net::Stripe::Error->new( %$args );
2791 0           my $trace = Devel::StackTrace->new( ignore_package => __PACKAGE__ );
2792 0           $args->{ 'trace' } = $trace;
2793 0           return( $self->error( $args ) );
2794             }
2795              
2796             sub _options2form
2797             {
2798 0     0     my $self = shift( @_ );
2799 0   0       my $opts = shift( @_ ) || return;
2800 0 0         return( $self->error( "Options hash reference provided ($opts) is not an hash reference" ) ) if( ref( $opts ) ne 'HASH' );
2801 0           my $form = {};
2802 0           my $opt_anti_loop = '_opt2form_anti_loop_' . time();
2803             local $crawl = sub
2804             {
2805 0     0     my $this = shift( @_ );
2806             ## $self->message( 3, "\tChecking '$this'" );
2807 0 0         if( Scalar::Util::blessed( $this ) )
    0          
    0          
2808             {
2809 0 0 0       $this->debug( $self->debug ) if( ref( $this ) =~ /Net::API::Telegram::/ && $this->can( 'debug' ) );
2810             ## $self->message( 3, "'$this' is a blessed object." );
2811 0 0         if( $this->can( 'as_hash' ) )
    0          
    0          
2812             {
2813             ## $self->message( 3, "'$this' can do as_hash: ", sub{ $self->dumper( $this ) } );
2814 0           return( $this->as_hash( $opt_anti_loop ) );
2815             }
2816             elsif( overload::Overloaded( $this ) )
2817             {
2818             ## $self->message( 3, "'$this' is overloaded. Returning '$this'." );
2819 0           return( "$this" );
2820             }
2821             elsif( $this->can( 'as_string' ) )
2822             {
2823             ## $self->message( 3, "'$this' can do as_string()." );
2824 0           return( $this->as_string );
2825             }
2826             else
2827             {
2828             ## $self->message( 3, "Clueless what to do with '$this'." );
2829 0           warn( "Warning: do not know what to do with this object '$this'. It does not support as_hash, as_string and is not overloaded.\n" );
2830             }
2831             }
2832             elsif( ref( $this ) eq 'HASH' )
2833             {
2834 0           my $ref = {};
2835 0 0         if( exists( $this->{ $opt_anti_loop } ) )
2836             {
2837 0           my @keys = grep( /^${opt_anti_loop}$/, keys( %$this ) );
2838 0           my $new = {};
2839 0           @$new{ @keys } = @$this{ @keys };
2840 0           return( $new );
2841             }
2842 0           foreach my $k ( keys( %$this ) )
2843             {
2844 0           $ref->{ $k } = $crawl->( $this->{ $k } );
2845             }
2846 0           return( $ref );
2847             }
2848             elsif( ref( $this ) eq 'ARRAY' )
2849             {
2850 0           my $arr = [];
2851 0           foreach my $v ( @$this )
2852             {
2853 0           my $res = $crawl->( $v );
2854 0 0         push( @$arr, $res ) if( length( $res ) );
2855             }
2856 0           return( $arr );
2857             }
2858             ## Not an object, a hash, an array. It's got to be a scalar...
2859             else
2860             {
2861             ## $self->message( 3, "\tReturning scalar '$this'." );
2862 0           return( $this );
2863             }
2864 0           };
2865            
2866 0     0     $self->message( 3, "Provided options data is: ", sub{ $self->dumper( $opts ) } );
  0            
2867 0           foreach my $k ( keys( %$opts ) )
2868             {
2869 0 0         if( length( $opts->{ $k } ) )
2870             {
2871 0           $form->{ $k } = $crawl->( $opts->{ $k } );
2872             }
2873             }
2874 0     0     $self->message( 3, "Resulting form data is: ", sub{ $self->dumper( $form ) } );
  0            
2875 0           return( $form );
2876             }
2877              
2878             sub _param2hash
2879             {
2880 0     0     my $self = shift( @_ );
2881 0           my $opts = {};
2882 0 0         if( scalar( @_ ) )
2883             {
2884 0 0         if( ref( $_[0] ) eq 'HASH' )
    0          
2885             {
2886 0           $opts = shift( @_ );
2887             }
2888             elsif( !( scalar( @_ ) % 2 ) )
2889             {
2890 0           $opts = { @_ };
2891             }
2892             else
2893             {
2894 0           return( $self->error( "Uneven number of parameters. I was expecting a hash or a hash reference." ) );
2895             }
2896             }
2897 0           return( $opts );
2898             }
2899              
2900             sub _param_check_array_object
2901             {
2902 0     0     my $self = shift( @_ );
2903 0   0       my $patt = shift( @_ ) || return( $self->error( "No pattern to check array of objects was provided." ) );
2904 0   0       my $arr = shift( @_ ) || return( $self->error( "No array of objects was provided." ) );
2905 0 0         return( $self->error( "Pattern provided is not a pattern object. I was expecting something like qr/^(?:Some::Thing)\$/" ) ) if( ref( $patt ) ne 'Regexp' );
2906 0 0         return( $self->error( "Array provided ($arr) is not an array reference." ) ) if( ref( $arr ) ne 'ARRAY' );
2907 0           foreach my $o ( @$arr )
2908             {
2909 0 0         return( $self->error( "Object provided '", ref( $o ), ", ' is not a valid object matching pattern $patt" ) ) if( ref( $o ) !~ /$patt/ );
2910             }
2911 0           return( 1 );
2912             }
2913              
2914             sub _response_to_object
2915             {
2916 0     0     my $self = shift( @_ );
2917 0           my $class = shift( @_ );
2918 0   0       my $hash = shift( @_ ) || return( $self->error( "No hash was provided" ) );
2919 0 0 0       return( $self->error( "Hash provided ($hash) is not a hash reference." ) ) if( $hash && ref( $hash ) ne 'HASH' );
2920 0           $self->message( 3, "Called for class $class with hash $hash" );
2921 0 0         $self->_load( [ $class ] ) || return( undef() );
2922 0           my $o;
2923 0           try
2924 1     1   22069 {
  0            
  0            
  0            
2925 0           $o = $class->new( $self, $hash );
2926             }
2927             catch( $e )
2928 1 0   1   24469 {
  0            
  0            
  0            
  0            
2929 0           return( $self->error( "Canot instantiate object for class $class: $e" ) );
2930             }
2931 0           $self->message( 3, "Returning object $o for class $class" );
  0            
2932 0           return( $o );
2933             }
2934              
2935             sub _response_array_to_object
2936             {
2937 0     0     my $self = shift( @_ );
2938 0           my $class = shift( @_ );
2939 0   0       my $arr = shift( @_ ) || return( $self->error( "No array reference was provided" ) );
2940 0 0 0       return( $self->error( "Array provided ($arr) is not an array reference." ) ) if( $arr && ref( $arr ) ne 'ARRAY' );
2941 0           $self->message( 3, "Called for class $class with array $arr" );
2942 0 0         $self->_load( [ $class ] ) || return( undef() );
2943 0           my $all = [];
2944 0           foreach my $ref ( @$arr )
2945             {
2946 0 0         if( ref( $ref ) eq 'HASH' )
2947             {
2948 0           my $o;
2949 0           try
2950 1     1   676 {
  0            
  0            
  0            
2951 0           $o = $class->new( $self, $ref );
2952             }
2953             catch( $e )
2954 1 0   1   24321 {
  0            
  0            
  0            
  0            
2955 0           return( $self->error( "Unable to instantiate an object of class $class: $e" ) );
2956             }
2957 0           push( @$all, $o );
  0            
2958             }
2959             else
2960             {
2961 0           $self->error( "Warning only: data provided to instaantiate object of class $class is not a hash reference" );
2962             }
2963             }
2964 0           return( $all );
2965             }
2966              
2967             # DESTROY
2968             # {
2969             # my $self = shift( @_ );
2970             # my( $pack, $file, $line ) = caller;
2971             # $self->message( 3, "Called from package $pack in file $file at line $line" );
2972             # $self->message( 3, "Cleaning up call from pid $$..." );
2973             # $self->message( 3, "Pid $$ is a child pid. We don't cleanup." ) if( exists( $CHILDREN->{ $$ } ) );
2974             # $self->message( 3, "Current children pid registered are: ", join( ', ', sort( keys( %$CHILDREN ) ) ) );
2975             # $self->cleanup unless( exists( $CHILDREN->{ $$ } ) );
2976             # ## Wrap it up within 5 seconds max
2977             # alarm( 5 );
2978             # eval
2979             # {
2980             # local $SIG{ 'ALRM' } = sub{ die( "Timeout\n" ); };
2981             # $self->stop;
2982             # };
2983             # alarm( 0 );
2984             # if( $@ =~ /timeout/i )
2985             # {
2986             # $self->message( 1, "Timeout when cleaning up before exiting." );
2987             # }
2988             # };
2989              
2990             1;
2991              
2992             __END__
2993              
2994             =encoding utf-8
2995              
2996             =head1 NAME
2997              
2998             Net::API::Telegram - Telegram Bot Interface
2999              
3000             =head1 SYNOPSIS
3001              
3002             my $t = Net::API::Telegram->new(
3003             debug => $DEBUG,
3004             webhook => 1,
3005             ## This would contain a token property with the Telegram api token
3006             config_file => "./settings.json",
3007             ## Since we are testing, we want to process even old messages
3008             skip_past_messages => -86400,
3009             # use_ssl => 1,
3010             # ssl_cert => $ssl_certificate,
3011             # ssl_key => $ssl_key,
3012             external_ssl => 1,
3013             external_path => 'tg',
3014             external_host => 'www.higotonofukuin.org',
3015             external_port => 443,
3016             logging => 1,
3017             log_file => $log_file,
3018             debug_log_file => $debug_log_file,
3019             error_handler => \&handleError,
3020             ) || die( Net::API::Telegram->error->message, "\n" );
3021            
3022             ## Declare some handlers
3023             $t->handler(
3024             message => \&processMessage,
3025             );
3026             $t->start || die( "Error starting: ", $t->error->message, "\n" );
3027              
3028             =head1 VERSION
3029              
3030             This is version 0.6
3031              
3032             =head1 DESCRIPTION
3033              
3034             L<Net::API::Telegram> is a powerful and yet simple interface to Telegram Bot api.
3035              
3036             L<Net::API::Telegram> inherits from C<Module::Generic> and all its module excepted for C<Net::API::Telegram::Generic> and C<Net::API::Telegram::Number> are aut generated base don Telegram api online documentation.
3037              
3038             =head1 CORE METHODS
3039              
3040             =over 4
3041              
3042             =item B<new>( [ TOKEN ], %PARAMETERS )
3043              
3044             This initiate a L<Net::API::Telegram> object as an accessor to all the core methods and api methods.
3045              
3046             It can take the following parameters:
3047              
3048             =over 8
3049              
3050             =item I<browser>
3051              
3052             This is the name of the browser our http agent will take as identity when communicating with the Telegram api.
3053              
3054             BY default, it looks like C<DEGUEST_Bot/0.1>
3055              
3056             =item I<conf_file>
3057              
3058             This is an optional configuration file in json format that contains properties. For example, it can contain the property I<token> to avoid passing it as argument.
3059              
3060             =item I<cookie_file>
3061              
3062             This takes a cookie file path. By default it is empty. The Telegram api does not send cookie, so it should not be needed.
3063              
3064             =item I<debug>
3065              
3066             Defaults to 0 (false). Can be set to any digit. The higher, the more debug output.
3067              
3068             =item I<encode_with_json>
3069              
3070             Can be true or false. Defaults to false.
3071              
3072             If true, L<Net::API::Telegram> will encode data in json format and send it to the server rather than using the url-encoded format.
3073              
3074             =item I<host>
3075              
3076             This is the host to set up the webhook. It will be provided as part of the uri our L<HTTP::Daemon> server listens to. The path is randomly generated to ensure some level of security.
3077              
3078             =item I<port>
3079              
3080             This is the host to set up the webhook.
3081              
3082             =item I<ssl_cert>
3083              
3084             Pass to the ssl certificate. This is used to run the ssl http server and to be sent to Telegram.
3085              
3086             This parameter is necessary only under ssl with the I<use_ssl>.
3087              
3088             If the server is run on a host with certificate signed by a proper authority like Let's Encrypt, the certificate does not need to be sent to Telegram.
3089              
3090             To create a ssl key and certificate, you can use the following command:
3091              
3092             openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/C=JP/ST=Tokyo/L=Tokyo/O=Deguest Pte. Ltd./OU=Org/CN=www.example.jp"
3093              
3094             Ref: L<https://stackoverflow.com/questions/10175812/how-to-create-a-self-signed-certificate-with-openssl>
3095              
3096             =item I<ssl_key>
3097              
3098             Path to the ssl key. This is used to run the ssl http server.
3099              
3100             This parameter is necessary only under ssl with the I<use_ssl>.
3101              
3102             =item I<timeout>
3103              
3104             The timeout in second when making http requests. It defaults to 5 seconds.
3105              
3106             =item I<token>
3107              
3108             This is a required item. It can be provided either the first parameter of the B<new>() method or as a hash parameter. Example:
3109              
3110             my $t = Net::API::Telegram->new( '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11', debug => 3, webhook => 1 );
3111            
3112             ## or
3113            
3114             my $t = Net::API::Telegram->new( 'token' => '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11', debug => 3, webhook => 1 );
3115              
3116             =item I<use_ssl>
3117              
3118             Can be true or false. If true, the server launched to handle the webhook will run under ssl. Please note that Telegram only accepts webhooks that run under ssl.
3119              
3120             =item I<verbose>
3121              
3122             Defaults to 0 (false).
3123              
3124             =item I<webhook>
3125              
3126             Either true or false. If true, this will initiate the web token and automatically declare it to the Telegram server. It defaults to false.
3127              
3128             =back
3129              
3130             =item B<agent>()
3131              
3132             It returns a L<LWP::UserAgent> object which is used to make http calls to Telegram api.
3133              
3134             =item B<api_uri>()
3135              
3136             This returns the uri of the api for our bot. It would be something like: L<https://api.telegram.org/bot123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11>
3137              
3138             =item B<data2json>( JSON )
3139              
3140             Given a json data this returns an equivalent structure in perl, so a hash reference.
3141              
3142             =item B<debug>( TRUE | FALSE )
3143              
3144             Set or get the debug value, which is an integer. 0 deactivate debug mode and a number greater than 0 activates it. The greater the number, the more debug output.
3145              
3146             =item B<error>( ERROR )
3147              
3148             Sets or get an error. When making calls to methods under this package and package children, if the return value is undef(), then it means an error has been set and can be retrieved with C<$t->error>
3149              
3150             The error retrieved is a L<Net::API::Telegram::Error> object that has the following properties:
3151              
3152             =over 8
3153              
3154             =item I<type>
3155              
3156             This is the type of error, if any. It could be empty.
3157              
3158             =item I<code>
3159              
3160             This is the error code using the http standard.
3161              
3162             =item I<message>
3163              
3164             This is the error message.
3165              
3166             =item I<file>
3167              
3168             The file from which the error came from.
3169              
3170             =item I<line>
3171              
3172             The line at which the error was triggered.
3173              
3174             =item I<package>
3175              
3176             The perl module name from which the error occurred.
3177              
3178             =item I<sub>
3179              
3180             The subroutine that triggered the error.
3181              
3182             =item I<trace>
3183              
3184             This is a Devel::StackTrace which can be stringified. This provides the full stack trace of the error.
3185              
3186             =item I<retry_after>
3187              
3188             This is optional, and represents the number of seconds to wait until the next attempt. This is provided as a response by the Telegram api.
3189              
3190             =back
3191              
3192             =item B<generate_uuid>()
3193              
3194             This will generate a new uuid using L<Data::UUID>.
3195              
3196             =item B<launch_daemon>()
3197              
3198             This will prepare a new http daemon to listen for the webhook
3199              
3200             =item B<port>( INTEGER )
3201              
3202             This sets the port that will be used by L<HTTP::Daemon> to listen for webhooks.
3203              
3204             The only acceptable ports, as per Telegram Bot API documentation, are: 443, 80, 88, 8443.
3205              
3206             It returns the current value set, if any.
3207              
3208             Ref: L<https://core.telegram.org/bots/api#setwebhook>
3209              
3210             =item B<query>( { PARAMETERS } )
3211              
3212             This takes an hash reference as parameters, and issues a http post request to Telegram api. If successful, it returns a hash reference of the data returned by Telegram api, otherwise it returns undef() upon an error.
3213              
3214             =item B<start>()
3215              
3216             This will start processing requests received by the bot.
3217              
3218             If the I<webhook> option was set, this will start the http daemon, as prepared with the B<launch_daemon>() method.
3219              
3220             Otherwise, this will probe indefinitely, in a loop, the Telegram server using the api method B<getUpdates>()
3221              
3222             It will receive json data from Telegram in the form of a L<Net::API::Telegram::Update> object.
3223              
3224             Ref: L<https://core.telegram.org/bots/api#update>
3225              
3226             =item B<verbose>( [ TRUE | FALSE ] )
3227              
3228             This sets or get the value of verbose.
3229              
3230             =item B<webhook>( [ TRUE | FALSE ] )
3231              
3232             This sets the boolean flag for the option I<webhook>. If set to true, this will call the B<launch_daemon>() method. It will also create a randomly generated path which can be retrieved using the B<webhook_path> method.
3233              
3234             =item B<webhook_path>()
3235              
3236             Returns the webhook path randomly generated. If webhook has not been activated this will return an empty string.
3237              
3238             =back
3239              
3240             =head1 API METHODS
3241              
3242             =over 4
3243              
3244             =item B<answerCallbackQuery>( %PARAMETERS )
3245              
3246             Use this method to send answers to callback queries sent from inline keyboards. The answer will be displayed to the user as a notification at the top of the chat screen or as an alert. On success, True is returned.
3247              
3248             Reference: L<https://core.telegram.org/bots/api#answercallbackquery>
3249              
3250             This methods takes the following parameters:
3251              
3252             =over 8
3253              
3254             =item I<cache_time>
3255              
3256             This parameter type is Integer and is optional.
3257              
3258             The maximum amount of time in seconds that the result of the callback query may be cached client-side. Telegram apps will support caching starting in version 3.14. Defaults to 0.
3259              
3260             =item I<callback_query_id>
3261              
3262             This parameter type is String and is required.
3263              
3264             Unique identifier for the query to be answered
3265              
3266             =item I<show_alert>
3267              
3268             This parameter type is Boolean and is optional.
3269              
3270             If true, an alert will be shown by the client instead of a notification at the top of the chat screen. Defaults to false.
3271              
3272             =item I<text>
3273              
3274             This parameter type is String and is optional.
3275              
3276             Text of the notification. If not specified, nothing will be shown to the user, 0-200 characters
3277              
3278             =item I<url>
3279              
3280             This parameter type is String and is optional.
3281              
3282             URL that will be opened by the user's client. If you have created a Game and accepted the conditions via @Botfather, specify the URL that opens your game – note that this will only work if the query comes from a callback_game button.Otherwise, you may use links like t.me/your_bot?start=XXXX that open your bot with a parameter.
3283              
3284             =back
3285              
3286             =item B<answerInlineQuery>( %PARAMETERS )
3287              
3288             Use this method to send answers to an inline query. On success, True is returned.No more than 50 results per query are allowed.
3289              
3290             Reference: L<https://core.telegram.org/bots/api#answerinlinequery>
3291              
3292             This methods takes the following parameters:
3293              
3294             =over 8
3295              
3296             =item I<cache_time>
3297              
3298             This parameter type is Integer and is optional.
3299              
3300             The maximum amount of time in seconds that the result of the inline query may be cached on the server. Defaults to 300.
3301              
3302             =item I<inline_query_id>
3303              
3304             This parameter type is String and is required.
3305              
3306             Unique identifier for the answered query
3307              
3308             =item I<is_personal>
3309              
3310             This parameter type is Boolean and is optional.
3311              
3312             Pass True, if results may be cached on the server side only for the user that sent the query. By default, results may be returned to any user who sends the same query
3313              
3314             =item I<next_offset>
3315              
3316             This parameter type is String and is optional.
3317              
3318             Pass the offset that a client should send in the next query with the same text to receive more results. Pass an empty string if there are no more results or if you don‘t support pagination. Offset length can’t exceed 64 bytes.
3319              
3320             =item I<results>
3321              
3322             This parameter type is an array of L<Net::API::Telegram::InlineQueryResult> and is required.
3323             A JSON-serialized array of results for the inline query
3324              
3325             =item I<switch_pm_parameter>
3326              
3327             This parameter type is String and is optional.
3328              
3329             Deep-linking parameter for the /start message sent to the bot when user presses the switch button. 1-64 characters, only A-Z, a-z, 0-9, _ and - are allowed.Example: An inline bot that sends YouTube videos can ask the user to connect the bot to their YouTube account to adapt search results accordingly. To do this, it displays a ‘Connect your YouTube account’ button above the results, or even before showing any. The user presses the button, switches to a private chat with the bot and, in doing so, passes a start parameter that instructs the bot to return an oauth link. Once done, the bot can offer a switch_inline button so that the user can easily return to the chat where they wanted to use the bot's inline capabilities.
3330              
3331             =item I<switch_pm_text>
3332              
3333             This parameter type is String and is optional.
3334              
3335             If passed, clients will display a button with specified text that switches the user to a private chat with the bot and sends the bot a start message with the parameter switch_pm_parameter
3336              
3337             =back
3338              
3339             =item B<answerPreCheckoutQuery>( %PARAMETERS )
3340              
3341             Once the user has confirmed their payment and shipping details, the Bot API sends the final confirmation in the form of an Update with the field pre_checkout_query. Use this method to respond to such pre-checkout queries. On success, True is returned. Note: The Bot API must receive an answer within 10 seconds after the pre-checkout query was sent.
3342              
3343             Reference: L<https://core.telegram.org/bots/api#answerprecheckoutquery>
3344              
3345             This methods takes the following parameters:
3346              
3347             =over 8
3348              
3349             =item I<error_message>
3350              
3351             This parameter type is String and is optional.
3352              
3353             Required if ok is False. Error message in human readable form that explains the reason for failure to proceed with the checkout (e.g. "Sorry, somebody just bought the last of our amazing black T-shirts while you were busy filling out your payment details. Please choose a different color or garment!"). Telegram will display this message to the user.
3354              
3355             =item I<ok>
3356              
3357             This parameter type is Boolean and is required.
3358              
3359             Specify True if everything is alright (goods are available, etc.) and the bot is ready to proceed with the order. Use False if there are any problems.
3360              
3361             =item I<pre_checkout_query_id>
3362              
3363             This parameter type is String and is required.
3364              
3365             Unique identifier for the query to be answered
3366              
3367             =back
3368              
3369             =item B<answerShippingQuery>( %PARAMETERS )
3370              
3371             If you sent an invoice requesting a shipping address and the parameter is_flexible was specified, the Bot API will send an Update with a shipping_query field to the bot. Use this method to reply to shipping queries. On success, True is returned.
3372              
3373             Reference: L<https://core.telegram.org/bots/api#answershippingquery>
3374              
3375             This methods takes the following parameters:
3376              
3377             =over 8
3378              
3379             =item I<error_message>
3380              
3381             This parameter type is String and is optional.
3382              
3383             Required if ok is False. Error message in human readable form that explains why it is impossible to complete the order (e.g. "Sorry, delivery to your desired address is unavailable'). Telegram will display this message to the user.
3384              
3385             =item I<ok>
3386              
3387             This parameter type is Boolean and is required.
3388              
3389             Specify True if delivery to the specified address is possible and False if there are any problems (for example, if delivery to the specified address is not possible)
3390              
3391             =item I<shipping_options>
3392              
3393             This parameter type is an array of L<Net::API::Telegram::ShippingOption> and is optional.
3394             Required if ok is True. A JSON-serialized array of available shipping options.
3395              
3396             =item I<shipping_query_id>
3397              
3398             This parameter type is String and is required.
3399              
3400             Unique identifier for the query to be answered
3401              
3402             =back
3403              
3404             =item B<createNewStickerSet>( %PARAMETERS )
3405              
3406             Use this method to create new sticker set owned by a user. The bot will be able to edit the created sticker set. Returns True on success.
3407              
3408             Reference: L<https://core.telegram.org/bots/api#createnewstickerset>
3409              
3410             This methods takes the following parameters:
3411              
3412             =over 8
3413              
3414             =item I<contains_masks>
3415              
3416             This parameter type is Boolean and is optional.
3417              
3418             Pass True, if a set of mask stickers should be created
3419              
3420             =item I<emojis>
3421              
3422             This parameter type is String and is required.
3423              
3424             One or more emoji corresponding to the sticker
3425              
3426             =item I<mask_position>
3427              
3428             This parameter type is an object L<Net::API::Telegram::MaskPosition> and is optional.
3429             A JSON-serialized object for position where the mask should be placed on faces
3430              
3431             =item I<name>
3432              
3433             This parameter type is String and is required.
3434              
3435             Short name of sticker set, to be used in t.me/addstickers/ URLs (e.g., animals). Can contain only english letters, digits and underscores. Must begin with a letter, can't contain consecutive underscores and must end in “_by_<bot username>”. <bot_username> is case insensitive. 1-64 characters.
3436              
3437             =item I<png_sticker>
3438              
3439             This parameter type is one of the following L<InputFile> or String and is required.
3440             Png image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More info on Sending Files »
3441              
3442             =item I<title>
3443              
3444             This parameter type is String and is required.
3445              
3446             Sticker set title, 1-64 characters
3447              
3448             =item I<user_id>
3449              
3450             This parameter type is Integer and is required.
3451              
3452             User identifier of created sticker set owner
3453              
3454             =back
3455              
3456             =item B<deleteChatPhoto>( %PARAMETERS )
3457              
3458             Use this method to delete a chat photo. Photos can't be changed for private chats. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
3459              
3460             Reference: L<https://core.telegram.org/bots/api#deletechatphoto>
3461              
3462             This methods takes the following parameters:
3463              
3464             =over 8
3465              
3466             =item I<chat_id>
3467              
3468             This parameter type is one of the following Integer or String and is required.
3469             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
3470              
3471             =back
3472              
3473             =item B<deleteChatStickerSet>( %PARAMETERS )
3474              
3475             Use this method to delete a group sticker set from a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success.
3476              
3477             Reference: L<https://core.telegram.org/bots/api#deletechatstickerset>
3478              
3479             This methods takes the following parameters:
3480              
3481             =over 8
3482              
3483             =item I<chat_id>
3484              
3485             This parameter type is one of the following Integer or String and is required.
3486             Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
3487              
3488             =back
3489              
3490             =item B<deleteMessage>( %PARAMETERS )
3491              
3492             Use this method to delete a message, including service messages, with the following limitations:- A message can only be deleted if it was sent less than 48 hours ago.- Bots can delete outgoing messages in private chats, groups, and supergroups.- Bots can delete incoming messages in private chats.- Bots granted can_post_messages permissions can delete outgoing messages in channels.- If the bot is an administrator of a group, it can delete any message there.- If the bot has can_delete_messages permission in a supergroup or a channel, it can delete any message there.Returns True on success.
3493              
3494             Reference: L<https://core.telegram.org/bots/api#deletemessage>
3495              
3496             This methods takes the following parameters:
3497              
3498             =over 8
3499              
3500             =item I<chat_id>
3501              
3502             This parameter type is one of the following Integer or String and is required.
3503             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
3504              
3505             =item I<message_id>
3506              
3507             This parameter type is Integer and is required.
3508              
3509             Identifier of the message to delete
3510              
3511             =back
3512              
3513             =item B<deleteStickerFromSet>( %PARAMETERS )
3514              
3515             Use this method to delete a sticker from a set created by the bot. Returns True on success.
3516              
3517             Reference: L<https://core.telegram.org/bots/api#deletestickerfromset>
3518              
3519             This methods takes the following parameters:
3520              
3521             =over 8
3522              
3523             =item I<sticker>
3524              
3525             This parameter type is String and is required.
3526              
3527             File identifier of the sticker
3528              
3529             =back
3530              
3531             =item B<deleteWebhook>()
3532              
3533             Use this method to remove webhook integration if you decide to switch back to getUpdates. Returns True on success. Requires no parameters.
3534              
3535             Reference: L<https://core.telegram.org/bots/api#deletewebhook>
3536              
3537             This method does not take any parameter.
3538              
3539             =item B<editMessageCaption>( %PARAMETERS )
3540              
3541             Use this method to edit captions of messages. On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned.
3542              
3543             Reference: L<https://core.telegram.org/bots/api#editmessagecaption>
3544              
3545             This methods takes the following parameters:
3546              
3547             =over 8
3548              
3549             =item I<caption>
3550              
3551             This parameter type is String and is optional.
3552              
3553             New caption of the message
3554              
3555             =item I<chat_id>
3556              
3557             This parameter type is one of the following Integer or String and is optional.
3558             Required if inline_message_id is not specified. Unique identifier for the target chat or username of the target channel (in the format @channelusername)
3559              
3560             =item I<inline_message_id>
3561              
3562             This parameter type is String and is optional.
3563              
3564             Required if chat_id and message_id are not specified. Identifier of the inline message
3565              
3566             =item I<message_id>
3567              
3568             This parameter type is Integer and is optional.
3569              
3570             Required if inline_message_id is not specified. Identifier of the message to edit
3571              
3572             =item I<parse_mode>
3573              
3574             This parameter type is String and is optional.
3575              
3576             Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
3577              
3578             =item I<reply_markup>
3579              
3580             This parameter type is an object L<Net::API::Telegram::InlineKeyboardMarkup> and is optional.
3581             A JSON-serialized object for an inline keyboard.
3582              
3583             =back
3584              
3585             =item B<editMessageLiveLocation>( %PARAMETERS )
3586              
3587             Use this method to edit live location messages. A location can be edited until its live_period expires or editing is explicitly disabled by a call to stopMessageLiveLocation. On success, if the edited message was sent by the bot, the edited Message is returned, otherwise True is returned.
3588              
3589             Reference: L<https://core.telegram.org/bots/api#editmessagelivelocation>
3590              
3591             This methods takes the following parameters:
3592              
3593             =over 8
3594              
3595             =item I<chat_id>
3596              
3597             This parameter type is one of the following Integer or String and is optional.
3598             Required if inline_message_id is not specified. Unique identifier for the target chat or username of the target channel (in the format @channelusername)
3599              
3600             =item I<inline_message_id>
3601              
3602             This parameter type is String and is optional.
3603              
3604             Required if chat_id and message_id are not specified. Identifier of the inline message
3605              
3606             =item I<latitude>
3607              
3608             This parameter type is Float number and is required.
3609              
3610             Latitude of new location
3611              
3612             =item I<longitude>
3613              
3614             This parameter type is Float number and is required.
3615              
3616             Longitude of new location
3617              
3618             =item I<message_id>
3619              
3620             This parameter type is Integer and is optional.
3621              
3622             Required if inline_message_id is not specified. Identifier of the message to edit
3623              
3624             =item I<reply_markup>
3625              
3626             This parameter type is an object L<Net::API::Telegram::InlineKeyboardMarkup> and is optional.
3627             A JSON-serialized object for a new inline keyboard.
3628              
3629             =back
3630              
3631             =item B<editMessageMedia>( %PARAMETERS )
3632              
3633             Use this method to edit animation, audio, document, photo, or video messages. If a message is a part of a message album, then it can be edited only to a photo or a video. Otherwise, message type can be changed arbitrarily. When inline message is edited, new file can't be uploaded. Use previously uploaded file via its file_id or specify a URL. On success, if the edited message was sent by the bot, the edited Message is returned, otherwise True is returned.
3634              
3635             Reference: L<https://core.telegram.org/bots/api#editmessagemedia>
3636              
3637             This methods takes the following parameters:
3638              
3639             =over 8
3640              
3641             =item I<chat_id>
3642              
3643             This parameter type is one of the following Integer or String and is optional.
3644             Required if inline_message_id is not specified. Unique identifier for the target chat or username of the target channel (in the format @channelusername)
3645              
3646             =item I<inline_message_id>
3647              
3648             This parameter type is String and is optional.
3649              
3650             Required if chat_id and message_id are not specified. Identifier of the inline message
3651              
3652             =item I<media>
3653              
3654             This parameter type is an object L<Net::API::Telegram::InputMedia> and is required.
3655             A JSON-serialized object for a new media content of the message
3656              
3657             =item I<message_id>
3658              
3659             This parameter type is Integer and is optional.
3660              
3661             Required if inline_message_id is not specified. Identifier of the message to edit
3662              
3663             =item I<reply_markup>
3664              
3665             This parameter type is an object L<Net::API::Telegram::InlineKeyboardMarkup> and is optional.
3666             A JSON-serialized object for a new inline keyboard.
3667              
3668             =back
3669              
3670             =item B<editMessageReplyMarkup>( %PARAMETERS )
3671              
3672             Use this method to edit only the reply markup of messages. On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned.
3673              
3674             Reference: L<https://core.telegram.org/bots/api#editmessagereplymarkup>
3675              
3676             This methods takes the following parameters:
3677              
3678             =over 8
3679              
3680             =item I<chat_id>
3681              
3682             This parameter type is one of the following Integer or String and is optional.
3683             Required if inline_message_id is not specified. Unique identifier for the target chat or username of the target channel (in the format @channelusername)
3684              
3685             =item I<inline_message_id>
3686              
3687             This parameter type is String and is optional.
3688              
3689             Required if chat_id and message_id are not specified. Identifier of the inline message
3690              
3691             =item I<message_id>
3692              
3693             This parameter type is Integer and is optional.
3694              
3695             Required if inline_message_id is not specified. Identifier of the message to edit
3696              
3697             =item I<reply_markup>
3698              
3699             This parameter type is an object L<Net::API::Telegram::InlineKeyboardMarkup> and is optional.
3700             A JSON-serialized object for an inline keyboard.
3701              
3702             =back
3703              
3704             =item B<editMessageText>( %PARAMETERS )
3705              
3706             Use this method to edit text and game messages. On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned.
3707              
3708             Reference: L<https://core.telegram.org/bots/api#editmessagetext>
3709              
3710             This methods takes the following parameters:
3711              
3712             =over 8
3713              
3714             =item I<chat_id>
3715              
3716             This parameter type is one of the following Integer or String and is optional.
3717             Required if inline_message_id is not specified. Unique identifier for the target chat or username of the target channel (in the format @channelusername)
3718              
3719             =item I<disable_web_page_preview>
3720              
3721             This parameter type is Boolean and is optional.
3722              
3723             Disables link previews for links in this message
3724              
3725             =item I<inline_message_id>
3726              
3727             This parameter type is String and is optional.
3728              
3729             Required if chat_id and message_id are not specified. Identifier of the inline message
3730              
3731             =item I<message_id>
3732              
3733             This parameter type is Integer and is optional.
3734              
3735             Required if inline_message_id is not specified. Identifier of the message to edit
3736              
3737             =item I<parse_mode>
3738              
3739             This parameter type is String and is optional.
3740              
3741             Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your bot's message.
3742              
3743             =item I<reply_markup>
3744              
3745             This parameter type is an object L<Net::API::Telegram::InlineKeyboardMarkup> and is optional.
3746             A JSON-serialized object for an inline keyboard.
3747              
3748             =item I<text>
3749              
3750             This parameter type is String and is required.
3751              
3752             New text of the message
3753              
3754             =back
3755              
3756             =item B<exportChatInviteLink>( %PARAMETERS )
3757              
3758             Use this method to generate a new invite link for a chat; any previously generated link is revoked. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns the new invite link as String on success.
3759              
3760             Reference: L<https://core.telegram.org/bots/api#exportchatinvitelink>
3761              
3762             This methods takes the following parameters:
3763              
3764             =over 8
3765              
3766             =item I<chat_id>
3767              
3768             This parameter type is one of the following Integer or String and is required.
3769             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
3770              
3771             =back
3772              
3773             =item B<forwardMessage>( %PARAMETERS )
3774              
3775             Use this method to forward messages of any kind. On success, the sent Message is returned.
3776              
3777             Reference: L<https://core.telegram.org/bots/api#forwardmessage>
3778              
3779             This methods takes the following parameters:
3780              
3781             =over 8
3782              
3783             =item I<chat_id>
3784              
3785             This parameter type is one of the following Integer or String and is required.
3786             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
3787              
3788             =item I<disable_notification>
3789              
3790             This parameter type is Boolean and is optional.
3791              
3792             Sends the message silently. Users will receive a notification with no sound.
3793              
3794             =item I<from_chat_id>
3795              
3796             This parameter type is one of the following Integer or String and is required.
3797             Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername)
3798              
3799             =item I<message_id>
3800              
3801             This parameter type is Integer and is required.
3802              
3803             Message identifier in the chat specified in from_chat_id
3804              
3805             =back
3806              
3807             =item B<getChat>( %PARAMETERS )
3808              
3809             Use this method to get up to date information about the chat (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.). Returns a Chat object on success.
3810              
3811             Reference: L<https://core.telegram.org/bots/api#getchat>
3812              
3813             This methods takes the following parameters:
3814              
3815             =over 8
3816              
3817             =item I<chat_id>
3818              
3819             This parameter type is one of the following Integer or String and is required.
3820             Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername)
3821              
3822             =back
3823              
3824             =item B<getChatAdministrators>( %PARAMETERS )
3825              
3826             Use this method to get a list of administrators in a chat. On success, returns an Array of ChatMember objects that contains information about all chat administrators except other bots. If the chat is a group or a supergroup and no administrators were appointed, only the creator will be returned.
3827              
3828             Reference: L<https://core.telegram.org/bots/api#getchatadministrators>
3829              
3830             This methods takes the following parameters:
3831              
3832             =over 8
3833              
3834             =item I<chat_id>
3835              
3836             This parameter type is one of the following Integer or String and is required.
3837             Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername)
3838              
3839             =back
3840              
3841             =item B<getChatMember>( %PARAMETERS )
3842              
3843             Use this method to get information about a member of a chat. Returns a ChatMember object on success.
3844              
3845             Reference: L<https://core.telegram.org/bots/api#getchatmember>
3846              
3847             This methods takes the following parameters:
3848              
3849             =over 8
3850              
3851             =item I<chat_id>
3852              
3853             This parameter type is one of the following Integer or String and is required.
3854             Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername)
3855              
3856             =item I<user_id>
3857              
3858             This parameter type is Integer and is required.
3859              
3860             Unique identifier of the target user
3861              
3862             =back
3863              
3864             =item B<getChatMembersCount>( %PARAMETERS )
3865              
3866             Use this method to get the number of members in a chat. Returns Int on success.
3867              
3868             Reference: L<https://core.telegram.org/bots/api#getchatmemberscount>
3869              
3870             This methods takes the following parameters:
3871              
3872             =over 8
3873              
3874             =item I<chat_id>
3875              
3876             This parameter type is one of the following Integer or String and is required.
3877             Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername)
3878              
3879             =back
3880              
3881             =item B<getFile>( %PARAMETERS )
3882              
3883             Use this method to get basic info about a file and prepare it for downloading. For the moment, bots can download files of up to 20MB in size. On success, a File object is returned. The file can then be downloaded via the link https://api.telegram.org/file/bot<token>/<file_path>, where <file_path> is taken from the response. It is guaranteed that the link will be valid for at least 1 hour. When the link expires, a new one can be requested by calling getFile again.
3884              
3885             Reference: L<https://core.telegram.org/bots/api#getfile>
3886              
3887             This methods takes the following parameters:
3888              
3889             =over 8
3890              
3891             =item I<file_id>
3892              
3893             This parameter type is String and is required.
3894              
3895             File identifier to get info about
3896              
3897             =back
3898              
3899             =item B<getGameHighScores>( %PARAMETERS )
3900              
3901             Use this method to get data for high score tables. Will return the score of the specified user and several of his neighbors in a game. On success, returns an Array of GameHighScore objects.
3902              
3903             Reference: L<https://core.telegram.org/bots/api#getgamehighscores>
3904              
3905             This methods takes the following parameters:
3906              
3907             =over 8
3908              
3909             =item I<chat_id>
3910              
3911             This parameter type is Integer and is optional.
3912              
3913             Required if inline_message_id is not specified. Unique identifier for the target chat
3914              
3915             =item I<inline_message_id>
3916              
3917             This parameter type is String and is optional.
3918              
3919             Required if chat_id and message_id are not specified. Identifier of the inline message
3920              
3921             =item I<message_id>
3922              
3923             This parameter type is Integer and is optional.
3924              
3925             Required if inline_message_id is not specified. Identifier of the sent message
3926              
3927             =item I<user_id>
3928              
3929             This parameter type is Integer and is required.
3930              
3931             Target user id
3932              
3933             =back
3934              
3935             =item B<getMe>()
3936              
3937             A simple method for testing your bot's auth token. Requires no parameters. Returns basic information about the bot in form of a User object.
3938              
3939             Reference: L<https://core.telegram.org/bots/api#getme>
3940              
3941             This method does not take any parameter.
3942              
3943             =item B<getStickerSet>( %PARAMETERS )
3944              
3945             Use this method to get a sticker set. On success, a StickerSet object is returned.
3946              
3947             Reference: L<https://core.telegram.org/bots/api#getstickerset>
3948              
3949             This methods takes the following parameters:
3950              
3951             =over 8
3952              
3953             =item I<name>
3954              
3955             This parameter type is String and is required.
3956              
3957             Name of the sticker set
3958              
3959             =back
3960              
3961             =item B<getUpdates>( %PARAMETERS )
3962              
3963             Use this method to receive incoming updates using long polling (wiki). An Array of Update objects is returned.
3964              
3965             Reference: L<https://core.telegram.org/bots/api#getupdates>
3966              
3967             This methods takes the following parameters:
3968              
3969             =over 8
3970              
3971             =item I<allowed_updates>
3972              
3973             This parameter type is an array of and is optional.
3974             List the types of updates you want your bot to receive. For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. See Update for a complete list of available update types. Specify an empty list to receive all updates regardless of type (default). If not specified, the previous setting will be used.Please note that this parameter doesn't affect updates created before the call to the getUpdates, so unwanted updates may be received for a short period of time.
3975              
3976             =item I<limit>
3977              
3978             This parameter type is Integer and is optional.
3979              
3980             Limits the number of updates to be retrieved. Values between 1—100 are accepted. Defaults to 100.
3981              
3982             =item I<offset>
3983              
3984             This parameter type is Integer and is optional.
3985              
3986             Identifier of the first update to be returned. Must be greater by one than the highest among the identifiers of previously received updates. By default, updates starting with the earliest unconfirmed update are returned. An update is considered confirmed as soon as getUpdates is called with an offset higher than its update_id. The negative offset can be specified to retrieve updates starting from -offset update from the end of the updates queue. All previous updates will forgotten.
3987              
3988             =item I<timeout>
3989              
3990             This parameter type is Integer and is optional.
3991              
3992             Timeout in seconds for long polling. Defaults to 0, i.e. usual short polling. Should be positive, short polling should be used for testing purposes only.
3993              
3994             =back
3995              
3996             =item B<getUserProfilePhotos>( %PARAMETERS )
3997              
3998             Use this method to get a list of profile pictures for a user. Returns a UserProfilePhotos object.
3999              
4000             Reference: L<https://core.telegram.org/bots/api#getuserprofilephotos>
4001              
4002             This methods takes the following parameters:
4003              
4004             =over 8
4005              
4006             =item I<limit>
4007              
4008             This parameter type is Integer and is optional.
4009              
4010             Limits the number of photos to be retrieved. Values between 1—100 are accepted. Defaults to 100.
4011              
4012             =item I<offset>
4013              
4014             This parameter type is Integer and is optional.
4015              
4016             Sequential number of the first photo to be returned. By default, all photos are returned.
4017              
4018             =item I<user_id>
4019              
4020             This parameter type is Integer and is required.
4021              
4022             Unique identifier of the target user
4023              
4024             =back
4025              
4026             =item B<getWebhookInfo>()
4027              
4028             Use this method to get current webhook status. Requires no parameters. On success, returns a WebhookInfo object. If the bot is using getUpdates, will return an object with the url field empty.
4029              
4030             Reference: L<https://core.telegram.org/bots/api#getwebhookinfo>
4031              
4032             This method does not take any parameter.
4033              
4034             =item B<kickChatMember>( %PARAMETERS )
4035              
4036             Use this method to kick a user from a group, a supergroup or a channel. In the case of supergroups and channels, the user will not be able to return to the group on their own using invite links, etc., unless unbanned first. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
4037              
4038             Reference: L<https://core.telegram.org/bots/api#kickchatmember>
4039              
4040             This methods takes the following parameters:
4041              
4042             =over 8
4043              
4044             =item I<chat_id>
4045              
4046             This parameter type is one of the following Integer or String and is required.
4047             Unique identifier for the target group or username of the target supergroup or channel (in the format @channelusername)
4048              
4049             =item I<until_date>
4050              
4051             This parameter type is Integer and is optional.
4052              
4053             Date when the user will be unbanned, unix time. If user is banned for more than 366 days or less than 30 seconds from the current time they are considered to be banned forever
4054              
4055             =item I<user_id>
4056              
4057             This parameter type is Integer and is required.
4058              
4059             Unique identifier of the target user
4060              
4061             =back
4062              
4063             =item B<leaveChat>( %PARAMETERS )
4064              
4065             Use this method for your bot to leave a group, supergroup or channel. Returns True on success.
4066              
4067             Reference: L<https://core.telegram.org/bots/api#leavechat>
4068              
4069             This methods takes the following parameters:
4070              
4071             =over 8
4072              
4073             =item I<chat_id>
4074              
4075             This parameter type is one of the following Integer or String and is required.
4076             Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername)
4077              
4078             =back
4079              
4080             =item B<pinChatMessage>( %PARAMETERS )
4081              
4082             Use this method to pin a message in a group, a supergroup, or a channel. The bot must be an administrator in the chat for this to work and must have the ‘can_pin_messages’ admin right in the supergroup or ‘can_edit_messages’ admin right in the channel. Returns True on success.
4083              
4084             Reference: L<https://core.telegram.org/bots/api#pinchatmessage>
4085              
4086             This methods takes the following parameters:
4087              
4088             =over 8
4089              
4090             =item I<chat_id>
4091              
4092             This parameter type is one of the following Integer or String and is required.
4093             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
4094              
4095             =item I<disable_notification>
4096              
4097             This parameter type is Boolean and is optional.
4098              
4099             Pass True, if it is not necessary to send a notification to all chat members about the new pinned message. Notifications are always disabled in channels.
4100              
4101             =item I<message_id>
4102              
4103             This parameter type is Integer and is required.
4104              
4105             Identifier of a message to pin
4106              
4107             =back
4108              
4109             =item B<promoteChatMember>( %PARAMETERS )
4110              
4111             Use this method to promote or demote a user in a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Pass False for all boolean parameters to demote a user. Returns True on success.
4112              
4113             Reference: L<https://core.telegram.org/bots/api#promotechatmember>
4114              
4115             This methods takes the following parameters:
4116              
4117             =over 8
4118              
4119             =item I<can_change_info>
4120              
4121             This parameter type is Boolean and is optional.
4122              
4123             Pass True, if the administrator can change chat title, photo and other settings
4124              
4125             =item I<can_delete_messages>
4126              
4127             This parameter type is Boolean and is optional.
4128              
4129             Pass True, if the administrator can delete messages of other users
4130              
4131             =item I<can_edit_messages>
4132              
4133             This parameter type is Boolean and is optional.
4134              
4135             Pass True, if the administrator can edit messages of other users and can pin messages, channels only
4136              
4137             =item I<can_invite_users>
4138              
4139             This parameter type is Boolean and is optional.
4140              
4141             Pass True, if the administrator can invite new users to the chat
4142              
4143             =item I<can_pin_messages>
4144              
4145             This parameter type is Boolean and is optional.
4146              
4147             Pass True, if the administrator can pin messages, supergroups only
4148              
4149             =item I<can_post_messages>
4150              
4151             This parameter type is Boolean and is optional.
4152              
4153             Pass True, if the administrator can create channel posts, channels only
4154              
4155             =item I<can_promote_members>
4156              
4157             This parameter type is Boolean and is optional.
4158              
4159             Pass True, if the administrator can add new administrators with a subset of his own privileges or demote administrators that he has promoted, directly or indirectly (promoted by administrators that were appointed by him)
4160              
4161             =item I<can_restrict_members>
4162              
4163             This parameter type is Boolean and is optional.
4164              
4165             Pass True, if the administrator can restrict, ban or unban chat members
4166              
4167             =item I<chat_id>
4168              
4169             This parameter type is one of the following Integer or String and is required.
4170             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
4171              
4172             =item I<user_id>
4173              
4174             This parameter type is Integer and is required.
4175              
4176             Unique identifier of the target user
4177              
4178             =back
4179              
4180             =item B<restrictChatMember>( %PARAMETERS )
4181              
4182             Use this method to restrict a user in a supergroup. The bot must be an administrator in the supergroup for this to work and must have the appropriate admin rights. Pass True for all permissions to lift restrictions from a user. Returns True on success.
4183              
4184             Reference: L<https://core.telegram.org/bots/api#restrictchatmember>
4185              
4186             This methods takes the following parameters:
4187              
4188             =over 8
4189              
4190             =item I<chat_id>
4191              
4192             This parameter type is one of the following Integer or String and is required.
4193             Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
4194              
4195             =item I<permissions>
4196              
4197             This parameter type is an object L<Net::API::Telegram::ChatPermissions> and is required.
4198             New user permissions
4199              
4200             =item I<until_date>
4201              
4202             This parameter type is Integer and is optional.
4203              
4204             Date when restrictions will be lifted for the user, unix time. If user is restricted for more than 366 days or less than 30 seconds from the current time, they are considered to be restricted forever
4205              
4206             =item I<user_id>
4207              
4208             This parameter type is Integer and is required.
4209              
4210             Unique identifier of the target user
4211              
4212             =back
4213              
4214             =item B<sendAnimation>( %PARAMETERS )
4215              
4216             Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future.
4217              
4218             Reference: L<https://core.telegram.org/bots/api#sendanimation>
4219              
4220             This methods takes the following parameters:
4221              
4222             =over 8
4223              
4224             =item I<animation>
4225              
4226             This parameter type is one of the following L<InputFile> or String and is required.
4227             Animation to send. Pass a file_id as String to send an animation that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get an animation from the Internet, or upload a new animation using multipart/form-data. More info on Sending Files »
4228              
4229             =item I<caption>
4230              
4231             This parameter type is String and is optional.
4232              
4233             Animation caption (may also be used when resending animation by file_id), 0-1024 characters
4234              
4235             =item I<chat_id>
4236              
4237             This parameter type is one of the following Integer or String and is required.
4238             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
4239              
4240             =item I<disable_notification>
4241              
4242             This parameter type is Boolean and is optional.
4243              
4244             Sends the message silently. Users will receive a notification with no sound.
4245              
4246             =item I<duration>
4247              
4248             This parameter type is Integer and is optional.
4249              
4250             Duration of sent animation in seconds
4251              
4252             =item I<height>
4253              
4254             This parameter type is Integer and is optional.
4255              
4256             Animation height
4257              
4258             =item I<parse_mode>
4259              
4260             This parameter type is String and is optional.
4261              
4262             Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
4263              
4264             =item I<reply_markup>
4265              
4266             This parameter type is one of the following L<InlineKeyboardMarkup> or L<ReplyKeyboardMarkup> or L<ReplyKeyboardRemove> or L<ForceReply> and is optional.
4267             Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
4268              
4269             =item I<reply_to_message_id>
4270              
4271             This parameter type is Integer and is optional.
4272              
4273             If the message is a reply, ID of the original message
4274              
4275             =item I<thumb>
4276              
4277             This parameter type is one of the following L<InputFile> or String and is optional.
4278             Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail‘s width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can’t be reused and can be only uploaded as a new file, so you can pass “attach://<file_attach_name>” if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. More info on Sending Files »
4279              
4280             =item I<width>
4281              
4282             This parameter type is Integer and is optional.
4283              
4284             Animation width
4285              
4286             =back
4287              
4288             =item B<sendAudio>( %PARAMETERS )
4289              
4290             Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size, this limit may be changed in the future.For sending voice messages, use the sendVoice method instead.
4291              
4292             Reference: L<https://core.telegram.org/bots/api#sendaudio>
4293              
4294             This methods takes the following parameters:
4295              
4296             =over 8
4297              
4298             =item I<audio>
4299              
4300             This parameter type is one of the following L<InputFile> or String and is required.
4301             Audio file to send. Pass a file_id as String to send an audio file that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get an audio file from the Internet, or upload a new one using multipart/form-data. More info on Sending Files »
4302              
4303             =item I<caption>
4304              
4305             This parameter type is String and is optional.
4306              
4307             Audio caption, 0-1024 characters
4308              
4309             =item I<chat_id>
4310              
4311             This parameter type is one of the following Integer or String and is required.
4312             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
4313              
4314             =item I<disable_notification>
4315              
4316             This parameter type is Boolean and is optional.
4317              
4318             Sends the message silently. Users will receive a notification with no sound.
4319              
4320             =item I<duration>
4321              
4322             This parameter type is Integer and is optional.
4323              
4324             Duration of the audio in seconds
4325              
4326             =item I<parse_mode>
4327              
4328             This parameter type is String and is optional.
4329              
4330             Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
4331              
4332             =item I<performer>
4333              
4334             This parameter type is String and is optional.
4335              
4336             Performer
4337              
4338             =item I<reply_markup>
4339              
4340             This parameter type is one of the following L<InlineKeyboardMarkup> or L<ReplyKeyboardMarkup> or L<ReplyKeyboardRemove> or L<ForceReply> and is optional.
4341             Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
4342              
4343             =item I<reply_to_message_id>
4344              
4345             This parameter type is Integer and is optional.
4346              
4347             If the message is a reply, ID of the original message
4348              
4349             =item I<thumb>
4350              
4351             This parameter type is one of the following L<InputFile> or String and is optional.
4352             Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail‘s width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can’t be reused and can be only uploaded as a new file, so you can pass “attach://<file_attach_name>” if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. More info on Sending Files »
4353              
4354             =item I<title>
4355              
4356             This parameter type is String and is optional.
4357              
4358             Track name
4359              
4360             =back
4361              
4362             =item B<sendChatAction>( %PARAMETERS )
4363              
4364             Use this method when you need to tell the user that something is happening on the bot's side. The status is set for 5 seconds or less (when a message arrives from your bot, Telegram clients clear its typing status). Returns True on success.We only recommend using this method when a response from the bot will take a noticeable amount of time to arrive.
4365              
4366             Reference: L<https://core.telegram.org/bots/api#sendchataction>
4367              
4368             This methods takes the following parameters:
4369              
4370             =over 8
4371              
4372             =item I<action>
4373              
4374             This parameter type is String and is required.
4375              
4376             Type of action to broadcast. Choose one, depending on what the user is about to receive: typing for text messages, upload_photo for photos, record_video or upload_video for videos, record_audio or upload_audio for audio files, upload_document for general files, find_location for location data, record_video_note or upload_video_note for video notes.
4377              
4378             =item I<chat_id>
4379              
4380             This parameter type is one of the following Integer or String and is required.
4381             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
4382              
4383             =back
4384              
4385             =item B<sendContact>( %PARAMETERS )
4386              
4387             Use this method to send phone contacts. On success, the sent Message is returned.
4388              
4389             Reference: L<https://core.telegram.org/bots/api#sendcontact>
4390              
4391             This methods takes the following parameters:
4392              
4393             =over 8
4394              
4395             =item I<chat_id>
4396              
4397             This parameter type is one of the following Integer or String and is required.
4398             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
4399              
4400             =item I<disable_notification>
4401              
4402             This parameter type is Boolean and is optional.
4403              
4404             Sends the message silently. Users will receive a notification with no sound.
4405              
4406             =item I<first_name>
4407              
4408             This parameter type is String and is required.
4409              
4410             Contact's first name
4411              
4412             =item I<last_name>
4413              
4414             This parameter type is String and is optional.
4415              
4416             Contact's last name
4417              
4418             =item I<phone_number>
4419              
4420             This parameter type is String and is required.
4421              
4422             Contact's phone number
4423              
4424             =item I<reply_markup>
4425              
4426             This parameter type is one of the following L<InlineKeyboardMarkup> or L<ReplyKeyboardMarkup> or L<ReplyKeyboardRemove> or L<ForceReply> and is optional.
4427             Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove keyboard or to force a reply from the user.
4428              
4429             =item I<reply_to_message_id>
4430              
4431             This parameter type is Integer and is optional.
4432              
4433             If the message is a reply, ID of the original message
4434              
4435             =item I<vcard>
4436              
4437             This parameter type is String and is optional.
4438              
4439             Additional data about the contact in the form of a vCard, 0-2048 bytes
4440              
4441             =back
4442              
4443             =item B<sendDocument>( %PARAMETERS )
4444              
4445             Use this method to send general files. On success, the sent Message is returned. Bots can currently send files of any type of up to 50 MB in size, this limit may be changed in the future.
4446              
4447             Reference: L<https://core.telegram.org/bots/api#senddocument>
4448              
4449             This methods takes the following parameters:
4450              
4451             =over 8
4452              
4453             =item I<caption>
4454              
4455             This parameter type is String and is optional.
4456              
4457             Document caption (may also be used when resending documents by file_id), 0-1024 characters
4458              
4459             =item I<chat_id>
4460              
4461             This parameter type is one of the following Integer or String and is required.
4462             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
4463              
4464             =item I<disable_notification>
4465              
4466             This parameter type is Boolean and is optional.
4467              
4468             Sends the message silently. Users will receive a notification with no sound.
4469              
4470             =item I<document>
4471              
4472             This parameter type is one of the following L<InputFile> or String and is required.
4473             File to send. Pass a file_id as String to send a file that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More info on Sending Files »
4474              
4475             =item I<parse_mode>
4476              
4477             This parameter type is String and is optional.
4478              
4479             Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
4480              
4481             =item I<reply_markup>
4482              
4483             This parameter type is one of the following L<InlineKeyboardMarkup> or L<ReplyKeyboardMarkup> or L<ReplyKeyboardRemove> or L<ForceReply> and is optional.
4484             Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
4485              
4486             =item I<reply_to_message_id>
4487              
4488             This parameter type is Integer and is optional.
4489              
4490             If the message is a reply, ID of the original message
4491              
4492             =item I<thumb>
4493              
4494             This parameter type is one of the following L<InputFile> or String and is optional.
4495             Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail‘s width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can’t be reused and can be only uploaded as a new file, so you can pass “attach://<file_attach_name>” if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. More info on Sending Files »
4496              
4497             =back
4498              
4499             =item B<sendGame>( %PARAMETERS )
4500              
4501             Use this method to send a game. On success, the sent Message is returned.
4502              
4503             Reference: L<https://core.telegram.org/bots/api#sendgame>
4504              
4505             This methods takes the following parameters:
4506              
4507             =over 8
4508              
4509             =item I<chat_id>
4510              
4511             This parameter type is Integer and is required.
4512              
4513             Unique identifier for the target chat
4514              
4515             =item I<disable_notification>
4516              
4517             This parameter type is Boolean and is optional.
4518              
4519             Sends the message silently. Users will receive a notification with no sound.
4520              
4521             =item I<game_short_name>
4522              
4523             This parameter type is String and is required.
4524              
4525             Short name of the game, serves as the unique identifier for the game. Set up your games via Botfather.
4526              
4527             =item I<reply_markup>
4528              
4529             This parameter type is an object L<Net::API::Telegram::InlineKeyboardMarkup> and is optional.
4530             A JSON-serialized object for an inline keyboard. If empty, one ‘Play game_title’ button will be shown. If not empty, the first button must launch the game.
4531              
4532             =item I<reply_to_message_id>
4533              
4534             This parameter type is Integer and is optional.
4535              
4536             If the message is a reply, ID of the original message
4537              
4538             =back
4539              
4540             =item B<sendInvoice>( %PARAMETERS )
4541              
4542             Use this method to send invoices. On success, the sent Message is returned.
4543              
4544             Reference: L<https://core.telegram.org/bots/api#sendinvoice>
4545              
4546             This methods takes the following parameters:
4547              
4548             =over 8
4549              
4550             =item I<chat_id>
4551              
4552             This parameter type is Integer and is required.
4553              
4554             Unique identifier for the target private chat
4555              
4556             =item I<currency>
4557              
4558             This parameter type is String and is required.
4559              
4560             Three-letter ISO 4217 currency code, see more on currencies
4561              
4562             =item I<description>
4563              
4564             This parameter type is String and is required.
4565              
4566             Product description, 1-255 characters
4567              
4568             =item I<disable_notification>
4569              
4570             This parameter type is Boolean and is optional.
4571              
4572             Sends the message silently. Users will receive a notification with no sound.
4573              
4574             =item I<is_flexible>
4575              
4576             This parameter type is Boolean and is optional.
4577              
4578             Pass True, if the final price depends on the shipping method
4579              
4580             =item I<need_email>
4581              
4582             This parameter type is Boolean and is optional.
4583              
4584             Pass True, if you require the user's email address to complete the order
4585              
4586             =item I<need_name>
4587              
4588             This parameter type is Boolean and is optional.
4589              
4590             Pass True, if you require the user's full name to complete the order
4591              
4592             =item I<need_phone_number>
4593              
4594             This parameter type is Boolean and is optional.
4595              
4596             Pass True, if you require the user's phone number to complete the order
4597              
4598             =item I<need_shipping_address>
4599              
4600             This parameter type is Boolean and is optional.
4601              
4602             Pass True, if you require the user's shipping address to complete the order
4603              
4604             =item I<payload>
4605              
4606             This parameter type is String and is required.
4607              
4608             Bot-defined invoice payload, 1-128 bytes. This will not be displayed to the user, use for your internal processes.
4609              
4610             =item I<photo_height>
4611              
4612             This parameter type is Integer and is optional.
4613              
4614             Photo height
4615              
4616             =item I<photo_size>
4617              
4618             This parameter type is Integer and is optional.
4619              
4620             Photo size
4621              
4622             =item I<photo_url>
4623              
4624             This parameter type is String and is optional.
4625              
4626             URL of the product photo for the invoice. Can be a photo of the goods or a marketing image for a service. People like it better when they see what they are paying for.
4627              
4628             =item I<photo_width>
4629              
4630             This parameter type is Integer and is optional.
4631              
4632             Photo width
4633              
4634             =item I<prices>
4635              
4636             This parameter type is an array of L<Net::API::Telegram::LabeledPrice> and is required.
4637             Price breakdown, a list of components (e.g. product price, tax, discount, delivery cost, delivery tax, bonus, etc.)
4638              
4639             =item I<provider_data>
4640              
4641             This parameter type is String and is optional.
4642              
4643             JSON-encoded data about the invoice, which will be shared with the payment provider. A detailed description of required fields should be provided by the payment provider.
4644              
4645             =item I<provider_token>
4646              
4647             This parameter type is String and is required.
4648              
4649             Payments provider token, obtained via Botfather
4650              
4651             =item I<reply_markup>
4652              
4653             This parameter type is an object L<Net::API::Telegram::InlineKeyboardMarkup> and is optional.
4654             A JSON-serialized object for an inline keyboard. If empty, one 'Pay total price' button will be shown. If not empty, the first button must be a Pay button.
4655              
4656             =item I<reply_to_message_id>
4657              
4658             This parameter type is Integer and is optional.
4659              
4660             If the message is a reply, ID of the original message
4661              
4662             =item I<send_email_to_provider>
4663              
4664             This parameter type is Boolean and is optional.
4665              
4666             Pass True, if user's email address should be sent to provider
4667              
4668             =item I<send_phone_number_to_provider>
4669              
4670             This parameter type is Boolean and is optional.
4671              
4672             Pass True, if user's phone number should be sent to provider
4673              
4674             =item I<start_parameter>
4675              
4676             This parameter type is String and is required.
4677              
4678             Unique deep-linking parameter that can be used to generate this invoice when used as a start parameter
4679              
4680             =item I<title>
4681              
4682             This parameter type is String and is required.
4683              
4684             Product name, 1-32 characters
4685              
4686             =back
4687              
4688             =item B<sendLocation>( %PARAMETERS )
4689              
4690             Use this method to send point on the map. On success, the sent Message is returned.
4691              
4692             Reference: L<https://core.telegram.org/bots/api#sendlocation>
4693              
4694             This methods takes the following parameters:
4695              
4696             =over 8
4697              
4698             =item I<chat_id>
4699              
4700             This parameter type is one of the following Integer or String and is required.
4701             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
4702              
4703             =item I<disable_notification>
4704              
4705             This parameter type is Boolean and is optional.
4706              
4707             Sends the message silently. Users will receive a notification with no sound.
4708              
4709             =item I<latitude>
4710              
4711             This parameter type is Float number and is required.
4712              
4713             Latitude of the location
4714              
4715             =item I<live_period>
4716              
4717             This parameter type is Integer and is optional.
4718              
4719             Period in seconds for which the location will be updated (see Live Locations, should be between 60 and 86400.
4720              
4721             =item I<longitude>
4722              
4723             This parameter type is Float number and is required.
4724              
4725             Longitude of the location
4726              
4727             =item I<reply_markup>
4728              
4729             This parameter type is one of the following L<InlineKeyboardMarkup> or L<ReplyKeyboardMarkup> or L<ReplyKeyboardRemove> or L<ForceReply> and is optional.
4730             Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
4731              
4732             =item I<reply_to_message_id>
4733              
4734             This parameter type is Integer and is optional.
4735              
4736             If the message is a reply, ID of the original message
4737              
4738             =back
4739              
4740             =item B<sendMediaGroup>( %PARAMETERS )
4741              
4742             Use this method to send a group of photos or videos as an album. On success, an array of the sent Messages is returned.
4743              
4744             Reference: L<https://core.telegram.org/bots/api#sendmediagroup>
4745              
4746             This methods takes the following parameters:
4747              
4748             =over 8
4749              
4750             =item I<chat_id>
4751              
4752             This parameter type is one of the following Integer or String and is required.
4753             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
4754              
4755             =item I<disable_notification>
4756              
4757             This parameter type is Boolean and is optional.
4758              
4759             Sends the messages silently. Users will receive a notification with no sound.
4760              
4761             =item I<media>
4762              
4763             This parameter type is an array of L<Net::API::Telegram::InputMediaPhoto> and L<Net::API::Telegram::InputMediaVideo> and is required.
4764             A JSON-serialized array describing photos and videos to be sent, must include 2–10 items
4765              
4766             =item I<reply_to_message_id>
4767              
4768             This parameter type is Integer and is optional.
4769              
4770             If the messages are a reply, ID of the original message
4771              
4772             =back
4773              
4774             =item B<sendMessage>( %PARAMETERS )
4775              
4776             Use this method to send text messages. On success, the sent Message is returned.
4777              
4778             Reference: L<https://core.telegram.org/bots/api#sendmessage>
4779              
4780             This methods takes the following parameters:
4781              
4782             =over 8
4783              
4784             =item I<chat_id>
4785              
4786             This parameter type is one of the following Integer or String and is required.
4787             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
4788              
4789             =item I<disable_notification>
4790              
4791             This parameter type is Boolean and is optional.
4792              
4793             Sends the message silently. Users will receive a notification with no sound.
4794              
4795             =item I<disable_web_page_preview>
4796              
4797             This parameter type is Boolean and is optional.
4798              
4799             Disables link previews for links in this message
4800              
4801             =item I<parse_mode>
4802              
4803             This parameter type is String and is optional.
4804              
4805             Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your bot's message.
4806              
4807             =item I<reply_markup>
4808              
4809             This parameter type is one of the following L<InlineKeyboardMarkup> or L<ReplyKeyboardMarkup> or L<ReplyKeyboardRemove> or L<ForceReply> and is optional.
4810             Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
4811              
4812             =item I<reply_to_message_id>
4813              
4814             This parameter type is Integer and is optional.
4815              
4816             If the message is a reply, ID of the original message
4817              
4818             =item I<text>
4819              
4820             This parameter type is String and is required.
4821              
4822             Text of the message to be sent
4823              
4824             =back
4825              
4826             =item B<sendPhoto>( %PARAMETERS )
4827              
4828             Use this method to send photos. On success, the sent Message is returned.
4829              
4830             Reference: L<https://core.telegram.org/bots/api#sendphoto>
4831              
4832             This methods takes the following parameters:
4833              
4834             =over 8
4835              
4836             =item I<caption>
4837              
4838             This parameter type is String and is optional.
4839              
4840             Photo caption (may also be used when resending photos by file_id), 0-1024 characters
4841              
4842             =item I<chat_id>
4843              
4844             This parameter type is one of the following Integer or String and is required.
4845             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
4846              
4847             =item I<disable_notification>
4848              
4849             This parameter type is Boolean and is optional.
4850              
4851             Sends the message silently. Users will receive a notification with no sound.
4852              
4853             =item I<parse_mode>
4854              
4855             This parameter type is String and is optional.
4856              
4857             Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
4858              
4859             =item I<photo>
4860              
4861             This parameter type is one of the following L<InputFile> or String and is required.
4862             Photo to send. Pass a file_id as String to send a photo that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a photo from the Internet, or upload a new photo using multipart/form-data. More info on Sending Files »
4863              
4864             =item I<reply_markup>
4865              
4866             This parameter type is one of the following L<InlineKeyboardMarkup> or L<ReplyKeyboardMarkup> or L<ReplyKeyboardRemove> or L<ForceReply> and is optional.
4867             Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
4868              
4869             =item I<reply_to_message_id>
4870              
4871             This parameter type is Integer and is optional.
4872              
4873             If the message is a reply, ID of the original message
4874              
4875             =back
4876              
4877             =item B<sendPoll>( %PARAMETERS )
4878              
4879             Use this method to send a native poll. A native poll can't be sent to a private chat. On success, the sent Message is returned.
4880              
4881             Reference: L<https://core.telegram.org/bots/api#sendpoll>
4882              
4883             This methods takes the following parameters:
4884              
4885             =over 8
4886              
4887             =item I<chat_id>
4888              
4889             This parameter type is one of the following Integer or String and is required.
4890             Unique identifier for the target chat or username of the target channel (in the format @channelusername). A native poll can't be sent to a private chat.
4891              
4892             =item I<disable_notification>
4893              
4894             This parameter type is Boolean and is optional.
4895              
4896             Sends the message silently. Users will receive a notification with no sound.
4897              
4898             =item I<options>
4899              
4900             This parameter type is an array of and is required.
4901             List of answer options, 2-10 strings 1-100 characters each
4902              
4903             =item I<question>
4904              
4905             This parameter type is String and is required.
4906              
4907             Poll question, 1-255 characters
4908              
4909             =item I<reply_markup>
4910              
4911             This parameter type is one of the following L<InlineKeyboardMarkup> or L<ReplyKeyboardMarkup> or L<ReplyKeyboardRemove> or L<ForceReply> and is optional.
4912             Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
4913              
4914             =item I<reply_to_message_id>
4915              
4916             This parameter type is Integer and is optional.
4917              
4918             If the message is a reply, ID of the original message
4919              
4920             =back
4921              
4922             =item B<sendSticker>( %PARAMETERS )
4923              
4924             Use this method to send static .WEBP or animated .TGS stickers. On success, the sent Message is returned.
4925              
4926             Reference: L<https://core.telegram.org/bots/api#sendsticker>
4927              
4928             This methods takes the following parameters:
4929              
4930             =over 8
4931              
4932             =item I<chat_id>
4933              
4934             This parameter type is one of the following Integer or String and is required.
4935             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
4936              
4937             =item I<disable_notification>
4938              
4939             This parameter type is Boolean and is optional.
4940              
4941             Sends the message silently. Users will receive a notification with no sound.
4942              
4943             =item I<reply_markup>
4944              
4945             This parameter type is one of the following L<InlineKeyboardMarkup> or L<ReplyKeyboardMarkup> or L<ReplyKeyboardRemove> or L<ForceReply> and is optional.
4946             Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
4947              
4948             =item I<reply_to_message_id>
4949              
4950             This parameter type is Integer and is optional.
4951              
4952             If the message is a reply, ID of the original message
4953              
4954             =item I<sticker>
4955              
4956             This parameter type is one of the following L<InputFile> or String and is required.
4957             Sticker to send. Pass a file_id as String to send a file that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a .webp file from the Internet, or upload a new one using multipart/form-data. More info on Sending Files »
4958              
4959             =back
4960              
4961             =item B<sendVenue>( %PARAMETERS )
4962              
4963             Use this method to send information about a venue. On success, the sent Message is returned.
4964              
4965             Reference: L<https://core.telegram.org/bots/api#sendvenue>
4966              
4967             This methods takes the following parameters:
4968              
4969             =over 8
4970              
4971             =item I<address>
4972              
4973             This parameter type is String and is required.
4974              
4975             Address of the venue
4976              
4977             =item I<chat_id>
4978              
4979             This parameter type is one of the following Integer or String and is required.
4980             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
4981              
4982             =item I<disable_notification>
4983              
4984             This parameter type is Boolean and is optional.
4985              
4986             Sends the message silently. Users will receive a notification with no sound.
4987              
4988             =item I<foursquare_id>
4989              
4990             This parameter type is String and is optional.
4991              
4992             Foursquare identifier of the venue
4993              
4994             =item I<foursquare_type>
4995              
4996             This parameter type is String and is optional.
4997              
4998             Foursquare type of the venue, if known. (For example, “arts_entertainment/default”, “arts_entertainment/aquarium” or “food/icecream”.)
4999              
5000             =item I<latitude>
5001              
5002             This parameter type is Float number and is required.
5003              
5004             Latitude of the venue
5005              
5006             =item I<longitude>
5007              
5008             This parameter type is Float number and is required.
5009              
5010             Longitude of the venue
5011              
5012             =item I<reply_markup>
5013              
5014             This parameter type is one of the following L<InlineKeyboardMarkup> or L<ReplyKeyboardMarkup> or L<ReplyKeyboardRemove> or L<ForceReply> and is optional.
5015             Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
5016              
5017             =item I<reply_to_message_id>
5018              
5019             This parameter type is Integer and is optional.
5020              
5021             If the message is a reply, ID of the original message
5022              
5023             =item I<title>
5024              
5025             This parameter type is String and is required.
5026              
5027             Name of the venue
5028              
5029             =back
5030              
5031             =item B<sendVideo>( %PARAMETERS )
5032              
5033             Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). On success, the sent Message is returned. Bots can currently send video files of up to 50 MB in size, this limit may be changed in the future.
5034              
5035             Reference: L<https://core.telegram.org/bots/api#sendvideo>
5036              
5037             This methods takes the following parameters:
5038              
5039             =over 8
5040              
5041             =item I<caption>
5042              
5043             This parameter type is String and is optional.
5044              
5045             Video caption (may also be used when resending videos by file_id), 0-1024 characters
5046              
5047             =item I<chat_id>
5048              
5049             This parameter type is one of the following Integer or String and is required.
5050             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
5051              
5052             =item I<disable_notification>
5053              
5054             This parameter type is Boolean and is optional.
5055              
5056             Sends the message silently. Users will receive a notification with no sound.
5057              
5058             =item I<duration>
5059              
5060             This parameter type is Integer and is optional.
5061              
5062             Duration of sent video in seconds
5063              
5064             =item I<height>
5065              
5066             This parameter type is Integer and is optional.
5067              
5068             Video height
5069              
5070             =item I<parse_mode>
5071              
5072             This parameter type is String and is optional.
5073              
5074             Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
5075              
5076             =item I<reply_markup>
5077              
5078             This parameter type is one of the following L<InlineKeyboardMarkup> or L<ReplyKeyboardMarkup> or L<ReplyKeyboardRemove> or L<ForceReply> and is optional.
5079             Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
5080              
5081             =item I<reply_to_message_id>
5082              
5083             This parameter type is Integer and is optional.
5084              
5085             If the message is a reply, ID of the original message
5086              
5087             =item I<supports_streaming>
5088              
5089             This parameter type is Boolean and is optional.
5090              
5091             Pass True, if the uploaded video is suitable for streaming
5092              
5093             =item I<thumb>
5094              
5095             This parameter type is one of the following L<InputFile> or String and is optional.
5096             Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail‘s width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can’t be reused and can be only uploaded as a new file, so you can pass “attach://<file_attach_name>” if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. More info on Sending Files »
5097              
5098             =item I<video>
5099              
5100             This parameter type is one of the following L<InputFile> or String and is required.
5101             Video to send. Pass a file_id as String to send a video that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a video from the Internet, or upload a new video using multipart/form-data. More info on Sending Files »
5102              
5103             =item I<width>
5104              
5105             This parameter type is Integer and is optional.
5106              
5107             Video width
5108              
5109             =back
5110              
5111             =item B<sendVideoNote>( %PARAMETERS )
5112              
5113             As of v.4.0, Telegram clients support rounded square mp4 videos of up to 1 minute long. Use this method to send video messages. On success, the sent Message is returned.
5114              
5115             Reference: L<https://core.telegram.org/bots/api#sendvideonote>
5116              
5117             This methods takes the following parameters:
5118              
5119             =over 8
5120              
5121             =item I<chat_id>
5122              
5123             This parameter type is one of the following Integer or String and is required.
5124             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
5125              
5126             =item I<disable_notification>
5127              
5128             This parameter type is Boolean and is optional.
5129              
5130             Sends the message silently. Users will receive a notification with no sound.
5131              
5132             =item I<duration>
5133              
5134             This parameter type is Integer and is optional.
5135              
5136             Duration of sent video in seconds
5137              
5138             =item I<length>
5139              
5140             This parameter type is Integer and is optional.
5141              
5142             Video width and height, i.e. diameter of the video message
5143              
5144             =item I<reply_markup>
5145              
5146             This parameter type is one of the following L<InlineKeyboardMarkup> or L<ReplyKeyboardMarkup> or L<ReplyKeyboardRemove> or L<ForceReply> and is optional.
5147             Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
5148              
5149             =item I<reply_to_message_id>
5150              
5151             This parameter type is Integer and is optional.
5152              
5153             If the message is a reply, ID of the original message
5154              
5155             =item I<thumb>
5156              
5157             This parameter type is one of the following L<InputFile> or String and is optional.
5158             Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail‘s width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can’t be reused and can be only uploaded as a new file, so you can pass “attach://<file_attach_name>” if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. More info on Sending Files »
5159              
5160             =item I<video_note>
5161              
5162             This parameter type is one of the following L<InputFile> or String and is required.
5163             Video note to send. Pass a file_id as String to send a video note that exists on the Telegram servers (recommended) or upload a new video using multipart/form-data. More info on Sending Files ». Sending video notes by a URL is currently unsupported
5164              
5165             =back
5166              
5167             =item B<sendVoice>( %PARAMETERS )
5168              
5169             Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .ogg file encoded with OPUS (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future.
5170              
5171             Reference: L<https://core.telegram.org/bots/api#sendvoice>
5172              
5173             This methods takes the following parameters:
5174              
5175             =over 8
5176              
5177             =item I<caption>
5178              
5179             This parameter type is String and is optional.
5180              
5181             Voice message caption, 0-1024 characters
5182              
5183             =item I<chat_id>
5184              
5185             This parameter type is one of the following Integer or String and is required.
5186             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
5187              
5188             =item I<disable_notification>
5189              
5190             This parameter type is Boolean and is optional.
5191              
5192             Sends the message silently. Users will receive a notification with no sound.
5193              
5194             =item I<duration>
5195              
5196             This parameter type is Integer and is optional.
5197              
5198             Duration of the voice message in seconds
5199              
5200             =item I<parse_mode>
5201              
5202             This parameter type is String and is optional.
5203              
5204             Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
5205              
5206             =item I<reply_markup>
5207              
5208             This parameter type is one of the following L<InlineKeyboardMarkup> or L<ReplyKeyboardMarkup> or L<ReplyKeyboardRemove> or L<ForceReply> and is optional.
5209             Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
5210              
5211             =item I<reply_to_message_id>
5212              
5213             This parameter type is Integer and is optional.
5214              
5215             If the message is a reply, ID of the original message
5216              
5217             =item I<voice>
5218              
5219             This parameter type is one of the following L<InputFile> or String and is required.
5220             Audio file to send. Pass a file_id as String to send a file that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More info on Sending Files »
5221              
5222             =back
5223              
5224             =item B<setChatDescription>( %PARAMETERS )
5225              
5226             Use this method to change the description of a group, a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
5227              
5228             Reference: L<https://core.telegram.org/bots/api#setchatdescription>
5229              
5230             This methods takes the following parameters:
5231              
5232             =over 8
5233              
5234             =item I<chat_id>
5235              
5236             This parameter type is one of the following Integer or String and is required.
5237             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
5238              
5239             =item I<description>
5240              
5241             This parameter type is String and is optional.
5242              
5243             New chat description, 0-255 characters
5244              
5245             =back
5246              
5247             =item B<setChatPermissions>( %PARAMETERS )
5248              
5249             Use this method to set default chat permissions for all members. The bot must be an administrator in the group or a supergroup for this to work and must have the can_restrict_members admin rights. Returns True on success.
5250              
5251             Reference: L<https://core.telegram.org/bots/api#setchatpermissions>
5252              
5253             This methods takes the following parameters:
5254              
5255             =over 8
5256              
5257             =item I<chat_id>
5258              
5259             This parameter type is one of the following Integer or String and is required.
5260             Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
5261              
5262             =item I<permissions>
5263              
5264             This parameter type is an object L<Net::API::Telegram::ChatPermissions> and is required.
5265             New default chat permissions
5266              
5267             =back
5268              
5269             =item B<setChatPhoto>( %PARAMETERS )
5270              
5271             Use this method to set a new profile photo for the chat. Photos can't be changed for private chats. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
5272              
5273             Reference: L<https://core.telegram.org/bots/api#setchatphoto>
5274              
5275             This methods takes the following parameters:
5276              
5277             =over 8
5278              
5279             =item I<chat_id>
5280              
5281             This parameter type is one of the following Integer or String and is required.
5282             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
5283              
5284             =item I<photo>
5285              
5286             This parameter type is an object L<Net::API::Telegram::InputFile> and is required.
5287             New chat photo, uploaded using multipart/form-data
5288              
5289             =back
5290              
5291             =item B<setChatStickerSet>( %PARAMETERS )
5292              
5293             Use this method to set a new group sticker set for a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success.
5294              
5295             Reference: L<https://core.telegram.org/bots/api#setchatstickerset>
5296              
5297             This methods takes the following parameters:
5298              
5299             =over 8
5300              
5301             =item I<chat_id>
5302              
5303             This parameter type is one of the following Integer or String and is required.
5304             Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
5305              
5306             =item I<sticker_set_name>
5307              
5308             This parameter type is String and is required.
5309              
5310             Name of the sticker set to be set as the group sticker set
5311              
5312             =back
5313              
5314             =item B<setChatTitle>( %PARAMETERS )
5315              
5316             Use this method to change the title of a chat. Titles can't be changed for private chats. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
5317              
5318             Reference: L<https://core.telegram.org/bots/api#setchattitle>
5319              
5320             This methods takes the following parameters:
5321              
5322             =over 8
5323              
5324             =item I<chat_id>
5325              
5326             This parameter type is one of the following Integer or String and is required.
5327             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
5328              
5329             =item I<title>
5330              
5331             This parameter type is String and is required.
5332              
5333             New chat title, 1-255 characters
5334              
5335             =back
5336              
5337             =item B<setGameScore>( %PARAMETERS )
5338              
5339             Use this method to set the score of the specified user in a game. On success, if the message was sent by the bot, returns the edited Message, otherwise returns True. Returns an error, if the new score is not greater than the user's current score in the chat and force is False.
5340              
5341             Reference: L<https://core.telegram.org/bots/api#setgamescore>
5342              
5343             This methods takes the following parameters:
5344              
5345             =over 8
5346              
5347             =item I<chat_id>
5348              
5349             This parameter type is Integer and is optional.
5350              
5351             Required if inline_message_id is not specified. Unique identifier for the target chat
5352              
5353             =item I<disable_edit_message>
5354              
5355             This parameter type is Boolean and is optional.
5356              
5357             Pass True, if the game message should not be automatically edited to include the current scoreboard
5358              
5359             =item I<force>
5360              
5361             This parameter type is Boolean and is optional.
5362              
5363             Pass True, if the high score is allowed to decrease. This can be useful when fixing mistakes or banning cheaters
5364              
5365             =item I<inline_message_id>
5366              
5367             This parameter type is String and is optional.
5368              
5369             Required if chat_id and message_id are not specified. Identifier of the inline message
5370              
5371             =item I<message_id>
5372              
5373             This parameter type is Integer and is optional.
5374              
5375             Required if inline_message_id is not specified. Identifier of the sent message
5376              
5377             =item I<score>
5378              
5379             This parameter type is Integer and is required.
5380              
5381             New score, must be non-negative
5382              
5383             =item I<user_id>
5384              
5385             This parameter type is Integer and is required.
5386              
5387             User identifier
5388              
5389             =back
5390              
5391             =item B<setPassportDataErrors>( %PARAMETERS )
5392              
5393             Informs a user that some of the Telegram Passport elements they provided contains errors. The user will not be able to re-submit their Passport to you until the errors are fixed (the contents of the field for which you returned the error must change). Returns True on success.Use this if the data submitted by the user doesn't satisfy the standards your service requires for any reason. For example, if a birthday date seems invalid, a submitted document is blurry, a scan shows evidence of tampering, etc. Supply some details in the error message to make sure the user knows how to correct the issues.
5394              
5395             Reference: L<https://core.telegram.org/bots/api#setpassportdataerrors>
5396              
5397             This methods takes the following parameters:
5398              
5399             =over 8
5400              
5401             =item I<errors>
5402              
5403             This parameter type is an array of L<Net::API::Telegram::PassportElementError> and is required.
5404             A JSON-serialized array describing the errors
5405              
5406             =item I<user_id>
5407              
5408             This parameter type is Integer and is required.
5409              
5410             User identifier
5411              
5412             =back
5413              
5414             =item B<setWebhook>( %PARAMETERS )
5415              
5416             Use this method to specify a url and receive incoming updates via an outgoing webhook. Whenever there is an update for the bot, we will send an HTTPS POST request to the specified url, containing a JSON-serialized Update. In case of an unsuccessful request, we will give up after a reasonable amount of attempts. Returns True on success.If you'd like to make sure that the Webhook request comes from Telegram, we recommend using a secret path in the URL, e.g. https://www.example.com/. Since nobody else knows your bot‘s token, you can be pretty sure it’s us.
5417              
5418             Reference: L<https://core.telegram.org/bots/api#setwebhook>
5419              
5420             This methods takes the following parameters:
5421              
5422             =over 8
5423              
5424             =item I<allowed_updates>
5425              
5426             This parameter type is an array of and is optional.
5427             List the types of updates you want your bot to receive. For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. See Update for a complete list of available update types. Specify an empty list to receive all updates regardless of type (default). If not specified, the previous setting will be used.Please note that this parameter doesn't affect updates created before the call to the setWebhook, so unwanted updates may be received for a short period of time.
5428              
5429             =item I<certificate>
5430              
5431             This parameter type is an object L<Net::API::Telegram::InputFile> and is optional.
5432             Upload your public key certificate so that the root certificate in use can be checked. See our self-signed guide for details.
5433              
5434             =item I<max_connections>
5435              
5436             This parameter type is Integer and is optional.
5437              
5438             Maximum allowed number of simultaneous HTTPS connections to the webhook for update delivery, 1-100. Defaults to 40. Use lower values to limit the load on your bot‘s server, and higher values to increase your bot’s throughput.
5439              
5440             =item I<url>
5441              
5442             This parameter type is String and is required.
5443              
5444             HTTPS url to send updates to. Use an empty string to remove webhook integration
5445              
5446             =back
5447              
5448             =item B<stopMessageLiveLocation>( %PARAMETERS )
5449              
5450             Use this method to stop updating a live location message before live_period expires. On success, if the message was sent by the bot, the sent Message is returned, otherwise True is returned.
5451              
5452             Reference: L<https://core.telegram.org/bots/api#stopmessagelivelocation>
5453              
5454             This methods takes the following parameters:
5455              
5456             =over 8
5457              
5458             =item I<chat_id>
5459              
5460             This parameter type is one of the following Integer or String and is optional.
5461             Required if inline_message_id is not specified. Unique identifier for the target chat or username of the target channel (in the format @channelusername)
5462              
5463             =item I<inline_message_id>
5464              
5465             This parameter type is String and is optional.
5466              
5467             Required if chat_id and message_id are not specified. Identifier of the inline message
5468              
5469             =item I<message_id>
5470              
5471             This parameter type is Integer and is optional.
5472              
5473             Required if inline_message_id is not specified. Identifier of the message with live location to stop
5474              
5475             =item I<reply_markup>
5476              
5477             This parameter type is an object L<Net::API::Telegram::InlineKeyboardMarkup> and is optional.
5478             A JSON-serialized object for a new inline keyboard.
5479              
5480             =back
5481              
5482             =item B<stopPoll>( %PARAMETERS )
5483              
5484             Use this method to stop a poll which was sent by the bot. On success, the stopped Poll with the final results is returned.
5485              
5486             Reference: L<https://core.telegram.org/bots/api#stoppoll>
5487              
5488             This methods takes the following parameters:
5489              
5490             =over 8
5491              
5492             =item I<chat_id>
5493              
5494             This parameter type is one of the following Integer or String and is required.
5495             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
5496              
5497             =item I<message_id>
5498              
5499             This parameter type is Integer and is required.
5500              
5501             Identifier of the original message with the poll
5502              
5503             =item I<reply_markup>
5504              
5505             This parameter type is an object L<Net::API::Telegram::InlineKeyboardMarkup> and is optional.
5506             A JSON-serialized object for a new message inline keyboard.
5507              
5508             =back
5509              
5510             =item B<unbanChatMember>( %PARAMETERS )
5511              
5512             Use this method to unban a previously kicked user in a supergroup or channel. The user will not return to the group or channel automatically, but will be able to join via link, etc. The bot must be an administrator for this to work. Returns True on success.
5513              
5514             Reference: L<https://core.telegram.org/bots/api#unbanchatmember>
5515              
5516             This methods takes the following parameters:
5517              
5518             =over 8
5519              
5520             =item I<chat_id>
5521              
5522             This parameter type is one of the following Integer or String and is required.
5523             Unique identifier for the target group or username of the target supergroup or channel (in the format @username)
5524              
5525             =item I<user_id>
5526              
5527             This parameter type is Integer and is required.
5528              
5529             Unique identifier of the target user
5530              
5531             =back
5532              
5533             =item B<unpinChatMessage>( %PARAMETERS )
5534              
5535             Use this method to unpin a message in a group, a supergroup, or a channel. The bot must be an administrator in the chat for this to work and must have the ‘can_pin_messages’ admin right in the supergroup or ‘can_edit_messages’ admin right in the channel. Returns True on success.
5536              
5537             Reference: L<https://core.telegram.org/bots/api#unpinchatmessage>
5538              
5539             This methods takes the following parameters:
5540              
5541             =over 8
5542              
5543             =item I<chat_id>
5544              
5545             This parameter type is one of the following Integer or String and is required.
5546             Unique identifier for the target chat or username of the target channel (in the format @channelusername)
5547              
5548             =back
5549              
5550             =item B<uploadStickerFile>( %PARAMETERS )
5551              
5552             Use this method to upload a .png file with a sticker for later use in createNewStickerSet and addStickerToSet methods (can be used multiple times). Returns the uploaded File on success.
5553              
5554             Reference: L<https://core.telegram.org/bots/api#uploadstickerfile>
5555              
5556             This methods takes the following parameters:
5557              
5558             =over 8
5559              
5560             =item I<png_sticker>
5561              
5562             This parameter type is an object L<Net::API::Telegram::InputFile> and is required.
5563             Png image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px. More info on Sending Files »
5564              
5565             =item I<user_id>
5566              
5567             This parameter type is Integer and is required.
5568              
5569             User identifier of sticker file owner
5570              
5571             =back
5572              
5573             =back
5574              
5575             =head1 COPYRIGHT
5576              
5577             Copyright (c) 2000-2019 DEGUEST Pte. Ltd.
5578              
5579             =head1 AUTHOR
5580              
5581             Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>
5582              
5583             =head1 SEE ALSO
5584              
5585             L<Net::API::Telegram>
5586              
5587             =head1 COPYRIGHT & LICENSE
5588              
5589             Copyright (c) 2018-2019 DEGUEST Pte. Ltd.
5590              
5591             You can use, copy, modify and redistribute this package and associated
5592             files under the same terms as Perl itself.
5593              
5594             =cut
5595