diff src/plugins/plugin_xep_0045.py @ 319:5bb1cfc105d0

plugin xep-0045: misc improvments - added getUniqueRoomName method to create a room with no name conflict (need improvment) - if the room is new, the basic configuration is used to create it - _join is now used for bridge, and join can be used if we need the deferred - a trigger is added when a user join a room ("MUC user joined")
author Goffi <goffi@goffi.org>
date Fri, 06 May 2011 15:38:32 +0200
parents 7c79d4a8c9e6
children abe08fcb42d7
line wrap: on
line diff
--- a/src/plugins/plugin_xep_0045.py	Fri May 06 15:34:02 2011 +0200
+++ b/src/plugins/plugin_xep_0045.py	Fri May 06 15:38:32 2011 +0200
@@ -26,7 +26,7 @@
 from twisted.words.protocols.jabber import error as jab_error
 from twisted.words.protocols.jabber.xmlstream import IQ
 import os.path
-import pdb
+import uuid
 
 from zope.interface import implements
 
@@ -58,9 +58,10 @@
         info(_("Plugin XEP_0045 initialization"))
         self.host = host
         self.clients={}
-        host.bridge.addMethod("joinMUC", ".communication", in_sign='ssss', out_sign='', method=self.join)
+        host.bridge.addMethod("joinMUC", ".communication", in_sign='ssss', out_sign='', method=self._join)
         host.bridge.addMethod("getRoomJoined", ".communication", in_sign='s', out_sign='a(ssass)', method=self.getRoomJoined)
         host.bridge.addMethod("getRoomSubjects", ".communication", in_sign='s', out_sign='a(sss)', method=self.getRoomSubjects)
+        host.bridge.addMethod("getUniqueRoomName", ".communication", in_sign='s', out_sign='s', method=self.getUniqueName)
         host.bridge.addSignal("roomJoined", ".communication", signature='ssasss') #args: room_id, room_service, room_nicks, user_nick, profile
         host.bridge.addSignal("roomUserJoined", ".communication", signature='sssa{ss}s') #args: room_id, room_service, user_nick, user_data, profile
         host.bridge.addSignal("roomUserLeft", ".communication", signature='sssa{ss}s') #args: room_id, room_service, user_nick, user_data, profile
@@ -80,9 +81,22 @@
 
     def __room_joined(self, room, profile):
         """Called when the user is in the requested room"""
+        def _sendBridgeSignal(ignore=None):
+            self.host.bridge.roomJoined(room.roomIdentifier, room.service, [user.nick for user in room.roster.values()], room.nick, profile)
+
         room_jid = room.roomIdentifier+'@'+room.service
         self.clients[profile].joined_rooms[room_jid] = room
-        self.host.bridge.roomJoined(room.roomIdentifier, room.service, [user.nick for user in room.roster.values()], room.nick, profile)
+        if room.status == '201':
+            #FIXME: the current behaviour is to create an instant room
+            #and send the signal only when the room is unlocked
+            #a proper configuration management should be done
+            #TODO: wokkel's muc currently doesn't manage correctly message from the room
+            #      service (without resource) in room.getUser 
+            self.clients[profile].configure(room_jid).addCallbacks(_sendBridgeSignal, lambda x: error(_('Error while configuring the room')))
+        else:
+            _sendBridgeSignal()
+        return room
+
 
     def __err_joining_room(self, failure, profile):
         """Called when something is going wrong when joining the room"""
@@ -118,6 +132,12 @@
             return []
         return self.clients[profile].rec_subjects.values()
 
+    def getUniqueName(self, profile_key='@DEFAULT@'):
+        """Return unique name for room, avoiding collision"""
+        #TODO: we should use #RFC-0045 10.1.4 when available here
+        #TODO: we should be able to select the MUC service here
+        return uuid.uuid1() 
+
     def join(self, service, roomId, nick, profile_key='@DEFAULT@'):
         profile = self.host.memory.getProfileName(profile_key)
         if not self.__check_profile(profile):
@@ -128,12 +148,19 @@
             return
         info (_("[%(profile)s] is joining room %(room)s with nick %(nick)s") % {'profile':profile,'room':roomId+'@'+service, 'nick':nick})
         try:
-            self.clients[profile].join(service, roomId, nick).addCallbacks(self.__room_joined, self.__err_joining_room, callbackKeywords={'profile':profile}, errbackKeywords={'profile':profile})
+            return self.clients[profile].join(service, roomId, nick).addCallbacks(self.__room_joined, self.__err_joining_room, callbackKeywords={'profile':profile}, errbackKeywords={'profile':profile})
         except:
             #XXX: this is a ugly workaround as MUCClient thrown an error if there is invalid chars in the room jid (like with the default string)
             #FIXME: must be removed when MUCClient manage this better
-            self.__err_joining_room(None, profile)
+            d = defer.Deferred()
+            d.addErrback(self.__err_joining_room, profile)
+            d.errback(Exception("ugly workaround"))
+            return d
 
+    def _join(self, service, roomId, nick, profile_key='@DEFAULT@'):
+        """join method used by bridge: use the _join method, but doesn't return any deferred"""
+        self.join(service, roomId, nick, profile_key)
+    
     def getHandler(self, profile):
         self.clients[profile] = SatMUCClient(self)
         return self.clients[profile]
@@ -156,6 +183,8 @@
 
     def userJoinedRoom(self, room, user):
         debug (_("user %(nick)s has joined room (%(room_id)s)") % {'nick':user.nick, 'room_id':room.occupantJID.userhost()})
+        if not self.host.trigger.point("MUC user joined", room, user, self.parent.profile):
+            return
         user_data={'entity':user.entity or '', 'affiliation':user.affiliation, 'role':user.role} 
         self.host.bridge.roomUserJoined(room.roomIdentifier, room.service, user.nick, user_data, self.parent.profile)