plum IRCのログをMSNで送信
http://d.hatena.ne.jp/holidays-l/20061108/p1
に影響されて、./module/log/msn.plm つくった(><*)
bot側はメンバからの追加リクエスト (1)の状態でメッセージを送れるので、registorしただけでok
plumよいよー(゜∀゜) plagger-ircbotをあえて使わない(ぉ
todo:
ログインし続ける双方向通信できそう。やった- log.msn.proxy: yes が必要
- 先頭 /でMSNで送るとコマンドとして解釈
- 先頭チャンネルなら "チャンネル + スペース + メッセージ" のフォーマット で発言できる
%萌えたんくらぶ はぁはぁ さくらちゃん かわいいよなー
↑サンプル
日本語化けるのは治ったmirandaのセイカ???(><*)Messagnr.exe いれたくねぇぇぇぇぇwebで確認 Bug 治す- バグ ネット
- なんか放置してたら2度とログインできなくなる(ぉ
- ERROR 800 (ユーザー名の変更を頻繁に行いすぎています。時間をおいて変更して下さい。)
- なんか放置してたら2度とログインできなくなる(ぉ
- 全世界ぷにろりうさみみ萌え
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><!-- $_ if 0; # -*- perl -*- # ./module/log/msn.plm 0.03.18 # # http://plum.sourceforge.jp/ 2.33.2 # http://sourceforge.jp/projects/plum/files/ 2.33.2 # http://plum.sourceforge.jp/ 2.33.1 # # base code is module/log/daily.plm @ http://plum.madoka.org # base code is sys/timer.plm @ http://plum.madoka.org (main_loop) # DOC: http://www.kwasan.kyoto-u.ac.jp/~shimono/tempfiles/plum2.33.1/doc/readme.html # base code is Plagger/Plugin/Publish/MSN.pm @ http://d.hatena.ne.jp/holidays-l/20061108/p1 (Net::MSN) # -- cat /usr/local/libdata/perl5/site_perl/Net/MSN.pm # -- cat /usr/local/libdata/perl5/site_perl/Net/MSN/Base.pm # DOC: http://search.cpan.org/~djr/Net-MSN-1.022/ # msn-messenger-protocol でぐぐるといろいろ出てくる # MSN-ERROR CODE: http://www.hypothetic.org/docs/msn/reference/error_list.php # MSN-ERROR CODJ: http://regnessem.sourceforge.jp/help/error/protocolerror.html # *** <MSN[error]> Switch Board closed the connection : 会議室が閉じたって感じ channelみたいなもん # cpan> install Digest::SHA Hash::Merge LWP Net::MSN Encode # $Id: MSN.pm,v 3.18 2999 oreoreoredayoore Exp $ package log_msn; use vars qw($VERSION); $VERSION = do { my @r=(q$Revision: 3.18 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r }; use Encode qw/ decode encode /; use Net::MSN; $TIMEOUT = 20; $WAIT = 3; $HEADER = '%H:%M'; $COMMAND = &'list('privmsg', 'join', 'part', 'kick' ,'invite', 'mode', 'nick', 'quit', 'topic'); $LOGLEVEL = 3; # 3 DEBUG / 2 INFO / 1 ERROR / 0 MSG Only [advice 2 is better] my @messages = (); my $msn; my $is_alive = 0; my $process_event; $_ = 'log_msn'; BEGIN { my $process_event = Net::MSN->can('process_event'); undef *Net::MSN::process_event; *Net::MSN::process_event = sub { my ( $self, $this_self, $line, $fh ) = @_; # print {*STDERR} ( substr $line, 0, 60 ) . "\n"; my ( $cmd, @data ) = split( / /, $line ); return unless ( defined $cmd && $cmd ); if ( $cmd eq 'LST' ) { $self->buddyupdate( $data[0], $data[1], 'NLN' ); return 1; # 対象一人なのでこれで. } elsif ( $cmd eq 'QNG' ) { if ( $self->if_callback_exists('_on_QNG') ) { &{ $self->{Callback}->{_on_QNG} }; } } goto &{$process_event}; }; } sub module_enable { local($userno) = @_; $msn = Net::MSN->new; $msn->{_Log} = \&c_msg; $msn->set_event( _on_QNG => sub { if ( $msn->is_buddy_online( &'property($userno, 'email') ) ) { $msn->call( &'property($userno, 'email') ); } }, on_message => \&msn_on_message, ); } sub module_disable { local($userno) = @_; if(defined $msn) { &msn_term(); } $is_alive = 0; } sub check_event { if(defined $msn) { # socket 確立してなくてもぶん回す eval '$msn->check_event()'; if($@) { warn $@ ; $is_alive = 0; # reconnect 準備 } } } sub msn_on_message { local ( $self, $chandle, $friendly, $message ) = @_; local ( $serverlist, $sno ); local ( $line ); # encode utf8 to shiftjis to 8bit-jis $message = &'sjis_jis( encode( "shiftjis", decode( "utf8", $message ))); foreach $line ( split( /\n/, $message )) { next if ( $line =~ /^$/ ); # empty? &c_msg( $friendly . '!' . $chandle . " $line" ); # command proxy next unless (&'property($userno, 'proxy') =~ /^yes/i ); next unless (&check_mask($userno, $friendly . '!' . $chandle)); # nickname!msnアカウント # send to server $cmd foreach $sno (&'array($'serverlist)) { next unless $userno == $'userno[$sno]; if( $line =~ /^\// ) { my $cmd = $'; &'s_print($sno, '', split( / /, $cmd, 1) ); # コマンドなら そういう風に送る } else { # 発言か my( $vchan, $mchan ) = split( /\s+/, $line, 2); $vchan = &'real($vchan); # % prifix をとる last unless( &'channel($vchan) ); # チャンネルなら... &'s_print($sno, '', 'PRIVMSG', $vchan, $mchan ); # それ以外は無視 } } # next.line } } sub main_loop { local($userno) = @_; local($now, $regex, $str, $date, $time, @addlist); # Connect to MSN and auto-reconnect if( $is_alive == 0 ) { $is_alive = 1; $msn->connect( &'property($userno, 'bot'), &'property($userno, 'password') ) or &msn_term(); } &check_event(); &msn_send(); } # send to MSN sub msn_send { local $timeout = &'property($userno, 'timeout') || $TIMEOUT; # -- 最大保留時間 local $wait = &'property($userno, 'wait') || $WAIT; # -- 洪水対策 local $email = &'property($userno, 'email'); local $t = time; &check_event(); while (1) { last unless $is_alive; last unless @messages; last if $timeout < time - $t; # join 待ち & IRC に制御戻す last unless($msn->is_buddy_online($email)); # 相手ログイン待ち if (1) { my $message = shift @messages; my $t2 = time; # 8bit-JIS to SJIS to UTF8 my $ret = $msn->sendmsg( $email, encode("utf8", decode( 'shiftjis' , &'jis_sjis($message) ) ) ); # wait loop while ( time - $t2 <= $wait ) { &check_event(); } # 相手がログインしてなくて送信待ち状態 unless(defined($ret)) { unshift @messages, $message; last; } } &check_event(); } &check_event(); } # IRC ログをストア + MSNへ投げる sub sendlog { local($fileno, $msg) = @_; local($userno, $name, $code, $dir, $header, $mode); $userno = $'userno[$fileno]; $code = &'property($userno, 'code'); $header = &'property($userno, 'header'); $header = $HEADER unless defined($header); $header = &'date($header); push @messages, $msg; &msn_send(); } sub msn_term{ if( $is_alive == 1 ) { $msn->disconnect; $is_alive = 0; } } # announce MSN infomation for All connected client sub c_msg { local ($msg , $level) = @_; local ($cno); $level = 0 unless(defined($level)); return if( $level > $LOGLEVEL ); my $info = ''; $info = '[error]' if($level == 1 ); $info = '[info]' if($level == 2 ); $info = '[debug]' if($level == 3 ); foreach $cno (&'array($'clientlist)) { next unless $'avail[$cno]; &'c_print($cno, '', 'NOTICE', $'nick[$cno], "*** <MSN$info> " . $msg ); } print '[' . localtime . "] *** <MSN$info>" . $msg . "\n"; } sub ss_privmsg { local($serverno, $prefix, $cmd, @params) = @_; local($nick, $vchan); if ($params[1] && &savecommand($'userno[$serverno], $cmd)) { $nick = &'prefix($prefix); if (&'channel($params[0])) { $vchan = &'alias($params[0]); if (&'exist($'nameslist{$serverno, $params[0]}, $nick, "\+$nick", "\@$nick")) { &sendlog($serverno, "<$vchan:$nick> $params[1]"); } else { &sendlog($serverno, "($vchan:$nick) $params[1]"); } } else { &sendlog($serverno, "=$nick= $params[1]"); } } return ($prefix, $cmd, @params); } sub ss_notice { local($serverno, $prefix, $cmd, @params) = @_; local($nick, $vchan); if ($params[1] && &savecommand($'userno[$serverno], $cmd)) { $nick = &'prefix($prefix); if (&'channel($params[0])) { $vchan = &'alias($params[0]); if (&'exist($'nameslist{$serverno, $params[0]}, $nick, "\+$nick", "\@$nick")) { &sendlog($serverno, "<$vchan:$nick> $params[1]"); } else { &sendlog($serverno, "($vchan:$nick) $params[1]"); } } else { &sendlog($serverno, "=$nick= $params[1]"); } } return ($prefix, $cmd, @params); } sub ss_join { local($serverno, $prefix, $cmd, @params) = @_; local($nick, $name, $mode, $vchan); if (&savecommand($'userno[$serverno], $cmd)) { $nick = &'prefix($prefix); ($name, $mode) = (split(/\cG/, $params[0]), ''); $vchan = &'alias($name); if (index($mode, 'o') != -1) { &sendlog($serverno, "+ \@$nick ($prefix) to $vchan"); } elsif (index($mode, 'v') != -1) { &sendlog($serverno, "+ +$nick ($prefix) to $vchan"); } else { &sendlog($serverno, "+ $nick ($prefix) to $vchan"); } } return ($prefix, $cmd, @params); } sub ss_part { local($serverno, $prefix, $cmd, @params) = @_; local($nick, $vchan, $msg); if (&savecommand($'userno[$serverno], $cmd)) { $nick = &'prefix($prefix); $vchan = &'alias($params[0]); $msg = $params[1] || ''; &sendlog($serverno, "- $nick from $vchan ($msg)"); } return ($prefix, $cmd, @params); } sub ss_kick { local($serverno, $prefix, $cmd, @params) = @_; local($nick, $vchan); if (&savecommand($'userno[$serverno], $cmd)) { $nick = &'prefix($prefix); $vchan = &'alias($params[0]); &sendlog($serverno, "- $params[1] by $nick from $vchan ($params[2])"); } return ($prefix, $cmd, @params); } sub ss_invite { local($serverno, $prefix, $cmd, @params) = @_; local($nick, $vchan); if (&savecommand($'userno[$serverno], $cmd)) { $nick = &'prefix($prefix); $vchan = &'alias($params[1]); &sendlog($serverno, "Invited by $nick: $vchan"); } return ($prefix, $cmd, @params); } sub ss_mode { local($serverno, $prefix, $cmd, @params) = @_; local($nick, $vchan, @mode); @mode = @params; shift(@mode); if (&savecommand($'userno[$serverno], $cmd)) { $nick = &'prefix($prefix); if (&'channel($params[0])) { $vchan = &'alias($params[0]); &sendlog($serverno, "Mode by $nick: $vchan " . join(' ', @mode)); } else { &sendlog($serverno, "Mode by $nick: $params[0] " . join(' ', @mode)); } } return ($prefix, $cmd, @params); } sub ss_nick { local($serverno, $prefix, $cmd, @params) = @_; local($nick); if (&savecommand($'userno[$serverno], $cmd)) { $nick = &'prefix($prefix); if ($nick eq $'nick[$serverno] || $params[0] eq $'nick[$serverno]) { &sendlog($serverno, "My nick is changed ($nick -\> $params[0])"); } else { &sendlog($serverno, "$nick -\> $params[0]"); } } return ($prefix, $cmd, @params); } sub ss_quit { local($serverno, $prefix, $cmd, @params) = @_; local($nick); if (&savecommand($'userno[$serverno], $cmd)) { $nick = &'prefix($prefix); &sendlog($serverno, "! $nick ($params[0])"); } return ($prefix, $cmd, @params); } sub ss_topic { local($serverno, $prefix, $cmd, @params) = @_; local($nick, $vchan); if (&savecommand($'userno[$serverno], $cmd)) { $nick = &'prefix($prefix); $vchan = &'alias($params[0]); &sendlog($serverno, "Topic of channel $vchan by $nick: $params[1]"); } return ($prefix, $cmd, @params); } sub sp_privmsg { local($serverno, $prefix, $cmd, @params) = @_; local($chan, $vchan); if ($params[1] && &savecommand($'userno[$serverno], $cmd)) { foreach $chan (split(/\,/, $params[0])) { if (&'channel($chan)) { $vchan = &'alias($chan); &sendlog($serverno, ">$vchan:$'nick[$serverno]< $params[1]"); } else { &sendlog($serverno, ">$chan< $params[1]"); } } } return ($prefix, $cmd, @params); } sub sp_notice { local($serverno, $prefix, $cmd, @params) = @_; local($chan, $vchan); if ($params[1] && &savecommand($'userno[$serverno], $cmd)) { foreach $chan (split(/\,/, $params[0])) { if (&'channel($chan)) { $vchan = &'alias($chan); &sendlog($serverno, ">$vchan:$'nick[$serverno]< $params[1]"); } else { &sendlog($serverno, ">$chan< $params[1]"); } } } return ($prefix, $cmd, @params); } sub savecommand { local($userno, $cmd) = @_; local($save); $save = &'property($userno, 'command'); if (defined($save)) { $save = ''; foreach $mask (&'property($userno, 'command')) { $save = &'add($save, split(/\,/, $mask)); } } else { $save = $COMMAND; } return &'exist($save, $cmd); } sub check_mask { local($userno, $prefix) = @_; local($user); foreach $user (&'property($userno, 'mask')) { if ($user =~ /^\-/) { $regex = &'regex(substr($user, 1)); return 0 if $prefix =~ /$regex/i; } if ($user =~ /^\+/) { $regex = &'regex(substr($user, 1)); } else { $regex = &'regex($user); } return 1 if $prefix =~ /$regex/i; } return 0; } __END__ --><HTML><HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-2022-JP"> <TITLE>log/msn.plm</TITLE></HEAD><BODY> オンラインドキュメント <HR><H3>名前</H3> log/msn.plm - メッセージをMSNで通知する <HR><H3>説明</H3> ログを指定したアカウントへ通知します。 <HR><H3>プロパティ</H3> <DL> <DT> log.msn.email 通知して欲しいアカウント </DT> <DD> !通知して欲しいアカウント </DD> <DT> log.msn.bot ボットのアカウント </DT> <DD> !ボットのアカウント </DD> <DT> log.msn.password ボットのパスワード </DT> <DD> !ボットのパスワード </DD> <DT> log.msn.header へッダ </DT> <DD> ログに出力する時刻のフォーマットを指定します。 %ではじまる文字があると対応する時間に変換されます。 デフォルトでは「%H:%M」です。 </DD> <DT> log.msn.command ({invite|join|kick|mode|nick|notice|part|privmsg|quit|topic}) </DT> <DD> 保存するメッセージの種類を指定します。 デフォルトでは「notice」以外のすべてです。 </DD> <DT> log.msn.timeout 20 </DT> <DD> メッセージ待つ時間 </DD> <DT> log.msn.wait 3 </DT> <DD> MSN洪水対策 </DD> <DT> log.msn.proxy no </DT> <DD> MSNから来た /**** メッセージを IRCD へ送る mask とあわせて使用してください </DD> <DT> log.msn.mask* {ニックネーム}!{MSNアカウント} </DT> <DD> 招待した人、およびチャンネルがここで指定された ものにマッチした場合かつproxy onの場合、転送します。 </DD> </DL> <HR><H3>設定例</H3> <PRE> + log/msn.plm </PRE> <PRE> + log/msn.plm log.msn.email: oreore@::1 log.msn.bot: ircmsg@::1 log.msn.password: password log.msn.command: privmsg,topic,join,part,kick,nick log.msn.proxy: yes log.msn.mask: *!*@::1 </PRE> 送信するログを「privmsg」、「topic」、「join」、「part」、「kick」、 「nick」の6種類にします。 oreore へ ircmsg から送ります。 ircmsgへコマンドを送信できますが、アカウント名が ::1 ドメインでなくてはいけません </BODY></HTML>