# HG changeset patch # User Goffi # Date 1391533572 -3600 # Node ID 02ee9ef952770ca12ffb2b10170fb0e609b9a3a4 # Parent e0770d977d585535477b223d831ed22f5220e3d0 plugin XEP-0045, primitivus: added MUC configuration diff -r e0770d977d58 -r 02ee9ef95277 frontends/src/primitivus/chat.py --- a/frontends/src/primitivus/chat.py Tue Feb 04 18:04:32 2014 +0100 +++ b/frontends/src/primitivus/chat.py Tue Feb 04 18:06:12 2014 +0100 @@ -24,6 +24,7 @@ from sat_frontends.quick_frontend.quick_chat import QuickChat from sat_frontends.primitivus.card_game import CardGame from sat_frontends.quick_frontend.quick_utils import escapePrivate, unescapePrivate +from sat_frontends.primitivus.xmlui import XMLUI import time from sat.tools.jid import JID @@ -131,7 +132,9 @@ menu = sat_widgets.Menu(self.host.loop) if self.type == 'group': game = _("Game") + muc = _("MUC") menu.addMenu(game, "Tarot", self.onTarotRequest) + menu.addMenu(muc, _("Configure room"), self.onConfigureRoom) elif self.type == 'one2one': menu.addMenu(_("Action"), _("Send file"), self.onSendFileRequest) return menu @@ -335,6 +338,13 @@ else: self.host.bridge.tarotGameCreate(self.id, list(self.occupants), self.host.profile) + def onConfigureRoom(self, menu): + def gotUI(xmlui): + self.host.addWindow(XMLUI(self.host, xmlui)) + def configureError(failure): + self.host.showPopUp(sat_widgets.Alert(_("Error"), unicode(failure), ok_cb=self.host.removePopUp)) + self.host.bridge.configureRoom(self.id, self.host.profile, callback=gotUI, errback=configureError) + def onSendFileRequest(self, menu): dialog = FileDialog(ok_cb=self.onFileSelected, cancel_cb=self.host.removePopUp) self.host.showPopUp(dialog, 80, 80) diff -r e0770d977d58 -r 02ee9ef95277 src/core/sat_main.py --- a/src/core/sat_main.py Tue Feb 04 18:04:32 2014 +0100 +++ b/src/core/sat_main.py Tue Feb 04 18:06:12 2014 +0100 @@ -903,7 +903,8 @@ @param help_string: string used to indicate what the menu do (can be show as a tooltip). /!\ use D_() instead of _() for translations @param type: one of: - - NORMAL: classical menu, can be shown in a menubar on top (e.g. something like File/Open) + - GLOBAL: classical menu, can be shown in a menubar on top (e.g. something like File/Open) + - ROOM: like a global menu, but only shown in multi-user chat - JID_CONTEXT: contextual menu, used with any jid (e.g.: ad hoc commands, jid is already filled) - ROSTER_JID_CONTEXT: like JID_CONTEXT, but restricted to jids in roster. - ROSTER_GROUP_CONTEXT: contextual menu, used with group (e.g.: publish microblog, group is already filled) diff -r e0770d977d58 -r 02ee9ef95277 src/plugins/plugin_xep_0045.py --- a/src/plugins/plugin_xep_0045.py Tue Feb 04 18:04:32 2014 +0100 +++ b/src/plugins/plugin_xep_0045.py Tue Feb 04 18:06:12 2014 +0100 @@ -23,10 +23,12 @@ from twisted.words.protocols.jabber import jid from sat.core import exceptions +from sat.memory import memory import uuid from wokkel import muc +from sat.tools import xml_tools try: @@ -56,18 +58,21 @@ info(_("Plugin XEP_0045 initialization")) self.host = host self.clients = {} + self._sessions = memory.Sessions() host.bridge.addMethod("joinMUC", ".plugin", in_sign='ssa{ss}s', out_sign='s', method=self._join) host.bridge.addMethod("mucNick", ".plugin", in_sign='sss', out_sign='', method=self.mucNick) - host.bridge.addMethod("mucLeave", ".plugin", in_sign='ss', out_sign='', method=self.mucLeave, async = True) + host.bridge.addMethod("mucLeave", ".plugin", in_sign='ss', out_sign='', method=self.mucLeave, async=True) host.bridge.addMethod("getRoomsJoined", ".plugin", in_sign='s', out_sign='a(sass)', method=self.getRoomsJoined) host.bridge.addMethod("getRoomsSubjects", ".plugin", in_sign='s', out_sign='a(ss)', method=self.getRoomsSubjects) host.bridge.addMethod("getUniqueRoomName", ".plugin", in_sign='ss', out_sign='s', method=self.getUniqueName) + host.bridge.addMethod("configureRoom", ".plugin", in_sign='ss', out_sign='s', method=self._configureRoom, async=True) host.bridge.addSignal("roomJoined", ".plugin", signature='sasss') # args: room_jid, room_nicks, user_nick, profile host.bridge.addSignal("roomLeft", ".plugin", signature='ss') # args: room_jid, profile host.bridge.addSignal("roomUserJoined", ".plugin", signature='ssa{ss}s') # args: room_jid, user_nick, user_data, profile host.bridge.addSignal("roomUserLeft", ".plugin", signature='ssa{ss}s') # args: room_jid, user_nick, user_data, profile host.bridge.addSignal("roomUserChangedNick", ".plugin", signature='ssss') # args: room_jid, old_nick, new_nick, profile host.bridge.addSignal("roomNewSubject", ".plugin", signature='sss') # args: room_jid, subject, profile + self.__submit_conf_id = host.registerCallback(self._submitConfiguration, with_data=True) def __check_profile(self, profile): """check if profile is used and connected @@ -169,6 +174,51 @@ nicks.append(nick) return nicks, missing + def _configureRoom(self, room_jid_s, profile_key='@NONE@'): + d = self.configureRoom(jid.JID(room_jid_s), profile_key) + d.addCallback(lambda xmlui: xmlui.toXml()) + return d + + def configureRoom(self, room_jid, profile_key='@NONE@'): + """ return the room configuration form + @param room: jid of the room to configure + @param profile_key: %(doc_profile_key)s + @return: configuration form as XMLUI + + """ + profile = self.host.memory.getProfileName(profile_key) + if not self.__check_profile(profile): + raise exceptions.ProfileUnknownError("Unknown or disconnected profile") + if room_jid.userhost() not in self.clients[profile].joined_rooms: + raise UnknownRoom("This room has not been joined") + + def config2XMLUI(result): + if not result: + return "" + session_id, session_data = self._sessions.newSession(profile=profile) + session_data["room_jid"] = room_jid + xmlui = xml_tools.dataForm2XMLUI(result, submit_id=self.__submit_conf_id) + xmlui.session_id = session_id + return xmlui + + d = self.clients[profile].getConfiguration(room_jid) + d.addCallback(config2XMLUI) + return d + + def _submitConfiguration(self, raw_data, profile): + try: + session_data = self._sessions.profileGet(raw_data["session_id"], profile) + except KeyError: + warning ("session id doesn't exist, session has probably expired") + # TODO: send error dialog + return defer.succeed({}) + + data = xml_tools.XMLUIResult2DataFormResult(raw_data) + d = self.clients[profile].configure(session_data['room_jid'], data) + d.addCallback(lambda ignore: {}) + del self._sessions[raw_data["session_id"]] + return d + def isNickInRoom(self, room_jid, nick, profile): """Tell if a nick is currently present in a room""" profile = self.host.memory.getProfileName(profile)