package PZ::Controller::Shortcut; use Mojo::Base 'Mojolicious::Controller', -signatures; use Data::Validate::URI qw(is_uri); use Image::PNG::QRCode 'qrpng'; use GD; use Mojo::UserAgent; use constant SHORTCUT => qr/^[a-z\d\-]{1,32}$/; sub redirect ($c) { my $shortcut = $c->schema->resultset('Shortcut')->search({ shortcut => $c->stash->{shortcut}, is_active => 1, deleted => undef, })->first; if ( ! $shortcut ) { $c->render( '404', status => 404 ); return; } $shortcut->update({ counter => $shortcut->counter + 1 }); $shortcut->add_to_log_items({ ip => ($c->forwarded_for || $c->tx->remote_address), ua => $c->req->headers->user_agent, referrer => $c->req->headers->referrer, }); $c->res->code($shortcut->code); $c->redirect_to($shortcut->url); } sub create ($c) { $c->openapi->valid_input or return; my $args = $c->req->json; my $url = $c->sanitize_url($args->{url}); return $c->error(400, 'Chybná URL adresa!') if ! is_uri($url); my $custom = lc($args->{shortcut}); if ( $custom ) { return $c->error(400, 'Neplatná zkratka') if $custom !~ SHORTCUT; my $exists = $c->schema->resultset('Shortcut')->search({ deleted => undef, shortcut => $custom, })->count; return $c->error(400, "Zkratka $custom už je použitá") if $exists; } my $title = ''; my $ua = Mojo::UserAgent->new; eval { $title = $ua->get($url)->result->dom->at('title')->text; }; my $shortcut = $c->user->add_to_shortcuts({ url => $url, title => $title, shortcut => ($custom || $c->schema->resultset('Shortcut')->generate()) }); $c->render( status => 201, openapi => { $shortcut->get_columns }, ); } sub get ($c) { my $shortcut = $c->shortcut() || return; $c->render(json => { $shortcut->get_columns } ); } sub update ($c) { my $shortcut = $c->shortcut() || return; return $c->error(400, 'Chybná URL adresa!') if ! is_uri($c->req->json->{url}); $shortcut->update({ code => $c->req->json->{code}, url => $c->req->json->{url}, title => $c->req->json->{title}, }); $c->render(status => 204, text => '' ); } sub delete ($c) { my $shortcut = $c->shortcut() || return; $shortcut->update({ deleted => \'now()' }); $c->render(status => 204, text => '' ); } sub list ($c) { my @shortcuts = (); SHORTCUT: foreach my $shortcut ( $c->user->shortcuts( { deleted => undef }, { order_by => {-desc => 'created'} }, ) ) { push @shortcuts, $c->spec_filter( { $shortcut->get_columns }, 'Shortcut' ); } $c->render(json => \@shortcuts, ); } sub qr ($c) { my $url = 'https://' . $c->config->{domain} . '/' . $c->stash->{shortcut}; $c->trace($url); my $png = qrpng (text => $url, level => 4, scale => 6); my $qr = GD::Image->new($png); my $logo = GD::Image->new($c->app->home . '/public/logo.png'); $qr->trueColor(1); $logo->trueColor(1); $logo->transparent($logo->colorClosest($logo->rgb($logo->getPixel(0,0)))); $qr->copyMerge($logo,73,73,0,0,100,100,80); $c->res->headers->content_type('image/png'); $c->render( data => $qr->png ); } 1;