Net-API-Telegram

 view release on metacpan or  search on metacpan

lib/Net/API/Telegram.pm  view on Meta::CPAN

    	## https://core.telegram.org/bots/webhooks
        ## while( my $client = $httpd->accept ) 
        my $client;
        my $loopback = Net::IP->new( '127.0.0.1' );
        while( !$self->{_stop_daemon} && !$TIME_TO_DIE )
        {
        	## Set when we receive signals
        	## last if( $self->{_stop_daemon} );
        	$client = $httpd->accept || do
			{
				$self->log( "Unable to accept queries on tcp port $self->{port}" );
				## https://www.perlmonks.org/bare/?node_id=244384
				next if( $! == EINTR );
				warn( "Error on accept: $!\n" );
				next;
			};
        	
			$client->autoflush( 1 );
			my $pid = POSIX::getpid();
			if( !defined( $pid = fork() ) )
			{
				$self->log( "Cannot fork child process: $!" );
			}
			## Parent process
			elsif( $pid )
			{
				$self->log( "Received an incoming connection, forking to $pid" );
				$CHILDREN->{ $pid } = [Time::HiRes::gettimeofday()];
				$pid = POSIX::getpid();
				$client->close();
				waitpid( $pid, 0 );
				sleep( 0.1 );
			}
			## Child process == 0
			else
			{
				## Close STDIN, STDOUT and STDERR
				$in->close;
				$out->close;
				$err->close;
				$log_io->close if( $log_io );
				## Then, re-open them
				$out->fdopen( fileno( STDOUT ), 'w' );
				$out->binmode( ':utf8' );
				$out->autoflush( 1 );
				$err->fdopen( fileno( STDERR ), 'w' );
				$err->binmode( ':utf8' );
				$err->autoflush( 1 );
				$in->fdopen( fileno( STDIN ), 'r' );
				$in->binmode( ':utf8' );
				
				$httpd->close();
				$pid = POSIX::getpid();
				$self->log( "Child answering on socket with pid $pid" );
				## Processing here
				my $req;
				my $ip_check = 0;
				REQUEST: while( $req = $client->get_request ) 
				{
					my $remote_addr;
					if( $req->header( 'X-Forwarded-For' ) )
					{
						$remote_addr = Net::IP->new( $req->header( 'X-Forwarded-For' ) );
					}
					else
					{
						$remote_addr = Net::IP->new( Socket::inet_ntoa( $client->peeraddr ) );
					}
					## First Check the IP
					if( !$ip_check )
					{
						$ip_check++;
						my $ok_ips = $self->authorised_ips;
						if( scalar( @$ok_ips ) )
						{
							$ip_is_authorised = 0;
							if( $remote_addr->overlaps( $loopback ) == $Net::IP::IP_IDENTICAL )
							{
								$ip_is_authorised++;
							}
							else
							{
								IP_BLOCK_CHECKED: foreach my $block ( @$ok_ips )
								{
									## We found an overlap, we're good.
									if( !( $remote_addr->overlaps( $block ) == $Net::IP::IP_NO_OVERLAP ) )
									{
										$ip_is_authorised++, last IP_BLOCK_CHECKED;
									}
								}
							}
						}
					}
					
					my $uri = $req->uri;
					if( $uri->path ne $self->{webhook_path} )
					{
						$client->send_response( HTTP::Response->new( 404 ) );
						last;
					}
					## We need to send back a reply to Telegram quicly or Telegram will issue a "read timeout" error and will re-send the message
					$client->send_response( HTTP::Response->new( 200 ) );
					my $res = $self->data2json( $req->decoded_content );
					$client->close();
					
					my $upd = $self->_response_to_object( 'Net::API::Telegram::Update', $res ) || do
					{
						$self->error( "Could not create a Net::API::Telegram::Update with following data: " . $self->dumper( $res ) );
						$client->send_response( HTTP::Response->new( 500 ) );
						next;
					};
					## Get the Webhook information for possible error
					my $info = $self->getWebhookInfo;
					if( length( $info->last_error_message ) )
					{
						my $err_time = $info->last_error_date;
						$self->error( sprintf( "Warning only: webhook error occured on $err_time: %s", $info->last_error_message ) );
					}
					my $msg_epoch = $upd->message->date if( $upd->message );
					if( !$self->{skip_past_messages} || 
						( $check_messages_after && $msg_epoch && $msg_epoch > $check_messages_after ) || 
						( $msg_epoch && $msg_epoch > $start ) )
					{



( run in 0.583 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )