From 33371638a8985df53f86ed9297b9e57c9f46c015 Mon Sep 17 00:00:00 2001 From: Treeki Date: Fri, 24 Jan 2014 20:28:25 +0100 Subject: show nick prefixes in client nicklist, sync modes correctly --- bouncer/core.h | 1 + bouncer/ircserver.cpp | 15 ++++++++++++ bouncer/window.cpp | 30 ++++++++++------------- python_client.py | 66 +++++++++++++++++++++++++++++++++++---------------- 4 files changed, 74 insertions(+), 38 deletions(-) diff --git a/bouncer/core.h b/bouncer/core.h index b5d3164..7236ff7 100644 --- a/bouncer/core.h +++ b/bouncer/core.h @@ -302,6 +302,7 @@ public: uint32_t getUserFlagByPrefix(char prefix) const; uint32_t getUserFlagByMode(char mode) const; int getChannelModeType(char mode) const; + char getEffectivePrefixChar(uint32_t modes) const; IRCServer(Bouncer *_bouncer); ~IRCServer(); diff --git a/bouncer/ircserver.cpp b/bouncer/ircserver.cpp index 31cbd6d..f13a481 100644 --- a/bouncer/ircserver.cpp +++ b/bouncer/ircserver.cpp @@ -391,3 +391,18 @@ int IRCServer::getChannelModeType(char mode) const { return 0; } + +char IRCServer::getEffectivePrefixChar(uint32_t modes) const { + uint32_t flag = 1; + const char *prefixes = serverPrefix; + + while (*prefixes != 0) { + if (modes & flag) + return *prefixes; + + ++prefixes; + flag <<= 1; + } + + return 0; +} diff --git a/bouncer/window.cpp b/bouncer/window.cpp index c971046..bf50325 100644 --- a/bouncer/window.cpp +++ b/bouncer/window.cpp @@ -152,6 +152,7 @@ void Channel::syncStateForClient(Buffer &output) { for (auto &i : users) { output.writeStr(i.first.c_str()); output.writeU32(i.second); + output.writeU8(server->getEffectivePrefixChar(i.second)); } output.writeStr(topic.c_str()); @@ -196,9 +197,9 @@ void Channel::handleNameReply(const char *str) { users[name] = modes; nameCount++; - //packet.writeU8(getEffectivePrefixChar(name)); packet.writeStr(name); packet.writeU32(modes); + packet.writeU8(server->getEffectivePrefixChar(modes)); // Get the next name name = strtok_r(NULL, " ", &strtok_var); @@ -233,6 +234,7 @@ void Channel::handleJoin(const UserRef &user) { packet.writeU32(1); packet.writeStr(user.nick.c_str()); packet.writeU32(0); + packet.writeU8(0); server->bouncer->sendToClients( Packet::B2C_CHANNEL_USER_ADD, packet); @@ -372,13 +374,21 @@ void Channel::handleMode(const UserRef &user, const char *str) { // 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; + + Buffer packet; + packet.writeU32(id); + packet.writeStr(target); + packet.writeU32(flags); + packet.writeU8(server->getEffectivePrefixChar(flags)); + + server->bouncer->sendToClients( + Packet::B2C_CHANNEL_USER_MODES, packet); } char buf[1024]; @@ -442,21 +452,7 @@ char Channel::getEffectivePrefixChar(const char *nick) const { 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; + return server->getEffectivePrefixChar(i->second); } diff --git a/python_client.py b/python_client.py index 39411c5..11c4a50 100644 --- a/python_client.py +++ b/python_client.py @@ -162,10 +162,25 @@ class WindowTab(QtWidgets.QWidget): self.output.setTextCursor(cursor) class ChannelTab(WindowTab): + class UserEntry: + def __init__(self, nick, prefix, modes, listwidget): + self.nick = nick + self.prefix = prefix + self.modes = modes + self.item = QtWidgets.QListWidgetItem('', listwidget) + self.syncItemText() + + def syncItemText(self): + if self.prefix == 0: + self.item.setText(self.nick) + else: + self.item.setText(chr(self.prefix) + self.nick) + def __init__(self, parent=None): WindowTab.__init__(self, parent) self.userList = QtWidgets.QListWidget(self) + self.users = {} def makeLayout(self): sublayout = QtWidgets.QVBoxLayout() @@ -180,7 +195,7 @@ class ChannelTab(WindowTab): userCount = u32.unpack_from(pdata, pos)[0] pos += 4 - users = [] + users = {} for i in range(userCount): #prefix = pdata[pos] #pos += 1 @@ -190,9 +205,10 @@ class ChannelTab(WindowTab): pos += nicklen modes = u32.unpack_from(pdata, pos)[0] pos += 4 - users.append(nick) - #self.userList.addItem(chr(prefix)+nick) - self.userList.addItem(nick) + prefix = pdata[pos] + pos += 1 + + users[nick] = self.UserEntry(nick, prefix, modes, self.userList) self.users = users @@ -214,14 +230,16 @@ class ChannelTab(WindowTab): pos += nicklen modes = u32.unpack_from(pdata, pos)[0] pos += 4 - self.users.append(nick) - self.userList.addItem(nick) + prefix = pdata[pos] + pos += 1 + + self.users[nick] = self.UserEntry(nick, prefix, modes, self.userList) def removeUsers(self, pdata): userCount = u32.unpack_from(pdata, 4)[0] pos = 8 if userCount == 0: - self.users = [] + self.users = {} self.userList.clear() else: for i in range(userCount): @@ -231,9 +249,10 @@ class ChannelTab(WindowTab): pos += nicklen print('Removing [%s]' % repr(nick)) - self.users.remove(nick) - items = self.userList.findItems(nick, QtCore.Qt.MatchExactly) - self.userList.takeItem(self.userList.row(items[0])) + uo = self.users[nick] + self.userList.takeItem(self.userList.row(uo.item)) + + del self.users[nick] def renameUser(self, pdata): pos = 4 @@ -245,20 +264,25 @@ class ChannelTab(WindowTab): pos += 4 tonick = pdata[pos:pos+nicklen].decode('utf-8', 'replace') - try: - idx = self.users.index(fromnick) - except ValueError: - self.pushMessage('Crap, [%s] was not found in the users list!' % fromnick) - return - - self.users[idx] = tonick + uo = self.users[fromnick] + del self.users[fromnick] + self.users[tonick] = uo - items = self.userList.findItems(fromnick, QtCore.Qt.MatchExactly) - items[0].setText(tonick) + uo.nick = tonick + uo.syncItemText() def changeUserMode(self, pdata): - # boop - pass + pos = 4 + nicklen = u32.unpack_from(pdata, pos)[0] + pos += 4 + nick = pdata[pos:pos+nicklen].decode('utf-8', 'replace') + pos += nicklen + modes, prefix = struct.unpack_from('