Ver Fonte

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 há 12 anos atrás
pai
commit
1f2e09b68e
2 ficheiros alterados com 89 adições e 68 exclusões
  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);