X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=IRCParser.c;h=8662f6d8399e3907f60ef1c9713cbc5a5e438d42;hb=795115bf680185ae01043bd1222b78bfed8c1d87;hp=710117cc4f646700c2c6ba924ec69116ec884a67;hpb=bd96073015180a8ad1655ccd48d1662a54d30031;p=NeonServV5.git diff --git a/IRCParser.c b/IRCParser.c index 710117c..8662f6d 100644 --- a/IRCParser.c +++ b/IRCParser.c @@ -6,6 +6,10 @@ #include "IRCEvents.h" #include "ClientSocket.h" #include "WHOHandler.h" +#include "lang.h" +#include "DBHelper.h" +#include "BanNode.h" +#include "ModeNode.h" struct irc_cmd *irc_commands = NULL; @@ -44,6 +48,7 @@ static void parse_line(struct ClientSocket *client, char *line) { if (*line == ':') { //the rest is a single parameter argv[argc++] = line + 1; + break; } argv[argc++] = line; if (argc >= MAXNUMPARAMS) @@ -78,32 +83,40 @@ static void parse_raw(struct ClientSocket *client, char *from, char *cmd, char * break; } } - if(!ret) { - //fprintf(stderr,"PARSE ERROR: %s", cmd); commented out right now - we're still developing and this is very spammy + if(!irc_cmd) { + event_raw(client, from, cmd, argv, argc); + } else if(!ret) { + fprintf(stderr,"PARSE ERROR: %s\n", cmd); } } static USERLIST_CALLBACK(got_channel_userlist) { - chan->flags |= CHANFLAG_RECEIVED_USERLIST; + struct ChanUser *chanuser = data; + event_join(chanuser); } static IRC_CMD(raw_001) { client->flags |= SOCKET_FLAG_READY; - putsock(client, "JOIN #pktest"); + event_bot_ready(client); return 1; } static IRC_CMD(raw_join) { if(from == NULL || argc < 1) return 0; struct UserNode *user = getUserByMask(from); + struct ChanNode *chan = getChanByName(argv[0]); + if(!chan && !(user->flags & USERFLAG_ISBOT)) return 0; if(user == NULL) { user = addUserMask(from); } - struct ChanNode *chan = getChanByName(argv[0]); if(chan == NULL) { chan = addChannel(argv[0]); //request member list - get_userlist(chan, got_channel_userlist); + chan->chanbot = user; + struct ChanUser *chanuser = addChanUser(chan, user); //it must be a bot + get_userlist(chan, got_channel_userlist, chanuser); + putsock(client, "MODE %s", chan->name); + putsock(client, "MODE %s +b", chan->name); } else if(!isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) { struct ChanUser *chanuser = addChanUser(chan, user); event_join(chanuser); @@ -112,7 +125,7 @@ static IRC_CMD(raw_join) { } static IRC_CMD(raw_part) { - if(from == NULL || argc < 2) return 0; + if(from == NULL || argc < 1) return 0; struct UserNode *user = getUserByMask(from); if(user == NULL) return 0; struct ChanNode *chan = getChanByName(argv[0]); @@ -120,59 +133,166 @@ static IRC_CMD(raw_part) { if(isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) { struct ChanUser *chanuser = getChanUser(user, chan); delChanUser(chanuser, 0); //we need to free the chanuser manually! - event_part(chanuser, argv[1]); + event_part(chanuser, (argc > 1 ? argv[1] : NULL)); free(chanuser); - if(user->flags & USERFLAG_ISBOT) { + if(chan->chanbot == user) { //check if theres another bot in the channel - otherwise free it - + checkChannelVisibility(chan); } } if(user->channel == NULL && !(user->flags & USERFLAG_ISBOT)) { //remove the user delUser(user, 1); } - return 1; } static IRC_CMD(raw_quit) { - if(from == NULL || argc < 2) return 0; + if(from == NULL || argc < 1) return 0; struct UserNode *user = getUserByMask(from); if(user == NULL) return 0; 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 - event_quit(user, argv[1]); + event_quit(user, argv[0]); if(user->flags & USERFLAG_ISBOT) { //check if there are other bots in the users channel - otherwise free them - + struct ChanUser *chanuser, *next; + for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next) { + next = getUserChannels(user, chanuser); + checkChannelVisibility(chanuser->chan); + } } delUser(user, 1); //now we fully free the user return 1; } +void bot_disconnect(struct ClientSocket *client) { + struct UserNode *user = client->user; + struct ChanUser *chanuser, *next; + delUser(user, 0); + event_quit(user, "disconnected"); + for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next) { + next = getUserChannels(user, chanuser); + checkChannelVisibility(chanuser->chan); + free(chanuser); + } + user->channel = NULL; +} + static IRC_CMD(raw_kick) { if(from == NULL || argc < 3) return 0; struct UserNode *user = getUserByMask(from); struct UserNode *target = getUserByNick(argv[1]); - if(user == NULL || target == NULL) return 0; struct ChanNode *chan = getChanByName(argv[0]); - if(chan == NULL) return 0; + if(chan == NULL || target == NULL) return 0; if(isUserOnChan(target, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) { + if(user == NULL) { + user = createTempUser(from); + user->flags |= USERFLAG_ISTMPUSER; + } struct ChanUser *chanuser = getChanUser(target, chan); delChanUser(chanuser, 0); //we need to free the chanuser manually! event_kick(user, chanuser, argv[1]); free(chanuser); if(target->flags & USERFLAG_ISBOT) { //check if theres another bot in the channel - otherwise free it - + checkChannelVisibility(chan); } } if(target->channel == NULL && !(target->flags & USERFLAG_ISBOT)) { //remove the user - delUser(user, 1); + delUser(target, 1); } return 1; } +static IRC_CMD(raw_topic) { + if(from == NULL || argc < 2) return 0; + struct UserNode *user = getUserByMask(from); + struct ChanNode *chan = getChanByName(argv[0]); + if(chan == NULL) return 0; + if(chan->chanbot != client->user) return 1; //just ignore it to prevent event duplicates + if(user == NULL) { + user = createTempUser(from); + user->flags |= USERFLAG_ISTMPUSER; + } + event_topic(user, chan, argv[1]); + strcpy(chan->topic, argv[1]); + return 1; +} + +static IRC_CMD(raw_privmsg) { + if(from == NULL || argc < 2) return 0; + struct UserNode *user = getUserByMask(from); + if(user == NULL) { + user = createTempUser(from); + user->flags |= USERFLAG_ISTMPUSER; + } + if(argv[0][0] == '#') { //Channel message + struct ChanNode *chan = getChanByName(argv[0]); + if(chan && chan->chanbot == client->user) { + if(argv[1][0] == '\001') { + char *cmd = &argv[1][1]; + char *text = strstr(cmd, " "); + if(text) { + *text = '\0'; + text++; + if(strlen(text) && text[strlen(text)-1] == '\001') + text[strlen(text)-1] = '\0'; + } else if(strlen(cmd) && cmd[strlen(cmd)-1] == '\001') + cmd[strlen(cmd)-1] = '\0'; + event_chanctcp(user, chan, cmd, text); + } else + event_chanmsg(user, chan, argv[1]); + } + } else { + struct UserNode *target = getUserByNick(argv[0]); + if(target) { + if(argv[1][0] == '\001') { + char *cmd = &argv[1][1]; + char *text = strstr(cmd, " "); + if(text) { + *text = '\0'; + text++; + if(strlen(text) && text[strlen(text)-1] == '\001') + text[strlen(text)-1] = '\0'; + } else if(strlen(cmd) && cmd[strlen(cmd)-1] == '\001') + cmd[strlen(cmd)-1] = '\0'; + event_privctcp(user, target, cmd, text); + } else + event_privmsg(user, target, argv[1]); + } + } + return 1; +} + +static IRC_CMD(raw_notice) { + if(from == NULL || argc < 2) return 0; + struct UserNode *user = getUserByMask(from); + if(user == NULL) { + user = createTempUser(from); + user->flags |= USERFLAG_ISTMPUSER; + } + if(argv[0][0] == '#') { //Channel notice + struct ChanNode *chan = getChanByName(argv[0]); + if(chan && chan->chanbot == client->user) + event_channotice(user, chan, argv[1]); + } else { + struct UserNode *target = getUserByNick(argv[0]); + if(target) + event_privnotice(user, target, argv[1]); + } + return 1; +} + +static IRC_CMD(raw_nick) { + if(from == NULL || argc == 0) return 0; + struct UserNode *user = getUserByMask(from); + if(user == NULL) return 0; + event_nick(user, argv[0]); + renameUser(user, argv[0]); + return 1; +} + static IRC_CMD(raw_ping) { if(argc == 0) return 0; putsock(client, "PONG :%s", argv[0]); @@ -189,14 +309,119 @@ static IRC_CMD(raw_315) { return 1; } -void parser_init() { +static IRC_CMD(raw_324) { //MODE LIST + //Watchcat #pktest +stnzN + if(from == NULL || argc < 3) return 0; + struct ChanNode *chan = getChanByName(argv[1]); + if(chan == NULL) return 0; + parseModes(chan->modes, argv[2], argv+3, argc-3); + return 1; +} + +static IRC_CMD(raw_invite) { + if(from == NULL || argc < 2) return 0; + struct UserNode *user = getUserByMask(from); + if(user == NULL) { + user = createTempUser(from); + user->flags |= USERFLAG_ISTMPUSER; + } + event_invite(client, user, argv[1]); + return 1; +} + +static IRC_CMD(raw_mode) { + if(from == NULL || argc < 2) return 0; + struct UserNode *user = getUserByMask(from); + if(user == NULL) { + user = createTempUser(from); + user->flags |= USERFLAG_ISTMPUSER; + } + if(argv[0][0] == '#') { + //ChannelMode + struct ChanNode *chan = getChanByName(argv[0]); + if(!chan) return 0; + if(chan->chanbot != client->user) return 1; + event_mode(user, chan, argv[1], argv+2, argc-2); + parseModes(chan->modes, argv[1], argv+2, argc-2); + } else { + //UserMode + } + return 1; +} + +static IRC_CMD(raw_367) { + //Watchcat #pktest pk911!*@* TestBot!~bot@pktest.user.WebGamesNet 1315863279 + struct ChanNode *chan = getChanByName(argv[1]); + if(!chan) return 0; + struct BanNode *ban; + while((ban = getMatchingChannelBan(chan, argv[2]))) { + removeChannelBan(ban); + } + addChannelBan(chan, argv[2]); + return 1; +} + +void init_parser() { //all the raws we receive... register_irc_function("001", raw_001); - register_irc_function("354", raw_354); - register_irc_function("315", raw_315); + register_irc_function("324", raw_324); + register_irc_function("367", raw_367); + register_irc_function("INVITE", raw_invite); + register_irc_function("NOTICE", raw_notice); + register_irc_function("TOPIC", raw_topic); register_irc_function("KICK", raw_kick); - register_irc_function("JOIN", raw_join); register_irc_function("PART", raw_part); register_irc_function("QUIT", raw_quit); + register_irc_function("JOIN", raw_join); + register_irc_function("MODE", raw_mode); + register_irc_function("NICK", raw_nick); + register_irc_function("354", raw_354); + register_irc_function("315", raw_315); register_irc_function("PING", raw_ping); + register_irc_function("PRIVMSG", raw_privmsg); +} + +void free_parser() { + struct irc_cmd *cmd, *next; + for(cmd = irc_commands; cmd; cmd = next) { + next = cmd->next; + free(cmd); + } +} + +void reply(struct ClientSocket *client, struct UserNode *user, const char *text, ...) { + const char *reply_format = get_language_string(user, text); + if(reply_format == NULL) + reply_format = text; + loadUserSettings(user); + char formatBuf[MAXLEN]; + sprintf(formatBuf, "%s %s :%s", ((user->flags & USERFLAG_REPLY_PRIVMSG) ? "PRIVMSG" : "NOTICE"), user->nick, reply_format); + va_list arg_list; + char sendBuf[MAXLEN]; + int pos; + if (!(client->flags & SOCKET_FLAG_CONNECTED)) return; + sendBuf[0] = '\0'; + va_start(arg_list, text); + pos = vsnprintf(sendBuf, MAXLEN - 2, formatBuf, arg_list); + va_end(arg_list); + if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2; + sendBuf[pos] = '\n'; + sendBuf[pos+1] = '\0'; + write_socket(client, sendBuf, pos+1); +} + +char* merge_argv(char **argv, int start, int end) { + return merge_argv_char(argv, start, end, ' '); +} + +char* merge_argv_char(char **argv, int start, int end, char seperator) { + int i; + char *p = NULL; + for(i = start; i < end; i++) { + p = argv[i]; + while(*p) p++; + *p = seperator; + } + if(p) *p = '\0'; + return argv[start]; }