package TgMagicPdf::Telegram; use v5.38.2; use strict; use warnings; use feature 'signatures'; use Moo; use Mojo::UserAgent; use Mojo::IOLoop; use Mojo::Promise; use TgMagicPdf::PdfBuilder; has _token => ( is => 'lazy', ); has _tg_root => ( is => 'lazy', ); has _ua => ( is => 'lazy', ); has _last_offset_update => ( is => 'rw', ); sub _build__token ($self) { require TgMagicPdf; return TgMagicPdf->new->config->{telegram}{token}; } sub run ($self) { $self->_dispatch_updates; my $promise_dispatch; while (1) { if (defined $promise_dispatch) { $promise_dispatch->wait; } $promise_dispatch = $self->_dispatch_updates; } } sub _dispatch_updates ($self) { my $updates_p = $self->_get_updates; my @promises; $updates_p->then( sub ($res) { my $updates = $res->result->json->{result}; for my $update (@$updates) { push @promises, $self->_dispatch_update($update); } } )->catch( sub ($err) { warn $err; } ); return Mojo::Promise->all($updates_p, @promises);; } sub _dispatch_update ( $self, $update ) { if ( !defined $self->_last_offset_update || $self->_last_offset_update < $update->{update_id} ) { $self->_last_offset_update( $update->{update_id} ); } my $promise; if ( defined $update->{message} ) { $promise = $self->_handle_message( $update->{message} ); } return $promise; } sub sendMessage ( $self, $chat_id, $text ) { my $url = "@{[$self->_tg_root]}/sendMessage"; my $ua = $self->_ua; return $ua->post_p( $url, json => { chat_id => $chat_id, text => $text } ); } sub _handle_message ( $self, $message ) { my $promise = Mojo::Promise->new; { my $chat_type = $message->{chat}{type}; if ( $chat_type ne 'private' ) { $promise->resolve; return; } my $chat_id = $message->{chat}{id}; my $text = $message->{text}; if ( !defined $text ) { $promise->resolve; return; } $self->sendMessage( $chat_id, 'Got your message, attempting to generate a pdf.' )->wait; my $pdf_builder = TgMagicPdf::PdfBuilder->new; $pdf_builder->from_text($text)->then( sub ($pdf) { $self->sendDocument( $chat_id, 'mtgprint.pdf', $pdf )->wait; $promise->resolve; } )->catch( sub ($err) { $promise->resolve; my $match = 0; for my $known_error ( $TgMagicPdf::PdfBuilder::ERR_INVALID_CARD, $TgMagicPdf::PdfBuilder::ERR_UNABLE_TO_FIND_IMAGE, $TgMagicPdf::PdfBuilder::ERR_TOO_MANY_CARDS ) { $match = 1 if ( index( $err, $known_error ) != -1 ); } if ($match) { my $error_to_user .= $err =~ s/ at.*$//r; if ( -1 != index $err, $TgMagicPdf::PdfBuilder::ERR_INVALID_CARD ) { $error_to_user .= ' ' . $pdf_builder->last_invalid_card; } if ( -1 != index $err, $TgMagicPdf::PdfBuilder::ERR_UNABLE_TO_FIND_IMAGE ) { $error_to_user .= ' ' . $pdf_builder->last_invalid_card; } $self->sendMessage( $chat_id, 'I could not process your deck take a look to this details: ' . $error_to_user )->wait; return; } warn $err; $self->sendMessage( $chat_id, 'I could not process your deck because of a server error' )->wait; } ); } return $promise; } sub sendDocument ( $self, $chat_id, $filename, $file_contents ) { my $url = "@{[$self->_tg_root]}/sendDocument"; my $ua = $self->_ua; my $res = $ua->post_p( $url, form => { chat_id => $chat_id, document => { content => $file_contents, 'Content-Type' => 'application/pdf', filename => $filename, }, } ); return $res; } sub _pdf_builder { return TgMagicPdf::PdfBuilder->new; } sub _build__ua ($self) { my $ua = Mojo::UserAgent->new; $ua->inactivity_timeout(60); return $ua; } sub _get_updates ($self) { my $ua = $self->_ua; my $url = "@{[$self->_tg_root]}/getUpdates"; my %params; if ( defined $self->_last_offset_update ) { $params{offset} = $self->_last_offset_update + 1; } return $ua->post_p( $url, json => {%params} ); } sub _build__tg_root ($self) { return "https://api.telegram.org/bot@{[$self->_token]}"; } 1;