comparison 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
comparison
equal deleted inserted replaced
318:b544bec477dd 319:5bb1cfc105d0
24 from twisted.internet import protocol, defer, threads, reactor 24 from twisted.internet import protocol, defer, threads, reactor
25 from twisted.words.protocols.jabber import client, jid, xmlstream 25 from twisted.words.protocols.jabber import client, jid, xmlstream
26 from twisted.words.protocols.jabber import error as jab_error 26 from twisted.words.protocols.jabber import error as jab_error
27 from twisted.words.protocols.jabber.xmlstream import IQ 27 from twisted.words.protocols.jabber.xmlstream import IQ
28 import os.path 28 import os.path
29 import pdb 29 import uuid
30 30
31 from zope.interface import implements 31 from zope.interface import implements
32 32
33 from wokkel import disco, iwokkel, muc 33 from wokkel import disco, iwokkel, muc
34 34
56 56
57 def __init__(self, host): 57 def __init__(self, host):
58 info(_("Plugin XEP_0045 initialization")) 58 info(_("Plugin XEP_0045 initialization"))
59 self.host = host 59 self.host = host
60 self.clients={} 60 self.clients={}
61 host.bridge.addMethod("joinMUC", ".communication", in_sign='ssss', out_sign='', method=self.join) 61 host.bridge.addMethod("joinMUC", ".communication", in_sign='ssss', out_sign='', method=self._join)
62 host.bridge.addMethod("getRoomJoined", ".communication", in_sign='s', out_sign='a(ssass)', method=self.getRoomJoined) 62 host.bridge.addMethod("getRoomJoined", ".communication", in_sign='s', out_sign='a(ssass)', method=self.getRoomJoined)
63 host.bridge.addMethod("getRoomSubjects", ".communication", in_sign='s', out_sign='a(sss)', method=self.getRoomSubjects) 63 host.bridge.addMethod("getRoomSubjects", ".communication", in_sign='s', out_sign='a(sss)', method=self.getRoomSubjects)
64 host.bridge.addMethod("getUniqueRoomName", ".communication", in_sign='s', out_sign='s', method=self.getUniqueName)
64 host.bridge.addSignal("roomJoined", ".communication", signature='ssasss') #args: room_id, room_service, room_nicks, user_nick, profile 65 host.bridge.addSignal("roomJoined", ".communication", signature='ssasss') #args: room_id, room_service, room_nicks, user_nick, profile
65 host.bridge.addSignal("roomUserJoined", ".communication", signature='sssa{ss}s') #args: room_id, room_service, user_nick, user_data, profile 66 host.bridge.addSignal("roomUserJoined", ".communication", signature='sssa{ss}s') #args: room_id, room_service, user_nick, user_data, profile
66 host.bridge.addSignal("roomUserLeft", ".communication", signature='sssa{ss}s') #args: room_id, room_service, user_nick, user_data, profile 67 host.bridge.addSignal("roomUserLeft", ".communication", signature='sssa{ss}s') #args: room_id, room_service, user_nick, user_data, profile
67 host.bridge.addSignal("roomNewSubject", ".communication", signature='ssss') #args: room_id, room_service, subject, profile 68 host.bridge.addSignal("roomNewSubject", ".communication", signature='ssss') #args: room_id, room_service, subject, profile
68 69
78 return False 79 return False
79 return True 80 return True
80 81
81 def __room_joined(self, room, profile): 82 def __room_joined(self, room, profile):
82 """Called when the user is in the requested room""" 83 """Called when the user is in the requested room"""
84 def _sendBridgeSignal(ignore=None):
85 self.host.bridge.roomJoined(room.roomIdentifier, room.service, [user.nick for user in room.roster.values()], room.nick, profile)
86
83 room_jid = room.roomIdentifier+'@'+room.service 87 room_jid = room.roomIdentifier+'@'+room.service
84 self.clients[profile].joined_rooms[room_jid] = room 88 self.clients[profile].joined_rooms[room_jid] = room
85 self.host.bridge.roomJoined(room.roomIdentifier, room.service, [user.nick for user in room.roster.values()], room.nick, profile) 89 if room.status == '201':
90 #FIXME: the current behaviour is to create an instant room
91 #and send the signal only when the room is unlocked
92 #a proper configuration management should be done
93 #TODO: wokkel's muc currently doesn't manage correctly message from the room
94 # service (without resource) in room.getUser
95 self.clients[profile].configure(room_jid).addCallbacks(_sendBridgeSignal, lambda x: error(_('Error while configuring the room')))
96 else:
97 _sendBridgeSignal()
98 return room
99
86 100
87 def __err_joining_room(self, failure, profile): 101 def __err_joining_room(self, failure, profile):
88 """Called when something is going wrong when joining the room""" 102 """Called when something is going wrong when joining the room"""
89 mess = _("Error when joining the room") 103 mess = _("Error when joining the room")
90 error (mess) 104 error (mess)
115 """Return received subjects of rooms""" 129 """Return received subjects of rooms"""
116 profile = self.host.memory.getProfileName(profile_key) 130 profile = self.host.memory.getProfileName(profile_key)
117 if not self.__check_profile(profile): 131 if not self.__check_profile(profile):
118 return [] 132 return []
119 return self.clients[profile].rec_subjects.values() 133 return self.clients[profile].rec_subjects.values()
134
135 def getUniqueName(self, profile_key='@DEFAULT@'):
136 """Return unique name for room, avoiding collision"""
137 #TODO: we should use #RFC-0045 10.1.4 when available here
138 #TODO: we should be able to select the MUC service here
139 return uuid.uuid1()
120 140
121 def join(self, service, roomId, nick, profile_key='@DEFAULT@'): 141 def join(self, service, roomId, nick, profile_key='@DEFAULT@'):
122 profile = self.host.memory.getProfileName(profile_key) 142 profile = self.host.memory.getProfileName(profile_key)
123 if not self.__check_profile(profile): 143 if not self.__check_profile(profile):
124 return 144 return
126 if self.clients[profile].joined_rooms.has_key(room_jid): 146 if self.clients[profile].joined_rooms.has_key(room_jid):
127 warning(_('%(profile)s is already in room %(room_jid)s') % {'profile':profile, 'room_jid':room_jid}) 147 warning(_('%(profile)s is already in room %(room_jid)s') % {'profile':profile, 'room_jid':room_jid})
128 return 148 return
129 info (_("[%(profile)s] is joining room %(room)s with nick %(nick)s") % {'profile':profile,'room':roomId+'@'+service, 'nick':nick}) 149 info (_("[%(profile)s] is joining room %(room)s with nick %(nick)s") % {'profile':profile,'room':roomId+'@'+service, 'nick':nick})
130 try: 150 try:
131 self.clients[profile].join(service, roomId, nick).addCallbacks(self.__room_joined, self.__err_joining_room, callbackKeywords={'profile':profile}, errbackKeywords={'profile':profile}) 151 return self.clients[profile].join(service, roomId, nick).addCallbacks(self.__room_joined, self.__err_joining_room, callbackKeywords={'profile':profile}, errbackKeywords={'profile':profile})
132 except: 152 except:
133 #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) 153 #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)
134 #FIXME: must be removed when MUCClient manage this better 154 #FIXME: must be removed when MUCClient manage this better
135 self.__err_joining_room(None, profile) 155 d = defer.Deferred()
136 156 d.addErrback(self.__err_joining_room, profile)
157 d.errback(Exception("ugly workaround"))
158 return d
159
160 def _join(self, service, roomId, nick, profile_key='@DEFAULT@'):
161 """join method used by bridge: use the _join method, but doesn't return any deferred"""
162 self.join(service, roomId, nick, profile_key)
163
137 def getHandler(self, profile): 164 def getHandler(self, profile):
138 self.clients[profile] = SatMUCClient(self) 165 self.clients[profile] = SatMUCClient(self)
139 return self.clients[profile] 166 return self.clients[profile]
140 167
141 168
154 def receivedGroupChat(self, room, user, body): 181 def receivedGroupChat(self, room, user, body):
155 debug('receivedGroupChat: room=%s user=%s body=%s', room, user, body) 182 debug('receivedGroupChat: room=%s user=%s body=%s', room, user, body)
156 183
157 def userJoinedRoom(self, room, user): 184 def userJoinedRoom(self, room, user):
158 debug (_("user %(nick)s has joined room (%(room_id)s)") % {'nick':user.nick, 'room_id':room.occupantJID.userhost()}) 185 debug (_("user %(nick)s has joined room (%(room_id)s)") % {'nick':user.nick, 'room_id':room.occupantJID.userhost()})
186 if not self.host.trigger.point("MUC user joined", room, user, self.parent.profile):
187 return
159 user_data={'entity':user.entity or '', 'affiliation':user.affiliation, 'role':user.role} 188 user_data={'entity':user.entity or '', 'affiliation':user.affiliation, 'role':user.role}
160 self.host.bridge.roomUserJoined(room.roomIdentifier, room.service, user.nick, user_data, self.parent.profile) 189 self.host.bridge.roomUserJoined(room.roomIdentifier, room.service, user.nick, user_data, self.parent.profile)
161 190
162 def userLeftRoom(self, room, user): 191 def userLeftRoom(self, room, user):
163 debug (_("user %(nick)s left room (%(room_id)s)") % {'nick':user.nick, 'room_id':room.occupantJID.userhost()}) 192 debug (_("user %(nick)s left room (%(room_id)s)") % {'nick':user.nick, 'room_id':room.occupantJID.userhost()})