Просмотр исходного кода

Merge branch '48-voice-updates'

* 48-voice-updates:
  Enforce 'chanmode' minutely (#48)
  Don't kick a user if already devoiced and -m (#48)
  Don't unset +m when unlocking channel from flood (#48)
  Allow any user op (+o) to enable/disable EVOICE (#48)
  Properly log response to flood (#48)
  Document 'voice-moderate' (#48)
  Respect devoices from other bots (#48)
  Set EVOICE on abusive clients (#48)
  Implement devoicing on flood (#48)
  DRY flood punishment (#48)
  Auto set +m when 'voice-moderate' is set (#48)
  Auto unset 'voice-moderate' if 'chanmode -m' is set (#48)
  Add chanset 'voice-moderate' (#48)
Bryan Drewery 14 лет назад
Родитель
Сommit
768894cdb3

+ 4 - 0
doc/UPDATES

@@ -47,6 +47,10 @@
   * Add chanset 'color-limit' to handle how many color codes are allowed in a message before kick (#8)
   * Add chanset 'closed-exempt' which will allow exempting non-users (who are opped or voice) from being kicked. (fixes #171)
   * Tweak limit range checking such that bot will set limit less often
+  * Bots now again respect devoices made by other bots and will not revoice those users.
+  * Add chanset 'voice-moderate' which will auto set +m in '+voice' channel and devoice flooding clients instead of kick. (#48)
+  * Bots now will enforce devoices made by ops (user +o) and allow any op (user +o) to revoice to disable that enforcement.
+    This used to use +m to enforce/allowed revoicing.
 
 1.3.4 - http://wraith.botpack.net/milestone/1.3.4
   * Fix various compile warnings with newer GCC

+ 2 - 0
doc/help.txt

@@ -437,6 +437,8 @@ See also: link%{+a}, newhub%{-}
                           channel is +protect.
         $bvoice-non-ident$b   If channel is +voice, clients without an ident will 
                           be voiced. Set to 0 to not voice clients without ident.
+        $bvoice-moderate$b    If channel is +voice, auto set +m and devoice flooders
+                          instead of kicking them. Set to 0 to disable.
  
    The following options choose how to respond to specific events.
         Each can be set as any of the specified options.

+ 1 - 0
src/chan.h

@@ -197,6 +197,7 @@ struct chanset_t {
   int closed_private;
   int closed_invite;
   int closed_exempt_mode;
+  int voice_moderate;
   deflag_t bad_cookie;
   deflag_t manop;
   deflag_t mdop;

+ 11 - 0
src/mod/channels.mod/chanmisc.c

@@ -452,6 +452,16 @@ int channel_modify(char *result, struct chanset_t *chan, int items, char **item,
         return ERROR;
       }
       chan->closed_ban = atoi(item[i]);
+    } else if (!strcmp(item[i], "voice-moderate")) {
+      i++;
+      if (i >= items) {
+        if (result)
+          strlcpy(result, "channel voice-moderate needs argument", RESULT_LEN);
+        return ERROR;
+      }
+      chan->voice_moderate = atoi(item[i]);
+      if (chan->mode_mns_prot & CHANMODER && chan->voice_moderate)
+        chan->voice_moderate = 0;
     } else if (!strcmp(item[i], "closed-invite")) {
       i++;
       if (i >= items) {
@@ -1082,6 +1092,7 @@ int channel_add(char *result, const char *newname, char *options, bool isdefault
     chan->closed_ban = 0;
     chan->closed_private = 1;
     chan->closed_invite = 1;
+    chan->voice_moderate = 1;
     chan->voice_non_ident = 1;
     chan->auto_delay = 5;
     chan->ban_type = 3;

+ 6 - 0
src/mod/channels.mod/channels.c

@@ -567,6 +567,9 @@ static void set_mode_protect(struct chanset_t *chan, char *set)
 
   if (chan->mode_mns_prot & CHANINV && chan->closed_invite)
     chan->closed_invite = 0;
+
+  if (chan->mode_mns_prot & CHANMODER && chan->voice_moderate)
+    chan->voice_moderate = 0;
 }
 
 static void get_mode_protect(struct chanset_t *chan, char *s, size_t ssiz)
@@ -790,6 +793,9 @@ void channels_report(int idx, int details)
         if (chan->closed_private)
           strlcat(s2, "p", sizeof(s2));
       }
+      if (channel_voice(chan) && chan->voice_moderate) {
+        strlcat(s2, "m", sizeof(s2));
+      }
 
       if (conf.bot->hub || shouldjoin(chan)) {
 	if (channel_active(chan)) {

+ 1 - 0
src/mod/channels.mod/cmdschan.c

@@ -1258,6 +1258,7 @@ static void cmd_chaninfo(int idx, char *par)
     SHOW_INT("Revenge: ", chan->revenge, DEFLAG_STR, "Ignore");
     SHOW_INT("Protect-backup: ", chan->protect_backup, "Do!", "Don't!");
     SHOW_INT("Voice-non-ident: ", chan->voice_non_ident, "Do!", "Don't!");
+    SHOW_INT("Voice-moderate:", chan->voice_moderate, NULL, "Don't!");
 
     dprintf(idx, "Flood settings:   chan bytes ctcp join kick deop nick mjoin mpub mbytes mctcp\n");
     dprintf(idx, "  number:          %3d  %4d  %3d  %3d  %3d  %3d  %3d   %3d  %3d   %4d   %3d\n",

+ 2 - 1
src/mod/channels.mod/userchan.c

@@ -719,7 +719,7 @@ flood-chan %d:%d flood-bytes %d:%d flood-ctcp %d:%d flood-join %d:%d \
 flood-kick %d:%d flood-deop %d:%d flood-nick %d:%d flood-mjoin %d:%d \
 flood-mpub %d:%d flood-mbytes %d:%d flood-mctcp %d:%d \
 capslimit %d colorlimit %d closed-ban %d closed-invite %d closed-private %d closed-exempt %d ban-time %d \
-exempt-time %d invite-time %d voice-non-ident %d auto-delay %d \
+exempt-time %d invite-time %d voice-non-ident %d voice-moderate %d auto-delay %d \
 flood-exempt %d flood-lock-time %d knock %d fish-key { %s } \
 %cmeankicks %cenforcebans %cdynamicbans %cuserbans %cbitch %cfloodban \
 %cprivate %ccycle %cinactive %cdynamicexempts %cuserexempts \
@@ -763,6 +763,7 @@ flood-exempt %d flood-lock-time %d knock %d fish-key { %s } \
         chan->exempt_time,
         chan->invite_time,
         chan->voice_non_ident,
+        chan->voice_moderate,
         chan->auto_delay,
         chan->flood_exempt_mode,
         chan->flood_lock_time,

+ 6 - 3
src/mod/irc.mod/chan.c

@@ -730,9 +730,8 @@ static bool detect_chan_flood(memberlist* m, const char *from, struct chanset_t
           char *s1 = quickban(chan, from);
           u_addmask('b', chan, s1, conf.bot->nick, "channel flood", now + (60 * chan->ban_time), 0);
         } else {
-          putlog(LOG_MODES, chan->dname, "Channel flood from %s -- kicking", m->nick);
-          dprintf(DP_MODE, "KICK %s %s :%s%s\n", chan->name, m->nick, kickprefix, response(RES_FLOOD));
-          m->flags |= SENTKICK;
+          const char *response = punish_flooder(chan, m);
+          putlog(LOG_MODES, chan->dname, "Channel flood from %s -- %s", m->nick, response);
         }
       }
       return 1;
@@ -1121,6 +1120,10 @@ void recheck_channel_modes(struct chanset_t *chan)
       mns &= ~CHANPRIV;
     }
   }
+  if (channel_voice(chan) && chan->voice_moderate) {
+    pls |= CHANMODER;
+    mns &= ~CHANMODER;
+  }
 
   if (!(chan->ircnet_status & CHAN_ASKEDMODES)) {
     if (pls & CHANINV && !(cur & CHANINV))

+ 38 - 7
src/mod/irc.mod/irc.c

@@ -184,29 +184,56 @@ detect_offense(memberlist* m, struct chanset_t *chan, char *msg)
   if (chan->capslimit && caps_count && tot >= 6) {
     caps_percentage = (caps_count)/(double(tot));
     if (caps_percentage >= caps_limit) {
-      putlog(LOG_MODES, chan->name, "Caps flood (%d%%) from %s -- kicking", int(caps_percentage * 100), m->nick);
-      dprintf(DP_SERVER, "KICK %s %s :%s%s\n", chan->name, m->nick, kickprefix, response(RES_FLOOD));
-      m->flags |= SENTKICK;
+      const char *response = punish_flooder(chan, m);
+      putlog(LOG_MODES, chan->name, "Caps flood (%d%%) from %s -- %s", int(caps_percentage * 100), m->nick, response);
       return 1;
     }
   } else if (chan->colorlimit && color_count) {
     if (color_count >= chan->colorlimit) {
-      putlog(LOG_MODES, chan->name, "Color flood (%d) from %s -- kicking", color_count, m->nick);
-      dprintf(DP_SERVER, "KICK %s %s :%s%s\n", chan->name, m->nick, kickprefix, response(RES_FLOOD));
-      m->flags |= SENTKICK;
+      const char *response = punish_flooder(chan, m);
+      putlog(LOG_MODES, chan->name, "Color flood (%d) from %s -- %s", color_count, m->nick, response);
       return 1;
     }
   }
   return 0;
 }
 
+void set_devoice(struct chanset_t *chan, memberlist* m) {
+  if (!(m->flags & EVOICE)) {
+    putlog(LOG_DEBUG, "@", "Giving EVOICE flag to: %s (%s)", m->nick, chan->dname);
+    m->flags |= EVOICE;
+  }
+}
+
+const char* punish_flooder(struct chanset_t* chan, memberlist* m, const char *reason) {
+  if (channel_voice(chan) && chan->voice_moderate) {
+    if (!chan_sentdevoice(m)) {
+      add_mode(chan, '-', 'v', m->nick);
+      m->flags |= SENTDEVOICE;
+      set_devoice(chan, m);
+      return "devoicing";
+    } else {
+      return "devoiced";
+    }
+  } else {
+    if (!chan_sentkick(m)) {
+      dprintf(DP_SERVER, "KICK %s %s :%s%s\n", chan->name, m->nick, kickprefix, reason ? reason : response(RES_FLOOD));
+      m->flags |= SENTKICK;
+      return "kicking";
+    } else {
+      return "kicked";
+    }
+  }
+  return "ignoring";
+}
+
 void unlock_chan(struct chanset_t *chan)
 {
   if (chan->channel.drone_set_mode) {
     char buf[3] = "", *p = buf;
     if ((chan->channel.drone_set_mode & CHANINV) && !(chan->mode_pls_prot & CHANINV))
       *p++ = 'i';
-    if ((chan->channel.drone_set_mode & CHANMODER) && !(chan->mode_pls_prot & CHANMODER))
+    if ((chan->channel.drone_set_mode & CHANMODER) && !((chan->mode_pls_prot & CHANMODER) || (channel_voice(chan) && chan->voice_moderate)))
       *p++ = 'm';
     *p = 0;
     dprintf(DP_MODE, "MODE %s :-%s\n", chan->name[0] ? chan->name : chan->dname, buf);
@@ -1554,6 +1581,10 @@ check_expired_chanstuff(struct chanset_t *chan)
     if (bot_ops && !im_opped) {
       request_op(chan);
     }
+
+    if (role == 3) {
+      recheck_channel_modes(chan);
+    }
   }
 }
 

+ 2 - 0
src/mod/irc.mod/irc.h

@@ -107,6 +107,8 @@ typedef struct resolvstruct resolv_member;
 void resolve_to_rbl(struct chanset_t *chan, const char *host, struct resolvstruct *r = NULL);
 static void do_mask(struct chanset_t *chan, masklist *m, char *mask, char Mode);
 static void get_channel_masks(struct chanset_t* chan);
+const char* punish_flooder(struct chanset_t* chan, memberlist* m, const char *reason = NULL);
+void set_devoice(struct chanset_t* chan, memberlist* m);
 
 #endif /* MAKING_IRC */
 

+ 5 - 8
src/mod/irc.mod/mode.c

@@ -1482,8 +1482,7 @@ gotmode(char *from, char *msg)
 
               if (msign == '+') {
                 if (mv->flags & EVOICE) {
-                  /* FIXME: This is a lame check, we need to expand on this more */
-                  if (!chan_master(user) && !glob_master(user) && !chk_voice(victim, chan)) {
+                  if (!chk_op(user, chan) && !chk_voice(victim, chan)) {
                     dv = 1;
                   } else {
                     mv->flags &= ~EVOICE;
@@ -1509,14 +1508,12 @@ gotmode(char *from, char *msg)
                     add_mode(chan, '+', 'v', mparam);
                     /* if they arent +v|v and VOICER is m+ then EVOICE them */
                   } else {
-                    /* FIXME: same thing here */
-                    if (!match_my_nick(nick) && channel_voice(chan) && !glob_bot(user) &&
-                        (glob_master(user) || chan_master(user)) &&
+                    if (!match_my_nick(nick) && channel_voice(chan) &&
+                        (chk_op(user, chan) || glob_bot(user)) &&
                         rfc_casecmp(nick, mparam)) {
                       /* if the user is not +q set them norEVOICE. */
-                      if (!chan_quiet(victim) && !(mv->flags & EVOICE)) {
-                        putlog(LOG_DEBUG, "@", "Giving EVOICE flag to: %s (%s)", mv->nick, chan->dname);
-                        mv->flags |= EVOICE;
+                      if (!chan_quiet(victim)) {
+                        set_devoice(chan, mv);
                       }
                     }
                   }