/bot.pl
Perl | 435 lines | 355 code | 75 blank | 5 comment | 37 complexity | 35be73cb91ea3e392b2eaf8d608a778e MD5 | raw file
- use strict;
- use warnings;
- use POE qw(Component::IRC
- Component::IRC::Plugin::CPAN::LinksToDocs
- Component::IRC::Plugin::URI::Find
- Component::IRC::Plugin::Google::Calculator
- Component::IKC::Server
- Component::IKC::Specifier
- );
- use Data::Dumper;
- use POE::Component::IKC::ClientLite;
- use DateTime;
- use constant PATH => $ENV{HOME} ."/irc/";
- use Encode qw/encode decode/;
- use URI;
- use URI::Escape;
- use YAML::Syck;
- use Web::Scraper;
- use LWP::UserAgent;
- use Net::Twitter;
- use Me2day;
- my $nickname = 'Perl_^^';
- my $ircname = 'Perl Bot :-)';
- my $server = 'irc.hanirc.org';
- my $translator = 'http://j2k.naver.com/j2k.php/korean/';
- my $dic_url = 'http://endic.naver.com/search.nhn?kind=keyword&query=';
- my $naver_map_url = 'http://map.naver.com/?query=';
- my $lang = "ko";
- my $google_url = 'http://www.google.com/search?hl='.$lang.'&q=';
- my $ping_time = 0;
- my $info;
- my @channels = ('#perl');
- my $base_url = "";
- binmode(STDOUT, ":utf8");
- my $config;
- if (-f 'config.yaml') {
- $config = LoadFile('config.yaml');
- }
- my $name = "Client$$";
- my $remote;
- my $twit = Net::Twitter->new(
- username => $config->{twitter}->{username},
- password => $config->{twitter}->{password},
- );
- my $me2day = Me2day->new(
- username => $config->{me2day}->{username},
- user_key => $config->{me2day}->{user_key},
- app_key => $config->{me2day}->{app_key},
- );
- POE::Component::IKC::Server->spawn(
- port => 31337,
- name => 'AppServer',
- );
- POE::Session->create(
- inline_states => {
- _start => \&service_start,
- update => \&service_update,
- did_something => \&service_response,
- }
- );
- unless (-d PATH) {
- mkdir PATH;
- print STDERR "Created Directory ".PATH."\n";
- }
- my $irc = POE::Component::IRC->spawn(
- nick => $nickname,
- ircname => $ircname,
- server => $server,
- ) or die "Oh noooo! $!";
- POE::Session->create(
- package_states => [
- main => [ qw(_default _start irc_001 irc_public irc_msg irc_urifind_uri irc_join irc_part irc_quit irc_353) ],
- ],
- heap => { irc => $irc },
- );
- POE::Kernel->run();
- sub service_start {
- my ( $kernel, $heap ) = @_[ KERNEL, HEAP ];
- my $service_name = "apphanirc";
- $kernel->alias_set($service_name);
- $kernel->call( IKC => publish => $service_name, ["update"] );
- }
- sub service_update {
- my ( $kernel, $heap, $request ) = @_[ KERNEL, HEAP, ARG0 ];
- $kernel->delay_set( did_something => 1, $request );
- }
- sub service_response {
- my ( $kernel, $heap, $res ) = @_[ KERNEL, HEAP, ARG0 ];
- my @data = @{ $res };
- $irc->yield( privmsg => "#perl" => $data[0] );
- }
- sub _encode {
- encode("cp949", decode("utf-8", shift));
- }
- sub _start {
- my $heap = $_[HEAP];
-
- my $irc = $heap->{irc};
- $irc->yield( register => 'all' );
- $irc->plugin_add( 'LinksToDocs' => POE::Component::IRC::Plugin::CPAN::LinksToDocs->new );
- $irc->plugin_add( 'UriFind' => POE::Component::IRC::Plugin::URI::Find->new );
- $irc->plugin_add( 'GoogleCalc' => POE::Component::IRC::Plugin::Google::Calculator->new );
- $irc->yield( connect => { } );
- return;
- }
- sub irc_001 {
- my $sender = $_[SENDER];
-
- my $irc = $sender->get_heap();
-
- print "Connected to ", $irc->server_name(), "\n";
- $irc->yield( join => $_ ) for @channels;
- return;
- }
- sub irc_msg {
- my ($sender, $who, $where, $what) = @_[SENDER, ARG0 .. ARG2];
- my $nick = ( split /!/, $who)[0];
- my $me = $where->[0];
- my $irc = $sender->get_heap();
- my ($channel,$target);
- my @block;
- if ($what =~ /^!([a-z]+)\s?(.*?)?$/) {
- my ($command, $desc) = ($1,$2);
- if ($command eq 'blah') {
- @block = split /\s+/, $desc;
- $channel = shift @block;
- my $blah = join(" ", @block);
- if ($channel && $channel =~ /^\#.*/ && $blah) {
- $irc->yield( privmsg => $channel => $blah );
- }
- }
- elsif ($command eq 'kick') {
- ($channel, $target) = split /\s+/, $desc;
- unless ($target) {
- $irc->yield( privmsg => $nick => _encode($config->{command}->{kick}) );
- } else {
- $irc->yield( kick => $channel => $target );
- }
- }
- elsif ($command eq 'oper') {
- ($channel, $target) = split /\s+/, $desc;
- $irc->yield( mode => $channel => "+oo" => $target );
- }
- elsif ($command eq 'reload') { # Config Reloader
- if (-f "config.yaml") {
- $config = LoadFile("config.yaml");
- $irc->yield( privmsg => $nick => "reloaded config file" );
- }
- }
- }
- }
- sub irc_public {
- my ($sender, $who, $where, $what) = @_[SENDER, ARG0 .. ARG2];
- my $nick = ( split /!/, $who )[0];
- my $channel = $where->[0];
- $channel =~ s/#//;
- unless ($remote) {
- $remote = create_ikc_client(
- port => 31338,
- name => $name,
- timeout => 1,
- );
- }
- $remote->post_respond( 'application/update', encode("utf-8", decode("cp949","[hanIRC] $nick: ".$what)) );
- unless(-d PATH.$channel) {
- print STDERR "Created Directory ". PATH.$channel . " for IRC Channel ".$channel."\n";
- mkdir PATH.$channel;
- }
- # Filtering by aero
- my $str = decode("euc-kr", $what);
- return 0 if $str =~ m/^\x{3151}/;
- my $time = DateTime->now( time_zone => 'Asia/Tokyo' );
- my $filepath = PATH.$channel."/".$time->ymd.".log";
- open my $fh, ">>:utf8", $filepath;
- my $desc = "[".$time->hms."] <".decode("cp949", $nick)."> ".
- decode("cp949", $what)."\n";
- print $fh $desc;
- print $desc;
- close $fh;
- my $irc = $sender->get_heap();
- # $command, $desc
- if ($what =~ /^!([a-z0-9]+)\s?(.*?)?$/) {
- my ($command, $desc) = ($1, $2);
- if ($command =~ /^(?:fish|nolog|kick|code|dic|search|map|twitter|me2day)$/ && !$desc) {
- $irc->yield( privmsg => "#".$channel => $nick." : "._encode($config->{command}->{$command}) );
- }
- elsif ($command eq 'kick') {
- $irc->yield( kick => "#".$channel => $desc );
- }
- elsif ($command eq 'j2k') {
- my $address = $translator;
- if ($desc) {
- $address .= $desc;
- }
- elsif ($base_url) {
- $address .= $base_url;
- }
- else {
- return;
- }
- $irc->yield( privmsg => "#".$channel => $address );
- }
- elsif ($command eq 'help') {
- foreach my $comment (@{ $config->{command}->{help} }) {
- $irc->yield( privmsg => "#".$channel => _encode($comment) );
- }
- }
- elsif ($command eq 'dic') {
- my $html = scraper {
- process 'table>tr>td[class="p3"]', text => 'TEXT';
- };
-
- my $data = $html->scrape(URI->new($dic_url.URI::Escape::uri_escape($desc)));
-
- my $text = $data->{text};
-
- $text = encode("cp949", $text) if utf8::valid($text);
-
- my @voca = split /\d/, $text;
-
- for my $dic (@voca) {
- $irc->yield( privmsg => "#".$channel => $dic );
- }
- }
- elsif($command eq 'map')
- {
- my $address = $naver_map_url . URI::Escape::uri_escape($desc);
- $irc->yield(privmsg=>"#".$channel=>$address);
- }
- elsif ($command eq 'search') {
- my $html = scraper {
- process 'div[class="g"]', text => 'TEXT';
- };
-
- my $data = $html->scrape(URI->new($google_url.URI::Escape::uri_escape($desc)));
-
- my $text = $data->{text};
- $text = encode("cp949", $text) if utf8::valid($text);
-
- my @entry = split /\d/, $text;
-
- for my $content (@entry) {
- $irc->yield( notic => "#".$channel => $content );
- }
- }
- elsif ($command eq 'lang') {
- if (!$desc || $desc !~ /^(?:en|ko|ja)$/) {
- $irc->yield( privmsg => "#".$channel => $nick." : "._encode($config->{command}->{lang}) );
- } else {
- $lang = $desc;
- $irc->yield( privmsg => "#".$channel => $nick." : "._encode($config->{log}->{lang}). ' => '.$lang );
- }
- }
- elsif ($command eq 'twitter') {
- $twit->update(encode("utf-8", decode("cp949", $nick. ": ".$desc)));
- $irc->yield( privmsg => "#".$channel => $nick ." : ". _encode($config->{log}->{twitter}) );
- }
- elsif ($command eq 'me2day') {
- my $res;
- if ($desc =~ /@\:/) {
- my ($post, $tag) = split /@\:/, $desc; #/
- $tag .= " me2irc";
- $res = $me2day->create_post( body => encode("utf-8", decode("cp949",$nick." : ".$post)), tags => encode("utf-8", decode("cp949", $tag)) );
- } else {
- $res = $me2day->create_post( body => encode("utf-8", decode("cp949",$nick." : ".$desc)), tags => "me2irc" );
- }
- if ($res->status_line =~ /200/) {
- $res->content =~ /<permalink>(.*?)<\/permalink>/;
- my $permalink = $1;
- $irc->yield( privmsg => "#".$channel => $nick ." : ". _encode($config->{log}->{me2day}). " ".$permalink );
- }
- }
- elsif ($command eq 'attention') {
- if ($info->{"#".$channel}) {
- $irc->yield( privmsg => "#".$channel => join(" ", @{ $info->{"#".$channel} }) );
- }
- }
- }
- }
- sub irc_join {
- my ($sender, $who, $where) = @_[SENDER, ARG0, ARG1];
- my $nick = ( split /!/, $who )[0];
-
- unless ($remote) {
- $remote = create_ikc_client(
- port => 31338,
- name => $name,
- timeout => 1,
- );
- }
- $remote->post_respond( 'application/update', encode("utf-8", decode("cp949","[hanIRC] $nick joined $where")) );
- }
- sub irc_part {
- my ($sender, $who, $where, $msg) = @_[SENDER, ARG0 .. ARG2];
- my $nick = (split /!/, $who)[0];
-
- unless ($remote) {
- $remote = create_ikc_client(
- port => 31338,
- name => $name,
- timeout => 1,
- );
- }
- $remote->post_respond( 'application/update', encode("utf-8", decode("cp949","[hanIRC] $nick parted $where")) );
- }
- sub irc_quit {
- my ($sender, $who, $msg) = @_[SENDER, ARG0, ARG1];
- my $nick = (split /!/, $who)[0];
- unless ($remote) {
- $remote = create_ikc_client(
- port => 31338,
- name => $name,
- timeout => 1,
- );
- }
- $remote->post_respond( 'application/update', encode("utf-8", decode("cp949","[hanIRC] $nick is quit")) );
- }
- sub irc_353 {
- my ($sender, $server, $desc, $desc_a) = @_[SENDER, ARG0 .. ARG2];
- my ($temp, $channel, $members) = @{ $desc_a };
- @{ $info->{$channel} }= map { s/@//; $_ } split /\s/, $members;
- }
- sub _default {
- my ($event, $args) = @_[ARG0 .. $#_];
- my @output = ( "$event: " );
- # irc_rss_notify($event);
- for my $arg (@$args) {
- if ( ref $arg eq 'ARRAY' ) {
- push( @output, '[' . join(' ,', @$arg ) . ']' );
- }
- else {
- push ( @output, "'$arg'" );
- }
- }
- print join ' ', @output, "\n";
- return 0;
- }
- # IRC RSS Notify
- sub irc_rss_notify {
- my ($event) = shift;
- if ($event eq 'irc_ping') {
- $ping_time++;
- if ($ping_time % 5 == 0) {
- system("perl aggregate.pl");
- }
- if ($ping_time % 7 == 0) {
- my $data = LoadFile("result.yaml");
- foreach my $key (keys %{ $data }) {
- foreach my $feed (@{ $data->{$key} }) {
- $irc->yield( privmsg => '#perl' => "[ ". $feed->{type} . " ] " .
- _encode($feed->{title}). '<'.($feed->{author} || "Unknown").'> :: '. $feed->{link} );
- }
- }
- }
- }
- }
- # URL Find : Title Notify
- sub irc_urifind_uri {
- my ($who, $channel, $url, $obj, $msg) = @_[ARG0 .. ARG4];
-
- my $ua = LWP::UserAgent->new;
- my $res = $ua->get($url);
- if ($res->is_success) {
- $base_url = $url;
- my $html = scraper {
- process 'title', title => 'TEXT';
- };
- my $data = $html->scrape(URI->new($url));
- return 0 unless $data->{title};
- my $title = $data->{title};
- $title = encode('cp949', $title) if utf8::valid($title);
- $irc->yield( privmsg => $channel => $title );
- $channel =~ s/#//;
- }
- }