summaryrefslogtreecommitdiff
path: root/window.cpp
diff options
context:
space:
mode:
authorTreeki <treeki@gmail.com>2014-01-23 02:06:43 +0100
committerTreeki <treeki@gmail.com>2014-01-23 02:06:43 +0100
commitdba90fe669f7f8d89bc4e722be0c29decc9afde8 (patch)
tree2e9b2ed5cd75498eab97821d5034000f95ad83ac /window.cpp
parent112d40591a6cfbbce62934753d60b0da03bfa848 (diff)
downloadbounce4-dba90fe669f7f8d89bc4e722be0c29decc9afde8.tar.gz
bounce4-dba90fe669f7f8d89bc4e722be0c29decc9afde8.zip
add most of the state tracking for users within channels
Diffstat (limited to 'window.cpp')
-rw-r--r--window.cpp224
1 files changed, 222 insertions, 2 deletions
diff --git a/window.cpp b/window.cpp
index 4f71982..f48164c 100644
--- a/window.cpp
+++ b/window.cpp
@@ -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;
+}