File Coverage

blib/lib/Net/API/Telegram.pm
Criterion Covered Total %
statement 100 1698 5.8
branch 0 1072 0.0
condition 0 604 0.0
subroutine 34 182 18.6
pod 78 87 89.6
total 212 3643 5.8


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