App-Ikachan

 view release on metacpan or  search on metacpan

bin/ikachan  view on Meta::CPAN

        key       => $irc_server,
        port      => $irc_port,
        password  => $irc_keyword,
        nickname  => $irc_nickname,
        user      => $irc_user,
        interval  => $irc_post_interval,
        enable_ssl => $enable_ssl,
        on_connect => sub {
            my ($con, $err) = @_;
            if (defined $err) {
                warn "connect error: $err\n";
                exit 1 unless $irc_reconnect_interval;
                sleep $irc_reconnect_interval;
                $con->disconnect('try reconnect');
            } else {
                warn 'connect';
                $is_connect      = 1;
            }
        },
        on_disconnect => sub {
            warn 'disconnect';
            # XXX: bad hack...
            undef $irc->{client};
            undef $irc->{SEND_TIMER};
            undef $irc;
            $is_connect = 0;
            $irc = $create_session->();
        },
        channels => {
            map { $_ => +{} } keys %{ $join_channels },
        };
};
$irc = $create_session->();

sub rendar {
    my($code, $msg) = @_;
    my $res = Plack::Response->new($code);
    $res->content_type('text/plain');
    $res->content_length(length $msg);
    $res->body($msg);
    $res->finalize;
}

sub join_channel {
    my ($channel, $key) = @_;
    $irc->join_channel($channel, $key);
    $join_channels->{$channel} = {
        join_at => time(),
    };
}

my $code = sub {
    my $req = Plack::Request->new(shift);
    my $method = $req->method;
    my $path   = $req->path;

    if ($method eq 'POST' && ! $is_connect) {
        my $html = q{<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>ikachan</title>
    <head>
    <body>
        can not connect to irc server
    </body>
</html>};
        my $res = Plack::Response->new(503);
        $res->content_type('text/html; charset=utf-8');
        $res->content_length(length $html);
        $res->body($html);
        return $res->finalize;
    }

    if ($method eq 'GET') {
        if ($path eq '/channel_list') {
            my $list = [ keys %{ $join_channels } ];
            return rendar(200, join("\n", @$list));
        } elsif ($path eq '/') {
            my $base = $req->base;
            my $logo = get_logo();
            my $css = get_css();
            my $html =<<HTML;
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>ikachan</title>
        <style>
            ${css}

        </style>
    <head>
    <body>
        <div class="container">
        <div class="row"><div class="span12">
        <h1>
            ikachan
            <img src="data:image/png;base64,${logo}" />
        </h1>

        <h2>join channel list</h2>
        <iframe src="/channel_list"></iframe>

        <h2>API usage</u2>

        <h3>channel join</h3>
        <section>
            <table class="table table-bordered">
                <tr><td>method</td><td>POST</td></tr>
                <tr><td>url</td><td>${base}join</td></tr>
                <tr><td>form params</td><td>channel=#channel&channel_keyword=keyword</td></tr>
            </table>
            <h4>testing form</h4>
            <form action="/join" method="post">
                join channel: <input name="channel" /><br />
                channel keyword(option): <input name="channel_keyword" /><input type="submit" value="join" class="btn" />
            </form>
        <section>

        <section>
            <h3>channel leave</h3>
            <table class="table table-bordered">
                <tr><td>method</td><td>POST</td></tr>
                <tr><td>url</td><td>${base}leave</td></tr>
                <tr><td>form params</td><td>channel=#channel</td></tr>
            </table>
            <form action="/leave" method="post">
                leave channel: <input name="channel" /><input type="submit" value="leave" class="btn" />
            </form>
        <section>

        <section>
            <h3>sent notice message to channel</h3>
            <table class="table table-bordered">
                <tr><td>method</td><td>POST</td></tr>
                <tr><td>url</td><td>${base}notice</td></tr>
                <tr><td>form params</td><td>channel=#channel&message=your_message</td></tr>
            </table>
            <form action="/notice" method="post">
                channel: <input name="channel" /><br />
                message: <input name="message" /><input type="submit" value="post" class="btn" />
            </form>
        </section>

        <section>
            <h3>sent privmsg message to channel</h3>
            <table class="table table-bordered">
                <tr><td>method</td><td>POST</td></tr>
                <tr><td>url</td><td>${base}privmsg</td></tr>
                <tr><td>form params</td><td>channel=#channel&message=your_message</td></tr>
            </table>
            <form action="/privmsg" method="post">
                channel: <input name="channel" /><br />
                message: <input name="message" />
                <input type="submit" value="post" class="btn" />
            </form>
        </section>
        </div>
        </div>
    </body>
</html>
HTML

            my $res = Plack::Response->new(200);
            $res->content_type('text/html; charset=utf-8');
            $res->content_length(length $html);
            $res->body($html);
            return $res->finalize;
        }
    } elsif ($method eq 'POST') {
        my $channel = $req->param('channel');

        if ($path eq '/join') {
            return rendar(403, "joinned channel: $channel") if $join_channels->{$channel};
            my $channel_keyword = $req->param('channel_keyword');
            join_channel($channel, $channel_keyword);
            return rendar(200, "join success channel: $channel");
        } elsif ($path eq '/leave' || $path eq '/part') {
            return rendar(404, "not joinned channel: $channel") unless $join_channels->{$channel};
            $irc->leave_channel($channel);
            delete $join_channels->{$channel};
            return rendar(200, "leave success channel: $channel");
        } elsif ($path eq '/notice') {
            if ($no_post_with_join) {
                return rendar(404, "not joinned channel: $channel") unless $join_channels->{$channel};
            } elsif (not $join_channels->{$channel}) {
                join_channel($channel);
            }
            my $message = $req->param('message');
            $irc->send_message( $message, channel => $channel );
            return rendar(200, "message sent channel: $channel $message");
        } elsif ($path eq '/privmsg') {
            if ($no_post_with_join) {
                return rendar(404, "not joinned channel: $channel") unless $join_channels->{$channel};
            } elsif (not $join_channels->{$channel}) {
                join_channel($channel);
            }
            my $message = $req->param('message');
            $irc->send_message( $message, channel => $channel, privmsg => 1 );
            return rendar(200, "message sent channel: $channel $message");
        }
    }

    return rendar(404, 'not found');
};
my $app = builder {
    if ( @reverse_proxy ) {
        enable match_if addr(\@reverse_proxy), 'Plack::Middleware::ReverseProxy';
    }
    enable 'Plack::Middleware::AccessLog', format => 'combined';
    $code;
};

warn "starting httpd: http://$http_host:$http_port/";
my $twiggy = Twiggy::Server->new(
    host => $http_host,
    port => $http_port,
);
$twiggy->register_service($app);

AnySan->run;

sub get_logo {
    'iVBORw0KGgoAAAANSUhEUgAAAKAAAAB8CAYAAADuM7t5AAAEJGlDQ1BJQ0MgUHJvZmlsZQAAOBGFVd9v21QUPolvUqQWPyBYR4eKxa9VU1u5GxqtxgZJk6XtShal6dgqJOQ6N4mpGwfb6baqT3uBNwb8AUDZAw9IPCENBmJ72fbAtElThyqqSUh76MQPISbtBVXhu3ZiJ1PEXPX6yznfOec7517bRD1fabWaGVWIlquunc8klZOnF...
}



( run in 2.091 seconds using v1.01-cache-2.11-cpan-df04353d9ac )