X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=blootbot%2Fsrc%2FIRC%2FIrc.pl;h=5159832125a9b11e8063db6aabab8e4c303ce8a1;hb=16c36ddd8e8e1f0c2e6add8e2ddc52005f5e7198;hp=9a1874858f10a6a9a085fbb1782bb684eafe8a63;hpb=ed6712c9ce857c2c3346d4f31e70f745b230e8eb;p=infobot.git diff --git a/blootbot/src/IRC/Irc.pl b/blootbot/src/IRC/Irc.pl index 9a18748..5159832 100644 --- a/blootbot/src/IRC/Irc.pl +++ b/blootbot/src/IRC/Irc.pl @@ -6,17 +6,22 @@ # use strict; + no strict 'refs'; +no strict 'subs'; # IN/STDIN -use vars qw(%floodjoin %nuh %dcc %cache %channels %param %mask +use vars qw(%floodjoin %nuh %dcc %cache %conns %channels %param %mask %chanconf %orig %ircPort %ircstats %last %netsplit); -use vars qw($irc $nickserv $ident $conn $msgType $who $talkchannel - $addressed); +use vars qw($irc $nickserv $conn $msgType $who $talkchannel + $addressed $postprocess); use vars qw($notcount $nottime $notsize $msgcount $msgtime $msgsize $pubcount $pubtime $pubsize); use vars qw($b_blue $ob); use vars qw(@ircServers); +#use open ':utf8'; +#use open ':std'; + $nickserv = 0; my $maxlinelen = 400; @@ -67,11 +72,15 @@ loop:; sub irc { my ($server,$port) = @_; + $irc = new Net::IRC; + + # TODO: move all this to an sql table my $iaddr = inet_aton($server); my $paddr = sockaddr_in($port, $iaddr); my $proto = getprotobyname('tcp'); - select STDOUT; + # why was this here? + #select STDOUT; # host->ip. my $resolve; @@ -87,9 +96,6 @@ sub irc { ### warning in Sys/Hostname line 78??? ### caused inside Net::IRC? } - &status("Connecting to port $port of server $server ($resolve) as $param{'ircNick'} ..."); - - $irc = new Net::IRC; my %args = ( Nick => $param{'ircNick'}, @@ -100,33 +106,64 @@ sub irc { $args{'LocalAddr'} = $param{'ircHost'} if ($param{'ircHost'}); $args{'Password'} = $param{'ircPasswd'} if ($param{'ircPasswd'}); - my $conn = $irc->newconn(%args); - - if (!defined $conn) { - &ERROR("IRC: connection failed."); - &ERROR("add \"set ircHost 0.0.0.0\" to your config. If that does not work"); - &ERROR("Please check /etc/hosts to see if you have a localhost line like:"); - &ERROR("127.0.0.1 localhost localhost"); - &ERROR("If this is still a problem, please contact the maintainer."); - return 1; - } - $conn->maxlinelen($maxlinelen); - - if ($param{'ircNick2'}) { - # prep for real multiple nick/server connects - # FIXME: all code should get nick/server out of self, not config - &status("Connecting to port $port of server $server ($resolve) as $param{'ircNick2'} ..."); - $args{'Nick'} = $param{'ircNick2'}; - my $conn = $irc->newconn(%args); - $conn->maxlinelen($maxlinelen); - } - - if ($param{'ircNick3'}) { - # prep for real multiple nick/server connects - # FIXME: all code should get nick/server out of self, not config - $args{'Nick'} = $param{'ircNick3'}; - my $conn = $irc->newconn(%args); - $conn->maxlinelen($maxlinelen); + foreach my $mynick (split ',', $param{'ircNick'}) { + &status("Connecting to port $port of server $server ($resolve) as $mynick ..."); + $args{'Nick'} = $mynick; + $conns{$mynick} = $irc->newconn(%args); + if (!defined $conns{$mynick}) { + &ERROR("IRC: connection failed."); + &ERROR("add \"set ircHost 0.0.0.0\" to your config. If that does not work"); + &ERROR("Please check /etc/hosts to see if you have a localhost line like:"); + &ERROR("127.0.0.1 localhost localhost"); + &ERROR("If this is still a problem, please contact the maintainer."); + } + $conns{$mynick}->maxlinelen($maxlinelen); + # handler stuff. + $conns{$mynick}->add_global_handler('caction', \&on_action); + $conns{$mynick}->add_global_handler('cdcc', \&on_dcc); + $conns{$mynick}->add_global_handler('cping', \&on_ping); + $conns{$mynick}->add_global_handler('crping', \&on_ping_reply); + $conns{$mynick}->add_global_handler('cversion', \&on_version); + $conns{$mynick}->add_global_handler('crversion', \&on_crversion); + $conns{$mynick}->add_global_handler('dcc_open', \&on_dcc_open); + $conns{$mynick}->add_global_handler('dcc_close', \&on_dcc_close); + $conns{$mynick}->add_global_handler('chat', \&on_chat); + $conns{$mynick}->add_global_handler('msg', \&on_msg); + $conns{$mynick}->add_global_handler('public', \&on_public); + $conns{$mynick}->add_global_handler('join', \&on_join); + $conns{$mynick}->add_global_handler('part', \&on_part); + $conns{$mynick}->add_global_handler('topic', \&on_topic); + $conns{$mynick}->add_global_handler('invite', \&on_invite); + $conns{$mynick}->add_global_handler('kick', \&on_kick); + $conns{$mynick}->add_global_handler('mode', \&on_mode); + $conns{$mynick}->add_global_handler('nick', \&on_nick); + $conns{$mynick}->add_global_handler('quit', \&on_quit); + $conns{$mynick}->add_global_handler('notice', \&on_notice); + $conns{$mynick}->add_global_handler('whoischannels', \&on_whoischannels); + $conns{$mynick}->add_global_handler('useronchannel', \&on_useronchannel); + $conns{$mynick}->add_global_handler('whois', \&on_whois); + $conns{$mynick}->add_global_handler('other', \&on_other); + $conns{$mynick}->add_global_handler('disconnect', \&on_disconnect); + $conns{$mynick}->add_global_handler([251,252,253,254,255], \&on_init); +# $conns{$mynick}->add_global_handler(302, \&on_init); # userhost + $conns{$mynick}->add_global_handler(303, \&on_ison); # notify. + $conns{$mynick}->add_global_handler(315, \&on_endofwho); + $conns{$mynick}->add_global_handler(422, \&on_endofwho); # nomotd. + $conns{$mynick}->add_global_handler(324, \&on_modeis); + $conns{$mynick}->add_global_handler(333, \&on_topicinfo); + $conns{$mynick}->add_global_handler(352, \&on_who); + $conns{$mynick}->add_global_handler(353, \&on_names); + $conns{$mynick}->add_global_handler(366, \&on_endofnames); + $conns{$mynick}->add_global_handler(376, \&on_endofmotd); # on_connect. + $conns{$mynick}->add_global_handler(433, \&on_nick_taken); + $conns{$mynick}->add_global_handler(439, \&on_targettoofast); + # for proper joinnextChan behaviour + $conns{$mynick}->add_global_handler(471, \&on_chanfull); + $conns{$mynick}->add_global_handler(473, \&on_inviteonly); + $conns{$mynick}->add_global_handler(474, \&on_banned); + $conns{$mynick}->add_global_handler(475, \&on_badchankey); + $conns{$mynick}->add_global_handler(443, \&on_useronchan); + # end of handler stuff. } &clearIRCVars(); @@ -138,53 +175,11 @@ sub irc { $ircstats{'Server'} = "$server:$port"; - # handler stuff. - $conn->add_global_handler('caction', \&on_action); - $conn->add_global_handler('cdcc', \&on_dcc); - $conn->add_global_handler('cping', \&on_ping); - $conn->add_global_handler('crping', \&on_ping_reply); - $conn->add_global_handler('cversion', \&on_version); - $conn->add_global_handler('crversion', \&on_crversion); - $conn->add_global_handler('dcc_open', \&on_dcc_open); - $conn->add_global_handler('dcc_close', \&on_dcc_close); - $conn->add_global_handler('chat', \&on_chat); - $conn->add_global_handler('msg', \&on_msg); - $conn->add_global_handler('public', \&on_public); - $conn->add_global_handler('join', \&on_join); - $conn->add_global_handler('part', \&on_part); - $conn->add_global_handler('topic', \&on_topic); - $conn->add_global_handler('invite', \&on_invite); - $conn->add_global_handler('kick', \&on_kick); - $conn->add_global_handler('mode', \&on_mode); - $conn->add_global_handler('nick', \&on_nick); - $conn->add_global_handler('quit', \&on_quit); - $conn->add_global_handler('notice', \&on_notice); - $conn->add_global_handler('whoischannels', \&on_whoischannels); - $conn->add_global_handler('useronchannel', \&on_useronchannel); - $conn->add_global_handler('whois', \&on_whois); - $conn->add_global_handler('other', \&on_other); - $conn->add_global_handler('disconnect', \&on_disconnect); - $conn->add_global_handler([251,252,253,254,255], \&on_init); -# $conn->add_global_handler(302, \&on_init); # userhost - $conn->add_global_handler(303, \&on_ison); # notify. - $conn->add_global_handler(315, \&on_endofwho); - $conn->add_global_handler(422, \&on_endofwho); # nomotd. - $conn->add_global_handler(324, \&on_modeis); - $conn->add_global_handler(333, \&on_topicinfo); - $conn->add_global_handler(352, \&on_who); - $conn->add_global_handler(353, \&on_names); - $conn->add_global_handler(366, \&on_endofnames); - $conn->add_global_handler(376, \&on_endofmotd); # on_connect. - $conn->add_global_handler(433, \&on_nick_taken); - $conn->add_global_handler(439, \&on_targettoofast); - # for proper joinnextChan behaviour - $conn->add_global_handler(471, \&on_chanfull); - $conn->add_global_handler(473, \&on_inviteonly); - $conn->add_global_handler(474, \&on_banned); - $conn->add_global_handler(475, \&on_badchankey); - $conn->add_global_handler(443, \&on_useronchan); + # works? needs to actually do something + # should likely listen on a tcp port instead + #$irc->addfh(STDIN, \&on_stdin, 'r'); - # end of handler stuff. + &status("starting main loop"); $irc->start; } @@ -197,7 +192,7 @@ sub rawout { my ($buf) = @_; $buf =~ s/\n//gi; - # slow down a bit if traffic is "high". + # slow down a bit if traffic is 'high'. # need to take into account time of last message sent. if ($last{buflen} > 256 and length($buf) > 256) { sleep 1; @@ -212,39 +207,54 @@ sub say { my ($msg) = @_; my $mynick = $conn->nick(); if (!defined $msg) { - $msg ||= "NULL"; + $msg ||= 'NULL'; &WARN("say: msg == $msg."); return; } + if (&getChanConf('silent', $talkchannel)) { + &DEBUG("say: silent in $talkchannel, not saying $msg"); + return; + } + + if ( $postprocess ) { + undef $postprocess; + } elsif ($postprocess = &getChanConf('postprocess', $talkchannel)) { + &DEBUG("say: $postprocess $msg"); + &parseCmdHook($postprocess . ' ' . $msg); + undef $postprocess; + return; + } &status("<$mynick/$talkchannel> $msg"); - if (&whatInterface() =~ /IRC/) { - $msg = "zero" if ($msg =~ /^0+$/); - my $t = time(); - - if ($t == $pubtime) { - $pubcount++; - $pubsize += length $msg; - - my $i = &getChanConfDefault("sendPublicLimitLines", 3); - my $j = &getChanConfDefault("sendPublicLimitBytes", 1000); - - if ( ($pubcount % $i) == 0 and $pubcount) { - sleep 1; - } elsif ($pubsize > $j) { - sleep 1; - $pubsize -= $j; - } - } else { - $pubcount = 0; - $pubtime = $t; - $pubsize = length $msg; + return unless (&whatInterface() =~ /IRC/); + + $msg = 'zero' if ($msg =~ /^0+$/); + + my $t = time(); + + if ($t == $pubtime) { + $pubcount++; + $pubsize += length $msg; + + my $i = &getChanConfDefault('sendPublicLimitLines', 3, $chan); + my $j = &getChanConfDefault('sendPublicLimitBytes', 1000, $chan); + + if ( ($pubcount % $i) == 0 and $pubcount) { + sleep 1; + } elsif ($pubsize > $j) { + sleep 1; + $pubsize -= $j; } - $conn->privmsg($talkchannel, $msg); + } else { + $pubcount = 0; + $pubtime = $t; + $pubsize = length $msg; } + + $conn->privmsg($talkchannel, $msg); } sub msg { @@ -255,11 +265,17 @@ sub msg { } if (!defined $msg) { - $msg ||= "NULL"; + $msg ||= 'NULL'; &WARN("msg: msg == $msg."); return; } + # some say() end up here (eg +help) + if (&getChanConf('silent', $nick)) { + &DEBUG("msg: silent in $nick, not saying $msg"); + return; + } + &status(">$nick< $msg"); return unless (&whatInterface() =~ /IRC/); @@ -269,8 +285,8 @@ sub msg { $msgcount++; $msgsize += length $msg; - my $i = &getChanConfDefault("sendPrivateLimitLines", 3); - my $j = &getChanConfDefault("sendPrivateLimitBytes", 1000); + my $i = &getChanConfDefault('sendPrivateLimitLines', 3, $chan); + my $j = &getChanConfDefault('sendPrivateLimitBytes', 1000, $chan); if ( ($msgcount % $i) == 0 and $msgcount) { sleep 1; } elsif ($msgsize > $j) { @@ -289,18 +305,24 @@ sub msg { # Usage: &action(nick || chan, txt); sub action { + my $mynick = $conn->nick(); my ($target, $txt) = @_; if (!defined $txt) { &WARN("action: txt == NULL."); return; } + if (&getChanConf('silent', $target)) { + &DEBUG("action: silent in $target, not doing $txt"); + return; + } + if (length $txt > 480) { &status("action: txt too long; truncating."); chop($txt) while (length $txt > 480); } - &status("* $ident/$target $txt"); + &status("* $mynick/$target $txt"); $conn->me($target, $txt); } @@ -320,8 +342,8 @@ sub notice { $notcount++; $notsize += length $txt; - my $i = &getChanConfDefault("sendNoticeLimitLines", 3); - my $j = &getChanConfDefault("sendNoticeLimitBytes", 1000); + my $i = &getChanConfDefault('sendNoticeLimitLines', 3, $chan); + my $j = &getChanConfDefault('sendNoticeLimitBytes', 1000, $chan); if ( ($notcount % $i) == 0 and $notcount) { sleep 1; @@ -364,6 +386,11 @@ sub performReply { $reply =~ /([\.\?\s]+)$/; + # FIXME need real throttling.... + if (length($reply) > $maxlinelen - 30) { + $reply = substr($reply, 0, $maxlinelen - 33); + $reply =~ s/ [^ ]*?$/ .../; + } &checkMsgType($reply); if ($msgType eq 'public') { @@ -398,14 +425,15 @@ sub performAddressedReply { &performReply(@_); } -sub pSReply { - &performStrictReply(@_); -} - # Usage: &performStrictReply($reply); sub performStrictReply { my ($reply) = @_; + # FIXME need real throttling.... + if (length($reply) > $maxlinelen - 30) { + $reply = substr($reply, 0, $maxlinelen - 33); + $reply =~ s/ [^ ]*?$/ .../; + } &checkMsgType($reply); if ($msgType eq 'private') { @@ -450,8 +478,9 @@ sub dcc_close { } sub joinchan { - my ($chan) = @_; - my $key = &getChanConf("chankey", $chan) || ""; + my ($chan, $key) = @_; + $key ||= &getChanConf('chankey', $chan); + $key ||= ''; # forgot for about 2 years to implement channel keys when moving # over to Net::IRC... @@ -461,10 +490,10 @@ sub joinchan { &status("join: already on $chan?"); } #} else { - &status("joining $b_blue$chan$ob"); + &status("joining $b_blue$chan $key$ob"); return if ($conn->join($chan, $key)); - return if (&validChan($chan)); + return if (&validChan($chan)); &DEBUG("joinchan: join failed. trying connect!"); &clearIRCVars(); @@ -476,7 +505,7 @@ sub part { my $chan; foreach $chan (@_) { - next if ($chan eq ""); + next if ($chan eq ''); $chan =~ tr/A-Z/a-z/; # lowercase. if ($chan !~ /^$mask{chan}$/) { @@ -512,23 +541,24 @@ sub mode { sub op { my ($chan, @who) = @_; - my $os = "o" x scalar(@who); + my $os = 'o' x scalar(@who); &mode($chan, "+$os @who"); } sub deop { my ($chan, @who) = @_; - my $os = "o" x scalar(@who); + my $os = 'o' x scalar(@who); &mode($chan, "-$os ".@who); } sub kick { my ($nick,$chan,$msg) = @_; - my (@chans) = ($chan eq "") ? (keys %channels) : lc($chan); + my (@chans) = ($chan eq '') ? (keys %channels) : lc($chan); + my $mynick = $conn->nick(); - if ($chan ne "" and &validChan($chan) == 0) { + if ($chan ne '' and &validChan($chan) == 0) { &ERROR("kick: invalid channel $chan."); return; } @@ -541,7 +571,7 @@ sub kick { next; } - if (!exists $channels{$chan}{o}{$ident}) { + if (!exists $channels{$chan}{o}{$mynick}) { &status("kick: do not have ops on $chan :("); next; } @@ -554,6 +584,7 @@ sub kick { sub ban { my ($mask,$chan) = @_; my (@chans) = ($chan =~ /^\*?$/) ? (keys %channels) : lc($chan); + my $mynick = $conn->nick(); my $ban = 0; if ($chan !~ /^\*?$/ and &validChan($chan) == 0) { @@ -562,7 +593,7 @@ sub ban { } foreach $chan (@chans) { - if (!exists $channels{$chan}{o}{$ident}) { + if (!exists $channels{$chan}{o}{$mynick}) { &status("ban: do not have ops on $chan :("); next; } @@ -578,12 +609,13 @@ sub ban { sub unban { my ($mask,$chan) = @_; my (@chans) = ($chan =~ /^\*?$/) ? (keys %channels) : lc($chan); + my $mynick = $conn->nick(); my $ban = 0; &DEBUG("unban: mask = $mask, chan = @chans"); foreach $chan (@chans) { - if (!exists $channels{$chan}{o}{$ident}) { + if (!exists $channels{$chan}{o}{$mynick}) { &status("unBan: do not have ops on $chan :("); next; } @@ -607,46 +639,36 @@ sub quit { } sub nick { - my ($nick) = @_; + my ($newnick) = @_; + my $mynick = $conn->nick(); - if (!defined $nick) { + if (!defined $newnick) { &ERROR("nick: nick == NULL."); return; } - if (defined $ident and $nick eq $ident) { - &WARN("nick: nick == ident == '$ident'."); + if (!defined $mynick) { + &WARN("nick: mynick == NULL."); return; } - my $bad = 0; - $bad++ if (exists $nuh{$conn->nick()}); - $bad++ if (&IsNickInAnyChan($conn->nick())); + my $bad = 0; + $bad++ if (exists $nuh{$newnick}); + $bad++ if (&IsNickInAnyChan($newnick)); if ($bad) { - &WARN("Nick: not going to try and get my nick back. [". - scalar(gmtime). "]"); -# hrm... over time we lose track of our own nick. -# return; + &WARN("Nick: not going to try to change from $mynick to $newnick. [". scalar(gmtime). "]"); + # hrm... over time we lose track of our own nick. + #return; } -# FIXME broken for multiple nicks -# if ($nick =~ /^$mask{nick}$/) { -# &rawout("NICK ".$nick); -# -# if (defined $ident) { -# &status("nick: Changing nick to $nick (from $ident)"); -# # following shouldn't be here :( -# $ident = $nick; -# } else { -# &DEBUG("first time nick change."); -# $ident = $nick; -# } -# -# return 1; -# } - &DEBUG("nick: failed... why oh why (nick => $nick)"); - + if ($newnick =~ /^$mask{nick}$/) { + &status("nick: Changing nick from $mynick to $newnick"); + # ->nick() will NOT change cause we are using rawout? + &rawout("NICK $newnick"); + return 1; + } + &DEBUG("nick: failed... why oh why (mynick=$mynick, newnick=$newnick)"); return 0; } @@ -663,20 +685,23 @@ sub invite { # Usage: &joinNextChan(); sub joinNextChan { - my @join = getJoinChans(1); - my $mynick = "UNDEF"; - - $mynick = $conn->nick() if $conn; - if (scalar @join) { - my $chan = shift @join; - &joinchan($chan); - - if (my $i = scalar @join) { - &status("joinNextChan: $mynick $i chans to join."); + my $joined = 0; + foreach (sort keys %conns) { + $conn = $conns{$_}; + my $mynick = $conn->nick(); + my @join = getJoinChans(1); + + if (scalar @join) { + my $chan = shift @join; + &joinchan($chan); + + if (my $i = scalar @join) { + &status("joinNextChan: $mynick $i chans to join."); + } + $joined = 1; } - - return; } + return if $joined; if (exists $cache{joinTime}) { my $delta = time() - $cache{joinTime} - 5; @@ -690,7 +715,7 @@ sub joinNextChan { } # chanserv check: global channels, in case we missed one. - foreach ( &ChanConfList("chanServ_ops") ) { + foreach ( &ChanConfList('chanServ_ops') ) { &chanServCheck($_); } } @@ -822,19 +847,19 @@ sub getJoinChans { my $nick = $conn->nick(); foreach (keys %chanconf) { - next if ($_ eq "_default"); + next if ($_ eq '_default'); my $skip = 0; my $val = $chanconf{$_}{autojoin}; if (defined $val) { - $skip++ if ($val eq "0"); - if ($val eq "1") { + $skip++ if ($val eq '0'); + if ($val eq '1') { # convert old +autojoin to autojoin - $val = $nick; + $val = lc $nick; $chanconf{$_}{autojoin} = $val; } - $skip++ if ($val ne $nick); + $skip++ if (lc $val ne lc $nick); } else { $skip++; } @@ -851,8 +876,8 @@ sub getJoinChans { } my $str; - $str .= ' in:' . join(',', sort @in) if scalar @in; - $str .= ' skip:' . join(',', sort @skip) if scalar @skip; + #$str .= ' in:' . join(',', sort @in) if scalar @in; + #$str .= ' skip:' . join(',', sort @skip) if scalar @skip; $str .= ' join:' . join(',', sort @join) if scalar @join; &status("Chans: ($nick)$str") if ($show); @@ -886,7 +911,7 @@ sub closeDCC { sub joinfloodCheck { my($who,$chan,$userhost) = @_; - return unless (&IsChanConf("joinfloodCheck")); + return unless (&IsChanConf('joinfloodCheck') > 0); if (exists $netsplit{lc $who}) { # netsplit join. &DEBUG("joinfloodCheck: $who was in netsplit; not checking.");