From bdbdb57fc3ae81c0dbb46c4e6ffdd6c0205a81c0 Mon Sep 17 00:00:00 2001 From: Treeki Date: Sat, 25 Jan 2014 01:34:11 +0100 Subject: add channel topic tracking --- bouncer/core.h | 3 +++ bouncer/ircserver.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ bouncer/window.cpp | 37 +++++++++++++++++++++++++++++++++ python_client.py | 18 ++++++++++++++-- 4 files changed, 113 insertions(+), 2 deletions(-) diff --git a/bouncer/core.h b/bouncer/core.h index 7236ff7..1d6b9db 100644 --- a/bouncer/core.h +++ b/bouncer/core.h @@ -102,6 +102,8 @@ public: void handleNick(const UserRef &user, const char *newNick); void handleMode(const UserRef &user, const char *str); void handlePrivmsg(const UserRef &user, const char *str); + void handleTopic(const UserRef &user, const char *message); + void handleTopicInfo(const char *user, int timestamp); char getEffectivePrefixChar(const char *nick) const; @@ -173,6 +175,7 @@ struct Packet { B2C_CHANNEL_USER_REMOVE = 0x121, B2C_CHANNEL_USER_RENAME = 0x122, B2C_CHANNEL_USER_MODES = 0x123, + B2C_CHANNEL_TOPIC = 0x124, C2B_OOB_LOGIN = 0x8001, diff --git a/bouncer/ircserver.cpp b/bouncer/ircserver.cpp index ecf5c64..3b09d49 100644 --- a/bouncer/ircserver.cpp +++ b/bouncer/ircserver.cpp @@ -233,6 +233,13 @@ void IRCServer::lineReceivedEvent(char *line, int size) { return; } + } else if (strcmp(cmdBuf, "TOPIC") == 0) { + Channel *c = findChannel(targetBuf, false); + if (c) { + c->handleTopic(user, paramsAfterFirst); + return; + } + } else if (strcmp(cmdBuf, "PRIVMSG") == 0) { Channel *c = findChannel(targetBuf, true); if (c) { @@ -251,6 +258,56 @@ void IRCServer::lineReceivedEvent(char *line, int size) { processISupport(paramsAfterFirst); return; + } else if (strcmp(cmdBuf, "331") == 0) { + // RPL_NOTOPIC: + // Params: Channel name, *maybe* text we can ignore + + char *space = strchr(paramsAfterFirst, ' '); + if (space) + *space = 0; + + Channel *c = findChannel(paramsAfterFirst, false); + if (c) { + c->handleTopic(UserRef(), ""); + return; + } + + } else if (strcmp(cmdBuf, "332") == 0) { + // RPL_TOPIC: + // Params: Channel name, text + + char *space = strchr(paramsAfterFirst, ' '); + if (space) { + *space = 0; + + char *topic = space + 1; + if (*topic == ':') + ++topic; + + Channel *c = findChannel(paramsAfterFirst, false); + if (c) { + c->handleTopic(UserRef(), topic); + return; + } + } + + } else if (strcmp(cmdBuf, "333") == 0) { + // Topic set + + char *strtok_var; + char *chanName = strtok_r(paramsAfterFirst, " ", &strtok_var); + char *setBy = strtok_r(NULL, " ", &strtok_var); + char *when = strtok_r(NULL, " ", &strtok_var); + + if (chanName && setBy && when) { + Channel *c = findChannel(chanName, false); + + if (c) { + c->handleTopicInfo(setBy, atoi(when)); + return; + } + } + } else if (strcmp(cmdBuf, "353") == 0) { // RPL_NAMEREPLY: // Target is always us diff --git a/bouncer/window.cpp b/bouncer/window.cpp index bf50325..5371176 100644 --- a/bouncer/window.cpp +++ b/bouncer/window.cpp @@ -447,6 +447,43 @@ void Channel::handlePrivmsg(const UserRef &user, const char *str) { } + + +void Channel::handleTopic(const UserRef &user, const char *message) { + char buf[1024]; + + if (user.isValid) { + snprintf(buf, sizeof(buf), + "%s changed the topic to: %s", + user.nick.c_str(), + message); + } else { + snprintf(buf, sizeof(buf), + "Topic: %s", + message); + } + pushMessage(buf); + + topic = message; + + Buffer packet; + packet.writeU32(id); + packet.writeStr(message); + server->bouncer->sendToClients( + Packet::B2C_CHANNEL_TOPIC, packet); +} + +void Channel::handleTopicInfo(const char *user, int timestamp) { + char buf[1024]; + snprintf(buf, sizeof(buf), + "Topic set by %s at %d", + user, + timestamp); + pushMessage(buf); +} + + + char Channel::getEffectivePrefixChar(const char *nick) const { auto i = users.find(nick); if (i == users.end()) diff --git a/python_client.py b/python_client.py index 11c4a50..4e7f1a3 100644 --- a/python_client.py +++ b/python_client.py @@ -61,7 +61,7 @@ def reader(): pos = 0 bufsize = len(readbuf) - print('[bufsize: %d]' % bufsize) + #print('[bufsize: %d]' % bufsize) while True: if (pos + 8) > bufsize: break @@ -107,7 +107,7 @@ def reader(): pos += size - print('[processed %d bytes]' % pos) + #print('[processed %d bytes]' % pos) readbuf = readbuf[pos:] def writePacket(type, data, allowUnauthed=False): @@ -179,11 +179,14 @@ class ChannelTab(WindowTab): def __init__(self, parent=None): WindowTab.__init__(self, parent) + self.topicLabel = QtWidgets.QLabel(self) + self.topicLabel.setWordWrap(True) self.userList = QtWidgets.QListWidget(self) self.users = {} def makeLayout(self): sublayout = QtWidgets.QVBoxLayout() + sublayout.addWidget(self.topicLabel) sublayout.addWidget(self.output) sublayout.addWidget(self.input) @@ -217,6 +220,8 @@ class ChannelTab(WindowTab): self.topic = pdata[pos:pos+topiclen].decode('utf-8', 'replace') pos += topiclen + self.topicLabel.setText(self.topic) + return pos def addUsers(self, pdata): @@ -284,6 +289,11 @@ class ChannelTab(WindowTab): uo.prefix = prefix uo.syncItemText() + def changeTopic(self, pdata): + tlen = u32.unpack_from(pdata, 4)[0] + self.topic = pdata[8:8+tlen].decode('utf-8', 'replace') + self.topicLabel.setText(self.topic) + class MainWindow(QtWidgets.QMainWindow): def __init__(self, parent=None): @@ -370,6 +380,10 @@ class MainWindow(QtWidgets.QMainWindow): # Change user modes in channel wndID = u32.unpack_from(pdata, 0)[0] self.tabLookup[wndID].changeUserMode(pdata) + elif ptype == 0x124: + # Change topic in channel + wndID = u32.unpack_from(pdata, 0)[0] + self.tabLookup[wndID].changeTopic(pdata) return True else: -- cgit v1.2.3