added support for independent "zero-bots" (bots without an own source file)
[NeonServV5.git] / src / modcmd.c
index 420567f825e7beda92b548c3c83e0c2ff8b14181..50f71c86c138c4fea960643a6c3e8ef2908eeb03 100644 (file)
@@ -80,10 +80,10 @@ static int get_binds_index(char first_char) {
     return 26;
 }
 
-struct ClientSocket* get_prefered_bot(int botid) {
+struct ClientSocket* get_botwise_prefered_bot(int botid, int clientid) {
     struct ClientSocket *client, *lowbot = NULL;
     for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
-        if(client->botid == botid) {
+        if(client->botid == botid && (botid || clientid == client->clientid)) {
             if((client->flags & SOCKET_FLAG_PREFERRED))
                 return client;
             else
@@ -93,10 +93,10 @@ struct ClientSocket* get_prefered_bot(int botid) {
     return lowbot;
 }
 
-static char* get_channel_trigger(int botid, struct ChanNode *chan) {
+static char* get_channel_trigger(int botid, int clientid, struct ChanNode *chan) {
     struct trigger_cache *trigger;
     for(trigger = chan->trigger; trigger; trigger = trigger->next) {
-        if(trigger->botid == botid)
+        if(trigger->botid == botid && (botid || trigger->clientid == clientid))
             return trigger->trigger;
     }
     struct trigger_callback *cb;
@@ -106,15 +106,16 @@ static char* get_channel_trigger(int botid, struct ChanNode *chan) {
     }
     char triggerStr[TRIGGERLEN];
     if(cb)
-        cb->func(chan, triggerStr);
+        cb->func(clientid, chan, triggerStr);
     else
-        strcpy(triggerStr, "+");
+        triggerStr[0] = '\0';
     trigger = malloc(sizeof(*trigger));
     if (!trigger) {
         perror("malloc() failed");
         return 0;
     }
     trigger->botid = botid;
+    trigger->clientid = clientid;
     trigger->trigger = (triggerStr[0] ? strdup(triggerStr) : NULL);
     trigger->next = chan->trigger;
     chan->trigger = trigger;
@@ -161,7 +162,7 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s
     }
     struct cmd_binding *cbind;
     for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
-        if(cbind->botid == client->botid && stricmp(cbind->cmd, message) == 0) {
+        if(cbind->botid == client->botid && (cbind->botid || cbind->clientid == client->clientid) && stricmp(cbind->cmd, message) == 0) {
             if(cbind->func->func == modcmd_linker) {
                 //links subcommands
                 char command[MAXLEN];
@@ -175,7 +176,7 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s
                     }
                     sprintf(command, "%s %s", parent_bind->cmd, subcmd);
                     for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
-                        if(cbind->botid == client->botid && stricmp(cbind->cmd, command) == 0)
+                        if(cbind->botid == client->botid && (cbind->botid || cbind->clientid == client->clientid) && stricmp(cbind->cmd, command) == 0)
                             break;
                     }
                     if(!cbind)
@@ -186,7 +187,7 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s
                     char subcommands[MAXLEN];
                     int subcompos = 0;
                     for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
-                        if(cbind->botid == client->botid && stricmplen(cbind->cmd, command, commandlen) == 0) {
+                        if(cbind->botid == client->botid && (cbind->botid || cbind->clientid == client->clientid) && stricmplen(cbind->cmd, command, commandlen) == 0) {
                             subcompos += sprintf(subcommands + subcompos, (subcompos ? ", %s" : "%s"), cbind->cmd + commandlen);
                         }
                     }
@@ -204,7 +205,7 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s
                 chan = sent_chan;
             }
             //get a text bot
-            tmp_text_client = get_prefered_bot(client->botid);
+            tmp_text_client = get_botwise_prefered_bot(client->botid, (client->botid == 0 ? client->clientid : 0));
             //parse the arguments...
             char *arga[MAXNUMPARAMS];
             char **argv;
@@ -511,23 +512,26 @@ static void handle_command_async(struct ClientSocket *client, struct UserNode *u
 }
 
 static void got_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) {
-    fd_set fds;
+    fd_set fds, fds2;
     char *trigger;
     struct ClientSocket *client;
     FD_ZERO(&fds);
+    FD_ZERO(&fds2);
     for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
-        if(isUserOnChan(client->user, chan) && (client->flags & SOCKET_FLAG_PREFERRED) && !FD_ISSET(client->botid, &fds)) {
-            FD_SET(client->botid, &fds);
-            trigger = get_channel_trigger(client->botid, chan);
+        if(isUserOnChan(client->user, chan) && (client->flags & SOCKET_FLAG_PREFERRED) && ((client->botid == 0 && !FD_ISSET(client->clientid, &fds)) || (client->botid && !FD_ISSET(client->botid, &fds2))))  {
+            FD_SET(client->clientid, &fds);
+            FD_SET(client->botid, &fds2);
+            trigger = get_channel_trigger(client->botid, client->clientid, chan);
             if(trigger && stricmplen(message, trigger, strlen(trigger)) == 0) {
                 handle_command(client, user, chan, message + strlen(trigger));
             }
         }
     }
     for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
-        if(isUserOnChan(client->user, chan) && !FD_ISSET(client->botid, &fds)) {
+        if(isUserOnChan(client->user, chan) && ((client->botid == 0 && !FD_ISSET(client->clientid, &fds)) || (client->botid && !FD_ISSET(client->botid, &fds2)))) {
             FD_SET(client->botid, &fds);
-            trigger = get_channel_trigger(client->botid, chan);
+            FD_SET(client->botid, &fds2);
+            trigger = get_channel_trigger(client->botid, client->clientid, chan);
             if(trigger && stricmplen(message, trigger, strlen(trigger)) == 0) {
                 handle_command(client, user, chan, message + strlen(trigger));
             }
@@ -587,10 +591,10 @@ int set_trigger_callback(int botid, trigger_callback_t *func) {
     return 1;
 }
 
-int changeChannelTrigger(int botid, struct ChanNode *chan, char *new_trigger) {
+int changeBotwiseChannelTrigger(int botid, int clientid, struct ChanNode *chan, char *new_trigger) {
     struct trigger_cache *trigger;
     for(trigger = chan->trigger; trigger; trigger = trigger->next) {
-        if(trigger->botid == botid) {
+        if(trigger->botid == botid && (botid || trigger->clientid == clientid)) {
             free(trigger->trigger);
             trigger->trigger = strdup(new_trigger);
             return 1;
@@ -599,11 +603,11 @@ int changeChannelTrigger(int botid, struct ChanNode *chan, char *new_trigger) {
     return 0;
 }
 
-int bind_cmd_to_function(int botid, char *cmd, struct cmd_function *func) {
+int bind_botwise_cmd_to_function(int botid, int clientid, char *cmd, struct cmd_function *func) {
     int bind_index = get_binds_index(cmd[0]);
     struct cmd_binding *cbind;
     for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
-        if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0)
+        if(((botid && cbind->botid == botid) || (botid == 0 && clientid == cbind->clientid)) && strcmp(cbind->cmd, cmd) == 0)
             return 0;
     }
     cbind = malloc(sizeof(*cbind));
@@ -612,6 +616,7 @@ int bind_cmd_to_function(int botid, char *cmd, struct cmd_function *func) {
         return 0;
     }
     cbind->botid = botid;
+    cbind->clientid = clientid;
     cbind->cmd = strdup(cmd);
     cbind->func = func;
     cbind->paramcount = 0;
@@ -624,7 +629,7 @@ int bind_cmd_to_function(int botid, char *cmd, struct cmd_function *func) {
     return 1;
 }
 
-int bind_cmd_to_command(int botid, char *cmd, char *func) {
+int bind_botwise_cmd_to_command(int botid, int clientid, char *cmd, char *func) {
     struct cmd_function *cmdfunc;
     int fbotid = botid;
     char *c;
@@ -648,7 +653,7 @@ int bind_cmd_to_command(int botid, char *cmd, char *func) {
     int bind_index = get_binds_index(cmd[0]);
     struct cmd_binding *cbind;
     for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
-        if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0)
+        if(((botid && cbind->botid == botid) || (botid == 0 && clientid == cbind->clientid)) && strcmp(cbind->cmd, cmd) == 0)
             return 0;
     }
     cbind = malloc(sizeof(*cbind));
@@ -657,6 +662,7 @@ int bind_cmd_to_command(int botid, char *cmd, char *func) {
         return 0;
     }
     cbind->botid = botid;
+    cbind->clientid = clientid;
     cbind->cmd = strdup(cmd);
     cbind->func = cmdfunc;
     cbind->next = cmd_binds[bind_index];
@@ -669,11 +675,11 @@ int bind_cmd_to_command(int botid, char *cmd, char *func) {
     return 1;
 }
 
-int unbind_cmd(int botid, char *cmd) {
+int unbind_botwise_cmd(int botid, int clientid, char *cmd) {
     int bind_index = get_binds_index(cmd[0]);
     struct cmd_binding *cbind, *last = NULL;
     for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
-        if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
+        if(cbind->botid == botid && (botid || clientid == cbind->clientid) && strcmp(cbind->cmd, cmd) == 0) {
             if(last)
                 last->next = cbind->next;
             else
@@ -766,11 +772,11 @@ void free_modcmd() {
     bot_aliases = NULL;
 }
 
-void bind_set_parameters(int botid, char *cmd, char *parameters) {
+void bind_botwise_set_parameters(int botid, int clientid, char *cmd, char *parameters) {
     int bind_index = get_binds_index(cmd[0]);
     struct cmd_binding *cbind;
     for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
-        if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
+        if(cbind->botid == botid && (botid || clientid == cbind->clientid) && strcmp(cbind->cmd, cmd) == 0) {
             if(cbind->paramcount) {
                 int i;
                 for(i = 0; i < cbind->paramcount; i++)
@@ -789,11 +795,11 @@ void bind_set_parameters(int botid, char *cmd, char *parameters) {
     }
 }
 
-void bind_set_global_access(int botid, char *cmd, int gaccess) {
+void bind_botwise_set_global_access(int botid, int clientid, char *cmd, int gaccess) {
     int bind_index = get_binds_index(cmd[0]);
     struct cmd_binding *cbind;
     for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
-        if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
+        if(cbind->botid == botid && (botid || clientid == cbind->clientid) && strcmp(cbind->cmd, cmd) == 0) {
             if(gaccess > -1) {
                 cbind->global_access = gaccess;
                 cbind->flags |= CMDFLAG_OVERRIDE_GLOBAL_ACCESS;
@@ -805,11 +811,11 @@ void bind_set_global_access(int botid, char *cmd, int gaccess) {
     }
 }
 
-void bind_set_channel_access(int botid, char *cmd, char *chanaccess) {
+void bind_botwise_set_channel_access(int botid, int clientid, char *cmd, char *chanaccess) {
     int bind_index = get_binds_index(cmd[0]);
     struct cmd_binding *cbind;
     for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
-        if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
+        if(cbind->botid == botid && (botid || clientid == cbind->clientid) && strcmp(cbind->cmd, cmd) == 0) {
             if(cbind->channel_access)
                 free(cbind->channel_access);
             if(chanaccess) {
@@ -824,18 +830,18 @@ void bind_set_channel_access(int botid, char *cmd, char *chanaccess) {
     }
 }
 
-struct cmd_binding *find_cmd_binding(int botid, char *cmd) {
+struct cmd_binding *find_botwise_cmd_binding(int botid, int clientid, char *cmd) {
     int bind_index = get_binds_index(cmd[0]);
     struct cmd_binding *cbind;
     for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
-        if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
+        if(cbind->botid == botid && (botid || clientid == cbind->clientid) && strcmp(cbind->cmd, cmd) == 0) {
             return cbind;
         }
     }
     return NULL;
 }
 
-void bind_unbound_required_functions(int botid) {
+void bind_botwise_unbound_required_functions(int botid, int clientid) {
     struct cmd_function *cmdfunc;
     int i, found;
     struct cmd_binding *cbind;
@@ -844,7 +850,7 @@ void bind_unbound_required_functions(int botid) {
             found = 0;
             for(i = 0; i < 27; i++) {
                 for(cbind = cmd_binds[i]; cbind; cbind = cbind->next) {
-                    if(cbind->botid == botid && cbind->func == cmdfunc) {
+                    if(cbind->botid == botid && (botid || clientid == cbind->clientid) && cbind->func == cmdfunc) {
                         found = 1;
                         break;
                     }
@@ -852,8 +858,8 @@ void bind_unbound_required_functions(int botid) {
                 if(found)
                     break;
             }
-            if(!found && bind_cmd_to_function(botid, cmdfunc->name, cmdfunc)) {
-                cbind = find_cmd_binding(botid, cmdfunc->name);
+            if(!found && bind_botwise_cmd_to_function(botid, clientid, cmdfunc->name, cmdfunc)) {
+                cbind = find_botwise_cmd_binding(botid, clientid, cmdfunc->name);
                 cbind->flags |= CMDFLAG_TEMPONARY_BIND;
             }
         }