fixed auto-rejoin when only bots are in an opless channel
[NeonServV5.git] / src / IRCParser.c
index 220283e1408025789d54c1269c3900bbf8532e46..2c30d6992dfe32f89abe3fd6b944d97b3e8652c4 100644 (file)
@@ -27,6 +27,7 @@
 #include "BanNode.h"
 #include "ModeNode.h"
 #include "tools.h"
+#include "bots.h"
 
 struct irc_cmd *irc_commands = NULL;
 static struct UserNode *registering_users = NULL;
@@ -238,11 +239,11 @@ static IRC_CMD(raw_join) {
             free(chan->rejoin_array);
             chan->flags &= ~CHANFLAG_REJOINING;
         }
-    } else if(chan->usercount == 1 && isUserOnChan(user, chan)) {
+    } else if(isUserOnChan(user, chan)) { //user is already in the channel? ^^
         //first bot rejoined
+        chan->flags &= ~CHANFLAG_RECEIVED_USERLIST;
         struct ChanUser *chanuser = getChanUser(user, chan);
-        chanuser->flags &= ~CHANUSERFLAG_VOICED;
-        chanuser->flags |= CHANUSERFLAG_OPPED;
+        get_userlist_with_invisible(chan, 0, got_channel_userlist, chanuser);
     }
     DESYNCHRONIZE(cache_sync);
     return 1;
@@ -328,8 +329,14 @@ static IRC_CMD(raw_part) {
     }
     else if(keep_channel && (chan->flags & CHANFLAG_REJOINING) && chan->usercount == 1) {
         //bot is alone... rejoin!
-        putsock(client, "PART %s :magic hop", chan->name);
-        putsock(client, "JOIN %s", chan->name);
+        struct ClientSocket *bot;
+        //find the last bot in the channel
+        for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+            if(bot->user == chan->chanbot) {
+                putsock(bot, "PART %s :magic hop", chan->name);
+                putsock(bot, "JOIN %s", chan->name);
+            }
+        }
     }
     DESYNCHRONIZE(cache_sync);
     return 1;
@@ -466,17 +473,28 @@ static IRC_CMD(raw_kick) {
 
 static IRC_CMD(raw_topic) {
     if(from == NULL || argc < 2) return 0;
+    SYNCHRONIZE(cache_sync);
     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(chan == NULL) {
+        DESYNCHRONIZE(cache_sync);
+        return 0;
+    }
+    if(chan->chanbot != client->user) {
+        DESYNCHRONIZE(cache_sync);
+        return 1; //just ignore it to prevent event duplicates
+    }
     if(user == NULL) {
         user = createTempUserMask(from);
-               if(!user) return 0;
+               if(!user) {
+            DESYNCHRONIZE(cache_sync);
+            return 0;
+        }
         user->flags |= USERFLAG_ISTMPUSER;
     }
     event_topic(user, chan, argv[1]);
     strcpy(chan->topic, argv[1]);
+    DESYNCHRONIZE(cache_sync);
     return 1;
 }
 
@@ -570,15 +588,26 @@ static void client_renamed(struct ClientSocket *client);
 
 static IRC_CMD(raw_nick) {
     if(from == NULL || argc == 0) return 0;
+    SYNCHRONIZE(cache_sync);
     struct UserNode *user = getUserByMask(from);
-    if(user == NULL) return 0;
+    if(user == NULL) {
+        DESYNCHRONIZE(cache_sync);
+        return 0;
+    }
     if(isBot(user)) {
-        if(client->user != user) return 1;
+        if(client->user != user) {
+            DESYNCHRONIZE(cache_sync);
+            return 1;
+        }
         client_renamed(client);
     }
-    else if(!is_firstBotSeeUser(client, user)) return 1; //we ignore it - but it's not a parse error
+    else if(!is_firstBotSeeUser(client, user)) {
+        DESYNCHRONIZE(cache_sync);
+        return 1; //we ignore it - but it's not a parse error
+    }
     event_nick(user, argv[0]);
     renameUser(user, argv[0]);
+    DESYNCHRONIZE(cache_sync);
     return 1;
 }
 
@@ -621,22 +650,38 @@ static IRC_CMD(raw_invite) {
 
 static IRC_CMD(raw_mode) {
     if(from == NULL || argc < 2) return 0;
+    SYNCHRONIZE(cache_sync);
     struct UserNode *user = getUserByMask(from);
     if(user == NULL) {
         user = createTempUserMask(from);
-               if(!user) return 0;
+               if(!user) {
+            DESYNCHRONIZE(cache_sync);
+            return 0;
+        }
         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;
+        if(!chan) {
+            DESYNCHRONIZE(cache_sync);
+            return 0;
+        }
+        if(chan->chanbot != client->user) {
+            DESYNCHRONIZE(cache_sync);
+            return 1;
+        }
         parseModes(chan->modes, argv[1], argv+2, argc-2);
         event_mode(user, chan, argv[1], argv+2, argc-2);
     } else {
         //UserMode
+        if(stricmp(client->user->nick, argv[0])) {
+            DESYNCHRONIZE(cache_sync);
+            return 0;
+        }
+        parseUserModes(client->user, argv[1]);
     }
+    DESYNCHRONIZE(cache_sync);
     return 1;
 }
 
@@ -760,6 +805,15 @@ static IRC_CMD(raw_005) {
     return 1;
 }
 
+static IRC_CMD(raw_nojoin) {
+    if(from == NULL || argc < 3) return 0;
+    struct ChanNode *chan = getChanByName(argv[1]);
+    if(chan == NULL) return 0;
+    if(client->flags & SOCKET_FLAG_REQUEST_INVITE)
+        requestInvite(client->user, chan);
+    return 1;
+}
+
 void init_parser() {
     //all the raws we receive...
     register_irc_function("437", raw_437);
@@ -770,6 +824,10 @@ void init_parser() {
     register_irc_function("324", raw_324);
     register_irc_function("332", raw_332);
     register_irc_function("367", raw_367);
+    register_irc_function("471", raw_nojoin);
+    register_irc_function("473", raw_nojoin);
+    register_irc_function("474", raw_nojoin);
+    register_irc_function("475", raw_nojoin);
     register_irc_function("INVITE", raw_invite);
     register_irc_function("NOTICE", raw_notice);
     register_irc_function("TOPIC", raw_topic);