Parcourir la source

Add new consistent dynamic roles

This will automatically assign roles to every bot in a channel
in a decentralized way. This ensures that both sides of a split
will have a bot covering every role and removes the need for
the leaf to share nicks to the hub and for the hub to have
to process roles continually.
Bryan Drewery il y a 12 ans
Parent
commit
1f2e09b68e
2 fichiers modifiés avec 89 ajouts et 68 suppressions
  1. 0 68
      src/mod/channels.mod/channels.c
  2. 89 0
      src/mod/irc.mod/irc.c

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

@@ -290,19 +290,6 @@ static void got_down(char *botnick, char *code, char *par)
   add_mode(chan, '-', 'o', botname);
 }
 
-static void got_role(char *botnick, char *code, char *par)
-{
-  struct chanset_t* chan = NULL;
-  int role;
-
-  role = atoi(newsplit(&par));
-
-  for (chan = chanset; chan; chan = chan->next) {
-    chan->role = role;
-  }
-  putlog(LOG_DEBUG, "@", "Got role index %d", role);
-}
-
 void got_kl(char *botnick, char *code, char *par)
 {
   killed_bots++;
@@ -313,59 +300,6 @@ void got_kl(char *botnick, char *code, char *par)
   }
 }
 
-
-static void rebalance_roles()
-{
-  struct bot_addr *ba = NULL;
-  int r[5] = { 0, 0, 0, 0, 0 };
-  unsigned int hNdx, lNdx, i;
-  char tmp[10] = "";
-
-  for (i = 0; i < (unsigned) dcc_total; i++) {
-    if (dcc[i].type && dcc[i].user && dcc[i].user->bot && bot_hublevel(dcc[i].user) == 999) {
-      ba = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, dcc[i].user);
-      if (ba && (ba->roleid > 0) && (ba->roleid < 5))
-        r[(ba->roleid - 1)]++;
-    }
-  }
-  /*
-     Find high & low
-     while (high-low) > 2
-     move from highNdx to lowNdx
-   */
-
-  hNdx = 0;
-  lNdx = 0;
-  for (i = 1; i <= 4; i++) {
-    if (r[i] < r[lNdx])
-      lNdx = i;
-    if (r[i] > r[hNdx])
-      hNdx = i;
-  }
-  while (r[hNdx] - r[lNdx] >= 2) {
-    for (i = 0; i < (unsigned) dcc_total; i++) {
-      if (dcc[i].type && dcc[i].user && dcc[i].user->bot && bot_hublevel(dcc[i].user) == 999) {
-        ba = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, dcc[i].user);
-        if (ba && (ba->roleid == (hNdx + 1))) {
-          ba->roleid = lNdx + 1;
-          simple_snprintf(tmp, sizeof(tmp), "rl %d", lNdx + 1);
-          putbot(dcc[i].nick, tmp);
-        }
-      }
-    }
-    r[hNdx]--;
-    r[lNdx]++;
-    hNdx = 0;
-    lNdx = 0;
-    for (i = 1; i <= 4; i++) {
-      if (r[i] < r[lNdx])
-        lNdx = i;
-      if (r[i] > r[hNdx])
-        hNdx = i;
-    }
-  }
-}
-
 static int
 check_slowjoinpart(struct chanset_t *chan)
 {
@@ -902,7 +836,6 @@ cmd_t channels_bot[] = {
   {"cset",	"", 	(Function) got_cset,  	NULL, 0},
   {"cycle",	"", 	(Function) got_cycle, 	NULL, LEAF},
   {"down",	"", 	(Function) got_down,  	NULL, LEAF},
-  {"rl",	"", 	(Function) got_role,  	NULL, 0},
   {"kl",	"", 	(Function) got_kl,    	NULL, 0},
   {"sj",	"", 	(Function) got_sj,    	NULL, 0},
   {"sp",	"", 	(Function) got_sp,    	NULL, 0},
@@ -922,7 +855,6 @@ void channels_init()
 {
   timer_create_secs(60, "check_expired_masks", (Function) check_expired_masks);
   if (conf.bot->hub) {
-    timer_create_secs(30, "rebalance_roles", (Function) rebalance_roles);
     timer_create_secs(30, "check_should_close", (Function) check_should_close);
 #ifdef G_BACKUP
     timer_create_secs(30, "check_should_backup", (Function) check_should_backup);

+ 89 - 0
src/mod/irc.mod/irc.c

@@ -1753,6 +1753,94 @@ static void bot_release_nick (char *botnick, char *code, char *par) {
   release_nick(par);
 }
 
+static void rebalance_roles_chans(struct chanset_t* chan)
+{
+  bd::Array<bd::String> bots;
+  int *bot_bits;
+  short role;
+  size_t botcount, mappedbot, omappedbot, botidx, roleidx, rolecount;
+  memberlist *m;
+
+  /* Reset current bits */
+  chan->bot_roles->clear();
+  chan->role_bots->clear();
+
+  /* Gather list of all bots in the channel. */
+  /* XXX: Keep this known in chan->bots */
+  for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
+    if (!member_getuser(m) || !is_bot(m->user)) {
+      continue;
+    }
+    bots << m->nick;
+  }
+  botcount = bots.length();
+  if (botcount == 0)
+    return;
+  bot_bits = (int*)calloc(botcount, sizeof(bot_bits[0]));
+
+  for (roleidx = 0; role_counts[roleidx].name; roleidx++) {
+    /* Map this role to a bot */
+    omappedbot = mappedbot = roleidx % botcount;
+    rolecount = role_counts[roleidx].count;
+    role = role_counts[roleidx].role;
+
+    /* Does the mapped bot have the bit yet? If not, check next bot,
+     * on max restart at 0 but avoid looping back to start. */
+    while (rolecount > 0) {
+      if (!(bot_bits[mappedbot] & role)) {
+        bot_bits[mappedbot] |= role;
+        --rolecount;
+      }
+
+      /* Try next bot */
+      ++mappedbot;
+
+      /* Reached the end, wrap around. */
+      if (mappedbot == botcount) {
+        mappedbot = 0;
+      }
+      /* Reached original bot, cannot satisfy the role need. */
+      if (mappedbot == omappedbot) {
+        break;
+      }
+    }
+  }
+
+  /* Take bitmask of assigned roles and apply to bots. */
+  for (botidx = 0; botidx < botcount; botidx++) {
+    if (bot_bits[botidx] != 0) {
+      (*chan->bot_roles)[bots[botidx]] = bot_bits[botidx];
+    }
+  }
+
+  /* Fill role_bots */
+  for (roleidx = 0; role_counts[roleidx].name; roleidx++) {
+    role = role_counts[roleidx].role;
+    /* Find all bots with this role */
+    for (botidx = 0; botidx < botcount; botidx++) {
+      if (bot_bits[botidx] & role) {
+        (*chan->role_bots)[role] << bots[botidx];
+      }
+    }
+  }
+
+  /* Set my own roles */
+  chan->role = (*chan->bot_roles)[botname];
+  free(bot_bits);
+}
+
+static void rebalance_roles()
+{
+  struct chanset_t* chan = NULL;
+
+  for (chan = chanset; chan; chan = chan->next) {
+    if (channel_pending(chan) || !channel_active(chan) ||
+        !shouldjoin(chan) || (chan->channel.mode & CHANANON))
+      continue;
+    rebalance_roles_chans(chan);
+  }
+}
+
 static cmd_t irc_bot[] = {
   {"gi", "", (Function) getin_request, NULL, LEAF},
   {"mr", "", (Function) mass_request, NULL, LEAF},
@@ -1764,6 +1852,7 @@ void
 irc_init()
 {
   timer_create_secs(60, "irc_minutely", (Function) irc_minutely);
+  timer_create_secs(30, "rebalance_roles", (Function) rebalance_roles);
 
   /* Add our commands to the imported tables. */
   add_builtins("dcc", irc_dcc);