#include "modcmd.h"
#include "IRCEvents.h"
+#include "ClientSocket.h"
+#include "UserNode.h"
+#include "ChanNode.h"
+#include "ChanUser.h"
+
+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;
+ for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
+ if(client->botid == botid && (client->flags & SOCKET_FLAG_PREFERRED))
+ 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(message[0] == '#') {
+ char *chanName = message;
+ message = strstr(message, " ");
+ if(!message) return;
+ *message = '\0';
+ message++;
+ struct ChanNode *chan2 = getChanByName(chanName);
+ if(chan2)
+ chan = chan2;
+ }
+ int bind_index = get_binds_index(message[0]);
+ char *args = strstr(message, " ");
+ if(args) {
+ *args = '\0';
+ args++;
+ }
+ struct cmd_binding *cbind;
+ for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
+ if(cbind->botid == client->botid && strcmp(cbind->cmd, message) == 0) {
+ //parse the arguments...
+ char *arga[MAXNUMPARAMS];
+ char **argv;
+ int argc = 0;
+ if(args) {
+ while(*args) {
+ //skip leading spaces
+ while (*args == ' ')
+ *args++ = 0;
+ arga[argc++] = args;
+ if (argc >= MAXNUMPARAMS)
+ break;
+ while (*args != ' ' && *args)
+ args++;
+ }
+ }
+ argv = arga;
+ if(argc != 0 && argv[0][0] == '#') {
+ struct ChanNode *chan2 = getChanByName(argv[0]);
+ if(chan2) {
+ argv += 1;
+ argc -= 1;
+ chan = chan2;
+ }
+ }
+ cbind->func->func(client, user, chan, argv, argc);
+ return;
+ }
+ }
+}
static void got_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) {
- struct ClientSocket *client = getBots(SOCKET_FLAG_READY, NULL);
- if(!strcmp(message, "users")) {
- struct ChanUser *chanuser;
- putsock(client, "PRIVMSG %s :[BOT JOIN] Users on this Channel:", chan->name);
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- putsock(client, "PRIVMSG %s : %s!%s@%s [%s] rights: %d", chan->name, chanuser->user->nick, chanuser->user->ident, chanuser->user->host, ((chanuser->user->flags & USERFLAG_ISAUTHED) ? chanuser->user->auth : "*"), chanuser->flags);
+ 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_PREFERRED) && !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));
+ }
}
}
- if(!strcmp(message, "modes")) {
- char modeBuf[MAXLEN];
- getModeString(chan, modeBuf);
- putsock(client, "PRIVMSG %s :Modes: %s", chan->name, modeBuf);
+ 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 *cbind;
+ for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
+ if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0)
+ return 0;
+ }
+ cbind = malloc(sizeof(*cbind));
+ if (!cbind) {
+ perror("malloc() failed");
+ return 0;
+ }
+ cbind->botid = botid;
+ cbind->cmd = strdup(cmd);
+ cbind->func = func;
+ cbind->next = cmd_binds[bind_index];
+ cmd_binds[bind_index] = cbind;
+ 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 *cbind;
+ for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
+ if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0)
+ return 0;
+ }
+ cbind = malloc(sizeof(*cbind));
+ if (!cbind) {
+ perror("malloc() failed");
+ return 0;
+ }
+ cbind->botid = botid;
+ cbind->cmd = strdup(cmd);
+ cbind->func = cmdfunc;
+ cbind->next = cmd_binds[bind_index];
+ cmd_binds[bind_index] = cbind;
+ return 1;
+}
+
+int unbind_cmd(int botid, 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(last)
+ last->next = cbind->next;
+ else
+ cmd_binds[bind_index] = cbind->next;
+ free(cbind->cmd);
+ free(cbind);
+ return 1;
+ } else
+ last = cbind;
+ }
+ 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);
+}
+
+void free_modcmd() {
+ int i;
+ for(i = 0; i < 27; i++) {
+ struct cmd_binding *cbind, *next;
+ for(cbind = cmd_binds[i]; cbind; cbind = next) {
+ next = cbind->next;
+ free(cbind->cmd);
+ free(cbind);
+ }
+ }
+ free(cmd_binds);
+ struct cmd_function *cmdfunct, *next;
+ for(cmdfunct = cmd_functions; cmdfunct; cmdfunct = next) {
+ next = cmdfunct->next;
+ free(cmdfunct->name);
+ free(cmdfunct);
+ }
+ struct trigger_callback *cb, *next_cb;
+ for(cb = trigger_callbacks; cb; cb = next_cb) {
+ next_cb = cb->next;
+ free(next_cb);
+ }
+ cmd_functions = NULL;
+ trigger_callbacks = NULL;
}