Merge branch 'main' of git.owlcode.tech:sergiotarxz/MTGPrint
This commit is contained in:
commit
247cb3cbfd
@ -28,20 +28,23 @@ sub _build__ua {
|
||||
return Mojo::UserAgent->new;
|
||||
}
|
||||
|
||||
our $ERR_TOO_MUCH_CARDS = 'TOO_MUCH_CARDS';
|
||||
our $ERR_TOO_MANY_CARDS = 'TOO_MANY_CARDS';
|
||||
our $ERR_INVALID_CARD = 'INVALID_CARD';
|
||||
our $ERR_UNABLE_TO_FIND_IMAGE = 'UNABLE_TO_FIND_IMAGE';
|
||||
our $MAX_CARDS = 9 * 50;
|
||||
|
||||
sub _build__db_all_printings($self) {
|
||||
sub _build__db_all_printings ($self) {
|
||||
return DBI->connect('dbi:SQLite:AllPrintings.sqlite');
|
||||
}
|
||||
|
||||
sub from_text( $self, $text ) {
|
||||
sub from_text ( $self, $text ) {
|
||||
my $promise = Mojo::Promise->new;
|
||||
{
|
||||
my @lines = split /\n+/, $text;
|
||||
@lines = grep { $self->_filter_lines($_); } @lines;
|
||||
if ( scalar @lines > $MAX_CARDS ) {
|
||||
die $ERR_TOO_MUCH_CARDS;
|
||||
$promise->reject($ERR_TOO_MANY_CARDS);
|
||||
next;
|
||||
}
|
||||
my @cards = map { s/^\s*(.*?)\s*$/$1/; $self->_parse_card($_) } @lines;
|
||||
my $n_cards = 0;
|
||||
@ -49,40 +52,52 @@ sub from_text( $self, $text ) {
|
||||
$n_cards += $card->{quantity};
|
||||
}
|
||||
if ( $n_cards > $MAX_CARDS ) {
|
||||
die $ERR_TOO_MUCH_CARDS;
|
||||
$promise->reject($ERR_TOO_MANY_CARDS);
|
||||
next;
|
||||
}
|
||||
@cards = map { $self->_fill_scryfall_id($_) } @cards;
|
||||
my $promise = Mojo::Promise->new;
|
||||
$self->_get_cards_images(\@cards)->then(sub ($images) {
|
||||
my $real_number_of_cards = 0;
|
||||
for my $card (@cards) {
|
||||
$real_number_of_cards += $card->{quantity} * scalar keys $images->{$card->{scryfallId}}->%*;
|
||||
eval {
|
||||
@cards = map { $self->_fill_scryfall_id($_) } @cards;
|
||||
};
|
||||
if ($@) {
|
||||
$promise->reject($@);
|
||||
next;
|
||||
}
|
||||
$self->_get_cards_images( \@cards )->then(
|
||||
sub ($images) {
|
||||
my $real_number_of_cards = 0;
|
||||
for my $card (@cards) {
|
||||
$real_number_of_cards += $card->{quantity} * scalar
|
||||
keys $images->{ $card->{scryfallId} }->%*;
|
||||
}
|
||||
if ( $real_number_of_cards > $MAX_CARDS ) {
|
||||
$promise->reject($ERR_TOO_MANY_CARDS);
|
||||
}
|
||||
my $pdf = $self->_generate_pdf( \@cards, $images );
|
||||
$promise->resolve($pdf);
|
||||
}
|
||||
if ($real_number_of_cards > $MAX_CARDS) {
|
||||
$promise->reject($ERR_TOO_MUCH_CARDS);
|
||||
)->catch(
|
||||
sub ($err) {
|
||||
$promise->reject($err);
|
||||
}
|
||||
my $pdf = $self->_generate_pdf(\@cards, $images);
|
||||
$promise->resolve($pdf);
|
||||
})->catch(sub ($err) {
|
||||
$promise->reject($err);
|
||||
});
|
||||
);
|
||||
}
|
||||
return $promise;
|
||||
}
|
||||
|
||||
sub _generate_pdf($self, $cards, $images) {
|
||||
sub _generate_pdf ( $self, $cards, $images ) {
|
||||
my $number_image = 0;
|
||||
my $pdf = PDF::API2->new;
|
||||
my $page = $pdf->page;
|
||||
my $pdf = PDF::API2->new;
|
||||
my $page = $pdf->page;
|
||||
$page->size('A4');
|
||||
my @rectangle = $page->size;
|
||||
my $n_pixels_per_cm = $rectangle[2] / 21.0;
|
||||
my @rectangle = $page->size;
|
||||
my $n_pixels_per_cm = $rectangle[2] / 21.0;
|
||||
for my $card (@$cards) {
|
||||
my $images_card = $images->{$card->{scryfallId}};
|
||||
for my $image_kind (keys %$images_card) {
|
||||
for (my $i = 0; $i < $card->{quantity}; $i++) {
|
||||
if ($number_image > 8) {
|
||||
my $images_card = $images->{ $card->{scryfallId} };
|
||||
for my $image_kind ( keys %$images_card ) {
|
||||
for ( my $i = 0 ; $i < $card->{quantity} ; $i++ ) {
|
||||
if ( $number_image > 8 ) {
|
||||
$number_image = 0;
|
||||
$page = $pdf->page;
|
||||
$page = $pdf->page;
|
||||
$page->size('A4');
|
||||
}
|
||||
my $margin_left = 25;
|
||||
@ -91,12 +106,17 @@ sub _generate_pdf($self, $cards, $images) {
|
||||
my $mtg_card_height = 8.89;
|
||||
my $small_line_to_cut_better_size = 0.5;
|
||||
open my $fh, '<', \$images_card->{$image_kind};
|
||||
my $image = $pdf->image($fh, format => 'jpeg');
|
||||
my $image = $pdf->image( $fh, format => 'jpeg' );
|
||||
my $page_position_x = $number_image % 3;
|
||||
my $page_position_y = abs(int($number_image / 3) - 2);
|
||||
$page->object($image,
|
||||
$margin_bottom + $page_position_x * $mtg_card_width * $n_pixels_per_cm + $small_line_to_cut_better_size * $page_position_x,
|
||||
$margin_bottom + $page_position_y * $mtg_card_height * $n_pixels_per_cm + $small_line_to_cut_better_size * $page_position_x,
|
||||
my $page_position_y = abs( int( $number_image / 3 ) - 2 );
|
||||
$page->object(
|
||||
$image,
|
||||
$margin_bottom +
|
||||
$page_position_x * $mtg_card_width * $n_pixels_per_cm +
|
||||
$small_line_to_cut_better_size * $page_position_x,
|
||||
$margin_bottom +
|
||||
$page_position_y * $mtg_card_height * $n_pixels_per_cm +
|
||||
$small_line_to_cut_better_size * $page_position_x,
|
||||
$n_pixels_per_cm * $mtg_card_width,
|
||||
);
|
||||
$number_image++;
|
||||
@ -106,7 +126,7 @@ sub _generate_pdf($self, $cards, $images) {
|
||||
return $pdf->to_string;
|
||||
}
|
||||
|
||||
sub _get_cards_images( $self, $cards ) {
|
||||
sub _get_cards_images ( $self, $cards ) {
|
||||
my %card_images;
|
||||
my @promises;
|
||||
my $ua = $self->_ua;
|
||||
@ -114,11 +134,11 @@ sub _get_cards_images( $self, $cards ) {
|
||||
my $scryfallId = $card->{scryfallId};
|
||||
my ( $first, $second ) = $scryfallId =~ /^(.)(.)/;
|
||||
my $url_front =
|
||||
"https://cards.scryfall.io/normal/front/$first/$second/$scryfallId.jpg";
|
||||
"https://cards.scryfall.io/normal/front/$first/$second/$scryfallId.jpg";
|
||||
my $url_back =
|
||||
"https://cards.scryfall.io/normal/back/$first/$second/$scryfallId.jpg";
|
||||
"https://cards.scryfall.io/normal/back/$first/$second/$scryfallId.jpg";
|
||||
my $promise_front = Mojo::Promise->new;
|
||||
my $promise_back = Mojo::Promise->new;
|
||||
my $promise_back = Mojo::Promise->new;
|
||||
$ua->get_p($url_front)->then(
|
||||
sub ($res) {
|
||||
my $content_type = $res->result->headers->content_type;
|
||||
@ -157,22 +177,26 @@ sub _get_cards_images( $self, $cards ) {
|
||||
push @promises, $promise_back;
|
||||
}
|
||||
my $final_promise = Mojo::Promise->new;
|
||||
Mojo::Promise->all(@promises)->then(sub {
|
||||
$final_promise->resolve(\%card_images);
|
||||
})->catch(sub ($err) {
|
||||
$final_promise->reject($err);
|
||||
});
|
||||
Mojo::Promise->all(@promises)->then(
|
||||
sub {
|
||||
$final_promise->resolve( \%card_images );
|
||||
}
|
||||
)->catch(
|
||||
sub ($err) {
|
||||
$final_promise->reject($err);
|
||||
}
|
||||
);
|
||||
return $final_promise;
|
||||
}
|
||||
|
||||
sub _fill_scryfall_id( $self, $card ) {
|
||||
sub _fill_scryfall_id ( $self, $card ) {
|
||||
if ( $card->{type} eq 'token' ) {
|
||||
return $self->_fill_scryfall_id_token($card);
|
||||
}
|
||||
return $self->_fill_scryfall_id_card($card);
|
||||
}
|
||||
|
||||
sub _fill_scryfall_id_card( $self, $card ) {
|
||||
sub _fill_scryfall_id_card ( $self, $card ) {
|
||||
my $db = $self->_db_all_printings;
|
||||
my $query = <<'EOF';
|
||||
select scryfallId
|
||||
@ -194,7 +218,7 @@ EOF
|
||||
return { %$card, };
|
||||
}
|
||||
|
||||
sub _fill_scryfall_id_token( $self, $token ) {
|
||||
sub _fill_scryfall_id_token ( $self, $token ) {
|
||||
my $db = $self->_db_all_printings;
|
||||
my $query = <<'EOF';
|
||||
SELECT scryfallId
|
||||
@ -203,28 +227,30 @@ FROM tokens
|
||||
ON tokens.uuid = tokenIdentifiers.uuid
|
||||
WHERE tokens.name = ?
|
||||
EOF
|
||||
my @args = ($token->{name});
|
||||
$query .= ' AND LOWER(tokens.setCode) = LOWER(?)' if defined $token->{set_code};
|
||||
my @args = ( $token->{name} );
|
||||
$query .= ' AND LOWER(tokens.setCode) = LOWER(?)'
|
||||
if defined $token->{set_code};
|
||||
push @args, $token->{set_code} if defined $token->{set_code};
|
||||
$query .= ' LIMIT 1';
|
||||
my $result = $db->selectrow_hashref( $query, undef, @args);
|
||||
my $result = $db->selectrow_hashref( $query, undef, @args );
|
||||
if ( !defined $result ) {
|
||||
$self->last_invalid_card(
|
||||
"@{[$token->{quantity}]} @{[$token->{name}]} @{[$token->{set_code}]}"
|
||||
);
|
||||
my $last_invalid_card = "@{[$token->{quantity}]} @{[$token->{name}]}";
|
||||
$last_invalid_card .= " @{[$token->{set_code}]}"
|
||||
if defined $token->{set_code};
|
||||
$self->last_invalid_card($last_invalid_card);
|
||||
die $ERR_INVALID_CARD;
|
||||
}
|
||||
$token->{scryfallId} = $result->{scryfallId};
|
||||
return {%$token};
|
||||
}
|
||||
|
||||
sub _filter_lines( $self, $arg ) {
|
||||
sub _filter_lines ( $self, $arg ) {
|
||||
return 0 if $arg =~ /^\w+:\s*$/;
|
||||
return 0 if $arg =~ /^\s*$/;
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub _parse_token( $self, $line ) {
|
||||
sub _parse_token ( $self, $line ) {
|
||||
my ( $quantity, $name, $set_code );
|
||||
if (
|
||||
!(
|
||||
@ -245,7 +271,7 @@ sub _parse_token( $self, $line ) {
|
||||
};
|
||||
}
|
||||
|
||||
sub _parse_card( $self, $line ) {
|
||||
sub _parse_card ( $self, $line ) {
|
||||
if ( $line !~ /\(/ ) {
|
||||
return $self->_parse_token($line);
|
||||
}
|
||||
|
@ -20,12 +20,12 @@ has _ua => ( is => 'lazy', );
|
||||
|
||||
has _last_offset_update => ( is => 'rw', );
|
||||
|
||||
sub _build__token($self) {
|
||||
sub _build__token ($self) {
|
||||
require TgMagicPdf;
|
||||
return TgMagicPdf->new->config->{telegram}{token};
|
||||
}
|
||||
|
||||
sub run($self) {
|
||||
sub run ($self) {
|
||||
$self->_dispatch_updates;
|
||||
Mojo::IOLoop->recurring(
|
||||
5 => sub {
|
||||
@ -34,7 +34,7 @@ sub run($self) {
|
||||
);
|
||||
}
|
||||
|
||||
sub _dispatch_updates($self) {
|
||||
sub _dispatch_updates ($self) {
|
||||
my $updates_p = $self->_get_updates;
|
||||
$updates_p->then(
|
||||
sub ($res) {
|
||||
@ -45,12 +45,12 @@ sub _dispatch_updates($self) {
|
||||
}
|
||||
)->catch(
|
||||
sub ($err) {
|
||||
say $err;
|
||||
warn $err;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
sub _dispatch_update( $self, $update ) {
|
||||
sub _dispatch_update ( $self, $update ) {
|
||||
if ( !defined $self->_last_offset_update
|
||||
|| $self->_last_offset_update < $update->{update_id} )
|
||||
{
|
||||
@ -61,68 +61,91 @@ sub _dispatch_update( $self, $update ) {
|
||||
}
|
||||
}
|
||||
|
||||
sub _handle_message( $self, $message ) {
|
||||
sub sendMessage ( $self, $chat_id, $text ) {
|
||||
my $url = "@{[$self->_tg_root]}/sendMessage";
|
||||
my $ua = $self->_ua;
|
||||
$ua->post_p( $url, json => { chat_id => $chat_id, text => $text } );
|
||||
}
|
||||
|
||||
sub _handle_message ( $self, $message ) {
|
||||
my $chat_type = $message->{chat}{type};
|
||||
if ( $chat_type ne 'private' ) {
|
||||
return;
|
||||
}
|
||||
my $chat_id = $message->{chat}{id};
|
||||
my $text = $message->{text};
|
||||
if (!defined $text) {
|
||||
my $chat_id = $message->{chat}{id};
|
||||
my $text = $message->{text};
|
||||
if ( !defined $text ) {
|
||||
return;
|
||||
}
|
||||
$self->sendMessage( $chat_id,
|
||||
'Got your message, attempting to generate a pdf.' );
|
||||
my $pdf_builder = TgMagicPdf::PdfBuilder->new;
|
||||
my $pdf_p;
|
||||
eval {
|
||||
$pdf_p = $pdf_builder->from_text($text);
|
||||
$pdf_p->then(sub ($pdf) {
|
||||
$self->sendDocument($chat_id, 'mtgprint.pdf', $pdf);
|
||||
})->catch(sub ($err) {
|
||||
if ($err eq $TgMagicPdf::PdfBuilder::ERR_INVALID_CARD) {
|
||||
warn $pdf_builder->last_invalid_card;
|
||||
}
|
||||
if ($err eq $TgMagicPdf::PdfBuilder::ERR_UNABLE_TO_FIND_IMAGE) {
|
||||
warn $pdf_builder->last_invalid_card;
|
||||
}
|
||||
warn $err
|
||||
});
|
||||
};
|
||||
if ($@) {
|
||||
if ($@ eq $TgMagicPdf::PdfBuilder::ERR_INVALID_CARD) {
|
||||
warn $pdf_builder->last_invalid_card;
|
||||
$pdf_builder->from_text($text)->then(
|
||||
sub ($pdf) {
|
||||
$self->sendDocument( $chat_id, 'mtgprint.pdf', $pdf );
|
||||
}
|
||||
if ($@ eq $TgMagicPdf::PdfBuilder::ERR_UNABLE_TO_FIND_IMAGE) {
|
||||
warn $pdf_builder->last_invalid_card;
|
||||
)->catch(
|
||||
sub ($err) {
|
||||
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 );
|
||||
return;
|
||||
}
|
||||
warn $err;
|
||||
$self->sendMessage( $chat_id,
|
||||
'I could not process your deck because of a server error' );
|
||||
}
|
||||
warn $@;
|
||||
return;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
sub sendDocument($self, $chat_id, $filename, $file_contents) {
|
||||
sub sendDocument ( $self, $chat_id, $filename, $file_contents ) {
|
||||
my $url = "@{[$self->_tg_root]}/sendDocument";
|
||||
my $ua = $self->_ua;
|
||||
my $res = $ua->post($url, form => {
|
||||
chat_id => $chat_id,
|
||||
document => {
|
||||
content => $file_contents,
|
||||
'Content-Type' => 'application/pdf',
|
||||
filename => $filename,
|
||||
},
|
||||
});
|
||||
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,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
sub _pdf_builder {
|
||||
return TgMagicPdf::PdfBuilder->new;
|
||||
}
|
||||
|
||||
sub _build__ua($self) {
|
||||
sub _build__ua ($self) {
|
||||
my $ua = Mojo::UserAgent->new;
|
||||
$ua->inactivity_timeout(30);
|
||||
return $ua;
|
||||
}
|
||||
|
||||
sub _get_updates($self) {
|
||||
sub _get_updates ($self) {
|
||||
my $ua = $self->_ua;
|
||||
my $url = "@{[$self->_tg_root]}/getUpdates";
|
||||
my %params;
|
||||
@ -132,7 +155,7 @@ sub _get_updates($self) {
|
||||
return $ua->post_p( $url, json => {%params} );
|
||||
}
|
||||
|
||||
sub _build__tg_root($self) {
|
||||
sub _build__tg_root ($self) {
|
||||
return "https://api.telegram.org/bot@{[$self->_token]}";
|
||||
}
|
||||
1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user