]> git.donarmstrong.com Git - infobot.git/blobdiff - src/IRC/IrcHelpers.pl
allow per-channel addressCharacter
[infobot.git] / src / IRC / IrcHelpers.pl
index 6358aeafa4cbe780211e4d723699a1a2ac93922d..13f44695b800463a2ff98383c909f2b59055f6d4 100644 (file)
@@ -6,19 +6,19 @@
 #        NOTE: Based on code by Kevin Lenzo & Patrick Cole  (c) 1997
 #
 
-if (&IsParam("useStrict")) { use strict; }
-
 #######################################################################
 ####### IRC HOOK HELPERS   IRC HOOK HELPERS   IRC HOOK HELPERS ########
 #######################################################################
 
 #####
-# Usage: &hookMode($chan, $modes, @targets);
+# Usage: &hookMode($nick, $modes, @targets);
 sub hookMode {
-    my ($chan, $modes, @targets) = @_;
+    my ($nick, $modes, @targets) = @_;
     my $parity = 0;
 
-    $chan = lc $chan;          # !!!.
+    if ($chan =~ tr/A-Z/a-z/) {
+       &VERB("hookMode: cased $chan.",2);
+    }
 
     my $mode;
     foreach $mode (split(//, $modes)) {
@@ -45,6 +45,16 @@ sub hookMode {
            if ($mode =~ /[bov]/) {
                $channels{$chan}{$mode}{$target}++      if  $parity;
                delete $channels{$chan}{$mode}{$target} if !$parity;
+
+               # lets do some custom stuff.
+               if ($mode eq "o" and $parity) {
+                   if ($nick eq "ChanServ" and $target =~ /^\Q$ident\E$/i) {
+                       &VERB("hookmode: chanserv deopped us! asking",2);
+                       &chanServCheck($chan);
+                   }
+
+                   &chanLimitVerify($chan);
+               }
            }
 
            if ($mode =~ /[l]/) {
@@ -73,6 +83,7 @@ sub hookMsg {
     $message   =~ s/[\cA-\c_]//ig;     # strip control characters
     $message   =~ s/^\s+//;            # initial whitespaces.
     $who       =~ tr/A-Z/a-z/;         # lowercase.
+    my $mynick = $conn->nick();
 
     &showProc();
 
@@ -80,12 +91,19 @@ sub hookMsg {
     if ($msgType =~ /private/) {
        # private messages.
        $addressed = 1;
+       if (&IsChanConf('addressCharacter')) {
+           $addressCharacter = getChanConf('addressCharacter');
+           if ($message =~ s/^\Q$addressCharacter\E//) {
+               &msg($who, "please don't use the the addressCharacter when private messaging");
+           }
+       }
     } else {
        # public messages.
        # addressing revamped by the xk.
        ### below needs to be fixed...
-       if (&IsParam("addressCharacter")) {
-           if ($message =~ s/^$param{'addressCharacter'}//) {
+       if (&IsChanConf('addressCharacter')) {
+           $addressCharacter = getChanConf('addressCharacter');
+           if ($message =~ s/^\Q$addressCharacter\E//) {
                $addrchar  = 1;
                $addressed = 1;
            }
@@ -93,7 +111,7 @@ sub hookMsg {
 
        if ($message =~ /^($mask{nick})([\;\:\>\, ]+) */) {
            my $newmessage = $';
-           if ($1 =~ /^\Q$ident\E$/i) {
+           if ($1 =~ /^\Q$mynick\E$/i) {
                $message   = $newmessage;
                $addressed = 1;
            } else {
@@ -105,15 +123,18 @@ sub hookMsg {
 
     # Determine floodwho.
     my $c      = "_default";
-    if ($msgType =~ /public/i) {               # public.
+    if ($msgType =~ /public/i) {
+       # public.
        $floodwho = $c = lc $chan;
-    } elsif ($msgType =~ /private/i) { # private.
+    } elsif ($msgType =~ /private/i) {
+       # private.
        $floodwho = lc $who;
-    } else {                           # dcc?
-       &DEBUG("FIXME: floodwho = ???");
+    } else {
+       # dcc?
+       &FIXME("floodwho = ???");
     }
 
-    my $val = &getChanConfDefault("floodRepeat", "2:10", $c);
+    my $val = &getChanConfDefault("floodRepeat", "2:5", $c);
     my ($count, $interval) = split /:/, $val;
 
     # flood repeat protection.
@@ -132,12 +153,10 @@ sub hookMsg {
 
            return if ($lobotomized);
 
-           if (scalar @who) {
-               &msg($who, "you already said what ".
-                               join(' ', @who)." have said.");
-           } else {
-               &msg($who,"Someone already said that ". (time - $time) ." seconds ago" );
+           if (!scalar @who) {
+               push(@who,"Someone");
            }
+           &msg($who,join(' ', @who)." already said that ". (time - $time) ." seconds ago" );
 
            ### TODO: delete old floodwarn{} keys.
            my $floodwarn = 0;
@@ -156,11 +175,11 @@ sub hookMsg {
        }
 
        if ($addrchar) {
-           &status("$b_cyan$who$ob is short-addressing me");
+           &status("$b_cyan$who$ob is short-addressing $mynick");
        } elsif ($msgType eq "private") {       # private.
-           &status("$b_cyan$who$ob is /msg'ing me");
+           &status("$b_cyan$who$ob is /msg'ing $mynick");
        } else {                                # public?
-           &status("$b_cyan$who$ob is addressing me");
+           &status("$b_cyan$who$ob is addressing $mynick");
        }
 
        $flood{$floodwho}{$message} = time();
@@ -177,17 +196,19 @@ sub hookMsg {
 
     # flood overflow protection.
     if ($addressed) {
-       foreach (keys %{$flood{$floodwho}}) {
+       foreach (keys %{ $flood{$floodwho} }) {
            next unless (time() - $flood{$floodwho}{$_} > $interval);
            delete $flood{$floodwho}{$_};
        }
 
-       my $i = scalar keys %{$flood{$floodwho}};
+       my $i = scalar keys %{ $flood{$floodwho} };
        if ($i > $count) {
-           &msg($who,"overflow of messages ($i > $count)");
+           my $expire = $param{'ignoreAutoExpire'} || 5;
+
+#          &msg($who,"overflow of messages ($i > $count)");
+           &msg($who,"Too many queries from you, ignoring for $expire minutes.");
            &status("FLOOD overflow detected from $floodwho; ignoring");
 
-           my $expire = $param{'ignoreAutoExpire'} || 5;
            &ignoreAdd("*!$uh", $chan, $expire, "flood overflow auto-detected.");
            return;
        }
@@ -209,8 +230,8 @@ sub hookMsg {
     }
     push(@ignore, keys %{ $ignore{"*"} }) if (exists $ignore{"*"});
 
-    if ((!$skipmessage or &IsChanConf("seenStoreAll")) and
-       &IsChanConf("seen") and
+    if ((!$skipmessage or &IsChanConf("seenStoreAll") > 0) and
+       &IsChanConf("seen") > 0 and
        $msgType =~ /public/
     ) {
        $seencache{$who}{'time'} = time();
@@ -220,14 +241,24 @@ sub hookMsg {
        $seencache{$who}{'msg'}  = $orig{message};
        $seencache{$who}{'msgcount'}++;
     }
-
+    if (&IsChanConf("minVolunteerLength")) {
+       # FIXME hack to treat unaddressed as if using addrchar
+       $addrchar = 1;
+    }
     return if ($skipmessage);
-    return unless (&IsParam("minVolunteerLength") or $addressed);
+    return unless ($addrchar or $addressed);
 
     foreach (@ignore) {
        s/\*/\\S*/g;
 
-       next unless (eval { $nuh =~ /^$_$/i });
+       next unless (eval { $nuh =~ /^$_$/i } );
+
+       # better to ignore an extra message than to allow one to get
+       # through, although it would be better to go through ignore
+       # checking again.
+       if (time() - ($cache{ignoreCheckTime} || 0) > 60) {
+           &ignoreCheck();
+       }
 
        &status("IGNORE <$who> $message");
        return;
@@ -247,33 +278,97 @@ sub hookMsg {
 #      &DEBUG("IrcHooks: process returned '$_'.");
     }
 
+    # hack to remove +o from ppl with +O flag.
+    if (exists $users{$userHandle} && exists $users{$userHandle}{FLAGS} &&
+       $users{$userHandle}{FLAGS} =~ /O/
+    ) {
+       $users{$userHandle}{FLAGS} =~ s/o//g;
+    }
+
     return;
 }
 
+# this is basically run on on_join or on_quit
 sub chanLimitVerify {
-    my($chan)  = @_;
+    my($c)     = @_;
+    $chan      = $c;
     my $l      = $channels{$chan}{'l'};
 
+    return unless (&IsChanConf("chanlimitcheck"));
+
+    if (scalar keys %netsplit) {
+       &WARN("clV: netsplit active (1, chan = $chan); skipping.");
+       return;
+    }
+
+    if (!defined $l) {
+       &DEBUG("$chan: running chanlimitCheck from chanLimitVerify.");
+       &chanlimitCheck();
+       return;
+    }
+
     # only change it if it's not set.
-    if (defined $l and &IsChanConf("chanlimitcheck")) {
-       my $plus  = &getChanConfDefault("chanlimitcheckPlus", 5, $chan);
-       my $count = scalar(keys %{ $channels{$chan}{''} });
+    my $plus  = &getChanConfDefault("chanlimitcheckPlus", 5, $chan);
+    my $count = scalar(keys %{ $channels{$chan}{''} });
+    my $int   = &getChanConfDefault("chanlimitcheckInterval", 10, $chan);
 
-       my $delta = $count + $plus - $l;
-       $delta    =~ s/^\-//;
+    my $delta = $count + $plus - $l;
+#   $delta    =~ s/^\-//;
 
-       if ($plus <= 3) {
-           &WARN("clc: stupid to have plus at $plus, fix it!");
-       }
+    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 > 5) {
-           &status("clc: big change in limit; changing.");
-           &rawout("MODE $chan +l ".($count+$plus) );
+    if (exists $cache{chanlimitChange}{$chan}) {
+       if (time() - $cache{chanlimitChange}{$chan} < $int*60) {
+           return;
        }
     }
+
+    &chanServCheck($chan);
+
+    ### TODO: unify code with chanlimitcheck()
+    return if ($delta > 5);
+
+    &status("clc: big change in limit for $chan ($delta);".
+               "going for it. (was: $l; now: ".($count+$plus).")");
+
+    $conn->mode($chan, "+l", $count+$plus);
+    $cache{chanlimitChange}{$chan} = time();
+}
+
+sub chanServCheck {
+    ($chan) = @_;
+
+    if (!defined $chan or $chan =~ /^\s*$/) {
+       &WARN("chanServCheck: chan == NULL.");
+       return 0;
+    }
+
+    if ($chan =~ tr/A-Z/a-z/) {
+       &DEBUG("chanServCheck: lowercased chan ($chan)");
+    }
+
+    if (! &IsChanConf("chanServ_ops") ) {
+       return 0;
+    }
+
+    &VERB("chanServCheck($chan) called.",2);
+
+    if ( &IsParam("nickServ_pass") and !$nickserv) {
+       $conn->who("NickServ");
+       return 0;
+    }
+
+    # check for first hash then for next hash.
+    # TODO: a function for &ischanop()? &isvoice()?
+    if (exists $channels{$chan} and exists $channels{$chan}{'o'}{$ident}) {
+       return 0;
+    }
+
+    &status("ChanServ ==> Requesting ops for $chan. (chanServCheck)");
+    &rawout("PRIVMSG ChanServ :OP $chan $ident");
+    return 1;
 }
 
 1;