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 )