Ver Fonte

Merge branch '35-speedup-request'

* 35-speedup-request:
  Fix unsigned/signed warning
  Move 'in-bots' logic to getin_request() (#35)
  Request help to join from all bots (#35)
  Update functions to accept consts
  Remove unneeded revenge code
  Only request_op() every few minutes if not already opped, and bots are opped (#35)
  Avoid unused cycling code
  Unset channel.do_opreq after first try
  Inline me_op()
  If another bot is opped, ask them for ops (#35)
  Avoid looping in any_ops() at end of /WHO to request ops (#35)
  Only reop if the victim was already an op
  No reason to request op in an opless channel (#35)
  Only reop if role 3 (#35)
  Don't auto reop if another bot deopped the victim (#35)
  Auto reop bots to speedup opping (#35)
  Cleanup reversing check
  No need to request_op every 5 seconds (#35)
Bryan Drewery há 14 anos atrás
pai
commit
4df5dc2708
9 ficheiros alterados com 117 adições e 98 exclusões
  1. 3 0
      doc/UPDATES
  2. 1 1
      src/botmsg.c
  3. 1 1
      src/botmsg.h
  4. 9 9
      src/flags.c
  5. 9 9
      src/flags.h
  6. 7 1
      src/mod/irc.mod/chan.c
  7. 50 69
      src/mod/irc.mod/irc.c
  8. 9 1
      src/mod/irc.mod/irc.h
  9. 28 7
      src/mod/irc.mod/mode.c

+ 3 - 0
doc/UPDATES

@@ -31,6 +31,9 @@
   * Improve output of 'bots' command by displaying and sorting nodename
   * Minus chrec if .chattr set no flags
   * Added 'chanset +floodban' to ban clients that violate 'flood-chan' and 'flood-ctcp'
+  * Bots now auto-reop other bots that get deopped
+  * Bots now ask for ops quicker if another bot is opped
+  * Bots now request/join +ilk channels much quicker
 
 maint
   * Fix various compile warnings with newer GCC

+ 1 - 1
src/botmsg.c

@@ -299,7 +299,7 @@ void putallbots(const char *par)
   return;
 }
 
-void putbot(const char *bot, char *par)
+void putbot(const char *bot, const char *par)
 {
   if (!bot || !par || !bot[0] || !par[0])
     return;

+ 1 - 1
src/botmsg.h

@@ -10,7 +10,7 @@
 
 void botnet_send_var(int idx, variable_t *);
 void botnet_send_var_broad(int idx, variable_t *);
-void putbot(const char *, char *);
+void putbot(const char *, const char *);
 void putallbots(const char *);
 int add_note(char *, char *, char *, int, int);
 

+ 9 - 9
src/flags.c

@@ -380,7 +380,7 @@ set_user_flagrec(struct userrec *u, struct flag_record *fr, const char *chname)
 /* Always pass the dname (display name) to this function for chname <cybah>
  */
 void
-get_user_flagrec(struct userrec *u, struct flag_record *fr, const char *chname, const struct chanset_t* chan)
+get_user_flagrec(const struct userrec *u, struct flag_record *fr, const char *chname, const struct chanset_t* chan)
 {
   fr->bot = 0;
   if (!u) {
@@ -427,7 +427,7 @@ get_user_flagrec(struct userrec *u, struct flag_record *fr, const char *chname,
  * restricted by +private for the channel
  */
 int
-privchan(struct flag_record fr, struct chanset_t *chan, int type)
+privchan(const struct flag_record fr, const struct chanset_t *chan, int type)
 {
   if (!chan || !channel_privchan(chan) || glob_bot(fr) || glob_owner(fr))
     return 0;                   /* user is implicitly not restricted by +private, they may however be lacking other flags */
@@ -444,7 +444,7 @@ privchan(struct flag_record fr, struct chanset_t *chan, int type)
 }
 
 int
-real_chk_op(struct flag_record fr, struct chanset_t *chan, bool botbitch)
+real_chk_op(const struct flag_record fr, const struct chanset_t *chan, bool botbitch)
 {
   if (!chan && glob_op(fr))
     return 1;
@@ -459,7 +459,7 @@ real_chk_op(struct flag_record fr, struct chanset_t *chan, bool botbitch)
 }
 
 int
-chk_autoop(struct flag_record fr, struct chanset_t *chan)
+chk_autoop(const struct flag_record fr, const struct chanset_t *chan)
 {
   if (glob_bot(fr))
     return 0;
@@ -471,7 +471,7 @@ chk_autoop(struct flag_record fr, struct chanset_t *chan)
 }
 
 int
-real_chk_deop(struct flag_record fr, struct chanset_t *chan, bool botbitch)
+real_chk_deop(const struct flag_record fr, const struct chanset_t *chan, bool botbitch)
 {
   if (chan && botbitch && channel_botbitch(chan) && !glob_bot(fr))
     return 1;
@@ -483,7 +483,7 @@ real_chk_deop(struct flag_record fr, struct chanset_t *chan, bool botbitch)
 }
 
 int
-doresolv(struct chanset_t *chan)
+doresolv(const struct chanset_t *chan)
 {
   if (!chan)
     return 0;
@@ -497,7 +497,7 @@ doresolv(struct chanset_t *chan)
 }
 
 int
-dovoice(struct chanset_t *chan)
+dovoice(const struct chanset_t *chan)
 {
   if (!chan)
     return 0;
@@ -511,7 +511,7 @@ dovoice(struct chanset_t *chan)
 }
 
 int
-doflood(struct chanset_t *chan)
+doflood(const struct chanset_t *chan)
 {
   struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_BOT, 0, 0, 0 };
   if (!chan)
@@ -524,7 +524,7 @@ doflood(struct chanset_t *chan)
 }
 
 int
-dolimit(struct chanset_t *chan)
+dolimit(const struct chanset_t *chan)
 {
   if (!chan)
     return 0;

+ 9 - 9
src/flags.h

@@ -142,7 +142,7 @@ struct flag_record {
 #define chan_doflood(x)				((x).chan & BOT_FLOODBOT)
 
 void init_flags(void);
-void get_user_flagrec(struct userrec *, struct flag_record *, const char *, const struct chanset_t* = NULL);
+void get_user_flagrec(const struct userrec *, struct flag_record *, const char *, const struct chanset_t* = NULL);
 void set_user_flagrec(struct userrec *, struct flag_record *, const char *);
 void break_down_flags(const char *, struct flag_record *, struct flag_record *);
 int build_flags(char *, struct flag_record *, struct flag_record *);
@@ -151,12 +151,12 @@ int flagrec_ok(struct flag_record *, struct flag_record *);
 flag_t sanity_check(flag_t, int);
 flag_t chan_sanity_check(flag_t, int);
 char geticon(int);
-int privchan(struct flag_record, struct chanset_t *, int);
+int privchan(const struct flag_record, const struct chanset_t *, int);
 #define chk_op(fr, chan) real_chk_op(fr, chan, 1)
-int real_chk_op(struct flag_record, struct chanset_t *, bool);
-int chk_autoop(struct flag_record, struct chanset_t *);
+int real_chk_op(const struct flag_record, const struct chanset_t *, bool);
+int chk_autoop(const struct flag_record, const struct chanset_t *);
 #define chk_deop(fr, chan) real_chk_deop(fr, chan, 1)
-int real_chk_deop(struct flag_record, struct chanset_t *, bool);
+int real_chk_deop(const struct flag_record, const struct chanset_t *, bool);
 #define chk_voice(fr, chan) (\
     (\
      (!chan || (!privchan(fr, chan, PRIV_VOICE) && !chk_devoice(fr))) \
@@ -166,10 +166,10 @@ int real_chk_deop(struct flag_record, struct chanset_t *, bool);
 #define chk_devoice(fr) ((chan_quiet(fr) || (glob_quiet(fr) && !chan_voice(fr))) ? 1 : 0)
 #define isupdatehub() ((conf.bot->hub && conf.bot->u && (conf.bot->u->flags & BOT_UPDATEHUB)) ? 1 : 0)
 #define ischanhub() ((!conf.bot->hub && conf.bot->u && (conf.bot->u->flags & BOT_CHANHUB)) ? 1 : 0)
-int doresolv(struct chanset_t *);
-int dovoice(struct chanset_t *);
-int doflood(struct chanset_t *);
-int dolimit(struct chanset_t *);
+int doresolv(const struct chanset_t *);
+int dovoice(const struct chanset_t *);
+int doflood(const struct chanset_t *);
+int dolimit(const struct chanset_t *);
 int whois_access(struct userrec *, struct userrec *);
 void deflag_user(struct userrec *, int, char *, struct chanset_t *);
 int deflag_translate(const char *);

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

@@ -1950,6 +1950,11 @@ static int got352or4(struct chanset_t *chan, char *user, char *host, char *nick,
       resolve_to_rbl(chan, m->userip);
   }
 
+  // If there's an opped bot, queue op to request_op
+  if (m->user && m->user->bot && chan_hasop(m)) {
+    chan->channel.do_opreq = 1;
+  }
+
   return 0;
 }
 
@@ -2064,8 +2069,9 @@ static int got315(char *from, char *msg)
       recheck_channel(chan, 2);
     else if (chan->channel.members == 1)
       chan->ircnet_status |= CHAN_STOP_CYCLE;
-    else if (any_ops(chan))
+    else if (chan->channel.do_opreq) {
       request_op(chan);
+    }
   }
   /* do not check for i-lines here. */
   return 0;

+ 50 - 69
src/mod/irc.mod/irc.c

@@ -598,8 +598,6 @@ getin_request(char *botnick, char *code, char *par)
 
   if (what[0] != 'K') {
     if (!(channel_pending(chan) || channel_active(chan))) {
-      putlog(LOG_GETIN, "*", "%sreq from %s/%s %s %s - I'm not on %s right now.", type, botnick, nick, desc, 
-                             chan->dname, chan->dname);
       return;
     }
   }
@@ -722,6 +720,27 @@ getin_request(char *botnick, char *code, char *par)
       return;
     }
 
+    // Should I respond to this request?
+    // If there's 18 eligible bots in the channel, and in-bots is 2, I have a 2/18 chance of replying.
+    int eligible_bots = 0;
+    for (memberlist* m = chan->channel.member; m && m->nick[0]; m = m->next) {
+      if (chan_hasop(m)) {
+        member_getuser(m, 0);
+        if (m->user && m->user->bot) {
+          ++eligible_bots;
+        }
+      }
+    }
+
+    if (!eligible_bots) {
+      return;
+    }
+
+    if (!((randint(eligible_bots) + 1) <= static_cast<unsigned int>(in_bots))) {
+      // Not my turn
+      return;
+    }
+
     bool sendi = 0;
 
     if (chan->channel.maxmembers) {
@@ -816,8 +835,10 @@ getin_request(char *botnick, char *code, char *par)
 static void
 request_op(struct chanset_t *chan)
 {
-  if (!chan || (chan && (channel_pending(chan) || !shouldjoin(chan) || !channel_active(chan) || me_op(chan))))
+  if (!chan || (chan && (channel_pending(chan) || !shouldjoin(chan) || !channel_active(chan) || me_op(chan)))) {
+    chan->channel.do_opreq = 0;
     return;
+  }
 
   if (chan->channel.no_op) {
     if (chan->channel.no_op > now)      /* dont op until this time has passed */
@@ -826,7 +847,6 @@ request_op(struct chanset_t *chan)
       chan->channel.no_op = 0;
   }
 
-  chan->channel.do_opreq = 0;
   /* check server lag */
   if (server_lag > lag_threshold) {
     putlog(LOG_GETIN, "*", "Not asking for ops on %s - I'm too lagged", chan->dname);
@@ -986,15 +1006,17 @@ request_in(struct chanset_t *chan)
   }
 
   int foundBots = 0;
-  char* botops[MAX_BOTS];
+//  char* botops[MAX_BOTS];
 
   for (tand_t* bot = tandbot; bot && (foundBots < MAX_BOTS); bot = bot->next) {
     if (bot->hub || !bot->u)
       continue;
 
     get_user_flagrec(bot->u, &fr, chan->dname, chan);
-    if (bot_shouldjoin(bot->u, &fr, chan) && chk_op(fr, chan))
-      botops[foundBots++] = bot->bot;
+    if (bot_shouldjoin(bot->u, &fr, chan) && chk_op(fr, chan)) {
+      ++foundBots;
+//      botops[foundBots++] = bot->bot;
+    }
   }
 
   if (!foundBots) {
@@ -1002,23 +1024,9 @@ request_in(struct chanset_t *chan)
     return;
   }
 
-  int cnt = foundBots < in_bots ? foundBots : in_bots;
-  char s[255] = "";
-  char l[1024] = "";
-  size_t len = 0;
-
-  simple_snprintf(s, sizeof(s), "gi i %s %s %s!%s %s", chan->dname, botname, botname, botuserhost, botuserip);
-
-  shuffleArray(botops, foundBots);
-  for (int n = 0; n < cnt; ++n) {
-    putbot(botops[n], s);
-
-    if (l[0])
-      len += strlcpy(l + len, ", ", sizeof(l) - len);
-    len += strlcpy(l + len, botops[n], sizeof(l) - len);
-  }
-  l[len] = 0;
-  putlog(LOG_GETIN, "*", "Requested help to join %s from %s", chan->dname, l);
+  bd::String request(bd::String::printf("gi i %s %s %s!%s %s", chan->dname, botname, botname, botuserhost, botuserip));
+  putallbots(request.c_str());
+  putlog(LOG_GETIN, "*", "Requested help to join %s", chan->dname);
 }
 
 
@@ -1276,21 +1284,6 @@ killmember(struct chanset_t *chan, char *nick)
   return 1;
 }
 
-/* Check if I am a chanop. Returns boolean 1 or 0.
- */
-bool
-me_op(const struct chanset_t *chan)
-{
-  memberlist *mx = ismember(chan, botname);
-
-  if (!mx)
-    return 0;
-  if (chan_hasop(mx))
-    return 1;
-  else
-    return 0;
-}
-
 /* Check whether I'm voice. Returns boolean 1 or 0.
  */
 bool
@@ -1423,8 +1416,6 @@ check_lonely_channel(struct chanset_t *chan)
       !shouldjoin(chan) || (chan->channel.mode & CHANANON))
     return;
 
-  memberlist *m = NULL;
-  char s[UHOSTLEN] = "";
   static int whined = 0;
 
   if ((chan->channel.members - chan->channel.splitmembers) == 1 && channel_cycle(chan) && !channel_stop_cycle(chan)) {
@@ -1436,15 +1427,10 @@ check_lonely_channel(struct chanset_t *chan)
     }
   } else if (any_ops(chan)) {
     whined = 0;
-    request_op(chan);
-/* need: op */
   } else {
     /* Other people here, but none are ops. If there are other bots make
      * them LEAVE!
      */
-    bool ok = 1;
-    struct userrec *u = NULL;
-
     if (!whined) {
       /* + is opless. Complaining about no ops when without special
        * help(services), we cant get them - Raist
@@ -1453,10 +1439,14 @@ check_lonely_channel(struct chanset_t *chan)
         putlog(LOG_MISC, "*", "%s is active but has no ops :(", chan->dname);
       whined = 1;
     }
+#ifdef disabled
+    memberlist *m = NULL;
+    bool ok = 1;
+
     for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
-      simple_snprintf(s, sizeof(s), "%s!%s", m->nick, m->userhost);
-      u = get_user_by_host(s);
-      if (!m->is_me && (!u || !u->bot)) {
+      member_getuser(m, 0);
+
+      if (!m->is_me && (!m->user || !m->user->bot)) {
         ok = 0;
         break;
       }
@@ -1468,11 +1458,8 @@ check_lonely_channel(struct chanset_t *chan)
 	if (!m->is_me)
 	  dprintf(DP_SERVER, "PRIVMSG %s :go %s\n", m->nick, chan->dname);
 */
-    } else {
-      /* Some humans on channel, but still op-less */
-      request_op(chan);
-/* need: op */
     }
+#endif
   }
 }
 
@@ -1622,10 +1609,11 @@ check_expired_chanstuff(struct chanset_t *chan)
       }
     } /* me_op */
 
-//    for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
-    int splitmembers = 0;
+    size_t splitmembers = 0, bot_ops = 0;
+    const bool im_opped = me_op(chan);
     for (m = chan->channel.member; m && m->nick[0]; m = n) {
       n = m->next;
+      // Update split members
       if (m->split) {
         ++splitmembers;
         if (now - m->split > wait_split) {
@@ -1648,7 +1636,7 @@ check_expired_chanstuff(struct chanset_t *chan)
         }
       }
 
-      if (me_op(chan)) {
+      if (im_opped) {
         if (dovoice(chan) && !loading) {      /* autovoice of +v users if bot is +y */
           if (!chan_hasop(m) && !chan_hasvoice(m) && !chan_sentvoice(m)) {
             member_getuser(m, 1);
@@ -1673,11 +1661,17 @@ check_expired_chanstuff(struct chanset_t *chan)
           }
         }
       }
+      if (m->user && m->user->bot) {
+        ++bot_ops;
+      }
       m = n;
     }
     // Update minutely
     chan->channel.splitmembers = splitmembers;
     check_lonely_channel(chan);
+    if (bot_ops && !im_opped) {
+      request_op(chan);
+    }
   }
 }
 
@@ -1801,23 +1795,10 @@ static cmd_t irc_bot[] = {
   {NULL, NULL, NULL, NULL, 0}
 };
 
-static void
-getin_5secondly()
-{
-  if (!server_online)
-    return;
-
-  for (register struct chanset_t *chan = chanset; chan; chan = chan->next) {
-    if ((!channel_pending(chan) && channel_active(chan)) && !me_op(chan))
-      request_op(chan);
-  }
-}
-
 void
 irc_init()
 {
   timer_create_secs(60, "irc_minutely", (Function) irc_minutely);
-  timer_create_secs(5, "getin_5secondly", (Function) getin_5secondly);
 
   /* Add our commands to the imported tables. */
   add_builtins("dcc", irc_dcc);

+ 9 - 1
src/mod/irc.mod/irc.h

@@ -7,6 +7,7 @@
 #define _EGG_MOD_IRC_IRC_H
 
 #include "src/auth.h"
+#include "src/chanprog.h"
 
 enum { BC_NOCOOKIE = 1, BC_SLACK, BC_HASH, BC_COUNTER };
 
@@ -117,7 +118,14 @@ void notice_invite(struct chanset_t *, char *, char *, char *, bool);
 void real_add_mode(struct chanset_t *, const char, const char, const char *, bool);
 #define add_mode(chan, pls, mode, nick) real_add_mode(chan, pls, mode, nick, 0)
 #define add_cookie(chan, nick) real_add_mode(chan, '+', 'o', nick, 1)
-bool me_op(const struct chanset_t *);
+/* Check if I am a chanop. Returns boolean 1 or 0.
+ */
+inline bool me_op(const struct chanset_t *chan)
+{
+  const memberlist *mx = ismember(chan, botname);
+  return mx && chan_hasop(mx);
+}
+
 bool me_voice(const struct chanset_t *);
 
 void check_this_ban(struct chanset_t *, char *, bool);

+ 28 - 7
src/mod/irc.mod/mode.c

@@ -557,7 +557,14 @@ got_op(struct chanset_t *chan, memberlist *m, memberlist *mv)
     meop = 1;
   }
 
-  get_user_flagrec(mv->user, &victim, chan->dname, chan);
+  if (mv->user) {
+    get_user_flagrec(mv->user, &victim, chan->dname, chan);
+
+    // Did some other bot just get opped, and I'm not opped yet?
+    if (mv->user->bot && !me_opped && !meop) {
+      chan->channel.do_opreq = 1;
+    }
+  }
   /* Flags need to be set correctly right from the beginning now, so that
    * add_mode() doesn't get irritated.
    */
@@ -647,11 +654,14 @@ got_deop(struct chanset_t *chan, memberlist *m, memberlist *mv, char *isserver)
 
   if (mdop_reversing && !was_op)
     return;
-  
+
+  /* m is NULL if a server made the change */
   if (m)
     simple_snprintf(s1, sizeof(s1), "%s!%s", m->nick, m->userhost);
 
-  get_user_flagrec(mv->user, &victim, chan->dname, chan);
+  if (mv->user) {
+    get_user_flagrec(mv->user, &victim, chan->dname, chan);
+  }
 
   /* Flags need to be set correctly right from the beginning now, so that
    * add_mode() doesn't get irritated.
@@ -666,12 +676,21 @@ got_deop(struct chanset_t *chan, memberlist *m, memberlist *mv, char *isserver)
   /* Deop'd someone on my oplist? */
   if (me_op(chan)) {
     /* do we want to reop victim? */
-    if ((reversing) && 
-        ((m && !m->is_me && rfc_casecmp(mv->nick, m->nick)) || (!m)) &&
-        !mv->is_me &&
-        (chk_op(victim, chan) || !chan_bitch(chan)))
+    if (
+        /* I didn't deop them, another bot didn't deop them and they didn't deop themselves. */
+        (was_op && ((m && !m->is_me && mv != m && !(m->user && m->user->bot)) || (!m))) && (
+          /*
+           * reversing
+           * They are either an op or this chan is -bitch
+           */
+          (reversing && (!chan_bitch(chan) || chk_op(victim, chan))) ||
+          /* Reop bots to avoid them needing to ask */
+          (role == 3 && mv->user && mv->user->bot && chk_op(victim, chan))
+        )
+       ) {
       /* Then we'll bless the victim */
       do_op(mv->nick, chan, 0, 0);
+    }
   }
 
   if (isserver[0])		/* !m */
@@ -701,12 +720,14 @@ got_deop(struct chanset_t *chan, memberlist *m, memberlist *mv, char *isserver)
     if (!m)
       putlog(LOG_MODES, chan->dname, "TS resync deopped me on %s :(", chan->dname);
   }
+#ifdef revenge
   if (m) {
     char s[UHOSTLEN] = "";
 
     simple_snprintf(s, sizeof(s), "%s!%s", mv->nick, mv->userhost);
 //    maybe_revenge(chan, s1, s, REVENGE_DEOP);
   }
+#endif
 }
 
 static void