summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormathieui <mathieui@mathieui.net>2014-04-14 22:32:34 +0200
committermathieui <mathieui@mathieui.net>2014-04-14 22:32:34 +0200
commit3221534b0f77a00043032c1e350814f607a56380 (patch)
tree6c7bd391e3c2e70c40efdb0c0249d676036899a3
parent245f5f050cd1b72f365a21c57d3462ed5207e0cc (diff)
downloadpoezio-3221534b0f77a00043032c1e350814f607a56380.tar.gz
poezio-3221534b0f77a00043032c1e350814f607a56380.tar.bz2
poezio-3221534b0f77a00043032c1e350814f607a56380.tar.xz
poezio-3221534b0f77a00043032c1e350814f607a56380.zip
Implement XEP-0249 (Direct MUC Invitations)
- fallback to mediated invitations if only the bare jid is given to the command or if the jid does not advertise support TODO: provide a way to send passwords
-rw-r--r--doc/source/dev/xep.rst2
-rw-r--r--src/connection.py1
-rw-r--r--src/core/commands.py6
-rw-r--r--src/core/completions.py7
-rw-r--r--src/core/core.py28
-rw-r--r--src/core/handlers.py34
6 files changed, 71 insertions, 7 deletions
diff --git a/doc/source/dev/xep.rst b/doc/source/dev/xep.rst
index 7cfffa20..7d303a03 100644
--- a/doc/source/dev/xep.rst
+++ b/doc/source/dev/xep.rst
@@ -50,6 +50,8 @@ Table of all XEPs implemented in poezio.
+----------+-------------------------+---------------------+
|0245 |The /me Command |80% |
+----------+-------------------------+---------------------+
+|0249 |Direct MUC Invitations |90% |
++----------+-------------------------+---------------------+
|0280 |Messsage Carbons |100% |
+----------+-------------------------+---------------------+
|0296 |Best Practices for |100% |
diff --git a/src/connection.py b/src/connection.py
index bf84bd6d..5dc7c8e4 100644
--- a/src/connection.py
+++ b/src/connection.py
@@ -115,6 +115,7 @@ class Connection(sleekxmpp.ClientXMPP):
if config.get('send_time', True):
self.register_plugin('xep_0202')
self.register_plugin('xep_0224')
+ self.register_plugin('xep_0249')
self.register_plugin('xep_0280')
self.register_plugin('xep_0297')
self.register_plugin('xep_0308')
diff --git a/src/core/commands.py b/src/core/commands.py
index 39bf505d..dcbd762f 100644
--- a/src/core/commands.py
+++ b/src/core/commands.py
@@ -698,10 +698,10 @@ def command_invite(self, arg):
args = common.shell_split(arg)
if len(args) < 2:
return
- reason = args[2] if len(args) > 2 else ''
+ reason = args[2] if len(args) > 2 else None
to = safeJID(args[0])
- room = safeJID(args[1])
- self.xmpp.plugin['xep_0045'].invite(room, str(to), reason)
+ room = safeJID(args[1]).bare
+ self.invite(to.full, room, reason=reason)
def command_decline(self, arg):
"""/decline <room@server.tld> [reason]"""
diff --git a/src/core/completions.py b/src/core/completions.py
index 1df8d23d..75122885 100644
--- a/src/core/completions.py
+++ b/src/core/completions.py
@@ -249,7 +249,12 @@ def completion_invite(self, the_input):
"""Completion for /invite"""
n = the_input.get_argument_position(quoted=True)
if n == 1:
- return the_input.new_completion(sorted(jid for jid in roster.jids()), n, quotify=True)
+ comp = reduce(lambda x, y: x + [i.jid for i in y], (roster[jid].resources for jid in roster.jids() if len(roster[jid])), [])
+ comp = sorted(comp)
+ bares = sorted(roster[contact].bare_jid for contact in roster.jids() if len(roster[contact]))
+ off = sorted(jid for jid in roster.jids() if jid not in bares)
+ comp = comp + bares + off
+ return the_input.new_completion(comp, n, quotify=True)
elif n == 2:
rooms = []
for tab in self.get_tabs(tabs.MucTab):
diff --git a/src/core/core.py b/src/core/core.py
index 41cb9586..b41bb1a4 100644
--- a/src/core/core.py
+++ b/src/core/core.py
@@ -188,7 +188,8 @@ class Core(object):
self.xmpp.add_event_handler("session_start", self.on_session_start_features)
self.xmpp.add_event_handler("groupchat_presence", self.on_groupchat_presence)
self.xmpp.add_event_handler("groupchat_message", self.on_groupchat_message)
- self.xmpp.add_event_handler("groupchat_invite", self.on_groupchat_invite)
+ self.xmpp.add_event_handler("groupchat_invite", self.on_groupchat_invitation)
+ self.xmpp.add_event_handler("groupchat_direct_invite", self.on_groupchat_direct_invitation)
self.xmpp.add_event_handler("groupchat_decline", self.on_groupchat_decline)
self.xmpp.add_event_handler("groupchat_config_status", self.on_status_codes)
self.xmpp.add_event_handler("groupchat_subject", self.on_groupchat_subject)
@@ -705,6 +706,27 @@ class Core(object):
self.current_tab().command_say(msg)
return True
+ def invite(self, jid, room, reason=None):
+ """
+ Checks if the sender supports XEP-0249, then send an invitation,
+ or a mediated one if it does not.
+ TODO: allow passwords
+ """
+ def callback(iq):
+ if not iq:
+ return
+ if 'jabber:x:conference' in iq['disco_info'].get_features():
+ self.xmpp.plugin['xep_0249'].send_invitation(
+ jid,
+ room,
+ reason=reason)
+ else: # fallback
+ self.xmpp.plugin['xep_0045'].invite(room, jid,
+ reason=reason or '')
+
+ self.xmpp.plugin['xep_0030'].get_info(jid=jid, block=False,
+ timeout=5, callback=callback)
+
def get_error_message(self, stanza, deprecated=False):
"""
Takes a stanza of the form <message type='error'><error/></message>
@@ -1422,6 +1444,7 @@ class Core(object):
if not desc and shortdesc:
desc = shortdesc
self.commands[name] = Command(func, desc, completion, shortdesc, usage)
+
def register_initial_commands(self):
"""
Register the commands when poezio starts
@@ -1623,7 +1646,8 @@ class Core(object):
on_session_start_features = handlers.on_session_start_features
on_carbon_received = handlers.on_carbon_received
on_carbon_sent = handlers.on_carbon_sent
- on_groupchat_invite = handlers.on_groupchat_invite
+ on_groupchat_invitation = handlers.on_groupchat_invitation
+ on_groupchat_direct_invitation = handlers.on_groupchat_direct_invitation
on_groupchat_decline = handlers.on_groupchat_decline
on_message = handlers.on_message
on_normal_message = handlers.on_normal_message
diff --git a/src/core/handlers.py b/src/core/handlers.py
index 076bd986..b0256246 100644
--- a/src/core/handlers.py
+++ b/src/core/handlers.py
@@ -76,7 +76,10 @@ def on_carbon_sent(self, message):
### Invites ###
-def on_groupchat_invite(self, message):
+def on_groupchat_invitation(self, message):
+ """
+ Mediated invitation received
+ """
jid = message['from']
if jid.bare in self.pending_invites:
return
@@ -97,8 +100,37 @@ def on_groupchat_invite(self, message):
self.pending_invites[jid.bare] = inviter.full
def on_groupchat_decline(self, decline):
+ "Mediated invitation declined; skip for now"
pass
+def on_groupchat_direct_invitation(self, message):
+ """
+ Direct invitation received
+ """
+ room = safeJID(message['groupchat_invite']['jid'])
+ if room.bare in self.pending_invites:
+ return
+
+ inviter = message['from']
+ reason = message['groupchat_invite']['reason']
+ password = message['groupchat_invite']['password']
+ continue_ = message['groupchat_invite']['continue']
+ msg = "You are invited to the room %s by %s" % (room, inviter.full)
+
+ if password:
+ msg += ' (password: "%s")' % password
+ if continue_:
+ msg += '\nto continue the discussion'
+ if reason:
+ msg += "\nreason: %s" % reason
+
+ self.information(msg, 'Info')
+ if 'invite' in config.get('beep_on', 'invite').split():
+ curses.beep()
+
+ self.pending_invites[room.bare] = inviter.full
+ logger.log_roster_change(inviter.full, 'invited you to %s' % room.bare)
+
### "classic" messages ###
def on_message(self, message):