Fix #2543 (irc plugin doesn't authenticate properly)

Join the fake room first, then send the message to nickserv, then join
initial rooms.

Also add two commands and one option.
This commit is contained in:
mathieui 2014-12-18 23:39:13 +01:00
parent b720a3f8ca
commit 510372cb39
No known key found for this signature in database
GPG key ID: C59F84CEEFD616E3

View file

@ -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, its 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,37 @@ 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
wont take place and you will join the rooms after a small delay.
wont 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.
Example configuration
~~~~~~~~~~~~~~~~~~~~~
@ -69,7 +101,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]
@ -84,38 +116,202 @@ Example configuration
"""
from plugin import BasePlugin
from decorators import command_args_parser
import common
import tabs
class Plugin(BasePlugin):
def init(self):
if self.config.get('initial_connect', True):
self.initial_connect()
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)
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)
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():
dest = '{}!{}'.format(login_nick, room_suffix[1:])
self.core.xmpp.send_message(mto=dest, mbody=login_command, mtype='chat')
delayed = self.api.create_delayed_event(5, self.join, gateway, section)
self.api.add_timed_event(delayed)
if not already_opened:
self.core.command_join(room_suffix + '/' + nick)
delayed = self.api.create_delayed_event(3, login)
self.api.add_timed_event(delayed)
else:
login()
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])
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
"""
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
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
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 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)