wrote modcmd bind system
authorpk910 <philipp@zoelle1.de>
Fri, 12 Aug 2011 22:33:51 +0000 (00:33 +0200)
committerpk910 <philipp@zoelle1.de>
Fri, 12 Aug 2011 22:33:51 +0000 (00:33 +0200)
ChanNode.c
ChanNode.h
ClientSocket.c
ClientSocket.h
main.c
main.h
modcmd.c
modcmd.h

index 7d2c9a54315cecf11afa56083a665ff3184c735b..5f769761d519695362fe365d30401cb146bb7f71 100644 (file)
@@ -1,6 +1,7 @@
 #include "ChanNode.h"
 #include "ChanUser.h"
 #include "UserNode.h"
+#include "modcmd.h"
 
 static struct ChanNode **chanList;
 static int modes_with_strarg, modes_with_intarg;
@@ -184,6 +185,14 @@ void freeChanNode(struct ChanNode* chan) {
         if(chan->mode_str_args[i])
             free(chan->mode_str_args[i]);
     }
+    if(chan->trigger) {
+        struct trigger_cache *trigger, *next_trigger;
+        for(trigger = chan->trigger; trigger; trigger = next_trigger) {
+            next_trigger = trigger;
+            free(trigger->trigger);
+            free(trigger);
+        }
+    }
     free(chan->mode_str_args);
     free(chan->mode_int_args);
     free(chan);
index dbb70c8bdbe5a13e8f6324207f0d39543c93a315..ea949fdf4b4c39e8308d68a09c07f6b75ab2781e 100644 (file)
@@ -3,6 +3,7 @@
 #include "main.h"
 
 struct ChanUser;
+struct trigger_cache;
 
 #define CHANFLAG_RECEIVED_USERLIST  0x01
 
@@ -15,6 +16,8 @@ struct ChanNode {
     char **mode_str_args;
     int *mode_int_args;
     struct UserNode *chanbot;
+    
+    struct trigger_cache *trigger;
        
     struct ChanNode *next;
 };
index c5e3877139b73993d61f8e66c20d32cf8b897394..0192b084fb97904eba1ce1462f5fe21ba97b3464 100644 (file)
@@ -37,6 +37,8 @@ struct ClientSocket* create_socket(char *host, int port, char *pass, struct User
     client->user = user;
     client->flags = 0;
     client->bufferpos = 0;
+       client->botid = 0;
+    client->trigger = NULL;
     client->next = sockets->data;
     sockets->data = client;
     return client;
index 69d305779f2e811184258d801a5ad7435e0a884e..d15be26e866d94151cd342464d94125fd8b97c5e 100644 (file)
@@ -6,11 +6,12 @@
 #define SOCKET_FLAG_DEAD      0x01
 #define SOCKET_FLAG_CONNECTED 0x02
 #define SOCKET_FLAG_READY     0x04
-#define SOCKET_FLAG_NOWHO     0x08
+#define SOCKET_FLAG_PREFERED  0x08 /* prefered bot to send datas to the IRC World (NOTICE's WHO's etc pp) */
 
 #define BUF_SIZ 512
 
 struct UserNode;
+struct trigger_cache;
 
 struct ClientSocket {
     int sock;
@@ -21,6 +22,8 @@ struct ClientSocket {
     int port;
     char *pass;
     struct UserNode *user;
+       
+       int botid;
     
     struct ClientSocket *next;
 };
diff --git a/main.c b/main.c
index 1b0ba1c42a92e0c34f380e65e1f4aba0ba2b1db6..564e7b0cfa34db3f328ef80cdd13028c93792250 100644 (file)
--- a/main.c
+++ b/main.c
@@ -58,3 +58,19 @@ int stricmp (const char *s1, const char *s2)
    return c1 - c2;
 }
 
+int stricmplen (const char *s1, const char *s2, int len)
+{
+   if (s1 == NULL) return s2 == NULL ? 0 : -(*s2);
+   if (s2 == NULL) return *s1;
+   char c1, c2;
+   int i = 0;
+   while ((c1 = tolower (*s1)) == (c2 = tolower (*s2)))
+   {
+     i++;
+     if (*s1 == '\0') break;
+     ++s1; ++s2;
+     if(i == len) break;
+   }
+   return c1 - c2;
+}
+
diff --git a/main.h b/main.h
index c25d743239b8fece8b37a3c1b9fac8914aa243bb..0af72895852f6fba0af2ed39264552b133329b2b 100644 (file)
--- a/main.h
+++ b/main.h
@@ -39,6 +39,7 @@
 #define TOPICLEN        500
 #define CHANNELLEN      200
 #define MAXLEN          512
+#define TRIGGERLEN      50
 
 //valid nick chars
 #define VALID_NICK_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890{|}~[\\]^_`"
@@ -51,5 +52,6 @@
 #define TEMPUSER_LIST_INDEX VALID_NICK_CHARS_FIRST_LEN
 
 int stricmp (const char *s1, const char *s2);
+int stricmplen (const char *s1, const char *s2, int len);
 
 #endif
\ No newline at end of file
index 839e815e9ec6277f3f6a849efefd803897120f88..180c9689ccf4bf523ae26b7f69d114d78626c0b6 100644 (file)
--- a/modcmd.c
+++ b/modcmd.c
@@ -6,8 +6,62 @@
 #include "ChanNode.h"
 #include "ChanUser.h"
 
-static void got_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) {
-       struct ClientSocket *client = getBots(SOCKET_FLAG_READY, NULL);
+struct trigger_callback {
+    int botid;
+    trigger_callback_t *func;
+    
+    struct trigger_callback *next;
+}
+
+static struct cmd_binding **cmd_binds;
+static struct cmd_function *cmd_functions = NULL;
+static struct trigger_callback *trigger_callbacks = NULL;
+
+static int get_binds_index(char first_char) {
+    if(tolower(first_char) >= 'a' && tolower(first_char) <= 'z') {
+        return tolower(first_char - 'a');
+    }
+    return 26;
+}
+
+struct* ClientSocket get_prefered_bot(int botid) {
+    struct ClientSocket *client, *source = NULL;
+    for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
+        if(client->botid == botid && (client->flags & SOCKET_FLAG_PREFERED))
+            return client;
+    }
+    return NULL;
+}
+
+static char* get_channel_trigger(int botid, struct ChanNode *chan) {
+    struct trigger_cache *trigger;
+    for(trigger = chan->trigger; trigger; trigger = trigger->next) {
+        if(trigger->botid == botid)
+            return trigger->trigger;
+    }
+    struct trigger_callback *cb;
+    for(cb = trigger_callbacks; cb; cb = cb->next) {
+        if(cb->botid == botid)
+            break;
+    }
+    char triggerStr[TRIGGERLEN];
+    if(cb)
+        cb->func(chan, triggerStr);
+    else
+        strcpy(triggerStr, "+");
+    trigger = malloc(sizeof(*trigger));
+    if (!trigger) {
+        perror("malloc() failed");
+        return 0;
+    }
+    trigger->botid = botid;
+    trigger->trigger = strdup(triggerStr);
+    trigger->next = chan->trigger;
+    chan->trigger = trigger;
+    return trigger->trigger;
+}
+
+static void handle_command(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message) {
     if(!strcmp(message, "users")) {
         struct ChanUser *chanuser;
         putsock(client, "PRIVMSG %s :[BOT JOIN] Users on this Channel:", chan->name);
@@ -22,12 +76,158 @@ static void got_chanmsg(struct UserNode *user, struct ChanNode *chan, char *mess
     }
 }
 
+static void got_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) {
+    fd_set fds;
+    char *trigger;
+    struct ClientSocket *client;
+    FD_ZERO(&fds);
+    for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
+        if(isUserOnChan(client->user, chan) && (client->flags & SOCKET_FLAG_PREFERED) && !FD_ISSET(client->botid, &fds)) {
+            FD_SET(client->botid, &fds);
+            trigger = get_channel_trigger(client->botid, chan);
+            if(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)) {
+            FD_SET(client->botid, &fds);
+            trigger = get_channel_trigger(client->botid, chan);
+            if(stricmplen(message, trigger, strlen(trigger)) == 0) {
+                handle_command(client, user, chan, message + strlen(trigger));
+            }
+        }
+    }
+}
+
 static void got_privmsg(struct UserNode *user, struct UserNode *target, char *message) {
-       
+    struct ClientSocket *client;
+    for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
+        if(client->user == target) {
+            handle_command(client, user, NULL, message);
+        }
+    }
+}
+
+int register_command(int botid, char *name, cmd_bind_t *func) {
+    struct cmd_function *cmdfunc;
+    for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) {
+        if(cmdfunc->botid == botid && strcmp(cmdfunc->name, name) == 0)
+            return 0;
+    }
+    cmdfunc = malloc(sizeof(*cmdfunc));
+    if (!cmdfunc) {
+        perror("malloc() failed");
+        return 0;
+    }
+    cmdfunc->botid = botid;
+    cmdfunc->name = strdup(name);
+    cmdfunc->func = func;
+    cmdfunc->next = cmd_functions;
+    cmd_functions = cmdfunc;
+    return 1;
+}
+
+int set_trigger_callback(int botid, trigger_callback_t *func) {
+    static struct trigger_callback *cb = NULL;
+    for(cb = trigger_callbacks; cb; cb = cb->next) {
+        if(cb->botid == botid)
+            break;
+    }
+    if(!cb) {
+        cb = malloc(sizeof(*cb));
+        if (!cb) {
+            perror("malloc() failed");
+            return 0;
+        }
+        cb->botid = botid;
+        cb->next = trigger_callbacks;
+        trigger_callbacks = cb;
+    }
+    cb->func = func;
+    return 1;
+}
+
+int changeChannelTrigger(int botid, struct ChanNode *chan, char *new_trigger) {
+    struct trigger_cache *trigger;
+    for(trigger = chan->trigger; trigger; trigger = trigger->next) {
+        if(trigger->botid == botid) {
+            free(trigger->trigger);
+            trigger->trigger = strdup(new_trigger);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+int bind_cmd_to_function(int botid, char *cmd, struct cmd_function *func) {
+    int bind_index = get_binds_index(cmd[0]);
+    struct cmd_binding *bind;
+    for(bind = cmd_binds[bind_index]; bind; bind = bind->next) {
+        if(bind->botid == botid && strcmp(bind->cmd, cmd) == 0)
+            return 0;
+    }
+    bind = malloc(sizeof(*bind));
+    if (!bind) {
+        perror("malloc() failed");
+        return 0;
+    }
+    bind->botid = botid;
+    bind->cmd = strdup(cmd);
+    bind->func = func;
+    bind->next = cmd_binds[bind_index];
+    cmd_binds[bind_index] = bind;
+    return 1;
+}
+
+int bind_cmd_to_command(int botid, char *cmd, char *func) {
+    struct cmd_function *cmdfunc;
+    for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) {
+        if(cmdfunc->botid == botid && strcmp(cmdfunc->name, func) == 0)
+            break;
+    }
+    if(!cmdfunc) return 0;
+    int bind_index = get_binds_index(cmd[0]);
+    struct cmd_binding *bind;
+    for(bind = cmd_binds[bind_index]; bind; bind = bind->next) {
+        if(bind->botid == botid && strcmp(bind->cmd, cmd) == 0)
+            return 0;
+    }
+    bind = malloc(sizeof(*bind));
+    if (!bind) {
+        perror("malloc() failed");
+        return 0;
+    }
+    bind->botid = botid;
+    bind->cmd = strdup(cmd);
+    bind->func = cmdfunc;
+    bind->next = cmd_binds[bind_index];
+    cmd_binds[bind_index] = bind;
+    return 1;
+}
+
+int unbind_cmd(int botid, char *cmd) {
+    int bind_index = get_binds_index(cmd[0]);
+    struct cmd_binding *bind, *last = NULL;
+    for(bind = cmd_binds[bind_index]; bind; bind = bind->next) {
+        if(bind->botid == botid && strcmp(bind->cmd, cmd) == 0) {
+            if(last)
+                last->next = bind->next;
+            else
+                cmd_binds[bind_index] = bind->next;
+            free(bind->cmd);
+            free(bind);
+            return 1;
+        } else
+            last = bind;
+    }
+    return 0;
 }
 
 void init_modcmd() {
-       bind_chanmsg(got_chanmsg);
-       bind_privmsg(got_privmsg);
+    cmd_binds = calloc(27, sizeof(*cmd_binds));
+    bind_chanmsg(got_chanmsg);
+    bind_privmsg(got_privmsg);
 }
 
index 8195145cefbbfb7ab3f97a8da24b6fd70df7d670..4bff7d9110ddc47c6fa7a7ca5510c820bf671a9b 100644 (file)
--- a/modcmd.h
+++ b/modcmd.h
@@ -2,6 +2,43 @@
 #define _modcmd_h
 #include "main.h"
 
+struct ClientSocket;
+struct UserNode;
+struct ChanNode;
+
+typedef void cmd_bind_t(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char **argv, char argc);
+typedef void trigger_callback_t(struct ChanNode *chan, char *trigger);
+
+struct cmd_function {
+    char *name;
+    int botid;
+    cmd_bind_t *func;
+    
+    struct cmd_binding *next;
+}
+
+struct cmd_binding {
+    char *cmd;
+    int botid;
+    struct cmd_function *func;
+    
+    struct cmd_binding *next;
+}
+
+struct trigger_cache {
+    int botid;
+    char *trigger;
+    
+    struct trigger_cache *next;
+}
+
 void init_modcmd();
+struct* ClientSocket get_prefered_bot(int botid);
+int register_command(int botid, char *name, cmd_bind_t *func);
+int set_trigger_callback(int botid, trigger_callback_t *func);
+int changeChannelTrigger(int botid, struct ChanNode *chan, char *new_trigger);
+int bind_cmd_to_function(int botid, char *cmd, struct cmd_function *func);
+int bind_cmd_to_command(int botid, char *cmd, char *func);
+int unbind_cmd(int botid, char *cmd);
 
 #endif
\ No newline at end of file