diff options
Diffstat (limited to 'plugins/irc.py')
-rw-r--r-- | plugins/irc.py | 303 |
1 files changed, 279 insertions, 24 deletions
diff --git a/plugins/irc.py b/plugins/irc.py index 6341851e..065b1e62 100644 --- a/plugins/irc.py +++ b/plugins/irc.py @@ -4,8 +4,9 @@ Plugin destined to be used together with the Biboumi IRC gateway. For more information about Biboumi, please see the `official website`_. This plugin is here as a non-default extension of the poezio configuration -made to work with IRC rooms and logins. Therefore, it does not define any -commands or do anything useful except on load. +made to work with IRC rooms and logins. It also defines commands aimed at +reducing the amount of effort needed to navigate smoothly between IRC and +XMPP rooms. Configuration ------------- @@ -21,6 +22,14 @@ Global configuration The JID of the IRC gateway to use. If empty, irc.poez.io will be used. Please try to run your own, though, it’s painless to setup. + initial_connect + **Default:** ``true`` + + If you want to join all the rooms and try to authenticate with + nickserv when the plugin gets loaded. If ``false``, you will have + to use the :term:`/irc_login` command to authenticate, and the + :term:`/irc_join` command to join preconfigured rooms. + .. note:: There is no nickname option because the default from poezio will be used. Server-specific configuration @@ -49,14 +58,46 @@ section name, and the following options: Your nickname on this server. If empty, the default configuration will be used. - rooms + rooms [IRC plugin] **Default:** ``[empty]`` The list of rooms to join on this server (e.g. ``#room1:#room2``). .. note:: If no login_command or login_nick is set, the authentication phase - won’t take place and you will join the rooms after a small delay. + won’t take place and you will join the rooms without authentication + with nickserv or whatever. + +Commands +~~~~~~~~ + +.. glossary:: + :sorted: + + /irc_login + **Usage:** ``/irc_login [server1] [server2]…`` + Authenticate with the specified servers if they are correctly + configured. If no servers are provided, the plugin will try + them all. (You need to set :term:`login_nick` and + :term:`login_command` as well) + + /irc_join + **Usage:** ``/irc_join <room or server>`` + + Join the specified room on the same server as the current tab (can + be a private conversation or a chatroom). If a server that appears + in the conversation is specified instead of a room, the plugin + will try to join all the rooms configured with autojoin on that + server. + + /irc_query + **Usage:** ``/irc_query <nickname> [message]`` + + Open a private conversation with the given nickname, on the same IRC + server as the current tab (can be a private conversation or a + chatroom). Doing `/irc_query foo "hello there"` when the current + tab is #foo%irc.example.com@biboumi.example.com is equivalent to + `/message foo!irc.example.com@biboumi.example.com "hello there"` Example configuration ~~~~~~~~~~~~~~~~~~~~~ @@ -69,7 +110,7 @@ Example configuration [irc.freenode.net] nickname = mynick login_nick = nickserv - login_command = identify mynick mypassword + login_command = identify mypassword rooms = #testroom1:#testroom2 [irc.geeknode.org] @@ -81,41 +122,255 @@ Example configuration .. _official website: http://biboumi.louiz.org/ + """ from plugin import BasePlugin +from decorators import command_args_parser +import common +import tabs class Plugin(BasePlugin): - def init(self): - - def join(server): - "Join rooms after a small delay" - nick = self.config.get('nickname', '', server) or self.core.own_nick - rooms = self.config.get('rooms', '', server).split(':') - for room in rooms: - room = '{}%{}@{}/{}'.format(room, server, gateway, nick) - self.core.command_join(room) + def init(self): + if self.config.get('initial_connect', True): + self.initial_connect() + + self.api.add_command('irc_login', self.command_irc_login, + usage='[server] [server]…', + help=('Connect to the specified servers if they ' + 'exist in the configuration and the login ' + 'options are set. If not is given, the ' + 'plugin will try all the sections in the ' + 'configuration.'), + short='Login to irc servers with nickserv', + completion=self.completion_irc_login) + + self.api.add_command('irc_join', self.command_irc_join, + usage='<room or server>', + help=('Join <room> in the same server as the ' + 'current tab (if it is an IRC tab). Or ' + 'join all the preconfigured rooms in ' + '<server> '), + short='Join irc rooms more easily', + completion=self.completion_irc_join) + + self.api.add_command('irc_query', self.command_irc_query, + usage='<nickname> [message]', + help=('Open a private conversation with the ' + 'given <nickname>, on the current IRC ' + 'server. Optionally immediately send ' + 'the given message. For example, if the ' + 'current tab is #foo%irc.example.com@' + 'biboumi.example.com, doing `/irc_query ' + 'nick "hi there"` is equivalent to ' + '`/message nick!irc.example.com@biboumi.' + 'example.com "hi there"`'), + short='Open a private conversation with an IRC user') + + def join(self, gateway, server): + "Join irc rooms on a server" + nick = self.config.get_by_tabname('nickname', server, default='') or self.core.own_nick + rooms = self.config.get_by_tabname('rooms', server, default='').split(':') + for room in rooms: + room = '{}%{}@{}/{}'.format(room, server, gateway, nick) + self.core.command_join(room) + + def initial_connect(self): gateway = self.config.get('gateway', 'irc.poez.io') sections = self.config.sections() for section in (s for s in sections if s != 'irc'): - server_suffix = '%{}@{}'.format(section, gateway) + + room_suffix = '%{}@{}'.format(section, gateway) already_opened = False for tab in self.core.tabs: - if tab.name.endswith(server_suffix): + if tab.name.endswith(room_suffix) and tab.joined: already_opened = True + break - login_command = self.config.get('login_command', '', section) - login_nick = self.config.get('login_nick', '', section) - nick = self.config.get('nickname', '', section) or self.core.own_nick - + login_command = self.config.get_by_tabname('login_command', section, default='') + login_nick = self.config.get_by_tabname('login_nick', section, default='') + nick = self.config.get_by_tabname('nickname', section, default='') or self.core.own_nick if login_command and login_nick: - dest = '{}{}/{}'.format(login_nick, server_suffix, nick) + def login(gw, sect, log_nick, log_cmd, room_suff): + dest = '{}!{}'.format(log_nick, room_suff) + self.core.xmpp.send_message(mto=dest, mbody=log_cmd, mtype='chat') + delayed = self.api.create_delayed_event(5, self.join, gw, sect) + self.api.add_timed_event(delayed) + if not already_opened: + self.core.command_join(room_suffix + '/' + nick) + delayed = self.api.create_delayed_event(5, login, gateway, section, + login_nick, login_command, + room_suffix[1:]) + self.api.add_timed_event(delayed) + else: + login(gateway, section, login_nick, login_command, room_suffix[1:]) + elif not already_opened: + self.join(gateway, section) + + @command_args_parser.quoted(0, -1) + def command_irc_login(self, args): + """ + /irc_login [server] [server]… + """ + gateway = self.config.get('gateway', 'irc.poez.io') + if args: + not_present = [] + sections = self.config.sections() + for section in args: + if section not in sections: + not_present.append(section) + continue + login_command = self.config.get_by_tabname('login_command', section, default='') + login_nick = self.config.get_by_tabname('login_nick', section, default='') + if not login_command and not login_nick: + not_present.append(section) + continue + + room_suffix = '%{}@{}'.format(section, gateway) + dest = '{}!{}'.format(login_nick, room_suffix[1:]) + self.core.xmpp.send_message(mto=dest, mbody=login_command, mtype='chat') + if len(not_present) == 1: + self.api.information('Section %s does not exist or is not configured' % not_present[0], 'Warning') + elif len(not_present) > 1: + self.api.information('Sections %s do not exist or are not configured' % ', '.join(not_present), 'Warning') + else: + sections = self.config.sections() + + for section in (s for s in sections if s != 'irc'): + login_command = self.config.get_by_tabname('login_command', section, default='') + login_nick = self.config.get_by_tabname('login_nick', section, default='') + if not login_nick and not login_command: + continue + + room_suffix = '%{}@{}'.format(section, gateway) + dest = '{}!{}'.format(login_nick, room_suffix[1:]) self.core.xmpp.send_message(mto=dest, mbody=login_command, mtype='chat') - if not already_opened: - delayed = self.api.create_delayed_event(5, join, section) - self.api.add_timed_event(delayed) + + def completion_irc_login(self, the_input): + """ + completion for /irc_login + """ + args = the_input.text.split() + if '' in args: + args.remove('') + pos = the_input.get_argument_position() + sections = self.config.sections() + if 'irc' in sections: + sections.remove('irc') + for section in args: + try: + sections.remove(section) + except: + pass + return the_input.new_completion(sections, pos) + + @command_args_parser.quoted(1, 1) + def command_irc_join(self, args): + """ + /irc_join <room or server> + """ + if not args: + return self.core.command_help('irc_join') + sections = self.config.sections() + if 'irc' in sections: + sections.remove('irc') + if args[0] in sections and self.config.get_by_tabname('rooms', args[0]): + self.join_server_rooms(args[0]) + else: + self.join_room(args[0]) + + @command_args_parser.quoted(1, 1) + def command_irc_query(self, args): + """ + Open a private conversation with the given nickname, on the current IRC + server. + """ + if args is None: + return self.core.command_help('irc_query') + current_tab_info = self.get_current_tab_irc_info() + if not current_tab_info: + return + server, gateway = current_tab_info + nickname = args[0] + message = None + if len(args) == 2: + message = args[1] + jid = '{}!{}@{}'.format(nickname, server, gateway) + if message: + self.core.command_message('{} "{}"'.format(jid, message)) + else: + self.core.command_message('{}'.format(jid)) + + def join_server_rooms(self, section): + """ + Join all the rooms configured for a section + (section = irc server) + """ + gateway = self.config.get('gateway', 'irc.poez.io') + rooms = self.config.get_by_tabname('rooms', section).split(':') + nick = self.config.get_by_tabname('nickname', section) + if nick: + nick = '/' + nick + else: + nick = '' + suffix = '%{}@{}{}'.format(section, gateway, nick) + + for room in rooms: + self.core.command_join(room + suffix) + + def join_room(self, name): + """ + Join a room with only its name and the current tab + """ + current_tab_info = self.get_current_tab_irc_info() + if not current_tab_info: + return + server, gateway = current_tab_info + + room = '{}%{}@{}'.format(name, server, gateway) + if self.config.get_by_tabname('nickname', server): + room += '/' + self.config.get_by_tabname('nickname', server) + + self.core.command_join(room) + + def get_current_tab_irc_info(self): + """ + Return a tuple with the irc server and the gateway hostnames of the + current tab. If the current tab is not an IRC channel or private + conversation, a warning is displayed and None is returned + """ + gateway = self.config.get('gateway', 'irc.poez.io') + current = self.core.current_tab() + current_jid = common.safeJID(current.name) + if not current_jid.server == gateway: + self.api.information('The current tab does not appear to be an IRC one', 'Warning') + return None + if isinstance(current, tabs.OneToOneTab): + if not '!' in current_jid.node: + server = current_jid.node + else: + ignored, server = current_jid.node.rsplit('!', 1) + elif isinstance(current, tabs.MucTab): + if not '%' in current_jid.node: + server = current_jid.node + else: + ignored, server = current_jid.node.rsplit('%', 1) + else: + self.api.information('The current tab does not appear to be an IRC one', 'Warning') + return None + return server, gateway + + def completion_irc_join(self, the_input): + """ + completion for /irc_join + """ + sections = self.config.sections() + if 'irc' in sections: + sections.remove('irc') + return the_input.new_completion(sections, 1) + |