Explorar el Código

* Port [3489] to 1.2.14
* Rewrote cmd_mdop into cmd_mmode. See 'help mmode' on a leaf bot.



svn: 3490

Bryan Drewery hace 19 años
padre
commit
fa3211caf0
Se han modificado 4 ficheros con 236 adiciones y 144 borrados
  1. 1 0
      doc/UPDATES
  2. 33 14
      misc/help.txt
  3. 201 129
      src/mod/irc.mod/cmdsirc.c
  4. 1 1
      src/mod/irc.mod/irc.c

+ 1 - 0
doc/UPDATES

@@ -54,6 +54,7 @@ Lines prefixed with '-' were disabled before release and are not finished, or ar
 * Fix logging/usage bug in cmd_mop. (fixes #313)
 * Fix logging/usage bug in cmd_mop. (fixes #313)
 * Bad uname EMAILS now include the localhub's nick. (fixes #354)
 * Bad uname EMAILS now include the localhub's nick. (fixes #354)
 * -host now accepts partial host masks, ie, '-host user@host'.
 * -host now accepts partial host masks, ie, '-host user@host'.
+* Rewrote cmd_mdop into cmd_mmode. See 'help mmode' on a leaf bot.
 
 
 1.2.13 - http://wraith.shatow.net/milestone/1.2.13
 1.2.13 - http://wraith.shatow.net/milestone/1.2.13
 * Fix cmd_chanset accepting invalid flags
 * Fix cmd_chanset accepting invalid flags

+ 33 - 14
misc/help.txt

@@ -1229,36 +1229,55 @@ See also: match
    Returns the MD5 hash of the specified string.
    Returns the MD5 hash of the specified string.
  
  
 See also: randstring, sha1, encrypt, decrypt
 See also: randstring, sha1, encrypt, decrypt
-:leaf:mdop:
-###  $bmdop$b <#channel> [bots=n] [alines=n] [slines=n] [overlap=n] [bitch] [simul]
-   For those of us who do not wish to be rocket scientists in the mdop department, 
-   a simple '%dmdop #channel' will suffice.
-   **Remember, the bot you mdop on will never participate in the deopping**
+::me
+###  $bme$b <text>
+   Performs an action on the party line. This appears as "* Wcc is leaving",
+   etc.
+:leaf:mmode:
+###  $bmmode$b <(+|-)MODE> <#channel> <a|o|v|d|r> [bots=n] [alines=n] [slines=n] [overlap=n] [bitch] [simul]
+   For those of us who do not wish to be rocket scientists in the mass mode department, 
+   a simple '%dmmode -o #channel o' will suffice.
+ 
+   **Remember, the bot you mmode on will never participate in the modes**
  
  
    options:
    options:
  
  
-     $bbitch$b   - set +bitch after finished with mdop.
-     $bsimul$b   - Simulates the mdop. IE: Gives you a practice run, will show who 
+     $ba$b = $ball.$b
+     $bo$b = $bops.$b
+     $bO$b = $buser-op.$b
+     $bv$b = $bvoices.$b
+     $bd$b = $bnon-ops.$b
+     $br$b = $bregulars (-ov).$b
+ 
+     $bbitch$b   - set +bitch after finished with mmode.
+     $bsimul$b   - Simulates the mmode. IE: Gives you a practice run, will show who 
                    does what in the dcc chat window.
                    does what in the dcc chat window.
  
  
      =============================================================================
      =============================================================================
      don't bother setting the following options unless you REALLY know what you're 
      don't bother setting the following options unless you REALLY know what you're 
      doing, and don't bother messaging me asking me how to use them if you don't.
      doing, and don't bother messaging me asking me how to use them if you don't.
      =============================================================================
      =============================================================================
-     $bbots$b    - Number of bots to use for mdop.
+     $bbots$b    - Number of bots to use.
      $balines$b  - Number of MODE lines to assume each participating bot will get through.
      $balines$b  - Number of MODE lines to assume each participating bot will get through.
      $bslines$b  - Number of MODE lines each participating bot will send.
      $bslines$b  - Number of MODE lines each participating bot will send.
-     $boverlap$b - Number of times to deop each target nick (using alines for calc).
+     $boverlap$b - Number of times to mode on each target nick (using alines for calc).
  
  
    bots, alines, slines and overlap are dependant on each other, set them wrong and
    bots, alines, slines and overlap are dependant on each other, set them wrong and
    the bot will complain. 
    the bot will complain. 
   
   
-   Defaults are alines=3, slines=5, overlap=2. alines will be increased up to 5 if 
+   Defaults are alines=1, slines=5, overlap=1. alines will be increased up to 5 if 
    there are not enough bots available.
    there are not enough bots available.
-::me
-###  $bme$b <text>
-   Performs an action on the party line. This appears as "* Wcc is leaving",
-   etc.
+ 
+   Examples:
+ 
+     To mass deop (old style '%dmdop')
+      '%dmmode -o #chan o overlap=2'
+     To mass voice non-ops
+      '%dmmode +v #chan d'
+     To mass voice non-ops and non-voices
+      '%dmmode +v #chan r'
+ 
+See also: mop
 :leaf:mop:
 :leaf:mop:
 ###  $bmop$b <channel|*>
 ###  $bmop$b <channel|*>
    Bot will op all users in the specified channel that are valid ops
    Bot will op all users in the specified channel that are valid ops

+ 201 - 129
src/mod/irc.mod/cmdsirc.c

@@ -525,44 +525,27 @@ static void cmd_op(int idx, char *par)
 
 
 }
 }
 
 
-static void cmd_mdop(int idx, char *par)
+static void cmd_mmode(int idx, char *par)
 {
 {
-  char *p = NULL, *chname = NULL;
-  int force_bots = 0,
-    force_alines = 0,
-    force_slines = 0,
-    force_overlap = 0;
-  int overlap = 0,
-    bitch = 0,
-    simul = 0;
-  int needed_deops,
-    max_deops,
-    bots,
-    deops,
-    sdeops;
-  memberlist **chanbots = NULL,
-  **targets = NULL,
-   *m = NULL;
-  int chanbotcount = 0,
-    targetcount = 0,
-    tpos = 0,
-    bpos = 0,
-    i;
-  struct chanset_t *chan = NULL;
-  char work[1024] = "";
-  
+  char *mode = newsplit(&par);
+  if (strlen(mode) > 2 || !strchr("+-", mode[0]) || !par[0]) {
+    dprintf(idx, "Usage: mmode <(+|-)MODE> <#channel> <a|o|v|d|r> [bots=n] [alines=n] [slines=n] [overlap=n] [bitch] [simul]\n");
+    dprintf(idx, "Ie. mmode -o #chan a\n");
+    return;
+  }
+
+  putlog(LOG_CMDS, "*", "#%s# mmode %s %s", dcc[idx].nick, mode, par);
 
 
-  putlog(LOG_CMDS, "*", "#%s# mdop %s", dcc[idx].nick, par);
+  char *chname = NULL;
 
 
   if (strchr(CHANMETA, par[0]) != NULL)
   if (strchr(CHANMETA, par[0]) != NULL)
     chname = newsplit(&par);
     chname = newsplit(&par);
   else
   else
-    chname = 0;
-  chan = get_channel(idx, chname);
+    chname = NULL;
+
+  struct chanset_t *chan = get_channel(idx, chname);
  
  
   if (chan) {
   if (chan) {
-    get_user_flagrec(dcc[idx].user, &user, chan->dname);
-
     if (!shouldjoin(chan) || !channel_active(chan))  {
     if (!shouldjoin(chan) || !channel_active(chan))  {
       dprintf(idx, "I'm not on %s\n", chan->dname);
       dprintf(idx, "I'm not on %s\n", chan->dname);
       return;
       return;
@@ -571,81 +554,129 @@ static void cmd_mdop(int idx, char *par)
       dprintf(idx, "Channel pending.\n");
       dprintf(idx, "Channel pending.\n");
       return;
       return;
     }
     }
+
+    get_user_flagrec(dcc[idx].user, &user, chan->dname, chan);
     if (!glob_owner(user) && !chan_owner(user)) {
     if (!glob_owner(user) && !chan_owner(user)) {
-      dprintf(idx, "You do not have mdop access for %s\n", chan->dname);
+      dprintf(idx, "You do not have mass mode access for %s\n", chan->dname);
       return;
       return;
     }
     }
   }
   }
   if (!chan || !chname[0]) {
   if (!chan || !chname[0]) {
-    dprintf(idx, "Usage: mdop <#channel> [bots=n] [alines=n] [slines=n] [overlap=n] [bitch] [simul]\n");
+    dprintf(idx, "Usage: mmode <(+|-)MODE> <#channel> <a|o|v|d|r> [bots=n] [alines=n] [slines=n] [overlap=n] [bitch] [simul]\n");
+    dprintf(idx, "Ie. mmode -o #chan a\n");
     return;
     return;
   }
   }
 
 
+  char *who = newsplit(&par);
 
 
-  targets = (memberlist **) my_calloc(1, chan->channel.members * sizeof(memberlist *));
+  if (strlen(who) > 1 || !strchr("aovdr", who[0])) {
+    dprintf(idx, "Usage: mmode <(+|-)MODE> <#channel> <a|o|v|d|r> [bots=n] [alines=n] [slines=n] [overlap=n] [bitch] [simul]\n");
+    dprintf(idx, "Ie. mmode -o #chan a\n");
+    dprintf(idx, "a = all.\n");
+    dprintf(idx, "o = ops.\n");
+    dprintf(idx, "O = user-op.\n");
+    dprintf(idx, "v = voices.\n");
+    dprintf(idx, "d = non-ops.\n");
+    dprintf(idx, "r = regulars (-ov).\n");
+    return;
+  }
 
 
-  chanbots = (memberlist **) my_calloc(1, chan->channel.members * sizeof(memberlist *));
+  memberlist** targets = (memberlist**) my_calloc(1, chan->channel.members * sizeof(memberlist *));
+  int* overlaps = (int *) my_calloc(1, chan->channel.members * sizeof(int *));
+  memberlist** chanbots = (memberlist **) my_calloc(1, chan->channel.members * sizeof(memberlist *));
+  memberlist *m = NULL;
+  int chanbotcount = 0, targetcount = 0;
+
+  for (m = chan->channel.member; m; m = m->next) {
+    if (m->user) {
+      if ((m->flags & CHANOP) && m->user->bot && (m->user->flags & USER_OP) &&
+          (!match_my_nick(m->nick)) && (nextbot(m->user->handle) >= 0)) {
+        chanbots[chanbotcount++] = m;
+        continue;
+      }
 
 
-ContextNote("!mdop!");
-  for (m = chan->channel.member; m; m = m->next)
-    if (m->flags & CHANOP) {
-      ContextNote(m->nick);
-      if (!m->user)
-	targets[targetcount++] = m;
-      else if (m->user->bot && (m->user->flags & USER_OP) 
-	       && (egg_strcasecmp(conf.bot->nick, m->user->handle))
-	       && (nextbot(m->user->handle) >= 0))
-	chanbots[chanbotcount++] = m;
-      else if (!(m->user->flags & USER_OP))
-	targets[targetcount++] = m;
+      get_user_flagrec(m->user, &user, chan->dname);
     }
     }
+
+    bool is_target = 0;
+
+    if (who[0] == 'o' && (m->flags & CHANOP))
+      is_target = 1;
+    else if (who[0] == 'O' && chk_op(user, chan))
+      is_target = 1;
+    else if (who[0] == 'd' && !(m->flags & CHANOP))
+      is_target = 1;
+    else if (who[0] == 'v' && !(m->flags & CHANOP) && (m->flags & CHANVOICE))
+      is_target = 1;
+    else if (who[0] == 'r' && !(m->flags & CHANOP) && !(m->flags & CHANVOICE))
+      is_target = 1;
+    else if (who[0] == 'a')
+      is_target = 1;
+
+    if (is_target)
+      targets[targetcount++] = m;
+  }
+
   if (!chanbotcount) {
   if (!chanbotcount) {
     dprintf(idx, "No bots opped on %s\n", chan->name);
     dprintf(idx, "No bots opped on %s\n", chan->name);
     free(targets);
     free(targets);
+    free(overlaps);
     free(chanbots);
     free(chanbots);
     return;
     return;
   }
   }
+
   if (!targetcount) {
   if (!targetcount) {
-    dprintf(idx, "Noone to deop on %s\n", chan->name);
+    dprintf(idx, "No one to mode on %s\n", chan->name);
     free(targets);
     free(targets);
+    free(overlaps);
     free(chanbots);
     free(chanbots);
     return;
     return;
   }
   }
+
+  int force_bots = 0, force_alines = 0, force_slines = 0, force_overlap = 0;
+  bool bitch = 0, simul = 0;
+
   while (par && par[0]) {
   while (par && par[0]) {
-    p = newsplit(&par);
-    if (!strncmp(p, "bots=", 5)) {
+    char *p = newsplit(&par);
+    if (!egg_strncasecmp(p, "bots=", 5)) {
       p += 5;
       p += 5;
       force_bots = atoi(p);
       force_bots = atoi(p);
       if ((force_bots < 1) || (force_bots > chanbotcount)) {
       if ((force_bots < 1) || (force_bots > chanbotcount)) {
 	dprintf(idx, "bots must be within 1-%i\n", chanbotcount);
 	dprintf(idx, "bots must be within 1-%i\n", chanbotcount);
 	free(targets);
 	free(targets);
+	free(overlaps);
 	free(chanbots);
 	free(chanbots);
 	return;
 	return;
       }
       }
-    } else if (!strncmp(p, "alines=", 7)) {
+    } else if (!egg_strncasecmp(p, "alines=", 7)) {
       p += 7;
       p += 7;
       force_alines = atoi(p);
       force_alines = atoi(p);
-      if ((force_alines < 1) || (force_alines > 5)) {
-	dprintf(idx, "alines must be within 1-5\n");
+      if ((force_alines < 1) || (force_alines > 20)) {
+	dprintf(idx, "alines must be within 1-20\n");
+        dprintf(idx, ">5 will fail without a floodless.\n");
 	free(targets);
 	free(targets);
+	free(overlaps);
 	free(chanbots);
 	free(chanbots);
 	return;
 	return;
       }
       }
-    } else if (!strncmp(p, "slines=", 7)) {
+    } else if (!egg_strncasecmp(p, "slines=", 7)) {
       p += 7;
       p += 7;
       force_slines = atoi(p);
       force_slines = atoi(p);
-      if ((force_slines < 1) || (force_slines > 6)) {
-	dprintf(idx, "slines must be within 1-6\n");
+      if ((force_slines < 1) || (force_slines > 20)) {
+	dprintf(idx, "slines must be within 1-20\n");
+        dprintf(idx, ">6 will fail without a floodless.\n");
 	free(targets);
 	free(targets);
+	free(overlaps);
 	free(chanbots);
 	free(chanbots);
 	return;
 	return;
       }
       }
-    } else if (!strncmp(p, "overlap=", 8)) {
+    } else if (!egg_strncasecmp(p, "overlap=", 8)) {
       p += 8;
       p += 8;
       force_overlap = atoi(p);
       force_overlap = atoi(p);
       if ((force_overlap < 1) || (force_overlap > 8)) {
       if ((force_overlap < 1) || (force_overlap > 8)) {
 	dprintf(idx, "overlap must be within 1-8\n");
 	dprintf(idx, "overlap must be within 1-8\n");
 	free(targets);
 	free(targets);
+	free(overlaps);
 	free(chanbots);
 	free(chanbots);
 	return;
 	return;
       }
       }
@@ -654,138 +685,179 @@ ContextNote("!mdop!");
     } else if (!strcmp(p, "simul")) {
     } else if (!strcmp(p, "simul")) {
       simul = 1;
       simul = 1;
     } else {
     } else {
-      dprintf(idx, "Unrecognized mdop option %s\n", p);
+      dprintf(idx, "Unrecognized option %s\n", p);
       free(targets);
       free(targets);
+      free(overlaps);
       free(chanbots);
       free(chanbots);
       return;
       return;
     }
     }
   }
   }
 
 
-  overlap = (force_overlap ? force_overlap : 2);
-  needed_deops = (overlap * targetcount);
-  max_deops = ((force_bots ? force_bots : chanbotcount) * (force_alines ? force_alines : 5) * 4);
+  int overlap = (force_overlap ? force_overlap : 1);
+  int needed_modes = (overlap * targetcount);
+  int max_modes = ((force_bots ? force_bots : chanbotcount) * (force_alines ? force_alines : 5) * modesperline);
 
 
-  if (needed_deops > max_deops) {
+  if (needed_modes > max_modes) {
+    dprintf(idx, "Need to make %d modes, but the max is %d.\n", needed_modes, max_modes);
+    dprintf(idx, "Try increasing [alines] or decreasing [overlap].\n");
     if (overlap == 1)
     if (overlap == 1)
       dprintf(idx, "Not enough bots.\n");
       dprintf(idx, "Not enough bots.\n");
     else
     else
       dprintf(idx, "Not enough bots. Try with overlap=1\n");
       dprintf(idx, "Not enough bots. Try with overlap=1\n");
     free(targets);
     free(targets);
+    free(overlaps);
     free(chanbots);
     free(chanbots);
     return;
     return;
   }
   }
 
 
+
+  int bots, modes;
+
   /* ok it's possible... now let's figure out how */
   /* ok it's possible... now let's figure out how */
   if (force_bots && force_alines) {
   if (force_bots && force_alines) {
     /* not much choice... overlap should not autochange */
     /* not much choice... overlap should not autochange */
     bots = force_bots;
     bots = force_bots;
-    deops = force_alines * 4;
+    modes = force_alines * modesperline;
   } else {
   } else {
     if (force_bots) {
     if (force_bots) {
-      /* calc needed deops per bot */
+      /* calc needed modes per bot */
       bots = force_bots;
       bots = force_bots;
-      deops = (needed_deops + (bots - 1)) / bots;
+      modes = (needed_modes + (bots - 1)) / bots;
     } else if (force_alines) {
     } else if (force_alines) {
-      deops = force_alines * 4;
-      bots = (needed_deops + (deops - 1)) / deops;
+      modes = force_alines * modesperline;
+      bots = (needed_modes + (modes - 1)) / modes;
     } else {
     } else {
-      deops = 12;
-      bots = (needed_deops + (deops - 1)) / deops;
-      if (bots > chanbotcount) {
-	deops = 16;
-	bots = (needed_deops + (deops - 1)) / deops;
-      }
-      if (bots > chanbotcount) {
-	deops = 20;
-	bots = (needed_deops + (deops - 1)) / deops;
+      /* Try minimizing alines, 1,2,3,4,5 against bots needed */
+      modes = 1 * modesperline;
+      bots = (needed_modes + (modes - 1)) / modes;
+
+      for (int min_alines = 2; min_alines <= 5; ++min_alines) {
+        if (bots > chanbotcount) {
+          modes = min_alines * modesperline;
+          bots = (needed_modes + (modes - 1)) / modes;
+        } else
+          break;
       }
       }
+
       if (bots > chanbotcount) {
       if (bots > chanbotcount) {
-	putlog(LOG_MISC, "*", "Totally fucked calculations in cmd_mdop. this CAN'T happen.");
-	dprintf(idx, "Something's wrong... bug the coder\n");
-	free(targets);
-	free(chanbots);
-	return;
+        putlog(LOG_MISC, "*", "Totally fucked calculations in cmd_mmode. this CAN'T happen.");
+        dprintf(idx, "Something's wrong... bug the coder\n");
+        free(targets);
+        free(overlaps);
+        free(chanbots);
+        return;
       }
       }
     }
     }
   }
   }
 
 
+  /* How many modes to send */
+  int smodes;
+
   if (force_slines)
   if (force_slines)
-    sdeops = force_slines * 4;
+    smodes = force_slines * modesperline;
   else
   else
-    sdeops = 20;
-  if (sdeops < deops)
-    sdeops = deops;
-
-  dprintf(idx, "Mass deop of %s\n", chan->name);
-  dprintf(idx, "  %d bots used for deop\n", bots);
-  dprintf(idx, "  %d assumed deops per participating bot\n", deops);
-  dprintf(idx, "  %d max deops per participating bot\n", sdeops);
-  dprintf(idx, "  %d assumed deops per target nick\n", overlap);
+    smodes = 5 * modesperline;
+  if (smodes < modes)
+    smodes = modes;
+
+  dprintf(idx, "Mass %s of %s\n", mode, chan->dname);
+  dprintf(idx, "  %d bots used.\n", bots);
+  dprintf(idx, "  %d targets.\n", targetcount);
+  dprintf(idx, "  %d assumed modes per participating bot.\n", modes);
+  dprintf(idx, "  %d max modes per participating bot.\n", smodes);
+  dprintf(idx, "  %d assumed modes per target nick.\n", overlap);
+
+  int tpos = 0, bpos = 0, i = 0;
+  char work[1024] = "";
 
 
-  /* now use bots/deops to distribute nicks to deop */
+  /* now use bots/modes to distribute nicks to MODE on */
   while (bots) {
   while (bots) {
     if (!simul)
     if (!simul)
-      simple_sprintf(work, "dp %s", chan->name);
+      simple_snprintf(work, sizeof(work), "dp %s %s", mode, chan->dname);
     else
     else
       work[0] = 0;
       work[0] = 0;
-    for (i = 0; i < deops; i++) {
-      strcat(work, " ");
-      strcat(work, targets[tpos]->nick);
-      tpos++;
-      if (tpos >= targetcount)
-	tpos = 0;
+    /* Make list of assumed lines (alines) */
+    for (i = 0; i < modes; i++) {
+      if (overlaps[tpos]++ < overlap) {
+        strcat(work, " ");
+        strcat(work, targets[tpos]->nick);
+      }
+      if (++tpos >= targetcount)
+        tpos = 0;
     }
     }
-    if (sdeops > deops) {
-      int atpos;
-
-      atpos = tpos;
-      for (i = 0; i < (sdeops - deops); i++) {
-	strcat(work, " ");
-	strcat(work, targets[atpos]->nick);
-	atpos++;
-	if (atpos >= targetcount)
-	  atpos = 0;
+    /* Now make lines of throttled modes (slines) */
+    if (smodes > modes) {
+      int atpos = tpos;
+      for (i = 0; i < (smodes - modes); i++) {
+        if (overlaps[tpos]++ < overlap) {
+          strcat(work, " ");
+          strcat(work, targets[atpos]->nick);
+        }
+	if (++atpos >= targetcount)
+          atpos = 0;
       }
       }
     }
     }
+
     if (simul)
     if (simul)
-      dprintf(idx, "%s deops%s\n", chanbots[bpos]->nick, work);
+      dprintf(idx, "%s MODE %s %s\n", chanbots[bpos]->nick, mode, work);
     else
     else
-      botnet_send_zapf(nextbot(chanbots[bpos]->user->handle), conf.bot->nick, chanbots[bpos]->user->handle, work);
-    bots--;
-    bpos++;
+      putbot(chanbots[bpos]->user->handle, work);
+    --bots;
+    ++bpos;
   }
   }
-  if (bitch && !simul && chan) {
+  if (bitch && !simul) {
     chan->status |= CHAN_BITCH;
     chan->status |= CHAN_BITCH;
     do_chanset(NULL, chan, "+bitch", DO_LOCAL | DO_NET);
     do_chanset(NULL, chan, "+bitch", DO_LOCAL | DO_NET);
   }
   }
   free(targets);
   free(targets);
+  free(overlaps);
   free(chanbots);
   free(chanbots);
   return;
   return;
 }
 }
 
 
-void mdop_request(char *botnick, char *code, char *par)
+void mass_mode_request(char *botnick, char *code, char *par)
 {
 {
-  char *chname = NULL, *p = NULL;
-  char work[2048] = "";
+  char* mode = newsplit(&par);
+
+  if (strlen(mode) > 2 || !strchr("+-", mode[0]))
+    return;
+
+  char* chname = newsplit(&par);
+
+  char list[101] = "", buf[2048] = "";
+  size_t list_len = 0, buf_len = 0;
 
 
-  chname = newsplit(&par);
-  work[0] = 0;
   while (par[0]) {
   while (par[0]) {
     int cnt = 0;
     int cnt = 0;
 
 
-    strcat(work, "MODE ");
-    strcat(work, chname);
-    strcat(work, " -oooo");
+    *(buf + buf_len++) = 'M';
+    *(buf + buf_len++) = 'O';
+    *(buf + buf_len++) = 'D';
+    *(buf + buf_len++) = 'E';
+    *(buf + buf_len++) = ' ';
+    buf_len += strlcpy(buf + buf_len, chname, sizeof(buf) - buf_len);
+    *(buf + buf_len++) = ' ';
+
     while ((cnt < 4) && par[0]) {
     while ((cnt < 4) && par[0]) {
-      p = newsplit(&par);
-      strcat(work, " ");
-      strcat(work, p);
-      cnt++;
+      /* add +mode into irc cmd */
+      buf_len += strlcpy(buf + buf_len, mode, sizeof(buf) - buf_len);
+
+      /* Make list of nicks */
+      char* nick = newsplit(&par);
+      list_len += strlcpy(list + list_len, nick, sizeof(list) - list_len); 
+      if (++cnt < 4 && par[0])
+        *(list + list_len++) = ' ';
     }
     }
-    strcat(work, "\r");
-    strcat(work, "\n");
+
+    /* buf is so far: 'MODE #chan +o+o+o+o' */
+    *(buf + buf_len++) = ' ';
+    buf_len += strlcpy(buf + buf_len, list, sizeof(buf) - buf_len);
+    *(buf + buf_len++) = '\r';
+    *(buf + buf_len++) = '\n';
+    list[0] = list_len = 0;
   }
   }
-  tputs(serv, work, strlen(work));
+  buf[buf_len] = 0;
+  tputs(serv, buf, buf_len);
 }
 }
 
 
 static void cmd_deop(int idx, char *par)
 static void cmd_deop(int idx, char *par)
@@ -1724,7 +1796,7 @@ static cmd_t irc_dcc[] =
 #endif /* CACHE */
 #endif /* CACHE */
   {"kick",		"o|o",	 (Function) cmd_kick,		NULL, LEAF|AUTH},
   {"kick",		"o|o",	 (Function) cmd_kick,		NULL, LEAF|AUTH},
   {"kickban",		"o|o",	 (Function) cmd_kickban,	NULL, LEAF|AUTH},
   {"kickban",		"o|o",	 (Function) cmd_kickban,	NULL, LEAF|AUTH},
-  {"mdop",              "n|n",	 (Function) cmd_mdop,		NULL, LEAF},
+  {"mmode",             "n|n",	 (Function) cmd_mmode,		NULL, LEAF},
   {"mop",		"n|m",	 (Function) cmd_mop,		NULL, LEAF|AUTH},
   {"mop",		"n|m",	 (Function) cmd_mop,		NULL, LEAF|AUTH},
   {"msg",		"o",	 (Function) cmd_msg,		NULL, LEAF|AUTH},
   {"msg",		"o",	 (Function) cmd_msg,		NULL, LEAF|AUTH},
   {"op",		"o|o",	 (Function) cmd_op,		NULL, LEAF|AUTH},
   {"op",		"o|o",	 (Function) cmd_op,		NULL, LEAF|AUTH},

+ 1 - 1
src/mod/irc.mod/irc.c

@@ -1613,7 +1613,7 @@ do_nettype()
 }
 }
 
 
 static cmd_t irc_bot[] = {
 static cmd_t irc_bot[] = {
-  {"dp", "", (Function) mdop_request, NULL, LEAF},
+  {"dp", "", (Function) mass_mode_request, NULL, LEAF},
   {"gi", "", (Function) getin_request, NULL, LEAF},
   {"gi", "", (Function) getin_request, NULL, LEAF},
   {NULL, NULL, NULL, NULL, 0}
   {NULL, NULL, NULL, NULL, 0}
 };
 };