From: pk910 Date: Fri, 12 Aug 2011 22:33:51 +0000 (+0200) Subject: wrote modcmd bind system X-Git-Tag: v5.3~574 X-Git-Url: http://git.pk910.de/?p=NeonServV5.git;a=commitdiff_plain;h=6e415e27feac22d80d613450b97cd372db0dd2a3 wrote modcmd bind system --- diff --git a/ChanNode.c b/ChanNode.c index 7d2c9a5..5f76976 100644 --- a/ChanNode.c +++ b/ChanNode.c @@ -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); diff --git a/ChanNode.h b/ChanNode.h index dbb70c8..ea949fd 100644 --- a/ChanNode.h +++ b/ChanNode.h @@ -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; }; diff --git a/ClientSocket.c b/ClientSocket.c index c5e3877..0192b08 100644 --- a/ClientSocket.c +++ b/ClientSocket.c @@ -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; diff --git a/ClientSocket.h b/ClientSocket.h index 69d3057..d15be26 100644 --- a/ClientSocket.h +++ b/ClientSocket.h @@ -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 1b0ba1c..564e7b0 100644 --- 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 c25d743..0af7289 100644 --- 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 diff --git a/modcmd.c b/modcmd.c index 839e815..180c968 100644 --- 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); } diff --git a/modcmd.h b/modcmd.h index 8195145..4bff7d9 100644 --- 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