App-Ikachan
view release on metacpan or search on metacpan
bin/ikachan view on Meta::CPAN
#!/usr/bin/env perl
use strict;
use warnings;
use 5.008001;
use File::Spec;
use File::Basename;
use lib File::Spec->catdir(dirname(__FILE__), '..', 'lib');
use AnySan;
use AnySan::Provider::IRC;
use Getopt::Long ();
use Pod::Usage;
use Plack::Builder;
use Plack::Builder::Conditionals;
use Plack::Request;
use Plack::Response;
use Twiggy::Server;
my $parser = Getopt::Long::Parser->new(
config => [ "no_ignore_case", "pass_through" ],
);
my %options;
my($http_host, $http_port, $irc_server, $irc_port, $irc_keyword, $irc_nickname, $irc_user, $no_post_with_join, $irc_post_interval, $irc_reconnect_interval, $enable_ssl) =
('127.0.0.1', 4979, undef, 6667, undef, 'ikachan', undef, 0, 2, 3, 0);
my @reverse_proxy;
$parser->getoptions(
'o|host=s' => \$http_host,
'p|port=i' => \$http_port,
'r|reverse-proxy=s' => \@reverse_proxy,
'S|Server=s' => \$irc_server,
'P|Port=i' => \$irc_port,
'K|Keyword=s' => \$irc_keyword,
'N|Nickname=s' => \$irc_nickname,
'U|User=s' => \$irc_user,
'i|interval=s' => \$irc_post_interval,
'enable-ssl' => \$enable_ssl,
'R|reconnect-interval=s' => \$irc_reconnect_interval,
'j|no-post-with-join' => \$no_post_with_join,
'h|help' => \$options{help},
'v|version' => \$options{version},
);
pod2usage(1) if $options{help};
pod2usage() unless defined $irc_server;
warn 'connecting to ' . join ' ', ($irc_server, $irc_port, ($irc_keyword || ''), $irc_nickname);
$irc_post_interval ||= 2;
my $irc;
my $join_channels = {};
my $is_connect = 0;
my $create_session; $create_session = sub {
irc $irc_server,
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>
bin/ikachan view on Meta::CPAN
border: 0;
}
.pre-scrollable {
max-height: 340px;
overflow-y: scroll;
}
form {
margin: 0 0 20px;
}
fieldset {
padding: 0;
margin: 0;
border: 0;
}
legend {
display: block;
width: 100%;
padding: 0;
margin-bottom: 20px;
font-size: 21px;
line-height: 40px;
color: #333333;
border: 0;
border-bottom: 1px solid #e5e5e5;
}
legend small {
font-size: 15px;
color: #999999;
}
label,
input,
button,
select,
textarea {
font-size: 14px;
font-weight: normal;
line-height: 20px;
}
input,
button,
select,
textarea {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
label {
display: block;
margin-bottom: 5px;
}
select,
textarea,
input[type="text"],
input[type="password"],
input[type="datetime"],
input[type="datetime-local"],
input[type="date"],
input[type="month"],
input[type="time"],
input[type="week"],
input[type="number"],
input[type="email"],
input[type="url"],
input[type="search"],
input[type="tel"],
input[type="color"],
.uneditable-input {
display: inline-block;
height: 20px;
padding: 4px 6px;
margin-bottom: 10px;
font-size: 14px;
line-height: 20px;
color: #555555;
vertical-align: middle;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
input,
textarea,
.uneditable-input {
width: 206px;
}
textarea {
height: auto;
}
textarea,
input[type="text"],
input[type="password"],
input[type="datetime"],
input[type="datetime-local"],
input[type="date"],
input[type="month"],
input[type="time"],
input[type="week"],
input[type="number"],
input[type="email"],
input[type="url"],
input[type="search"],
input[type="tel"],
input[type="color"],
.uneditable-input {
background-color: #ffffff;
border: 1px solid #cccccc;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
-moz-transition: border linear 0.2s, box-shadow linear 0.2s;
-o-transition: border linear 0.2s, box-shadow linear 0.2s;
transition: border linear 0.2s, box-shadow linear 0.2s;
}
textarea:focus,
input[type="text"]:focus,
input[type="password"]:focus,
input[type="datetime"]:focus,
input[type="datetime-local"]:focus,
input[type="date"]:focus,
input[type="month"]:focus,
input[type="time"]:focus,
input[type="week"]:focus,
input[type="number"]:focus,
input[type="email"]:focus,
input[type="url"]:focus,
input[type="search"]:focus,
input[type="tel"]:focus,
input[type="color"]:focus,
.uneditable-input:focus {
border-color: rgba(82, 168, 236, 0.8);
outline: 0;
outline: thin dotted \9;
/* IE6-9 */
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
}
input[type="radio"],
input[type="checkbox"] {
margin: 4px 0 0;
margin-top: 1px \9;
*margin-top: 0;
line-height: normal;
}
input[type="file"],
input[type="image"],
input[type="submit"],
input[type="reset"],
input[type="button"],
input[type="radio"],
input[type="checkbox"] {
width: auto;
}
select,
input[type="file"] {
height: 30px;
/* In IE7, the height of the select element cannot be changed by height, only font-size */
*margin-top: 4px;
/* For IE7, add top margin to align select with labels */
line-height: 30px;
}
select {
width: 220px;
background-color: #ffffff;
border: 1px solid #cccccc;
}
select[multiple],
select[size] {
bin/ikachan view on Meta::CPAN
.hide {
display: none;
}
.show {
display: block;
}
.invisible {
visibility: hidden;
}
.affix {
position: fixed;
}
...
}
__END__
=head1 NAME
ikachan - IRC message delivery by HTTP
=head1 SYNOPSIS
# connect to chat.freenode.net
ikachan -S chat.freenode.net
=head1 OPTIONS
=over 4
=item -o, --host
The interface a TCP based server daemon binds to. Defauts to undef,
which lets most server backends bind the any (*) interface. This
option doesn't mean anything if the server does not support TCP
socket.
=item -p, --port (default: 4979)
The port number a TCP based server daemon listens on. Defaults to
5000. This option doesn't mean anything if the server does not support
TCP socket.
=item -S, --Server
irc server address.
=item -P, --Port (default: 6667)
irc server port.
=item --enable-ssl
use ssl connection.
=item -K, --Keyword
irc server password
=item -N, --Nickname
irc nickname
=item -U, --User
irc user name
=item -r, --reverse-proxy
treat X-Forwarded-For as REMOTE_ADDR if REMOTE_ADDR match this argument.
see L<Plack::Middleware::ReverseProxy>.
=item -i, --interval
irc post interval. for Excess Flood
=item -R, --reconnect-interval
interval of reconnect to irc server.
exit application if interval == 0.
=item -j, --no-post-with-join
disable to irc message post with channel join
=back
=head1 AUTHOR
Kazuhiro Osawa E<lt>yappo {at} shibuya {dot} plE<gt>
=head1 SEE ALSO
L<AnySan::Provider::IRC>, L<Twiggy>
=head1 LICENSE
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
( run in 0.603 second using v1.01-cache-2.11-cpan-5b529ec07f3 )