7 #include "ClientSocket.h"
8 #include "WHOHandler.h"
10 struct irc_cmd *irc_commands = NULL;
12 static void parse_line(struct ClientSocket *client, char *line);
13 static void register_irc_function(char *command, irc_cmd_t *func);
14 static void parse_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc);
16 int parse_lines(struct ClientSocket *client, char *lines, int len) {
19 for(i = 0; i < len; i++) {
20 if(lines[i] == '\r') //just zero it out :D
22 if(lines[i] == '\n') {
24 parse_line(client, line);
32 static void parse_line(struct ClientSocket *client, char *line) {
34 char *argv[MAXNUMPARAMS];
35 printf("[recv %lu] %s\n", (unsigned long) strlen(line), line);
45 //the rest is a single parameter
46 argv[argc++] = line + 1;
49 if (argc >= MAXNUMPARAMS)
51 while (*line != ' ' && *line)
55 parse_raw(client, argv[0], argv[1], argv+2, argc-2);
59 static void register_irc_function(char *command, irc_cmd_t *func) {
60 struct irc_cmd *irc_cmd = malloc(sizeof(*irc_cmd));
63 perror("malloc() failed");
66 irc_cmd->cmd = command;
68 irc_cmd->next = irc_commands;
69 irc_commands = irc_cmd;
72 static void parse_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc) {
73 struct irc_cmd *irc_cmd;
75 for(irc_cmd = irc_commands; irc_cmd; irc_cmd = irc_cmd->next) {
76 if(!stricmp(irc_cmd->cmd, cmd)) {
77 ret = irc_cmd->func(client, from, argv, argc);
82 //fprintf(stderr,"PARSE ERROR: %s", cmd); commented out right now - we're still developing and this is very spammy
86 static USERLIST_CALLBACK(got_channel_userlist) {
87 struct ChanUser *chanuser = data;
89 putsock(client, "PRIVMSG %s :[BOT JOIN] Users on this Channel:", chan->name);
90 for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
91 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);
95 static IRC_CMD(raw_001) {
96 client->flags |= SOCKET_FLAG_READY;
97 putsock(client, "JOIN #pktest");
101 static IRC_CMD(raw_join) {
102 if(from == NULL || argc < 1) return 0;
103 struct UserNode *user = getUserByMask(from);
104 struct ChanNode *chan = getChanByName(argv[0]);
105 if(!chan && !(user->flags & USERFLAG_ISBOT)) return 0;
107 user = addUserMask(from);
110 chan = addChannel(argv[0]);
111 //request member list
112 chan->chanbot = user;
113 struct ChanUser *chanuser = addChanUser(chan, user); //it must be a bot
114 get_userlist(chan, got_channel_userlist, chanuser);
115 } else if(!isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
116 struct ChanUser *chanuser = addChanUser(chan, user);
117 event_join(chanuser);
122 static IRC_CMD(raw_part) {
123 if(from == NULL || argc < 2) return 0;
124 struct UserNode *user = getUserByMask(from);
125 if(user == NULL) return 0;
126 struct ChanNode *chan = getChanByName(argv[0]);
127 if(chan == NULL) return 0;
128 if(isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
129 struct ChanUser *chanuser = getChanUser(user, chan);
130 delChanUser(chanuser, 0); //we need to free the chanuser manually!
131 event_part(chanuser, argv[1]);
133 if(chan->chanbot == user) {
134 //check if theres another bot in the channel - otherwise free it
135 checkChannelVisibility(chan);
138 if(user->channel == NULL && !(user->flags & USERFLAG_ISBOT)) {
145 static IRC_CMD(raw_quit) {
146 if(from == NULL || argc < 2) return 0;
147 struct UserNode *user = getUserByMask(from);
148 if(user == NULL) return 0;
149 delUser(user, 0); //a little bit crazy, but we want to delete the user on the channel's userlists - but not the users channel list
150 event_quit(user, argv[1]);
151 if(user->flags & USERFLAG_ISBOT) {
152 //check if there are other bots in the users channel - otherwise free them
153 struct ChanUser *chanuser, *next;
154 for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next) {
155 next = getUserChannels(user, chanuser);
156 checkChannelVisibility(chanuser->chan);
159 delUser(user, 1); //now we fully free the user
163 void bot_disconnect(struct ClientSocket *client) {
164 struct UserNode *user = client->user;
165 struct ChanUser *chanuser, *next;
167 event_quit(user, "disconnected");
168 for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next) {
169 next = getUserChannels(user, chanuser);
170 checkChannelVisibility(chanuser->chan);
173 user->channel = NULL;
176 static IRC_CMD(raw_kick) {
177 if(from == NULL || argc < 3) return 0;
178 struct UserNode *user = getUserByMask(from);
179 struct UserNode *target = getUserByNick(argv[1]);
180 struct ChanNode *chan = getChanByName(argv[0]);
181 if(chan == NULL || target == NULL) return 0;
182 if(isUserOnChan(target, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
184 user = createTempUser(from);
185 user->flags |= USERFLAG_ISTMPUSER;
187 struct ChanUser *chanuser = getChanUser(target, chan);
188 delChanUser(chanuser, 0); //we need to free the chanuser manually!
189 event_kick(user, chanuser, argv[1]);
191 if(user->flags & USERFLAG_ISTMPUSER) {
194 if(target->flags & USERFLAG_ISBOT) {
195 //check if theres another bot in the channel - otherwise free it
196 checkChannelVisibility(chan);
199 if(target->channel == NULL && !(target->flags & USERFLAG_ISBOT)) {
206 static IRC_CMD(raw_topic) {
207 if(from == NULL || argc < 2) return 0;
208 struct UserNode *user = getUserByMask(from);
209 struct ChanNode *chan = getChanByName(argv[0]);
210 if(chan == NULL) return 0;
211 if(chan->chanbot != client->user) return 1; //just ignore it to prevent event duplicates
213 user = createTempUser(from);
214 user->flags |= USERFLAG_ISTMPUSER;
216 event_topic(user, chan, argv[1]);
217 strcpy(chan->topic, argv[1]);
218 if(user->flags & USERFLAG_ISTMPUSER) {
224 static IRC_CMD(raw_privmsg) {
225 if(from == NULL || argc < 2) return 0;
226 struct UserNode *user = getUserByMask(from);
228 user = createTempUser(from);
229 user->flags |= USERFLAG_ISTMPUSER;
231 if(argv[0][0] == '#') { //Channel message
232 struct ChanNode *chan = getChanByName(argv[0]);
233 if(chan && chan->chanbot == client->user)
234 event_chanmsg(user, chan, argv[1]);
236 struct UserNode *target = getUserByNick(argv[0]);
238 event_privmsg(user, target, argv[1]);
240 if(user->flags & USERFLAG_ISTMPUSER) {
246 static IRC_CMD(raw_ping) {
247 if(argc == 0) return 0;
248 putsock(client, "PONG :%s", argv[0]);
252 static IRC_CMD(raw_354) {
253 recv_whohandler_354(client, argv, argc);
257 static IRC_CMD(raw_315) {
258 recv_whohandler_315(client, argv, argc);
263 //all the raws we receive...
264 register_irc_function("001", raw_001);
265 register_irc_function("TOPIC", raw_topic);
266 register_irc_function("KICK", raw_kick);
267 register_irc_function("JOIN", raw_join);
268 register_irc_function("PART", raw_part);
269 register_irc_function("QUIT", raw_quit);
270 register_irc_function("354", raw_354);
271 register_irc_function("315", raw_315);
272 register_irc_function("PING", raw_ping);
273 register_irc_function("PRIVMSG", raw_privmsg);