From 0f6205d29bf9a42939e82914c905aab118be4fc7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maxime=20=E2=80=9Cpep=E2=80=9D=20Buquet?= <pep@bouah.net>
Date: Sat, 24 Nov 2018 04:36:19 +0000
Subject: Add /invite for ConversationTab to generate new room with all
 invitees
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
---
 poezio/core/commands.py        | 13 ++++--
 poezio/core/core.py            | 95 ++++++++++++++++++++++++++++--------------
 poezio/tabs/conversationtab.py |  6 +++
 3 files changed, 79 insertions(+), 35 deletions(-)

diff --git a/poezio/core/commands.py b/poezio/core/commands.py
index f301e801..86df9a93 100644
--- a/poezio/core/commands.py
+++ b/poezio/core/commands.py
@@ -6,6 +6,7 @@ import logging
 
 log = logging.getLogger(__name__)
 
+import asyncio
 from xml.etree import cElementTree as ET
 
 from slixmpp.exceptions import XMPPError
@@ -764,17 +765,21 @@ class CommandCore:
         self.core.information('Invited %s to %s' % (to.bare, room), 'Info')
 
     @command_args_parser.quoted(1, 0)
-    def impromptu(self, args):
+    def impromptu(self, args: str) -> None:
         """/impromptu <jid> [<jid> ...]"""
 
         if args is None:
             return self.help('impromptu')
 
-        jids = []
+        jids = set()
+        current_tab = self.core.tabs.current_tab
+        if isinstance(current_tab, tabs.ConversationTab):
+            jids.add(current_tab.general_jid)
+
         for jid in common.shell_split(' '.join(args)):
-            jids.append(safeJID(jid).bare)
+            jids.add(safeJID(jid).bare)
 
-        self.core.impromptu(jids)
+        asyncio.ensure_future(self.core.impromptu(jids))
         self.core.information('Invited %s to a random room' % (' '.join(jids)), 'Info')
 
     @command_args_parser.quoted(1, 1, [''])
diff --git a/poezio/core/core.py b/poezio/core/core.py
index edec3b0c..9ffa59a9 100644
--- a/poezio/core/core.py
+++ b/poezio/core/core.py
@@ -15,11 +15,14 @@ import shutil
 import time
 import uuid
 from collections import defaultdict
-from typing import Callable, Dict, List, Optional, Tuple, Type
+from typing import Callable, Dict, List, Optional, Set, Tuple, Type
+from xml.etree import cElementTree as ET
+from functools import partial
 
 from slixmpp import JID
 from slixmpp.util import FileSystemPerJidCache
 from slixmpp.xmlstream.handler import Callback
+from slixmpp.exceptions import IqError, IqTimeout
 
 from poezio import connection
 from poezio import decorators
@@ -869,7 +872,35 @@ class Core:
         self.xmpp.plugin['xep_0030'].get_info(
             jid=jid, timeout=5, callback=callback)
 
-    def impromptu(self, jids: List[JID]) -> None:
+    def _impromptu_room_form(self, room, _jids):
+        # TODO: Use jids to generate user-friendly room name and description
+        fields = [
+            {'ftype': 'hidden', 'var': 'FORM_TYPE', 'value': 'http://jabber.org/protocol/muc#roomconfig'},
+            {'ftype': 'text-single', 'var': 'muc#roomconfig_roomname', 'value': 'Foo'},
+            {'ftype': 'text-single', 'var': 'muc#roomconfig_roomdesc', 'value': 'Bar'},
+            {'ftype': 'boolean', 'var': 'muc#roomconfig_changesubject', 'value': True},
+            {'ftype': 'boolean', 'var': 'muc#roomconfig_allowinvites', 'value': True},
+            {'ftype': 'boolean', 'var': 'muc#roomconfig_persistent', 'value': True},
+            {'ftype': 'boolean', 'var': 'muc#roomconfig_membersonly', 'value': True},
+            {'ftype': 'boolean', 'var': 'muc#roomconfig_publicroom', 'value': False},
+            {'ftype': 'list-single', 'var': 'muc#roomconfig_allowpm', 'value': 'none'},
+            {'ftype': 'list-single', 'var': 'muc#roomconfig_whois', 'value': 'anyone'},
+        ]
+
+        form = self.xmpp['xep_0004'].make_form()
+        form['type'] = 'submit'
+        for field in fields:
+            form.add_field(**field)
+
+        iq = self.xmpp.Iq()
+        iq['type'] = 'set'
+        iq['to'] = room
+        query = ET.Element('{http://jabber.org/protocol/muc#owner}query')
+        query.append(form.xml)
+        iq.append(query)
+        return iq
+
+    async def impromptu(self, jids: Set[JID]) -> None:
         """
         Generates a new "Impromptu" room with a random localpart on the muc
         component of the user who initiated the request. One the room is
@@ -877,41 +908,43 @@ class Core:
         contacts to join in.
         """
 
-        def callback(results):
-            muc_from_identity = ''
+        results = await self.xmpp['xep_0030'].get_info_from_domain()
 
-            for info in results:
-                for identity in info['disco_info']['identities']:
-                    if identity[0] == 'conference' and identity[1] == 'text':
-                        muc_from_identity = info['from'].bare
+        muc_from_identity = ''
+        for info in results:
+            for identity in info['disco_info']['identities']:
+                if identity[0] == 'conference' and identity[1] == 'text':
+                    muc_from_identity = info['from'].bare
 
-            # Use config.default_muc_service as muc component if available,
-            # otherwise find muc component by disco#items-ing the user domain.
-            # If not, give up
-            default_muc = config.get('default_muc_service', muc_from_identity)
-            if not default_muc:
-                self.information(
-                    "Error finding a MUC service to join. If your server does not "
-                    "provide one, set 'default_muc_service' manually to a MUC "
-                    "service that allows room creation.",
-                    'Error'
-                )
-                return
+        # Use config.default_muc_service as muc component if available,
+        # otherwise find muc component by disco#items-ing the user domain.
+        # If not, give up
+        default_muc = config.get('default_muc_service', muc_from_identity)
+        if not default_muc:
+            self.information(
+                "Error finding a MUC service to join. If your server does not "
+                "provide one, set 'default_muc_service' manually to a MUC "
+                "service that allows room creation.",
+                'Error'
+            )
+            return
 
-            nick = self.own_nick
-            room = uuid.uuid4().hex + '@' + default_muc
+        nick = self.own_nick
+        room = uuid.uuid4().hex + '@' + default_muc
 
-            self.open_new_room(room, nick).join()
-            self.information('Room %s created' % room, 'Info')
+        self.open_new_room(room, nick).join()
+        iq = self._impromptu_room_form(room, jids)
+        try:
+            await iq.send()
+        except (IqError, IqTimeout):
+            self.information('Failed to create configure impromptu room.', 'Info')
+            # TODO: destroy? leave room.
+            return None
 
-            for jid in jids:
-                self.invite(jid, room)
+        self.information('Room %s created' % room, 'Info')
 
-        asyncio.ensure_future(
-            self.xmpp['xep_0030'].get_info_from_domain(
-                callback=callback,
-            )
-        )
+        for jid in jids:
+            self.invite(jid, room)
 
     def get_error_message(self, stanza, deprecated: bool = False):
         """
diff --git a/poezio/tabs/conversationtab.py b/poezio/tabs/conversationtab.py
index 7e7a7488..94f1d719 100644
--- a/poezio/tabs/conversationtab.py
+++ b/poezio/tabs/conversationtab.py
@@ -79,6 +79,12 @@ class ConversationTab(OneToOneTab):
             ' allow you to see his presence, and allow them to'
             ' see your presence.',
             shortdesc='Add a user to your roster.')
+        self.register_command(
+            'invite',
+            self.core.command.impromptu,
+            desc='Invite people into an impromptu room.',
+            shortdesc='Invite other users to the discussion',
+            completion=self.core.completion.impromptu)
         self.update_commands()
         self.update_keys()
 
-- 
cgit v1.2.3