guestbook-ng/guestbook-ng.pl

161 lines
4.4 KiB
Perl
Raw Normal View History

2021-12-04 05:11:37 +00:00
#!/usr/bin/env perl
# Dec 2021
# Daniel Bowling <swaggboi@slackware.uk>
use Mojolicious::Lite -signatures;
2021-12-04 23:34:35 +00:00
use Mojo::Pg;
2022-01-01 03:32:39 +00:00
use List::Util qw{shuffle};
2022-01-02 07:01:45 +00:00
use Regexp::Common qw{URI};
2022-01-12 00:51:45 +00:00
use Number::Format qw{format_number};
2022-01-10 17:53:10 +00:00
#use Data::Dumper; # Uncomment for debugging
2022-01-01 03:32:39 +00:00
# Load the model
2021-12-04 07:26:25 +00:00
use lib 'lib';
use GuestbookNg::Model::Message;
2022-02-10 02:17:49 +00:00
use GuestbookNg::Model::Counter;
2021-12-04 07:26:25 +00:00
2021-12-04 23:34:35 +00:00
# Plugins
plugin 'Config';
2021-12-12 02:02:54 +00:00
plugin 'TagHelpers::Pagination';
2021-12-23 04:18:35 +00:00
plugin AssetPack => {pipes => [qw{Css JavaScript Combine}]};
2021-12-04 23:34:35 +00:00
# Helpers
helper pg => sub {
my $env = app->mode() eq 'development' ? 'dev_env' : 'prod_env';
state $pg = Mojo::Pg->new(app->config->{$env}{'pg_string'});
2021-12-04 23:34:35 +00:00
};
2021-12-05 04:06:05 +00:00
helper message => sub {
state $message = GuestbookNg::Model::Message->new(pg => shift->pg)
2021-12-05 04:06:05 +00:00
};
2022-02-10 02:17:49 +00:00
helper counter => sub {
state $counter = GuestbookNg::Model::Counter->new(pg => shift->pg)
};
# Routes
2021-12-19 04:03:53 +00:00
under sub ($c) {
# Opt out of Google FLoC
# https://paramdeo.com/blog/opting-your-website-out-of-googles-floc-network
$c->res->headers->header('Permissions-Policy', 'interest-cohort=()');
unless ($c->session('counted')) {
$c->counter->increment_visitor_count();
$c->session(
expiration => 1800,
counted => 1
);
}
2022-01-02 04:37:41 +00:00
2022-01-09 03:01:51 +00:00
$c->stash(status => 403) if $c->flash('error');
2022-01-09 02:21:22 +00:00
2022-04-04 01:04:09 +00:00
$c->stash(
post_count => format_number($c->message->get_post_count),
visitor_count => format_number($c->counter->get_visitor_count)
);
2022-01-12 01:15:53 +00:00
2021-12-19 04:03:53 +00:00
1;
};
get '/' => sub ($c) {
$c->redirect_to('view');
};
2022-01-12 20:18:34 +00:00
2021-12-19 05:43:18 +00:00
any [qw{GET POST}], '/sign' => sub ($c) {
2022-01-09 02:21:22 +00:00
my $v = $c->validation();
if ($c->req->method eq 'POST' && $v->has_data) {
2022-01-01 04:05:34 +00:00
my $name = $c->param('name') || 'Anonymous';
my $url = $c->param('url');
my $message = $c->param('message');
2022-01-02 22:53:43 +00:00
my $spam =
!$c->param('answer') ? 1 :
$message =~ /$RE{URI}{HTTP}{-scheme => qr<https?>}/ ? 1 :
0;
2022-01-02 07:01:45 +00:00
2022-01-09 02:21:22 +00:00
$v->required('name' )->size(1, 63);
$v->required('message')->size(2, 2000);
$v->optional('url', 'not_empty')->size(1, 255)
->like(qr/$RE{URI}{HTTP}{-scheme => qr<https?>}/);
unless ($v->has_error) {
2022-01-02 06:31:33 +00:00
$c->message->create_post($name, $message, $url, $spam);
2022-01-02 22:53:43 +00:00
$c->flash(error => 'This message was flagged as spam') if $spam;
2022-04-08 03:04:09 +00:00
return $c->redirect_to('view');
2022-01-02 04:37:41 +00:00
}
}
2022-01-09 02:21:22 +00:00
# Try to randomize things for the CAPTCHA challenge. The
# string 'false' actually evaluates to true so this is an
# attempt to confuse a (hypothetical) bot that would try to
# select what it thinks is the right answer
my @answers = shuffle(0, 'false', undef);
2022-04-03 21:11:02 +00:00
my $right_answer_label = "I'm ready to sign (choose this one)";
2022-01-09 02:21:22 +00:00
my @wrong_answer_labels = shuffle(
2022-04-03 21:11:02 +00:00
"I don't want to sign (wrong answer)",
"This is spam/I'm a bot, do not sign"
2022-01-09 02:21:22 +00:00
);
$c->stash(
answers => \@answers,
right_answer_label => $right_answer_label,
wrong_answer_labels => \@wrong_answer_labels
);
$c->render();
};
group {
under '/message';
2022-04-05 01:21:11 +00:00
get '/:message_id', [message_id => qr/[0-9]+/] => sub ($c) {
my $message_id = $c->param('message_id');
my @view_post = $c->message->get_post_by_id($message_id);
2022-04-05 01:21:11 +00:00
$c->stash(status => 404) unless $view_post[0];
$c->stash(view_post => @view_post);
$c->render();
};
};
group {
2022-04-08 03:04:09 +00:00
under '/:page', [page => ['spam', 'view']];
get '/:number', [number => qr/[0-9]+/], {number => 1} => sub ($c) {
my $base_path = $c->url_for(number => undef);
2022-04-08 03:04:09 +00:00
my $this_page = $c->param('number');
2022-04-08 16:59:15 +00:00
my $last_page = $base_path eq '/view'
? $c->message->get_last_page()
: $c->message->get_last_page(1);
my $view_posts = $base_path eq '/view'
? $c->message->get_posts($this_page)
: $c->message->get_spam($this_page);
$c->stash(
view_posts => $view_posts,
this_page => $this_page,
last_page => $last_page,
base_path => $base_path
);
$c->render();
};
};
2021-12-04 23:34:35 +00:00
# Send it
2021-12-05 08:32:22 +00:00
app->secrets(app->config->{'secrets'}) || die $@;
2021-12-12 06:50:07 +00:00
app->message->max_posts(app->config->{'max_posts'})
if app->config->{'max_posts'};
2022-04-04 01:04:09 +00:00
app->pg->migrations->from_dir('migrations')->migrate(8);
2021-12-12 06:50:07 +00:00
2021-12-23 04:18:35 +00:00
app->asset->process('swagg.css', 'css/swagg.css');
2021-12-04 05:11:37 +00:00
app->start();