File Coverage

blib/lib/Net/API/Telegram.pm
Criterion Covered Total %
statement 94 1493 6.3
branch 0 990 0.0
condition 0 577 0.0
subroutine 32 165 19.3
pod 78 87 89.6
total 204 3312 6.1


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