소스 검색

Merge branch '21-botgroups' into next

* 21-botgroups:
  * Fix cmd_channels showing 'inactive' on hub bots
  * Support group in cmd_channels
  * Const cleanup
  * Add command 'groups' to list all groups and which bots are in them.
  * Only match botcmd on non-hubs for groups
  * Remove unneeded botjoin/botpart
  * When overriding botset 'groups', auto include the global to avoid mistakingly making the bot part all channels immediately
  * Return the global set for default, then use the default

Conflicts:
	doc/UPDATES
Bryan Drewery 14 년 전
부모
커밋
36cccb80fe
14개의 변경된 파일135개의 추가작업 그리고 116개의 파일을 삭제
  1. 3 0
      doc/UPDATES
  2. 13 21
      doc/help.txt
  3. 1 1
      src/chan.h
  4. 3 3
      src/chanprog.c
  5. 2 2
      src/chanprog.h
  6. 55 8
      src/cmds.c
  7. 1 1
      src/flags.c
  8. 1 1
      src/flags.h
  9. 44 27
      src/misc.c
  10. 0 46
      src/mod/channels.mod/cmdschan.c
  11. 2 2
      src/mod/irc.mod/irc.c
  12. 2 2
      src/mod/irc.mod/irc.h
  13. 7 2
      src/set.c
  14. 1 0
      src/set.h

+ 3 - 0
doc/UPDATES

@@ -4,6 +4,9 @@ next
   * Add [bot]set var 'groups' to configure what groups bots are in
   * Add [bot]set var 'groups' to configure what groups bots are in
   * Add chanset 'groups' to take a list of groups that should join. 'chanset #chan groups { main backup }'
   * Add chanset 'groups' to take a list of groups that should join. 'chanset #chan groups { main backup }'
   * Added group support to 'botcmd': 'botcmd %group cmd'
   * Added group support to 'botcmd': 'botcmd %group cmd'
+  * 'botjoin' and 'botpart' have been removed. Just use .+chan, .chanset, .botset to control groups.
+  * Add command 'groups' to list all groups and which bots are in them.
+  * Command 'channels' now accepts a '%group' param to show which channels a group are in.
 
 
 1.4.0 - http://wraith.botpack.net/milestone/1.4.0
 1.4.0 - http://wraith.botpack.net/milestone/1.4.0
   * Updated server list, 'set -yes servers -' and 'set -yes servers6 -' to get new list.
   * Updated server list, 'set -yes servers -' and 'set -yes servers6 -' to get new list.

+ 13 - 21
doc/help.txt

@@ -262,15 +262,6 @@ See also: -ban, +ban, console%{+m|m}, chanset, chaninfo%{-}, stick, unstick
      bl -> botcmd ?
      bl -> botcmd ?
  
  
 See also: cmdpass
 See also: cmdpass
-::botjoin
-###  $bbotjoin$b <bot> <channel> [options]
-   Adds a channel to the bot's channel list. If options are specified, the 
-   channel will be configured with the options.
- 
-   $bTHIS CMD IS CURRENTLY EXPERIMENTAL AND WILL NOT ACTUALLY SAVE STATE$b
-   $bMEANING, ALL BOTS WILL JOIN EVENTUALLY AFTER DOING BOTJOIN$b
- 
-See also: botpart, +chan, -chan, chanset, chaninfo
 :hub:botjump:
 :hub:botjump:
 ###  $bbotjump$b <bot> [server [port [pass]]]
 ###  $bbotjump$b <bot> [server [port [pass]]]
    Makes the bot jump to another server. If you don't specify a
    Makes the bot jump to another server. If you don't specify a
@@ -292,11 +283,6 @@ See also: msg%{+n}
    The specified bot will display its current nick over DCC.
    The specified bot will display its current nick over DCC.
  
  
 See also: netnick, nick
 See also: netnick, nick
-::botpart
-###  $bbotpart$b <bot> <channel>
-   Removes bot from the specified channel
- 
-See also: botjoin, +chan, -chan, chanset, chaninfo
 :hub:bots
 :hub:bots
 ###  $bbots$b [nodename]
 ###  $bbots$b [nodename]
    Shows the list of bots currently on the botnet.
    Shows the list of bots currently on the botnet.
@@ -308,7 +294,7 @@ See also: botjoin, +chan, -chan, chanset, chaninfo
    Specifying a nodename will display all bots up/down on that nodename.
    Specifying a nodename will display all bots up/down on that nodename.
    Bots with a * preceeding its name is down.
    Bots with a * preceeding its name is down.
  
  
-See also: downbots%{+n}, bottree%{-}
+See also: groups, downbots%{+n}, bottree%{-}
 :hub:botserver:
 :hub:botserver:
 ###  $bbotserver$b <bot>
 ###  $bbotserver$b <bot>
    The bot will display its current server and lag over DCC.
    The bot will display its current server and lag over DCC.
@@ -339,7 +325,7 @@ See also: set
    Red: localhubs (first bot in binary, see '%dhelp conf')
    Red: localhubs (first bot in binary, see '%dhelp conf')
    Other: normal leaf bots
    Other: normal leaf bots
  
  
-See also: bots, downbots
+See also: bots, downbots, groups
 ::botversion:
 ::botversion:
 ###  $bbotversion$b <bot>
 ###  $bbotversion$b <bot>
    The bot will display its pack version and uname.
    The bot will display its pack version and uname.
@@ -597,13 +583,14 @@ See also: %{-}%{+n}+chan, -chan%{-}%{+m|m}, chanset%{-}
  
  
 See also: status, whois
 See also: status, whois
 ::channels:
 ::channels:
-###  $bchannels$b %{+m}[user]%{-}
+###  $bchannels$b %{+m}[user|%group]%{-}
    Displays channels that you have access to, and any important 
    Displays channels that you have access to, and any important 
    flags that are set on them.
    flags that are set on them.
 %{+m}
 %{+m}
    Masters: You can specify other users to see what channels their 
    Masters: You can specify other users to see what channels their 
             flags grant them access to.%{-}
             flags grant them access to.%{-}
-See also: whois%{+m}, chattr, chaninfo%{-}
+   Special %%group to see what channels a particular group is in.
+See also: whois%{+m}, chattr, chaninfo, groups%{-}
 ::chanset
 ::chanset
 ###  $bchanset$b [#&!+channel|*|default] <settings>
 ###  $bchanset$b [#&!+channel|*|default] <settings>
    Allows you to change the channel settings (see $b'chaninfo'$b for the
    Allows you to change the channel settings (see $b'chaninfo'$b for the
@@ -654,8 +641,8 @@ See also: whois
 :hub:checkchannels
 :hub:checkchannels
 ###  $bcheckchannels$b
 ###  $bcheckchannels$b
    This will make all leaf bots display which channels they are currently
    This will make all leaf bots display which channels they are currently
-   not in but *should* be in.  This command will not show channels which
-   the bot is not active in due to '$bbotpart$b'.
+   not in but *should* be in.  This will only shows channels that contain
+   the groups the bot are in.
  
  
 See also: botcmd, channels, channel, status
 See also: botcmd, channels, channel, status
 :hub:chhandle
 :hub:chhandle
@@ -969,7 +956,7 @@ See also: cycle
    Example:
    Example:
       Down bots: cEvin, ruthie, Killa1
       Down bots: cEvin, ruthie, Killa1
  
  
-See also: bots
+See also: bots, groups
 :leaf:dump
 :leaf:dump
 ###  $bdump$b <text>
 ###  $bdump$b <text>
    dumps the text to the server.  keep in mind that this bot doesn't
    dumps the text to the server.  keep in mind that this bot doesn't
@@ -1066,6 +1053,11 @@ See also: -exempt, +exempt, console%{+m|m}, chanset, chaninfo%{-}, stick, unstic
    specified, your console channel is used.
    specified, your console channel is used.
  
  
 See also: console, channels%{+m}, status%{-}
 See also: console, channels%{+m}, status%{-}
+:hub:groups
+###  $bgroups$b
+   Shows the list of groups and which bots are in them.
+ 
+See also: bots, downbots%{+n}, bottree%{-}
 ::handle
 ::handle
 ###  $bhandle$b <new-handle>
 ###  $bhandle$b <new-handle>
    Changes your handle on the bot. This is the handle (nickname) that the
    Changes your handle on the bot. This is the handle (nickname) that the

+ 1 - 1
src/chan.h

@@ -270,7 +270,7 @@ struct chanset_t {
 #define CHAN_STOP_CYCLE     BIT9	/* Some efnetservers have defined NO_CHANOPS_WHEN_SPLIT */
 #define CHAN_STOP_CYCLE     BIT9	/* Some efnetservers have defined NO_CHANOPS_WHEN_SPLIT */
 
 
 /* prototypes */
 /* prototypes */
-memberlist *ismember(struct chanset_t *, const char *);
+memberlist *ismember(const struct chanset_t *, const char *);
 struct chanset_t *findchan(const char *name);
 struct chanset_t *findchan(const char *name);
 struct chanset_t *findchan_by_dname(const char *name);
 struct chanset_t *findchan_by_dname(const char *name);
 
 

+ 3 - 3
src/chanprog.c

@@ -95,7 +95,7 @@ void rmspace(char *s)
 
 
 /* Returns memberfields if the nick is in the member list.
 /* Returns memberfields if the nick is in the member list.
  */
  */
-memberlist *ismember(struct chanset_t *chan, const char *nick)
+memberlist *ismember(const struct chanset_t *chan, const char *nick)
 {
 {
   register memberlist	*x = NULL;
   register memberlist	*x = NULL;
 
 
@@ -743,7 +743,7 @@ int isowner(char *name)
   }
   }
 }
 }
 
 
-bool bot_shouldjoin(struct userrec* u, struct flag_record* fr, struct chanset_t* chan, bool ignore_inactive)
+bool bot_shouldjoin(struct userrec* u, struct flag_record* fr, const struct chanset_t* chan, bool ignore_inactive)
 {
 {
   // If restarting, keep this channel.
   // If restarting, keep this channel.
   if (restarting && (reset_chans == 2) && (channel_active(chan) || channel_pending(chan))) return 1;
   if (restarting && (reset_chans == 2) && (channel_active(chan) || channel_pending(chan))) return 1;
@@ -787,7 +787,7 @@ bool bot_shouldjoin(struct userrec* u, struct flag_record* fr, struct chanset_t*
       );
       );
 }
 }
 
 
-bool shouldjoin(struct chanset_t *chan)
+bool shouldjoin(const struct chanset_t *chan)
 {
 {
   struct flag_record fr = { FR_CHAN|FR_GLOBAL|FR_BOT, 0, 0, 0 };
   struct flag_record fr = { FR_CHAN|FR_GLOBAL|FR_BOT, 0, 0, 0 };
   get_user_flagrec(conf.bot->u, &fr, chan->dname, chan);
   get_user_flagrec(conf.bot->u, &fr, chan->dname, chan);

+ 2 - 2
src/chanprog.h

@@ -23,8 +23,8 @@ void rmspace(char *s);
 void set_chanlist(const char *host, struct userrec *rec);
 void set_chanlist(const char *host, struct userrec *rec);
 void clear_chanlist(void);
 void clear_chanlist(void);
 void clear_chanlist_member(const char *nick);
 void clear_chanlist_member(const char *nick);
-bool bot_shouldjoin(struct userrec* , struct flag_record *, struct chanset_t *, bool = 0);
-bool shouldjoin(struct chanset_t *);
+bool bot_shouldjoin(struct userrec* , struct flag_record *, const struct chanset_t *, bool = 0);
+bool shouldjoin(const struct chanset_t *);
 char *samechans(const char *, const char *);
 char *samechans(const char *, const char *);
 void add_myself_to_userlist();
 void add_myself_to_userlist();
 void add_child_bots();
 void add_child_bots();

+ 55 - 8
src/cmds.c

@@ -901,23 +901,69 @@ static void cmd_userlist(int idx, char *par)
   return;
   return;
 }
 }
 
 
+static void cmd_groups(int idx, char *par)
+{
+  struct userrec *u = NULL;
+
+  putlog(LOG_CMDS, "*", "#%s# groups", dcc[idx].nick);
+
+  bd::Array<bd::String> globalgroups = bd::String(var_get_gdata("groups")).split(",");
+  bd::Array<bd::String> allgroups;
+  bd::HashTable<bd::String, bd::Array<bd::String> > groupBots;
+  bd::HashTable<bd::String, bd::Array<bd::String> > botGroups;
+  size_t maxGroupLen = 0;
+
+  // Need to loop over every bot and make a list of all groups and bots which are in those groups
+  for (u = userlist; u; u = u->next) {
+    if (u->bot && bot_hublevel(u) == 999) {
+      // Gather all the groups for this bot
+      botGroups[u->handle] = bd::String(var_get_bot_data(u, "groups", true)).split(",");
+      for (size_t i = 0; i < botGroups[u->handle].length(); ++i) {
+        const bd::String group(botGroups[u->handle][i]);
+        if (group.length() > maxGroupLen) {
+          maxGroupLen = group.length();
+        }
+        // Add their groups into the master list
+        if (allgroups.find(group) == allgroups.npos) {
+          allgroups << group;
+        }
+        // Add them to the list for this group
+        groupBots[group] << u->handle;
+
+      }
+    }
+  }
+
+  // Display all groups and which bots are in them
+  for (size_t i = 0; i < allgroups.length(); ++i) {
+    const bd::String group(allgroups[i]);
+    const bd::Array<bd::String> bots(groupBots[group]);
+    dumplots(idx, bd::String::printf("%-*s: ", int(maxGroupLen), group.c_str()).c_str(), static_cast<bd::String>(bots.join(" ")).c_str());
+  }
+
+  dprintf(idx, "Total groups: %zu\n", allgroups.length());
+  return;
+}
+
 static void cmd_channels(int idx, char *par) {
 static void cmd_channels(int idx, char *par) {
   putlog(LOG_CMDS, "*", "#%s# channels %s", dcc[idx].nick, par);
   putlog(LOG_CMDS, "*", "#%s# channels %s", dcc[idx].nick, par);
   if (par[0] && (dcc[idx].user->flags & USER_MASTER)) {
   if (par[0] && (dcc[idx].user->flags & USER_MASTER)) {
-    struct userrec *user = NULL;
-
-    user = get_user_by_handle(userlist, par);
-    if (user && whois_access(dcc[idx].user, user)) {
+    if (par[0] == '%') {
       show_channels(idx, par);
       show_channels(idx, par);
-    } else  {
-      dprintf(idx, "No such user.\n");
+    } else {
+      struct userrec *user = get_user_by_handle(userlist, par);
+      if (user && whois_access(dcc[idx].user, user)) {
+        show_channels(idx, par);
+      } else  {
+        dprintf(idx, "No such user.\n");
+      }
     }
     }
   } else {
   } else {
       show_channels(idx, NULL);
       show_channels(idx, NULL);
   }
   }
 
 
   if ((dcc[idx].user->flags & USER_MASTER) && !(par && par[0]))
   if ((dcc[idx].user->flags & USER_MASTER) && !(par && par[0]))
-    dprintf(idx, "You can also %schannels <user>\n", (dcc[idx].u.chat->channel >= 0) ? settings.dcc_prefix : "");
+    dprintf(idx, "You can also %schannels <user|%%group>\n", (dcc[idx].u.chat->channel >= 0) ? settings.dcc_prefix : "");
 }
 }
 
 
 
 
@@ -1389,7 +1435,7 @@ static void cmd_botcmd(int idx, char *par)
       continue;
       continue;
     cnt++;
     cnt++;
     bool group_match = false;
     bool group_match = false;
-    if (botm[0] == '%') {
+    if (botm[0] == '%' && bot_hublevel(botu) == 999) {
       bd::String botgroups = var_get_bot_data(botu, "groups", true);
       bd::String botgroups = var_get_bot_data(botu, "groups", true);
       if (botgroups.split(',').find(botm + 1) != bd::String::npos) {
       if (botgroups.split(',').find(botm + 1) != bd::String::npos) {
         group_match = true;
         group_match = true;
@@ -4729,6 +4775,7 @@ cmd_t C_dcc[] =
   {"version", 		"o", 	(Function) cmd_version, 	NULL, 0},
   {"version", 		"o", 	(Function) cmd_version, 	NULL, 0},
   {"netversion", 	"o", 	(Function) cmd_netversion, 	NULL, HUB},
   {"netversion", 	"o", 	(Function) cmd_netversion, 	NULL, HUB},
   {"userlist", 		"m", 	(Function) cmd_userlist, 	NULL, 0},
   {"userlist", 		"m", 	(Function) cmd_userlist, 	NULL, 0},
+  {"groups", 		"m", 	(Function) cmd_groups, 		NULL, HUB},
   {"ps", 		"n", 	(Function) cmd_ps, 		NULL, 0},
   {"ps", 		"n", 	(Function) cmd_ps, 		NULL, 0},
   {"last", 		"n", 	(Function) cmd_last, 		NULL, 0},
   {"last", 		"n", 	(Function) cmd_last, 		NULL, 0},
   {"exec", 		"a", 	(Function) cmd_exec, 		NULL, 0},
   {"exec", 		"a", 	(Function) cmd_exec, 		NULL, 0},

+ 1 - 1
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>
 /* Always pass the dname (display name) to this function for chname <cybah>
  */
  */
 void
 void
-get_user_flagrec(struct userrec *u, struct flag_record *fr, const char *chname, struct chanset_t* chan)
+get_user_flagrec(struct userrec *u, struct flag_record *fr, const char *chname, const struct chanset_t* chan)
 {
 {
   fr->bot = 0;
   fr->bot = 0;
   if (!u) {
   if (!u) {

+ 1 - 1
src/flags.h

@@ -142,7 +142,7 @@ struct flag_record {
 #define chan_doflood(x)				((x).chan & BOT_FLOODBOT)
 #define chan_doflood(x)				((x).chan & BOT_FLOODBOT)
 
 
 void init_flags(void);
 void init_flags(void);
-void get_user_flagrec(struct userrec *, struct flag_record *, const char *, struct chanset_t* = NULL);
+void get_user_flagrec(struct userrec *, struct flag_record *, const char *, const struct chanset_t* = NULL);
 void set_user_flagrec(struct userrec *, struct flag_record *, const char *);
 void set_user_flagrec(struct userrec *, struct flag_record *, const char *);
 void break_down_flags(const char *, struct flag_record *, struct flag_record *);
 void break_down_flags(const char *, struct flag_record *, struct flag_record *);
 int build_flags(char *, struct flag_record *, struct flag_record *);
 int build_flags(char *, struct flag_record *, struct flag_record *);

+ 44 - 27
src/misc.c

@@ -431,45 +431,62 @@ void show_motd(int idx)
 
 
 void show_channels(int idx, char *handle)
 void show_channels(int idx, char *handle)
 {
 {
-  struct chanset_t *chan = NULL;
-  struct flag_record fr = { FR_CHAN | FR_GLOBAL, 0, 0, 0 };
   struct userrec *u = NULL;
   struct userrec *u = NULL;
-  int first = 0, total = 0;
-  size_t l = 0;
-  char format[120] = "";
+  size_t maxChannelLength = 0;
+  bd::Array<bd::String> channelNames;
+  bd::HashTable<bd::String, struct chanset_t*> channels;
+  bd::String group;
 
 
-  if (handle)
+  if (handle && handle[0] != '%') {
     u = get_user_by_handle(userlist, handle);
     u = get_user_by_handle(userlist, handle);
-  else
+  } else {
     u = dcc[idx].user;
     u = dcc[idx].user;
+    if (handle && handle[0] == '%') {
+      group = handle + 1;
+    }
+  }
 
 
-  for (chan = chanset;chan ;chan = chan->next) {
+  for (struct chanset_t* chan = chanset; chan; chan = chan->next) {
+    struct flag_record fr = { FR_CHAN | FR_GLOBAL, 0, 0, 0 };
+    const bd::String chname(chan->dname);
+    // If a group was passed, ensure it matches
+    if (group.length() && chan->groups->find(group) == chan->groups->npos) {
+      continue;
+    }
     get_user_flagrec(u, &fr, chan->dname);
     get_user_flagrec(u, &fr, chan->dname);
-    if (l < strlen(chan->dname)) {
-      l = strlen(chan->dname);
+    if (group.length() || real_chk_op(fr, chan, 0)) {
+      if (maxChannelLength < chname.length()) {
+        maxChannelLength = chname.length();
+      }
+      channelNames << chname;
+      channels[chname] = chan;
     }
     }
-    if (real_chk_op(fr, chan, 0))
-      total++;
   }
   }
 
 
-  simple_snprintf(format, sizeof(format), "  %%c%%-%zus %%-s%%-s%%-s%%-s%%-s%%-s\n", (l+2));
+  if (channelNames.length()) {
+    char format[120] = "";
+    simple_snprintf(format, sizeof(format), "  %%c%%-%zus %%-s%%-s%%-s%%-s%%-s%%-s\n", (maxChannelLength+2));
+    if (group.length()) {
+      dprintf(idx, "group '%s' is in %zu channel%s:\n", group.c_str(), channelNames.length(), (channelNames.length() > 1) ? "s" : "");
+    } else {
+      dprintf(idx, "%s %s access to %zu channel%s:\n", handle ? u->handle : "You", handle ? "has" : "have", channelNames.length(), (channelNames.length() > 1) ? "s" : "");
+    }
 
 
-  for (chan = chanset;chan;chan = chan->next) {
-    get_user_flagrec(u, &fr, chan->dname);
-    if (real_chk_op(fr, chan, 0)) {
-        if (!first) { 
-          dprintf(idx, "%s %s access to %d channel%s:\n", handle ? u->handle : "You", handle ? "has" : "have", total, (total > 1) ? "s" : "");
-          
-          first = 1;
-        }
-        dprintf(idx, format, !conf.bot->hub && me_op(chan) ? '@' : ' ', chan->dname, !shouldjoin(chan) ? "(inactive) " : "", 
-           channel_privchan(chan) ? "(private)  " : "", chan->manop ? "(no manop) " : "", 
-           channel_bitch(chan) && !channel_botbitch(chan) ? "(bitch)    " : channel_botbitch(chan) ? "(botbitch) " : "",
-           channel_closed(chan) ?  "(closed) " : "", channel_backup(chan) ? "(backup)" : "");
+    for (size_t i = 0; i < channelNames.length(); ++i) {
+      const bd::String chname(channelNames[i]);
+      const struct chanset_t* chan = channels[chname];
+      dprintf(idx, format, !conf.bot->hub && me_op(chan) ? '@' : ' ', chan->dname, ((conf.bot->hub && channel_inactive(chan)) || (!conf.bot->hub && !shouldjoin(chan))) ? "(inactive) " : "",
+          channel_privchan(chan) ? "(private)  " : "", chan->manop ? "(no manop) " : "", 
+          channel_bitch(chan) && !channel_botbitch(chan) ? "(bitch)    " : channel_botbitch(chan) ? "(botbitch) " : "",
+          channel_closed(chan) ?  "(closed) " : "", channel_backup(chan) ? "(backup)" : "");
+    }
+  } else {
+    if (group.length()) {
+      dprintf(idx, "No channels found for group '%s'\n", group.c_str());
+    } else {
+      dprintf(idx, "%s %s not have access to any channels.\n", handle ? u->handle : "You", handle ? "does" : "do");
     }
     }
   }
   }
-  if (!first)
-    dprintf(idx, "%s %s not have access to any channels.\n", handle ? u->handle : "You", handle ? "does" : "do");
 }
 }
 
 
 /* Create a string with random letters and digits
 /* Create a string with random letters and digits

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

@@ -1008,29 +1008,6 @@ static void cmd_pls_chan(int idx, char *par)
   pls_chan(idx, par, NULL);
   pls_chan(idx, par, NULL);
 }
 }
 
 
-static void cmd_botjoin(int idx, char *par)
-{
-  char *bot = NULL;
-  struct userrec *botu = NULL;
-
-  putlog(LOG_CMDS, "*", "#%s# botjoin %s", dcc[idx].nick, par);
-
-  if (!par[0]) {
-    dprintf(idx, "Usage: botjoin <bot> [%s]<channel> [options]\n", CHANMETA);
-    return;
-  }
-  bot = newsplit(&par);
-  botu = get_user_by_handle(userlist, bot);
-  if (botu && botu->bot) {
-    pls_chan(idx, par, bot);
-  } else {
-    dprintf(idx, "Error: '%s' is not a bot.\n", bot);
-  }
-
-  dprintf(idx, "!!!! Warning: botjoin is an unfinished feature which will pretty much make all bots join the channel.\n");
-  dprintf(idx, "!!!! Warning: You should probably -chan the channel now to avoid problems/confusion later.\n");
-}
-
 static void mns_chan(int idx, char *par, char *bot)
 static void mns_chan(int idx, char *par, char *bot)
 {
 {
   char *chname = NULL, buf2[1024] = "";
   char *chname = NULL, buf2[1024] = "";
@@ -1084,27 +1061,6 @@ static void cmd_mns_chan(int idx, char *par)
   mns_chan(idx, par, NULL);
   mns_chan(idx, par, NULL);
 }
 }
 
 
-static void cmd_botpart(int idx, char *par)
-{
-  char *bot = NULL;
-  struct userrec *botu = NULL;
-
-  putlog(LOG_CMDS, "*", "#%s# botpart %s", dcc[idx].nick, par);
-  
-  if (!par[0]) {
-    dprintf(idx, "Usage: botpart <bot> [%s]<channel> [options]\n", CHANMETA);
-    return;
-  }
-
-  bot = newsplit(&par);
-  botu = get_user_by_handle(userlist, bot);
-  if (botu && botu->bot) {
-    mns_chan(idx, par, bot);
-  } else {
-    dprintf(idx, "Error: '%s' is not a bot.\n", bot);
-  }
-}
-
 /* thanks Excelsior */
 /* thanks Excelsior */
 #define FLAG_COLS 4
 #define FLAG_COLS 4
 static void show_flag(int idx, char *work, int *cnt, const char *name, unsigned int state, size_t worksiz)
 static void show_flag(int idx, char *work, int *cnt, const char *name, unsigned int state, size_t worksiz)
@@ -1420,8 +1376,6 @@ static cmd_t C_dcc_channels[] =
   {"-exempt",	"o|o",	(Function) cmd_mns_exempt,	NULL, AUTH},
   {"-exempt",	"o|o",	(Function) cmd_mns_exempt,	NULL, AUTH},
   {"-invite",	"o|o",	(Function) cmd_mns_invite,	NULL, AUTH},
   {"-invite",	"o|o",	(Function) cmd_mns_invite,	NULL, AUTH},
   {"bans",	"o|o",	(Function) cmd_bans,		NULL, 0},
   {"bans",	"o|o",	(Function) cmd_bans,		NULL, 0},
-  {"botjoin",	"n",	(Function) cmd_botjoin,		NULL, 0},
-  {"botpart",	"n",	(Function) cmd_botpart,		NULL, 0},
   {"exempts",	"o|o",	(Function) cmd_exempts,		NULL, 0},
   {"exempts",	"o|o",	(Function) cmd_exempts,		NULL, 0},
   {"invites",	"o|o",	(Function) cmd_invites,		NULL, 0},
   {"invites",	"o|o",	(Function) cmd_invites,		NULL, 0},
   {"chaninfo",	"m|m",	(Function) cmd_chaninfo,	NULL, 0},
   {"chaninfo",	"m|m",	(Function) cmd_chaninfo,	NULL, 0},

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

@@ -1279,7 +1279,7 @@ killmember(struct chanset_t *chan, char *nick)
 /* Check if I am a chanop. Returns boolean 1 or 0.
 /* Check if I am a chanop. Returns boolean 1 or 0.
  */
  */
 bool
 bool
-me_op(struct chanset_t *chan)
+me_op(const struct chanset_t *chan)
 {
 {
   memberlist *mx = ismember(chan, botname);
   memberlist *mx = ismember(chan, botname);
 
 
@@ -1294,7 +1294,7 @@ me_op(struct chanset_t *chan)
 /* Check whether I'm voice. Returns boolean 1 or 0.
 /* Check whether I'm voice. Returns boolean 1 or 0.
  */
  */
 bool
 bool
-me_voice(struct chanset_t *chan)
+me_voice(const struct chanset_t *chan)
 {
 {
   memberlist *mx = ismember(chan, botname);
   memberlist *mx = ismember(chan, botname);
 
 

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

@@ -117,8 +117,8 @@ void notice_invite(struct chanset_t *, char *, char *, char *, bool);
 void real_add_mode(struct chanset_t *, const char, const char, const 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_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)
 #define add_cookie(chan, nick) real_add_mode(chan, '+', 'o', nick, 1)
-bool me_op(struct chanset_t *);
-bool me_voice(struct chanset_t *);
+bool me_op(const struct chanset_t *);
+bool me_voice(const struct chanset_t *);
 
 
 void check_this_ban(struct chanset_t *, char *, bool);
 void check_this_ban(struct chanset_t *, char *, bool);
 void check_this_exempt(struct chanset_t *, char *, bool);
 void check_this_exempt(struct chanset_t *, char *, bool);

+ 7 - 2
src/set.c

@@ -525,6 +525,11 @@ static inline variable_t *var_get_var_by_name(const char *name)
   return (variable_t*) bsearch(&key, &vars, lengthof(vars) - 1, sizeof(variable_t), comp_variable_t);
   return (variable_t*) bsearch(&key, &vars, lengthof(vars) - 1, sizeof(variable_t), comp_variable_t);
 }
 }
 
 
+const char *var_get_gdata(const char *name) {
+  variable_t* var = var_get_var_by_name(name);
+  return var && var->gdata ? var->gdata : NULL;
+}
+
 void var_set(variable_t *var, const char *target, const char *datain)
 void var_set(variable_t *var, const char *target, const char *datain)
 {
 {
   /* Don't set locally if the variable doesn't permit it. */
   /* Don't set locally if the variable doesn't permit it. */
@@ -715,7 +720,7 @@ const char *var_get_bot_data(struct userrec *u, const char *name, bool useDefaul
   }
   }
   if (useDefault) {
   if (useDefault) {
     variable_t *var = var_get_var_by_name(name);
     variable_t *var = var_get_var_by_name(name);
-    return var->def;
+    return var->gdata ? var->gdata : var->def;
   }
   }
   return NULL;
   return NULL;
 }
 }
@@ -816,7 +821,7 @@ static int var_add_list(const char *botnick, variable_t *var, const char *elemen
   char *data = NULL, *olddata = NULL, *botdata = NULL;
   char *data = NULL, *olddata = NULL, *botdata = NULL;
 
 
   if (botnick) {                          //fetch data from bot's USERENTRY_SET
   if (botnick) {                          //fetch data from bot's USERENTRY_SET
-    botdata = (char *) var_get_bot_data(get_user_by_handle(userlist, (char *) botnick), var->name);
+    botdata = (char *) var_get_bot_data(get_user_by_handle(userlist, (char *) botnick), var->name, true);
     olddata = botdata ? botdata : NULL;
     olddata = botdata ? botdata : NULL;
   } else                                  //use global, no bot specified
   } else                                  //use global, no bot specified
     olddata = var->gdata ? var->gdata : NULL;
     olddata = var->gdata ? var->gdata : NULL;

+ 1 - 0
src/set.h

@@ -87,6 +87,7 @@ void init_vars();
 void var_set_by_name(const char *, const char *, const char *);
 void var_set_by_name(const char *, const char *, const char *);
 void var_set_userentry(const char *, const char *, const char *);
 void var_set_userentry(const char *, const char *, const char *);
 const char *var_get_bot_data(struct userrec *u, const char *name, bool useDefault = false);
 const char *var_get_bot_data(struct userrec *u, const char *name, bool useDefault = false);
+const char *var_get_gdata(const char *name);
 int cmd_set_real(const char *, int idx, char *);
 int cmd_set_real(const char *, int idx, char *);
 const char *var_get_str_by_name(const char *);
 const char *var_get_str_by_name(const char *);