fixed last commit #4
[NeonServV5.git] / modcmd.c
1
2 #include "modcmd.h"
3 #include "IRCEvents.h"
4 #include "ClientSocket.h"
5 #include "UserNode.h"
6 #include "ChanNode.h"
7 #include "ChanUser.h"
8
9 struct trigger_callback {
10     int botid;
11     trigger_callback_t *func;
12     
13     struct trigger_callback *next;
14 };
15
16 static struct cmd_binding **cmd_binds;
17 static struct cmd_function *cmd_functions = NULL;
18 static struct trigger_callback *trigger_callbacks = NULL;
19
20 static int get_binds_index(char first_char) {
21     if(tolower(first_char) >= 'a' && tolower(first_char) <= 'z') {
22         return tolower(first_char - 'a');
23     }
24     return 26;
25 }
26
27 struct ClientSocket* get_prefered_bot(int botid) {
28     struct ClientSocket *client;
29     for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
30         if(client->botid == botid && (client->flags & SOCKET_FLAG_PREFERED))
31             return client;
32     }
33     return NULL;
34 }
35
36 static char* get_channel_trigger(int botid, struct ChanNode *chan) {
37     struct trigger_cache *trigger;
38     for(trigger = chan->trigger; trigger; trigger = trigger->next) {
39         if(trigger->botid == botid)
40             return trigger->trigger;
41     }
42     struct trigger_callback *cb;
43     for(cb = trigger_callbacks; cb; cb = cb->next) {
44         if(cb->botid == botid)
45             break;
46     }
47     char triggerStr[TRIGGERLEN];
48     if(cb)
49         cb->func(chan, triggerStr);
50     else
51         strcpy(triggerStr, "+");
52     trigger = malloc(sizeof(*trigger));
53     if (!trigger) {
54         perror("malloc() failed");
55         return 0;
56     }
57     trigger->botid = botid;
58     trigger->trigger = strdup(triggerStr);
59     trigger->next = chan->trigger;
60     chan->trigger = trigger;
61     return trigger->trigger;
62 }
63
64 static void handle_command(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message) {
65     if(!strcmp(message, "users")) {
66         struct ChanUser *chanuser;
67         putsock(client, "PRIVMSG %s :[BOT JOIN] Users on this Channel:", chan->name);
68         for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
69             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);
70         }
71     }
72     if(!strcmp(message, "modes")) {
73         char modeBuf[MAXLEN];
74         getModeString(chan, modeBuf);
75         putsock(client, "PRIVMSG %s :Modes: %s", chan->name, modeBuf);
76     }
77 }
78
79 static void got_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) {
80     fd_set fds;
81     char *trigger;
82     struct ClientSocket *client;
83     FD_ZERO(&fds);
84     for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
85         if(isUserOnChan(client->user, chan) && (client->flags & SOCKET_FLAG_PREFERED) && !FD_ISSET(client->botid, &fds)) {
86             FD_SET(client->botid, &fds);
87             trigger = get_channel_trigger(client->botid, chan);
88             if(stricmplen(message, trigger, strlen(trigger)) == 0) {
89                 handle_command(client, user, chan, message + strlen(trigger));
90             }
91         }
92     }
93     for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
94         if(isUserOnChan(client->user, chan) && !FD_ISSET(client->botid, &fds)) {
95             FD_SET(client->botid, &fds);
96             trigger = get_channel_trigger(client->botid, chan);
97             if(stricmplen(message, trigger, strlen(trigger)) == 0) {
98                 handle_command(client, user, chan, message + strlen(trigger));
99             }
100         }
101     }
102 }
103
104 static void got_privmsg(struct UserNode *user, struct UserNode *target, char *message) {
105     struct ClientSocket *client;
106     for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
107         if(client->user == target) {
108             handle_command(client, user, NULL, message);
109         }
110     }
111 }
112
113 int register_command(int botid, char *name, cmd_bind_t *func) {
114     struct cmd_function *cmdfunc;
115     for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) {
116         if(cmdfunc->botid == botid && strcmp(cmdfunc->name, name) == 0)
117             return 0;
118     }
119     cmdfunc = malloc(sizeof(*cmdfunc));
120     if (!cmdfunc) {
121         perror("malloc() failed");
122         return 0;
123     }
124     cmdfunc->botid = botid;
125     cmdfunc->name = strdup(name);
126     cmdfunc->func = func;
127     cmdfunc->next = cmd_functions;
128     cmd_functions = cmdfunc;
129     return 1;
130 }
131
132 int set_trigger_callback(int botid, trigger_callback_t *func) {
133     static struct trigger_callback *cb = NULL;
134     for(cb = trigger_callbacks; cb; cb = cb->next) {
135         if(cb->botid == botid)
136             break;
137     }
138     if(!cb) {
139         cb = malloc(sizeof(*cb));
140         if (!cb) {
141             perror("malloc() failed");
142             return 0;
143         }
144         cb->botid = botid;
145         cb->next = trigger_callbacks;
146         trigger_callbacks = cb;
147     }
148     cb->func = func;
149     return 1;
150 }
151
152 int changeChannelTrigger(int botid, struct ChanNode *chan, char *new_trigger) {
153     struct trigger_cache *trigger;
154     for(trigger = chan->trigger; trigger; trigger = trigger->next) {
155         if(trigger->botid == botid) {
156             free(trigger->trigger);
157             trigger->trigger = strdup(new_trigger);
158             return 1;
159         }
160     }
161     return 0;
162 }
163
164 int bind_cmd_to_function(int botid, char *cmd, struct cmd_function *func) {
165     int bind_index = get_binds_index(cmd[0]);
166     struct cmd_binding *cbind;
167     for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
168         if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0)
169             return 0;
170     }
171     cbind = malloc(sizeof(*cbind));
172     if (!cbind) {
173         perror("malloc() failed");
174         return 0;
175     }
176     cbind->botid = botid;
177     cbind->cmd = strdup(cmd);
178     cbind->func = func;
179     cbind->next = cmd_binds[bind_index];
180     cmd_binds[bind_index] = cbind;
181     return 1;
182 }
183
184 int bind_cmd_to_command(int botid, char *cmd, char *func) {
185     struct cmd_function *cmdfunc;
186     for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) {
187         if(cmdfunc->botid == botid && strcmp(cmdfunc->name, func) == 0)
188             break;
189     }
190     if(!cmdfunc) return 0;
191     int bind_index = get_binds_index(cmd[0]);
192     struct cmd_binding *cbind;
193     for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
194         if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0)
195             return 0;
196     }
197     cbind = malloc(sizeof(*cbind));
198     if (!cbind) {
199         perror("malloc() failed");
200         return 0;
201     }
202     cbind->botid = botid;
203     cbind->cmd = strdup(cmd);
204     cbind->func = cmdfunc;
205     cbind->next = cmd_binds[bind_index];
206     cmd_binds[bind_index] = cbind;
207     return 1;
208 }
209
210 int unbind_cmd(int botid, char *cmd) {
211     int bind_index = get_binds_index(cmd[0]);
212     struct cmd_binding *cbind, *last = NULL;
213     for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
214         if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
215             if(last)
216                 last->next = cbind->next;
217             else
218                 cmd_binds[bind_index] = cbind->next;
219             free(cbind->cmd);
220             free(cbind);
221             return 1;
222         } else
223             last = cbind;
224     }
225     return 0;
226 }
227
228 void init_modcmd() {
229     cmd_binds = calloc(27, sizeof(*cmd_binds));
230     bind_chanmsg(got_chanmsg);
231     bind_privmsg(got_privmsg);
232 }
233