root/lang/perl/mobirc/trunk/mobirc/lib/Mobirc/HTTPD/Controller.pm @ 840

Revision 840, 7.4 kB (checked in by tokuhirom, 6 years ago)

lang/perl/mobirc: colorize nick. my nick and other's nick have different color ;-)

Line 
1package Mobirc::HTTPD::Controller;
2use strict;
3use warnings;
4use boolean ':all';
5
6use Carp;
7use CGI;
8use Encode;
9use Template;
10use File::Spec;
11use URI::Find;
12use URI::Escape;
13use HTTP::Response;
14use HTML::Entities;
15use Scalar::Util qw/blessed/;
16use List::Util qw/first/;
17use CGI::Cookie;
18
19use Mobirc;
20use Mobirc::Util;
21
22sub call {
23    my ($class, $method, @args) = @_;
24    DEBUG "CALL METHOD $method with @args";
25    $class->$method(@args);
26}
27
28# this module contains MVC's C.
29
30sub dispatch_index {
31    my ($class, $c) = @_;
32
33    return render(
34        $c,
35        'index' => {
36            exists_recent_entries => (
37                grep( $c->{irc_heap}->{unread_lines}->{$_}, keys %{ $c->{irc_heap}->{unread_lines} } )
38                ? true
39                : false
40            ),
41            canon_channels => [
42                reverse
43                  sort {
44                    $c->{irc_heap}->{channel_mtime}->{$a} <=> $c->{irc_heap}->{channel_mtime}->{$b}
45                  }
46                  keys %{ $c->{irc_heap}->{channel_name} }
47            ],
48        }
49    );
50}
51
52# recent messages on every channel
53sub dispatch_recent {
54    my ($class, $c) = @_;
55
56    my $out = render(
57        $c,
58        'recent' => {
59        },
60    );
61
62    # reset counter.
63    for my $canon_channel ( sort keys %{ $c->{irc_heap}->{channel_name} } ) {
64        $c->{irc_heap}->{unread_lines}->{$canon_channel}   = 0;
65        $c->{irc_heap}->{channel_recent}->{$canon_channel} = [];
66    }
67
68    return $out;
69}
70
71# topic on every channel
72sub dispatch_topics {
73    my ($class, $c) = @_;
74
75    return render(
76        $c,
77        'topics' => { },
78    );
79}
80
81sub post_dispatch_show_channel {
82    my ( $class, $c, $recent_mode, $channel) = @_;
83
84    $channel = decode('utf8', $channel); # maybe $channel is not flagged utf8.
85
86    my $r       = CGI->new( $c->{req}->content );
87    my $message = $r->param('msg');
88    $message = decode( $c->{config}->{httpd}->{charset}, $message );
89
90    DEBUG "POST MESSAGE $message";
91
92    if ($message) {
93        if ($message =~ m{^/}) {
94            DEBUG "SENDING COMMAND";
95            $message =~ s!^/!!g;
96
97            my @args =
98              map { encode( $c->{config}->{irc}->{incode}, $_ ) } split /\s+/,
99              $message;
100
101            $c->{poe}->kernel->post('mobirc_irc', @args);
102        } else {
103            DEBUG "NORMAL PRIVMSG";
104
105            $c->{poe}->kernel->post( 'mobirc_irc',
106                privmsg => encode( $c->{config}->{irc}->{incode}, $channel ) =>
107                encode( $c->{config}->{irc}->{incode}, $message ) );
108
109            DEBUG "Sending message $message";
110            add_message(
111                $c->{poe},
112                $channel,
113                $c->{irc_heap}->{irc}->nick_name,
114                $message,
115                'publicfromhttpd',
116            );
117        }
118    }
119
120    my $response = HTTP::Response->new(302);
121    $response->push_header( 'Location' => $c->{req}->uri . '?time=' . time); # TODO: must be absoulute url.
122    return $response;
123}
124
125
126sub dispatch_show_channel {
127    my ($class, $c, $recent_mode, $channel) = @_;
128
129    DEBUG "show channel page: $channel";
130    $channel = decode('utf8', $channel); # maybe $channel is not flagged utf8.
131
132    my $out = render(
133        $c,
134        'show_channel' => {
135            canon_channel  => canon_name($channel),
136            channel        => $channel,
137            subtitle       => compact_channel_name($channel),
138            recent_mode    => $recent_mode,
139        }
140    );
141
142    {
143        my $canon_channel = canon_name($channel);
144
145        # clear unread counter
146        $c->{irc_heap}->{unread_lines}->{$canon_channel} = 0;
147
148        # clear recent messages buffer
149        $c->{irc_heap}->{channel_recent}->{$canon_channel} = [];
150    }
151
152    return $out;
153}
154
155sub render {
156    my ( $c, $name, $args ) = @_;
157
158    croak "invalid args : $args" unless ref $args eq 'HASH';
159
160    DEBUG "rendering template";
161
162    # set default vars
163    $args = {
164        compact_channel_name => \&compact_channel_name,
165        docroot              => $c->{config}->{httpd}->{root},
166        render_line          => sub { render_line( $c, @_ ) },
167        user_agent           => $c->{user_agent},
168        title                => $c->{config}->{httpd}->{title},
169        version              => $Mobirc::VERSION,
170
171        %{ $c->{irc_heap} },
172
173        %$args,
174    };
175
176    my $tt = Template->new(
177        ABSOLUTE => 1,
178        INCLUDE_PATH =>
179          File::Spec->catfile( $c->{config}->{global}->{assets_dir}, 'tmpl', )
180    );
181    $tt->process(
182        File::Spec->catfile(
183            $c->{config}->{global}->{assets_dir},
184            'tmpl', "$name.html"
185        ),
186        $args,
187        \my $out
188    ) or die $tt->error;
189
190    DEBUG "rendering done";
191
192    my $content = Encode::is_utf8($out) ? $out : decode( 'utf8', $out );
193    $content = encode($c->{config}->{httpd}->{charset}, $content);
194
195    my $response = HTTP::Response->new(200);
196    $response->push_header( 'Content-type' => $c->{config}->{httpd}->{content_type} );
197    $response->push_header('Content-Length' => length($content) );
198
199    if ( $c->{config}->{httpd}->{use_cookie} ) {
200        set_cookie( $c, $response );
201    }
202
203    $response->content( $content );
204    return $response;
205}
206
207sub set_cookie {
208    my $c        = shift;
209    my $response = shift;
210
211    my ( $user_info, ) =
212      map { $_->{config} }
213      first { $_->{module} =~ /Cookie$/ }
214    @{ $c->{config}->{httpd}->{authorizer} };
215    croak "Can't get user_info" unless $user_info;
216
217    $response->push_header(
218        'Set-Cookie' => CGI::Cookie->new(
219            -name    => 'username',
220            -value   => $user_info->{username},
221            -expires => $c->{config}->{httpd}->{cookie_expires}
222        )
223    );
224    $response->push_header(
225        'Set-Cookie' => CGI::Cookie->new(
226            -name    => 'passwd',
227            -value   => $user_info->{username},
228            -expires => $c->{config}->{httpd}->{cookie_expires}
229        )
230    );
231}
232
233sub render_line {
234    my $c   = shift;
235    my $src = shift;
236
237    return "" unless $src;
238    croak "must be flagged utf8: $src" unless Encode::is_utf8($src);
239
240    $src = encode_entities($src, q(<>&"'));
241
242    URI::Find->new(
243        sub {
244            my ( $uri, $orig_uri ) = @_;
245
246            my $out = qq{<a href="$uri" rel="nofollow">$orig_uri</a>};
247            if ( $c->{config}->{httpd}->{au_pcsv} ) {
248                $out .=
249                  sprintf( '<a href="device:pcsiteviewer?url=%s">[PCSV]</a>',
250                    $uri );
251            }
252            $out .=
253              sprintf(
254'<a href="http://mgw.hatena.ne.jp/?url=%s&noimage=0&split=1">[ph]</a>',
255                uri_escape($uri) );
256            return $out;
257        }
258    )->find( \$src );
259
260    $src =~
261s!\b(0\d{1,3})([-(]?)(\d{2,4})([-)]?)(\d{4})\b!<a href="tel:$1$3$5">$1$2$3$4$5</a>!g;
262    $src =~
263      s!\b(\w[\w.+=-]+\@[\w.-]+[\w]\.[\w]{2,4})\b!<a href="mailto:$1">$1</a>!g;
264
265    $src = decorate_irc_color($src);
266
267    $src =~ s{^\*([a-z_]+)\*(\d+):(\d+)\s*(.+)$}{
268        my ($class, $hour, $minute, $body) = ($1, $2, $3, $4);
269
270        if ($class eq 'notice' || $class eq 'public') {
271            $body =~ s!^([^&]+)&gt; (.+)$!sprintf "<span class='%s'>$1</span>&gt; $2", ($1 eq $c->{irc_heap}->{irc}->nick_name) ? 'nick_myself' : 'nick_normal'!e;
272        }
273
274        my $res = qq!<span class="time"><span class="hour">$hour</span><span class="colon">:</span><span class="minute">$minute</span></span>!;
275           $res .= " ";
276           $res .= qq!<span class="$class">$body</span>!;
277           $res;
278    }e;
279
280    return $src;
281}
282
2831;
Note: See TracBrowser for help on using the browser.