diff options
Diffstat (limited to '')
-rw-r--r-- | window.cpp | 224 |
1 files changed, 222 insertions, 2 deletions
@@ -110,6 +110,43 @@ void Channel::syncStateForClient(Buffer &output) { } +void Channel::handleNameReply(const char *str) { + char copy[4096]; + strncpy(copy, str, 4096); + copy[4095] = 0; + + char *strtok_var; + char *name = strtok_r(copy, " ", &strtok_var); + + while (name) { + uint32_t modes = 0; + + // Check the beginning of the name for as many valid + // mode prefixes as possible + // Servers may only send one, but I want to take into + // account the possibility that they might send multiple + // ones. Just in case. + + while (*name != 0) { + uint32_t flag = server->getUserFlagByPrefix(*name); + + if (flag == 0) + break; + else + modes |= flag; + + ++name; + } + + // Got it! + users[name] = modes; + + // TODO: push add command + + // Get the next name + name = strtok_r(NULL, " ", &strtok_var); + } +} void Channel::handleJoin(const UserRef &user) { if (user.isSelf) { @@ -117,6 +154,9 @@ void Channel::handleJoin(const UserRef &user) { inChannel = true; pushMessage("You have joined the channel!"); } else { + users[user.nick] = 0; + // TODO: push add command + char buf[1024]; snprintf(buf, 1024, "%s (%s@%s) has joined", @@ -127,12 +167,192 @@ void Channel::handleJoin(const UserRef &user) { pushMessage(buf); } } + +void Channel::handlePart(const UserRef &user, const char *message) { + auto i = users.find(user.nick); + if (i != users.end()) { + users.erase(i); + // TODO: push remove command + } + + char buf[1024]; + + if (user.isSelf) { + inChannel = false; + + snprintf(buf, 1024, + "You have left the channel (%s)", + message); + pushMessage(buf); + } else { + snprintf(buf, 1024, + "%s (%s@%s) has parted (%s)", + user.nick.c_str(), + user.ident.c_str(), + user.hostmask.c_str(), + message); + + pushMessage(buf); + } +} + +void Channel::handleQuit(const UserRef &user, const char *message) { + if (user.isSelf) + inChannel = false; + + auto i = users.find(user.nick); + if (i == users.end()) + return; + + users.erase(i); + // TODO: push remove command + pushMessage("Removed from users"); + + char buf[1024]; + + snprintf(buf, 1024, + "%s (%s@%s) has quit (%s)", + user.nick.c_str(), + user.ident.c_str(), + user.hostmask.c_str(), + message); + + pushMessage(buf); +} + +void Channel::handleNick(const UserRef &user, const char *newNick) { + auto i = users.find(user.nick); + if (i == users.end()) + return; + + users[newNick] = i->second; + users.erase(i); + // TODO: push rename command + + char buf[1024]; + snprintf(buf, 1024, + "%s is now known as %s", + user.nick.c_str(), + newNick); + + pushMessage(buf); +} + +void Channel::handleMode(const UserRef &user, const char *str) { + char copy[4096]; + strncpy(copy, str, 4096); + copy[4095] = 0; + + char *strtok_var; + char *modes = strtok_r(copy, " ", &strtok_var); + + if (!modes) + return; + + bool addFlag = true; + + while (*modes != 0) { + char mode = *(modes++); + + uint32_t flag; + + if (mode == '+') { + addFlag = true; + } else if (mode == '-') { + addFlag = false; + + } else if ((flag = server->getUserFlagByMode(mode)) != 0) { + bool oops = false; + char *target = strtok_r(NULL, " ", &strtok_var); + + auto i = users.find(target); + if (i == users.end()) { + // Oops? Spit out an error... + oops = true; + } else { + // TODO: push mode change to clients + uint32_t flags = i->second; + if (addFlag) + flags |= flag; + else + flags &= ~flag; + users[target] = flags; + } + + char buf[1024]; + snprintf(buf, 1024, + "%s %s mode %c on %s%s", + user.nick.c_str(), + addFlag ? "set" : "cleared", + mode, + target, + oops ? ", but something went wrong!" : ""); + pushMessage(buf); + + } else { + int type = server->getChannelModeType(mode); + char *param = 0; + + switch (type) { + case 1: + case 2: + // Always get a parameter + param = strtok_r(NULL, " ", &strtok_var); + break; + case 3: + // Only get a parameter if adding + if (addFlag) + param = strtok_r(NULL, " ", &strtok_var); + break; + } + + char buf[1024]; + snprintf(buf, 1024, + "%s %s channel mode %c%s%s", + user.nick.c_str(), + addFlag ? "set" : "cleared", + mode, + param ? " " : "", + param ? param : ""); + pushMessage(buf); + } + } +} + void Channel::handlePrivmsg(const UserRef &user, const char *str) { + char prefix[2]; + prefix[0] = getEffectivePrefixChar(user.nick.c_str()); + prefix[1] = 0; + char buf[15000]; snprintf(buf, 15000, - "<%s> %s", + "<%s%s> %s", + prefix, user.nick.c_str(), str); - + pushMessage(buf); } + + +char Channel::getEffectivePrefixChar(const char *nick) const { + auto i = users.find(nick); + if (i == users.end()) + return 0; + + // Maybe this bit would work best as an IRCServer method? + + uint32_t modes = i->second; + uint32_t flag = 1; + char *prefixes = server->serverPrefix; + + while (*prefixes != 0) { + if (modes & flag) + return *prefixes; + + ++prefixes; + flag <<= 1; + } + + return 0; +} |