+static IRC_CMD(raw_join) {
+ if(from == NULL || argc < 1) return 0;
+ SYNCHRONIZE(cache_sync);
+ struct UserNode *user = getUserByMask(from);
+ struct ChanNode *chan = getChanByName(argv[0]);
+ struct ChanUser *chanuser;
+ if(!chan && (!user || !(user->flags & USERFLAG_ISBOT))) {
+ //parse error if the channel is not known, yet and it's not a bot joining
+ DESYNCHRONIZE(cache_sync);
+ return 0;
+ }
+ if(user == NULL)
+ user = addUserMask(from);
+ if(chan == NULL) {
+ //new channel
+ chan = addChannel(argv[0]);
+ chanuser = addChanUser(chan, user);
+ chanuser->visCount = 1;
+ chan->botcount = 1;
+ get_userlist_with_invisible(chan, 0, got_channel_userlist, chanuser);
+ putsock(client, "MODE %s", chan->name);
+ putsock(client, "MODE %s +b", chan->name);
+ } else if((user->flags & USERFLAG_WAS_REGISTERING)) {
+ //user rejoined after registering (should still be present in the channel)
+ if(!(chanuser = getChanUser(user, chan)))
+ chanuser = addChanUser(chan, user);
+ chanuser->visCount++;
+
+ event_registered(user, from);
+ user->flags &= ~USERFLAG_WAS_REGISTERING;
+ if(user->last_who > REWHO_TIMEOUT)
+ user->last_who -= REWHO_TIMEOUT;
+
+ event_join(chanuser);
+ } else if(!(chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
+ if(client->user != user) { //bots are allowed to add themselves
+ DESYNCHRONIZE(cache_sync);
+ return 1; //ignore join
+ }
+
+ if(!(chanuser = getChanUser(user, chan))) {
+ chanuser = addChanUser(chan, user);
+ }
+ chanuser->visCount++;
+ chan->botcount++;
+
+ if(isModeSet(chan->modes, 'D')) //if the bot joins a channel it could also be invisible
+ chanuser->flags |= CHANUSERFLAG_INVISIBLE;
+
+ get_userlist_with_invisible(chan, 0, got_channel_userlist, chanuser);
+ } else if(!isUserOnChan(user, chan)) {
+ //join user to an existing channel
+ chanuser = addChanUser(chan, user);
+ chanuser->visCount = 1;
+ if(isBot(user) && client->user == user) {
+ if(isModeSet(chan->modes, 'D')) //if the bot joins a channel it could also be invisible
+ chanuser->flags |= CHANUSERFLAG_INVISIBLE;
+ increase_viscount_butone(chan, chanuser);
+ chan->botcount++;
+ }
+
+ event_join(chanuser);
+
+ if(!(user->flags & USERFLAG_ISBOT) && (chan->flags & CHANFLAG_REJOINING)) {
+ //ABORT AUTOMATIC REJOIN (security break)
+ free_rejoin_clients(chan, 1);
+ chan->flags &= ~CHANFLAG_REJOINING;
+ }
+ } else {
+ //user is already in the channel
+ chanuser = getChanUser(user, chan);
+ chanuser->visCount++;
+
+ if(isBot(user) && client->user == user) {
+ increase_viscount_butone(chan, chanuser);
+ chan->botcount++;
+ }
+
+ if(chanuser->visCount > chan->botcount) {
+ printf_log("main", LOG_WARNING, "visCount (%d) bigger than botcount (%d) on channel %s (user %s).", chanuser->visCount, chan->botcount, chan->name, user->nick);
+ chanuser->visCount = chan->botcount;
+ }
+
+ //if multiple bots see the user, it can't be invisible
+ chanuser->flags &= ~CHANUSERFLAG_INVISIBLE;
+ }
+ DESYNCHRONIZE(cache_sync);
+ return 1;
+}
+