*** VERSION 5.2.0 ***
[NeonServV5.git] / src / IRCParser.c
index 55f3713b15483cd406f15a27bbea7de7d94423b4..5d17786d4b2878e5bbc110ee87a2500026b6b583 100644 (file)
@@ -1,4 +1,4 @@
-/* IRCParser.c - NeonServ v5.1
+/* IRCParser.c - NeonServ v5.2
  * Copyright (C) 2011  Philipp Kreil (pk910)
  * 
  * This program is free software: you can redistribute it and/or modify
@@ -117,11 +117,38 @@ static IRC_CMD(raw_001) {
     return 1;
 }
 
+static int is_firstBotSeeUser(struct ClientSocket *client, struct UserNode *user) {
+    struct ClientSocket *bot, *pref_bot = NULL, *unpref_bot = NULL;
+    struct ChanUser *chanuser;
+    int found;
+    for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+        found = 0;
+        for(chanuser = getUserChannels(bot->user, NULL); chanuser; chanuser = getUserChannels(bot->user, chanuser)) {
+            if(isUserOnChan(user, chanuser->chan)) {
+                found = 1;
+                break;
+            }
+        }
+        if(!found) continue;
+        if(bot->flags & SOCKET_FLAG_PREFERRED) {
+            pref_bot = bot;
+            break;
+        } else
+            unpref_bot = bot;
+    }
+    bot = (pref_bot ? pref_bot : unpref_bot);
+    if(client == bot)
+        return 1;
+    else
+        return 0;
+}
+
 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(chan && chan->chanbot != client->user) return 1; //we ignore it - but it's not a parse error
     if(user == NULL) {
         user = addUserMask(from);
     }
@@ -146,11 +173,12 @@ static IRC_CMD(raw_part) {
     if(user == NULL) return 0;
     struct ChanNode *chan = getChanByName(argv[0]);
     if(chan == NULL) return 0;
+    if(chan->chanbot != client->user) return 1; //we ignore it - but it's not a parse error
     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, (argc > 1 ? argv[1] : NULL));
-        free(chanuser);
+        freeChanUser(chanuser);
         if(chan->chanbot == user) {
             //check if theres another bot in the channel - otherwise free it
             checkChannelVisibility(chan);
@@ -167,6 +195,7 @@ static IRC_CMD(raw_quit) {
     if(from == NULL || argc < 1) return 0;
     struct UserNode *user = getUserByMask(from);
     if(user == NULL) return 0;
+    if(!is_firstBotSeeUser(client, user)) return 1; //we ignore it - but it's not a parse error
     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[0]);
     if(user->flags & USERFLAG_ISBOT) {
@@ -174,7 +203,16 @@ static IRC_CMD(raw_quit) {
         struct ChanUser *chanuser, *next;
         for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next) {
             next = getUserChannels(user, chanuser);
-            checkChannelVisibility(chanuser->chan);
+            if(chanuser->chan->chanbot == user)
+                checkChannelVisibility(chanuser->chan);
+        }
+        //search the user representing the bot in the world of IRC
+        struct ClientSocket *bot;
+        for(bot = getBots(0, NULL); bot; bot = getBots(0, bot)) {
+            if(bot->user == user) {
+                bot->user = NULL;
+                break;
+            }
         }
     }
     delUser(user, 1); //now we fully free the user
@@ -184,14 +222,19 @@ static IRC_CMD(raw_quit) {
 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);
+    if(user) {
+        delUser(user, 0);
+        event_quit(user, "disconnected");
+        for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next) {
+            next = getUserChannels(user, chanuser);
+            if(chanuser->chan->chanbot == user)
+                checkChannelVisibility(chanuser->chan);
+            freeChanUser(chanuser);
+        }
+        user->channel = NULL;
+        delUser(user, 1); //now we fully free the user
+        client->user = NULL;
     }
-    user->channel = NULL;
 }
 
 static IRC_CMD(raw_kick) {
@@ -200,6 +243,7 @@ static IRC_CMD(raw_kick) {
     struct UserNode *target = getUserByNick(argv[1]);
     struct ChanNode *chan = getChanByName(argv[0]);
     if(chan == NULL || target == NULL) return 0;
+    if(chan->chanbot != client->user) return 1; //we ignore it - but it's not a parse error
     if(isUserOnChan(target, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
         if(user == NULL) {
             user = createTempUser(from);
@@ -208,8 +252,8 @@ static IRC_CMD(raw_kick) {
         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) {
+        freeChanUser(chanuser);
+        if(chanuser->chan->chanbot == user) {
             //check if theres another bot in the channel - otherwise free it
             checkChannelVisibility(chan);
         }
@@ -304,6 +348,7 @@ static IRC_CMD(raw_nick) {
     if(from == NULL || argc == 0) return 0;
     struct UserNode *user = getUserByMask(from);
     if(user == NULL) return 0;
+    if(!is_firstBotSeeUser(client, user)) return 1; //we ignore it - but it's not a parse error
     event_nick(user, argv[0]);
     renameUser(user, argv[0]);
     return 1;