diff --git a/pickups/__main__.py b/pickups/__main__.py index a6a6b8d..5918f3c 100644 --- a/pickups/__main__.py +++ b/pickups/__main__.py @@ -12,14 +12,16 @@ logging.basicConfig(level=logging.INFO, stream=sys.stdout) logging.getLogger('hangups').setLevel(logging.WARNING) dirs = appdirs.AppDirs('hangups', 'hangups') - default_cookies_path = os.path.join(dirs.user_cache_dir, 'cookies.json') - cookies = hangups.auth.get_auth_stdin(default_cookies_path) parser = argparse.ArgumentParser(description='IRC Gateway for Hangouts') + parser.add_argument('--cookies', help='cookies filename', default='cookies.json') parser.add_argument('--address', help='bind address', default='127.0.0.1') parser.add_argument('--port', help='bind port', default=6667) parser.add_argument('--ascii-smileys', action='store_true', help='display smileys in ascii') args = parser.parse_args() + default_cookies_path = os.path.join(dirs.user_cache_dir, args.cookies) + cookies = hangups.auth.get_auth_stdin(default_cookies_path) + Server(cookies, args.ascii_smileys).run(args.address, args.port) diff --git a/pickups/irc.py b/pickups/irc.py index 040a73d..cd7d216 100644 --- a/pickups/irc.py +++ b/pickups/irc.py @@ -1,4 +1,5 @@ import logging +from . import util RPL_WELCOME = 1 RPL_WHOISUSER = 311 @@ -22,12 +23,14 @@ class Client(object): - def __init__(self, reader, writer): + def __init__(self, server, reader, writer): + self.server = server self.reader = reader self.writer = writer self.nickname = None self.sent_messages = [] + self.joined_channels = set() def readline(self): return self.reader.readline() @@ -64,7 +67,12 @@ 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) + 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.""" @@ -87,6 +95,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 e5f5759..8269ad0 100644 --- a/pickups/server.py +++ b/pickups/server.py @@ -57,7 +57,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") @@ -102,25 +102,37 @@ def _handle_client(self, client): segments = hangups.ChatMessageSegment.from_str(message[1:]) asyncio.async(conv.send_message(segments)) elif line.startswith('JOIN'): - channel = line.split(' ')[1] - conv = util.channel_to_conversation(channel, self._conv_list) - if not conv: - client.swrite(irc.ERR_NOSUCHCHANNEL, - ':{}: Channel not found'.format(channel)) - else: - # If a JOIN is successful, the user receives a JOIN message - # as confirmation and is then sent the channel's topic - # (using RPL_TOPIC) and the list of users who are on the - # channel (using RPL_NAMREPLY), which MUST include the user - # joining. + channel_line = line.split(' ')[1] + channels = channel_line.split(',') + for channel in channels: + conv = util.channel_to_conversation(channel, self._conv_list) + if not conv: + client.swrite(irc.ERR_NOSUCHCHANNEL, + ':{}: Channel not found'.format(channel)) + else: + # If a JOIN is successful, the user receives a JOIN message + # as confirmation and is then sent the channel's topic + # (using RPL_TOPIC) and the list of users who are on the + # channel (using RPL_NAMREPLY), which MUST include the user + # joining. + client.write(util.get_nick(self._user_list._self_user), + 'JOIN', channel) + 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 = line.split(' ')[1] + channels = channel_line.split(',') + for channel in channels: + if channel in client.joined_channels: + client.joined_channels.remove(channel) client.write(util.get_nick(self._user_list._self_user), - 'JOIN', channel) - client.topic(channel, util.get_topic(conv)) - client.list_nicks(channel, (util.get_nick(user) - for user in conv.users)) + 'PART', channel) elif line.startswith('WHO'): query = line.split(' ')[1] if query.startswith('#'): + channel = line.split(' ')[1] conv = util.channel_to_conversation(channel, self._conv_list) if not conv: