X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=src%2FIRC%2FIrcHooks.pl;h=9eec53b043cfa0fa0276b020e810951d36e62ac2;hb=3c042d9173714f2e7ef7d484672f3bfaa1702478;hp=f716b6f9ff7e71bdc73310837bf3297a35016b7c;hpb=e00f8cdfd78b4098a0c0d2aedf6ac2d57a0ba1b7;p=infobot.git diff --git a/src/IRC/IrcHooks.pl b/src/IRC/IrcHooks.pl index f716b6f..9eec53b 100644 --- a/src/IRC/IrcHooks.pl +++ b/src/IRC/IrcHooks.pl @@ -7,8 +7,6 @@ if (&IsParam("useStrict")) { use strict; } -my $nickserv = 0; - # GENERIC. TO COPY. sub on_generic { my ($self, $event) = @_; @@ -43,29 +41,32 @@ sub on_chat { my $sock = ($event->to)[0]; my $nick = $event->nick(); - if (!exists $nuh{lc $nick}) { - &DEBUG("chat: nuh{$nick} doesn't exist; hrm should retry."); - &msg($nick, "could not get whois info?"); + if (!exists $nuh{$nick}) { + &DEBUG("chat: nuh{$nick} doesn't exist; trying WHOIS ."); + $self->whois($nick); return; - } else { - $message = $msg; - $who = lc $nick; - $orig{who} = $nick; - $orig{message} = $msg; - $nuh = $nuh{$who}; - $uh = (split /\!/, $nuh)[1]; - $addressed = 1; - $msgType = 'chat'; } + ### set vars that would have been set in hookMsg. + $userHandle = ""; # reset. + $who = lc $nick; + $message = $msg; + $orig{who} = $nick; + $orig{message} = $msg; + $nuh = $nuh{$who}; + $uh = (split /\!/, $nuh)[1]; + $addressed = 1; + $msgType = 'chat'; + if (!exists $dcc{'CHATvrfy'}{$nick}) { $userHandle = &verifyUser($who, $nuh); my $crypto = $users{$userHandle}{PASS}; my $success = 0; + ### TODO: prevent users without CRYPT chatting. if (!defined $crypto) { &DEBUG("chat: no pass required."); - $success++; +### $success++; } elsif (&ckpasswd($msg, $crypto)) { # stolen from eggdrop. @@ -73,7 +74,7 @@ sub on_chat { $self->privmsg($sock, "Commands start with '.' (like '.quit' or '.help')"); $self->privmsg($sock, "Everything else goes out to the party line."); - &dccStatus(2) if (scalar keys %{ $dcc{'CHAT'} } == 1); + &dccStatus(2) unless (exists $sched{"dccStatus"}{RUNNING}); $success++; @@ -88,28 +89,23 @@ sub on_chat { if ($success) { &status("DCC CHAT: user $nick is here!"); -# &DCCBroadcast("$nick ($uh) has joined the chat arena."); &DCCBroadcast("*** $nick ($uh) joined the party line."); - $dcc{'CHATvrfy'}{$nick} = 1; - if ($userHandle ne "_default") { - &dccsay($nick,"Flags: $users{$userHandle}{FLAGS}"); - } + $dcc{'CHATvrfy'}{$nick} = $userHandle; + + return if ($userHandle eq "_default"); + + &dccsay($nick,"Flags: $users{$userHandle}{FLAGS}"); } return; } - if (defined $userHandle) { - &DEBUG("IrcHooks.pl: line 104: remove vUser"); - } - - $userHandle = &verifyUser($who, $nuh); &status("$b_red=$b_cyan$who$b_red=$ob $message"); if ($message =~ s/^\.//) { # dcc chat commands. ### TODO: make use of &Forker(); here? - &loadMyModule($myModules{'ircdcc'}); + &loadMyModule( $myModules{'ircdcc'} ); &DCCBroadcast("#$who# $message","m"); @@ -138,7 +134,7 @@ sub on_endofmotd { $ircstats{'ConnectTime'} = time(); $ircstats{'ConnectCount'}++; - if (&IsParam("wingate")) { + if (&IsChanConf("wingate")) { my $file = "$bot_base_dir/$param{'ircUser'}.wingate"; open(IN, $file); while () { @@ -150,7 +146,7 @@ sub on_endofmotd { } if ($firsttime) { - $conn->schedule(60, \&setupSchedulers, ""); + &ScheduleThis(1, \&setupSchedulers); $firsttime = 0; } @@ -174,7 +170,10 @@ sub on_dcc { my $nick = $event->nick(); # pity Net::IRC doesn't store nuh. Here's a hack :) - $self->whois($nick); + if (!exists $nuh{lc $nick}) { + $self->whois($nick); + $nuh{lc $nick} = "GETTING-NOW"; # trying. + } $type ||= "???"; if ($type eq 'SEND') { # GET for us. @@ -190,10 +189,10 @@ sub on_dcc { \*DCCGET ); } elsif ($type eq 'GET') { # SEND for us? - &DEBUG("starting get."); + &status("DCC: Initializing SEND for $nick."); $self->new_send($event->args); } elsif ($type eq 'CHAT') { - &DEBUG("starting chat."); + &status("DCC: Initializing CHAT for $nick."); $self->new_chat($event); } else { &WARN("${b_green}DCC $type$ob (1)"); @@ -211,8 +210,6 @@ sub on_dcc_close { &delForked($forker); } - &DEBUG("dcc_close: nick => '$nick'."); - if (exists $dcc{'SEND'}{$nick} and -f "$param{tempDir}/$nick.txt") { &status("${b_green}DCC SEND$ob close from $b_cyan$nick$ob"); @@ -223,6 +220,7 @@ sub on_dcc_close { } elsif (exists $dcc{'CHAT'}{$nick} and $dcc{'CHAT'}{$nick} eq $sock) { &status("${b_green}DCC CHAT$ob close from $b_cyan$nick$ob"); delete $dcc{'CHAT'}{$nick}; + delete $dcc{'CHATvrfy'}{$nick}; } else { &status("${b_green}DCC$ob UNKNOWN close from $b_cyan$nick$ob (2)"); } @@ -233,35 +231,68 @@ sub on_dcc_open { my $type = uc( ($event->args)[0] ); my $nick = $event->nick(); my $sock = ($event->to)[0]; - $msgType = 'chat'; + $msgType = 'chat'; $type ||= "???"; + ### BUG: who is set to bot's nick? + # lets do it. if ($type eq 'SEND') { &status("${b_green}DCC lGET$ob established with $b_cyan$nick$ob"); - } elsif ($type eq 'CHAT') { - &status("${b_green}DCC CHAT$ob established with $b_cyan$nick$ob $b_yellow($ob$nuh{$nick}$b_yellow)$ob"); - $userHandle = &verifyUser($nick, $nuh{lc $nick}); - my $crypto = $users{$userHandle}{PASS}; - $dcc{'CHAT'}{$nick} = $sock; - - foreach (keys %{ $users{$userHandle} }) { - &VERB(" $_ => $users{$userHandle}{$_}",2); - } - if (defined $crypto) { -### &dccsay($nick,"Enter your password, $userHandle."); - &dccsay($nick,"Enter your password."); + } elsif ($type eq 'CHAT') { + # very cheap hack. + ### TODO: run ScheduleThis inside on_dcc_open_chat recursively + ### 1,3,5,10 seconds then fail. + if ($nuh{$nick} eq "GETTING-NOW") { + &ScheduleThis(3/60, "on_dcc_open_chat", $nick, $sock); } else { - &dccsay($nick,"Welcome to blootbot DCC CHAT interface, $userHandle."); + on_dcc_open_chat(undef, $nick, $sock); } + } elsif ($type eq 'SEND') { &DEBUG("Starting DCC receive."); foreach ($event->args) { &DEBUG(" => '$_'."); } + } else { &WARN("${b_green}DCC $type$ob (3)"); + + } +} + +# really custom sub to get NUH since Net::IRC doesn't appear to support +# it. +sub on_dcc_open_chat { + my(undef, $nick,$sock) = @_; + + &DEBUG("nuh{$nick} => $nuh{$nick}."); + if ($nuh{$nick} =~ /^(\S+)(\d+)$/) { + my $i = $2; + $i++; + $nuh{$nick} = $1.$i; + &DEBUG("getting nuh for $nick failed. FIXME."); + return; + } + + &status("${b_green}DCC CHAT$ob established with $b_cyan$nick$ob $b_yellow($ob$nuh{$nick}$b_yellow)$ob"); + + &verifyUser($nick, $nuh{lc $nick}); + + if (!exists $users{$userHandle}{HOSTS}) { + &pSReply("you have no hosts defined in my user file; rejecting."); + ### TODO: $sock->close(); + return; + } + + my $crypto = $users{$userHandle}{PASS}; + $dcc{'CHAT'}{$nick} = $sock; + + if (defined $crypto) { + &dccsay($nick,"Enter your password."); + } else { + &dccsay($nick,"Welcome to blootbot DCC CHAT interface, $userHandle."); } } @@ -281,7 +312,7 @@ sub on_disconnect { &clearIRCVars(); if (!$self->connect()) { &WARN("not connected? help me. gonna call ircCheck() in 1800s"); - $conn->schedule(1800, \&ircCheck(), ""); + &ScheduleThis(30, "ircCheck"); } } @@ -289,8 +320,8 @@ sub on_endofnames { my ($self, $event) = @_; my $chan = ($event->args)[1]; - if (exists $jointime{$chan}) { - my $delta_time = sprintf("%.03f", &gettimeofday() - $jointime{$chan}); + if (exists $cache{jointime}{$chan}) { + my $delta_time = sprintf("%.03f", &gettimeofday() - $cache{jointime}{$chan}); $delta_time = 0 if ($delta_time < 0); &status("$b_blue$chan$ob: sync in ${delta_time}s."); @@ -315,17 +346,14 @@ sub on_endofnames { if (scalar @joinchan) { # remaining channels to join. &joinNextChan(); - } else { - ### chanserv support. - ### TODO: what if we rejoin a channel.. need to set a var that - ### we've done the request-for-ops-on-join. - return unless (&IsChanConf("chanServ_ops") > 0); - return unless ($nickserv); - - if (!exists $channels{$chan}{'o'}{$ident}) { - &status("ChanServ ==> Requesting ops for $chan."); - &rawout("PRIVMSG ChanServ :OP $chan $ident"); - } + } + + return unless (&IsChanConf("chanServ_ops") > 0); + return unless ($nickserv); + + if (!exists $channels{$chan}{'o'}{$ident}) { + &status("ChanServ ==> Requesting ops for $chan."); + &rawout("PRIVMSG ChanServ :OP $chan $ident"); } } @@ -339,19 +367,16 @@ sub on_init { sub on_invite { my ($self, $event) = @_; - my $chan = ($event->args)[0]; + my $chan = lc( ($event->args)[0] ); my $nick = $event->nick; - &DEBUG("on_invite: chan => '$chan', nick => '$nick'."); - - # chan + possible_key. - ### do we need to know the key if we're invited??? - ### grep the channel list? - foreach (split /[\s\t]+/, $param{'join_channels'}) { - next unless /^\Q$chan\E(,\S+)?$/i; - s/,/ /; + if ($nick =~ /^\Q$ident\E$/) { + &DEBUG("on_invite: self invite."); + return; + } - next if ($nick =~ /^\Q$ident\E$/); + ### TODO: join key. + if (exists $chanconf{$chan}) { if (&validChan($chan)) { &msg($who, "i'm already in \002$chan\002."); next; @@ -369,7 +394,7 @@ sub on_join { $who = $event->nick(); $chanstats{$chan}{'Join'}++; - $userstats{lc $who}{'Join'} = time() if (&IsParam("seenStats")); + $userstats{lc $who}{'Join'} = time() if (&IsChanConf("seenStats")); &joinfloodCheck($who, $chan, $event->userhost); @@ -381,7 +406,7 @@ sub on_join { } if ($netsplit and !$netsplittime) { - &status("ok.... re-running chanlimitCheck in 60."); + &DEBUG("on_join: ok.... re-running chanlimitCheck in 60."); $conn->schedule(60, sub { &chanlimitCheck(); $netsplittime = undef; @@ -418,19 +443,22 @@ sub on_join { ### ROOTWARN: &rootWarn($who,$user,$host,$chan) - if (&IsParam("rootWarn") && + if (&IsChanConf("rootWarn") && $user =~ /^r(oo|ew|00)t$/i && $channels{$chan}{'o'}{$ident}); + ### chanlimit check. + &chanLimitVerify($chan); + # used to determine sync time. if ($who =~ /^$ident$/i) { - if (defined( my $whojoin = $joinverb{$chan} )) { + if (defined( my $whojoin = $cache{join}{$chan} )) { &msg($chan, "Okay, I'm here. (courtesy of $whojoin)"); - delete $joinverb{$chan}; + delete $cache{join}{$chan}; } ### TODO: move this to &joinchan()? - $jointime{$chan} = &gettimeofday(); + $cache{jointime}{$chan} = &gettimeofday(); rawout("WHO $chan"); } else { ### TODO: this may go wild on a netjoin :) @@ -602,16 +630,14 @@ sub on_part { my $nick = $event->nick; my $userhost = $event->userhost; - if (!exists $floodjoin{$chan}{$nick}{Time}) { - &WARN("on_part: $nick/$chan not in floodjoin hash?"); - } else { + if (exists $floodjoin{$chan}{$nick}{Time}) { delete $floodjoin{$chan}{$nick}; } $chanstats{$chan}{'Part'}++; &DeleteUserInfo($nick,$chan); &clearChanVars($chan) if ($nick eq $ident); - if (!&IsNickInAnyChan($nick) and &IsParam("seenStats")) { + if (!&IsNickInAnyChan($nick) and &IsChanConf("seenStats")) { delete $userstats{lc $nick}; } @@ -665,12 +691,12 @@ sub on_public { $msgtime = time(); $lastWho{$chan} = $nick; ### TODO: use $nick or lc $nick? - if (&IsParam("seenStats")) { + if (&IsChanConf("seenStats")) { $userstats{lc $nick}{'Count'}++; $userstats{lc $nick}{'Time'} = time(); } -# if (&IsParam("hehCounter")) { +# if (&IsChanConf("hehCounter")) { # #... # } @@ -685,21 +711,31 @@ sub on_quit { foreach (keys %channels) { # fixes inconsistent chanstats bug #1. - next unless (&IsNickInChan($nick,$_)); + if (!&IsNickInChan($nick,$_)) { + &DEBUG("on_quit: nick $nick was not in chan $_."); + next; + } $chanstats{$_}{'SignOff'}++; } + &DeleteUserInfo($nick, keys %channels); + if (exists $nuh{lc $nick}) { delete $nuh{lc $nick}; } else { &DEBUG("on_quit: nuh{lc $nick} does not exist! FIXME"); } - delete $userstats{lc $nick} if (&IsParam("seenStats")); + delete $userstats{lc $nick} if (&IsChanConf("seenStats")); # should fix chanstats inconsistencies bug #2. if ($reason=~/^($mask{host})\s($mask{host})$/) { # netsplit. $reason = "NETSPLIT: $1 <=> $2"; + if (&ChanConfList("chanlimitcheck") and !scalar keys %netsplit) { + &DEBUG("on_quit: netsplit detected; disabling chan limit."); + &rawout("MODE $chan -l"); + } + $netsplit{lc $nick} = time(); if (!exists $netsplitservers{$1}{$2}) { &status("netsplit detected between $1 and $2."); @@ -709,8 +745,9 @@ sub on_quit { &status(">>> $b_cyan$nick$ob has signed off IRC $b_red($ob$reason$b_red)$ob"); if ($nick =~ /^\Q$ident\E$/) { - &DEBUG("!!! THIS SHOULD NEVER HAPPEN. FIXME HOPEFULLY"); + &DEBUG("^^^ THIS SHOULD NEVER HAPPEN."); } + if ($nick !~ /^\Q$ident\E$/ and $nick =~ /^\Q$param{'ircNick'}\E$/i) { &status("own nickname became free; changing."); &nick($param{'ircNick'}); @@ -720,19 +757,11 @@ sub on_quit { sub on_targettoofast { my ($self, $event) = @_; my $nick = $event->nick(); - my $chan = ($event->to)[0]; - - &DEBUG("on_targettoofast: nick => '$nick'."); - &DEBUG("on_targettoofast: chan => '$chan'."); - - foreach ($event->args) { - &DEBUG("on_targettoofast: args => '$_'."); - } + my($me,$chan,$why) = $event->args(); ### .* wait (\d+) second/) { &status("X1 $msg"); - my $sleep = $3 + 10; - + my $sleep = 5; &status("going to sleep for $sleep..."); sleep $sleep; &joinNextChan(); @@ -756,13 +785,13 @@ sub on_topic { # this may be fixed at a later date with topic queueing. ### - $topic{$chan}{'Current'} = $topic if (1 and &IsParam("topic") == 1); + $topic{$chan}{'Current'} = $topic if (1); $chanstats{$chan}{'Topic'}++; &status(">>> topic/$b_blue$chan$ob by $b_cyan$nick$ob -> $topic"); } else { # join. my ($nick, $chan, $topic) = $event->args; - if (&IsParam("topic")) { + if (&IsChanConf("topic")) { $topic{$chan}{'Current'} = $topic; &topicAddHistory($chan,$topic); } @@ -850,6 +879,8 @@ sub on_whoisuser { my ($self, $event) = @_; my @args = $event->args; + &DEBUG("on_whoisuser: @args"); + $nuh{lc $args[1]} = $args[1]."!".$args[2]."\@".$args[3]; } @@ -949,15 +980,17 @@ sub hookMsg { } # Determine floodwho. + my $c = "_default"; if ($msgType =~ /public/i) { # public. - $floodwho = lc $chan; + $floodwho = $c = lc $chan; } elsif ($msgType =~ /private/i) { # private. $floodwho = lc $who; } else { # dcc? &DEBUG("FIXME: floodwho = ???"); } - my ($count, $interval) = split(/:/, $param{'floodRepeat'} || "2:10"); + my $val = &getChanConfDefault("floodRepeat", "2:10", $c); + my ($count, $interval) = split /:/, $val; # flood repeat protection. if ($addressed) { @@ -967,9 +1000,12 @@ sub hookMsg { ### public != personal who so the below is kind of pointless. my @who; foreach (keys %flood) { - next if (/^\Q$floodwho\E$/ or /^\Q$chan\E$/); + next if (/^\Q$floodwho\E$/); + next if (defined $chan and /^\Q$chan\E$/); + push(@who, grep /^\Q$message\E$/i, keys %{$flood{$_}}); } + if (scalar @who) { &msg($who, "you already said what ". join(' ', @who)." have said."); @@ -995,14 +1031,18 @@ sub hookMsg { if ($addrchar) { &status("$b_cyan$who$ob is short-addressing me"); - } else { + } elsif ($msgType eq "private") { # private. + &status("$b_cyan$who$ob is /msg'ing me"); + } else { # public? &status("$b_cyan$who$ob is addressing me"); } $flood{$floodwho}{$message} = time(); } - ($count, $interval) = split(/:/, $param{'floodMessages'} || "5:30"); + $val = &getChanConfDefault("floodMessages", "5:30", $c); + ($count, $interval) = split /:/, $val; + # flood overflow protection. if ($addressed) { foreach (keys %{$flood{$floodwho}}) { @@ -1034,8 +1074,8 @@ sub hookMsg { &DEBUG("unknown msgType => $msgType."); } - if ((!$skipmessage or &IsParam("seenStoreAll")) and - &IsParam("seen") and + if ((!$skipmessage or &IsChanConf("seenStoreAll")) and + &IsChanConf("seen") and $msgType =~ /public/ ) { $seencache{$who}{'time'} = time(); @@ -1061,10 +1101,10 @@ sub hookMsg { } if (defined $nuh) { - if (defined $userHandle) { - &DEBUG("line 1074: remove verifyUser"); + if (!defined $userHandle) { + &DEBUG("line 1074: need verifyUser?"); + &verifyUser($who, $nuh); } - $userHandle = &verifyUser($who, $nuh); } else { &DEBUG("hookMsg: 'nuh' not defined?"); } @@ -1077,4 +1117,29 @@ sub hookMsg { return; } +sub chanLimitVerify { + my($chan) = @_; + my $l = $channels{$chan}{'l'}; + + # only change it if it's not set. + if (defined $l and &IsChanConf("chanlimitcheck")) { + my $plus = &getChanConfDefault("chanlimitcheckPlus", 5, $chan); + my $nowl = scalar(keys %{ $channels{$chan}{''} }); + my $delta = $nowl - $l; + $delta =~ s/^\-//; + + if ($plus <= 3) { + &WARN("clc: stupid to have plus at $plus, fix it!"); + } + + ### todo: check if we have ops. + ### todo: if not, check if nickserv/chanserv is avail. + ### todo: unify code with chanlimitcheck() + if ($delta > 3) { + &WARN("clc: nowl($nowl) > l($l) - 3"); + &rawout("MODE $chan +l ".($nowl+$plus) ); + } + } +} + 1;