From 83147625a47687b6b2a0c244ca668141e30ddf2e Mon Sep 17 00:00:00 2001 From: GermainZ Date: Tue, 17 Feb 2015 16:41:23 +0200 Subject: [PATCH 1/5] Don't expose hashes in the channel names --- pickups/util.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pickups/util.py b/pickups/util.py index a3d14b9..f48e7fe 100644 --- a/pickups/util.py +++ b/pickups/util.py @@ -6,21 +6,23 @@ CONV_HASH_LEN = 7 +hashes = {} def conversation_to_channel(conv): """Return channel name for hangups.Conversation.""" # Must be 50 characters max and not contain space or comma. - conv_hash = hashlib.sha1(conv.id_.encode()).hexdigest() name = get_conv_name(conv).replace(',', '_').replace(' ', '') - return '#{}[{}]'.format(name[:50 - CONV_HASH_LEN - 3], - conv_hash[:CONV_HASH_LEN]) + name = "#{}".format(name[:49]) + conv_hash = hashlib.sha1(conv.id_.encode()).hexdigest() + hashes[name] = conv_hash + return name def channel_to_conversation(channel, conv_list): """Return hangups.Conversation for channel name.""" - conv_hash = re.match(r'^.*\[([a-f0-9]+)\]$', channel).group(1) - return {hashlib.sha1(conv.id_.encode()).hexdigest()[:CONV_HASH_LEN]: conv - for conv in conv_list.get_all()}[conv_hash] + conv_hash = hashes[channel] + return {hashlib.sha1(conv.id_.encode()).hexdigest(): conv for conv in + conv_list.get_all()}[conv_hash] def get_nick(user): From 3555cdad4ff7d4b8b38c9bb02ed917d5c9e5a441 Mon Sep 17 00:00:00 2001 From: GermainZ Date: Tue, 17 Feb 2015 17:57:38 +0200 Subject: [PATCH 2/5] Automatically join channel if new message is received --- pickups/irc.py | 6 +++++- pickups/server.py | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pickups/irc.py b/pickups/irc.py index aef6025..7e29cfb 100644 --- a/pickups/irc.py +++ b/pickups/irc.py @@ -26,6 +26,7 @@ def __init__(self, reader, writer): self.nickname = None self.sent_messages = [] + self.joined_channels = set() def readline(self): return self.reader.readline() @@ -62,7 +63,8 @@ def list_channels(self, info): def join(self, channel): """Tells the client to join a channel.""" - self.write(self.nickname, 'JOIN', ':{}'.format(channel)) + self.joined_channels.add(channel) + self.write(self.nickname, 'JOIN', channel) def list_nicks(self, channel, nicks): """Tells the client what nicks are in channel.""" @@ -85,6 +87,8 @@ def topic(self, channel, topic): def privmsg(self, hostmask, target, message): """Sends the client a message from someone.""" + if target not in self.joined_channels: + self.join(target) for line in message.splitlines(): if line: self.write(hostmask, 'PRIVMSG', target, ':{}'.format(line)) diff --git a/pickups/server.py b/pickups/server.py index 96e07d3..03627b7 100644 --- a/pickups/server.py +++ b/pickups/server.py @@ -112,6 +112,10 @@ def _handle_client(self, client): client.topic(channel, util.get_topic(conv)) client.list_nicks(channel, (util.get_nick(user) for user in conv.users)) + client.joined_channels.add(channel) + elif line.startswith('PART'): + channel = line.split(' ')[1] + client.joined_channels.remove(channel) elif line.startswith('WHO'): query = line.split(' ')[1] if query.startswith('#'): From cabec652e264c7b8f1fd88d7fe8dc42ada69ba5e Mon Sep 17 00:00:00 2001 From: GermainZ Date: Tue, 17 Feb 2015 18:52:33 +0200 Subject: [PATCH 3/5] Set topic/nicklist when channel is joined automatically --- pickups/irc.py | 8 +++++++- pickups/server.py | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pickups/irc.py b/pickups/irc.py index 7e29cfb..2e8e73c 100644 --- a/pickups/irc.py +++ b/pickups/irc.py @@ -1,4 +1,5 @@ import logging +from . import util RPL_WELCOME = 1 RPL_WHOISUSER = 311 @@ -20,7 +21,8 @@ class Client(object): - def __init__(self, reader, writer): + def __init__(self, server, reader, writer): + self.server = server self.reader = reader self.writer = writer @@ -65,6 +67,10 @@ def join(self, channel): """Tells the client to join a channel.""" self.joined_channels.add(channel) self.write(self.nickname, 'JOIN', channel) + conv = util.channel_to_conversation(channel, self.server._conv_list) + self.topic(channel, util.get_topic(conv)) + self.list_nicks(channel, (util.get_nick(user) for user in conv.users)) + def list_nicks(self, channel, nicks): """Tells the client what nicks are in channel.""" diff --git a/pickups/server.py b/pickups/server.py index 03627b7..e63353e 100644 --- a/pickups/server.py +++ b/pickups/server.py @@ -58,7 +58,7 @@ def _on_hangups_event(self, conv_event): def _on_client_connect(self, client_reader, client_writer): """Called when an IRC client connects.""" - client = irc.Client(client_reader, client_writer) + client = irc.Client(self, client_reader, client_writer) task = asyncio.Task(self._handle_client(client)) self.clients[task] = client logger.info("New Connection") From 37c2892e19eb2364bcd22afeae9ff38cef226efd Mon Sep 17 00:00:00 2001 From: GermainZ Date: Tue, 17 Feb 2015 18:56:27 +0200 Subject: [PATCH 4/5] Fix: 'channel' referenced before assignment --- pickups/server.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pickups/server.py b/pickups/server.py index e63353e..3d1c23b 100644 --- a/pickups/server.py +++ b/pickups/server.py @@ -119,6 +119,7 @@ def _handle_client(self, client): elif line.startswith('WHO'): query = line.split(' ')[1] if query.startswith('#'): + channel = line.split(' ')[1] conv = util.channel_to_conversation(channel, self._conv_list) responses = [{ From 50a23c897d69dba96f290316cbd84b297e8fa12b Mon Sep 17 00:00:00 2001 From: GermainZ Date: Tue, 17 Feb 2015 19:19:08 +0200 Subject: [PATCH 5/5] Avoid channel name collisions --- pickups/util.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pickups/util.py b/pickups/util.py index f48e7fe..61a1931 100644 --- a/pickups/util.py +++ b/pickups/util.py @@ -14,6 +14,13 @@ def conversation_to_channel(conv): name = get_conv_name(conv).replace(',', '_').replace(' ', '') name = "#{}".format(name[:49]) conv_hash = hashlib.sha1(conv.id_.encode()).hexdigest() + # Avoid name collisions. + if name in hashes and hashes[name] != conv_hash: + while name in hashes: + if len(name) > 50: + name = "{}_".format(name[:-1]) + else: + name = "{}_".format(name) hashes[name] = conv_hash return name