Bump version and update Changes
[nethack-naodash.git] / lib / App / Web / NAOdash.pm
CommitLineData
01ba3ddc
MG
1package App::Web::NAOdash;
2
3use 5.014000;
4use strict;
5use warnings;
6use re '/saa';
7use parent qw/Plack::Component/;
8
350c8f14 9our $VERSION = '0.003';
01ba3ddc
MG
10
11use Digest::SHA qw/sha256_base64/;
12use File::Slurp;
13use HTML::TreeBuilder;
14use JSON::MaybeXS qw/encode_json/;
15use NetHack::NAOdash qw/naodash_user/;
89ac7b44 16use Plack::Request;
01ba3ddc
MG
17
18my ($dash, $css, $css_hash);
19
20{
21 $css = read_file 'web/dash.css';
22 $css =~ y/\n\t//d;
23 $css =~ s/([):]) /$1/g;
24 $css =~ s/ ([{(])/$1/g;
25 $css_hash = 'sha256-' . sha256_base64($css) . '=';
26 my $tb = HTML::TreeBuilder->new;
27 $tb->ignore_unknown(0);
28 $dash = $tb->parse_file('web/dash.html');
29 $dash->find('link')->postinsert([style => $css])->detach;
30}
31
32sub format_time {
33 my ($time) = @_;
34 return unless defined $time;
35 my %units = (
36 s => 60,
37 m => 60,
38 h => 24,
39 d => 7,
40 w => 1e9,
41 );
42 my @parts;
43 for (qw/s m h d w/) {
44 use integer;
45 last unless $time;
46 unshift @parts, ($time % $units{$_}) . $_;
47 $time /= $units{$_};
48 }
49 join ' ', @parts;
50}
51
52sub make_html {
89ac7b44 53 my ($name, $query, $result) = @_;
01ba3ddc
MG
54 my @checks = @{$result->{checks}};
55 my %numbers = %{$result->{numbers}};
56 $numbers{totalrealtime} = format_time $numbers{totalrealtime};
57 $numbers{minrealtime} = format_time $numbers{minrealtime};
58
59 my $tree = $dash->clone;
60 $tree->find('title')->delete_content->push_content("Dashboard for $name");
61 $tree->find('a')->attr(href => $tree->find('a')->attr('href') . $name);
62 $tree->find('a')->delete_content->push_content($name);
63 for (@checks) {
64 my $el = $tree->look_down(id => $_);
65 warn "No element for check $_" unless $el; ## no critic (RequireCarping)
66 $el->attr(class => 'done') if $el;
67 }
68 while (my ($id, $num) = each %numbers) {
69 next unless defined $num;
70 my $el = $tree->look_down(id => $id);
71 warn "No element for check $id" unless $el; ## no critic (RequireCarping)
72 $el->delete_content->push_content($num);
73 }
89ac7b44
MG
74 my $ahref = $tree->look_down(href => "?$query");
75 $ahref->replace_with(join '', $ahref->content_list) if $ahref;
01ba3ddc
MG
76 $tree->as_HTML;
77}
78
79sub reply {
80 my ($code, $message, $type) = @_;
81 $type //= 'text/plain';
82 [$code, [
83 'Cache-Control' => ($code < 500 ? 'max-age=86400' : 'no-cache'),
84 'Content-Type' => "$type; charset=utf-8",
85 'Content-Length' => length $message,
86# Safari implements CSP Level 1 but not CSP Level 2
87# 'Content-Security-Policy' => "default-src 'none'; style-src '$css_hash';",
88 ], [$message]]
89}
90
91sub call {
92 my ($self, $env) = @_;
89ac7b44
MG
93 my $req = Plack::Request->new($env);
94 return reply 400, 'Bad request: user contains characters outside [a-zA-Z0-9_]' unless $req->path =~ m{^/(\w+)$};
01ba3ddc 95 my $name = $1;
89ac7b44
MG
96 my %args = (
97 include_versions => [$req->query_parameters->get_all('include_versions')],
98 exclude_versions => [$req->query_parameters->get_all('exclude_versions')],
99 );
100 my $result = eval { naodash_user \%args, $name } or return reply 500, $@;
01ba3ddc
MG
101
102 return reply 200, encode_json($result), 'application/json' if $self->{json};
89ac7b44 103 return reply 200, make_html($name, $req->query_string, $result), 'text/html';
01ba3ddc
MG
104}
105
1061;
107__END__
108
109=encoding utf-8
110
111=head1 NAME
112
113App::Web::NAOdash - Analyze NetHack xlogfiles and extract statistics (web interface)
114
115=head1 SYNOPSIS
116
117 # In app.psgi
118 use App::Web::NAOdash;
119 use Plack::Builder;
120
121 builder {
122 mount '/dash/' => App::Web::NAOdash->new->to_app;
123 mount '/json/' => App::Web::NAOdash->new(json => 1)->to_app;
124 ...
125 }
126
127=head1 DESCRIPTION
128
129App::Web::NAOdash is a web interface to L<NetHack::NAOdash>.
130
131It handles URLs of the form C</username>, where I<username> is a NAO
132username. It retrieves the xlogfile from NAO and returns the result of
133the analysis.
134
89ac7b44
MG
135Two query parameters are accepted: include_versions and
136exclude_versions, both of which can take multiple values by
137specifiying them multiple times. They are passed directly to the
138B<naodash_user> function, see the documentation of L<NetHack::NAOdash>
139for an explanation of their function.
140
01ba3ddc
MG
141The constructor takes a single named parameter, I<json>, that is false
142by default. The result will be returned as HTML is I<json> is false,
143as JSON if I<json> is true.
144
145=head1 SEE ALSO
146
147L<NetHack::NAOdash>, L<App::NAOdash>
148
149=head1 AUTHOR
150
151Marius Gavrilescu, E<lt>marius@ieval.roE<gt>
152
153=head1 COPYRIGHT AND LICENSE
154
155Copyright (C) 2015 by Marius Gavrilescu
156
157This library is free software; you can redistribute it and/or modify
158it under the same terms as Perl itself, either Perl version 5.20.2 or,
159at your option, any later version of Perl 5 you may have available.
160
161
162=cut
This page took 0.019786 seconds and 4 git commands to generate.