plugin XEP-0045, quick_frontend + primitivus (chat): cleaning of XEP-0045 (first pass):
- bridge methods/signals now all start with "muc" to follow new convention
- internal method use client instead of profile to follow new convention
- removed excetpions from plugin XEP-0045 in favor of core.exceptions, NotReady added
- cleaned/simplified several part of the code. checkClient removed as it is not needed anymore
- self.clients map removed, muc data are now stored directly in client
- getRoomEntityNick and getRoomNicksOfUsers are removed as they don't look sane.
/!\ This break all room game plugins for the moment
- use of uuid4 instead of uuid1 for getUniqueName, as host ID and current time are used for uuid1
This commit is contained in:
parent
a28bb7be8f
commit
04515e5013
14 changed files with 296 additions and 309 deletions
|
|
@ -30,6 +30,7 @@ from sat_frontends.primitivus.constants import Const as C
|
|||
from sat_frontends.primitivus.keys import action_key_map as a_key
|
||||
from sat_frontends.primitivus.widget import PrimitivusWidget
|
||||
import time
|
||||
import locale
|
||||
from sat_frontends.tools import jid
|
||||
from functools import total_ordering
|
||||
import bisect
|
||||
|
|
@ -117,8 +118,8 @@ class MessageWidget(urwid.WidgetWrap):
|
|||
# timestamp
|
||||
if self.parent.show_timestamp:
|
||||
# if the message was sent before today, we print the full date
|
||||
time_format = "%c" if self.timestamp < self.parent.day_change else "%H:%M"
|
||||
markup.append(('date', "[{}]".format(time.strftime(time_format, self.timestamp).decode('utf-8'))))
|
||||
time_format = u"%c" if self.timestamp < self.parent.day_change else u"%H:%M"
|
||||
markup.append(('date', u"[{}]".format(time.strftime(time_format, self.timestamp).decode(locale.getlocale()[1]))))
|
||||
|
||||
# nickname
|
||||
if self.parent.show_short_nick:
|
||||
|
|
|
|||
|
|
@ -855,7 +855,7 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
|
||||
def onJoinRoomRequest(self, menu):
|
||||
"""User wants to join a MUC room"""
|
||||
pop_up_widget = sat_widgets.InputDialog(_("Entering a MUC room"), _("Please enter MUC's JID"), default_txt=self.bridge.getDefaultMUC(), ok_cb=self.onJoinRoom)
|
||||
pop_up_widget = sat_widgets.InputDialog(_("Entering a MUC room"), _("Please enter MUC's JID"), default_txt=self.bridge.mucGetDefaultService(), ok_cb=self.onJoinRoom)
|
||||
pop_up_widget.setCallback('cancel', lambda dummy: self.removePopUp(pop_up_widget))
|
||||
self.showPopUp(pop_up_widget)
|
||||
|
||||
|
|
|
|||
|
|
@ -116,12 +116,12 @@ class ProfileManager(object):
|
|||
for sub in waiting_sub:
|
||||
self.host.subscribeHandler(waiting_sub[sub], sub, self.profile)
|
||||
|
||||
self.bridge.getRoomsJoined(self.profile, callback=self._plug_profile_gotRoomsJoined)
|
||||
self.bridge.mucGetRoomsJoined(self.profile, callback=self._plug_profile_gotRoomsJoined)
|
||||
|
||||
def _plug_profile_gotRoomsJoined(self, rooms_args):
|
||||
#Now we open the MUC window where we already are:
|
||||
for room_args in rooms_args:
|
||||
self.host.roomJoinedHandler(*room_args, profile=self.profile)
|
||||
self.host.mucRoomJoinedHandler(*room_args, profile=self.profile)
|
||||
#Presence must be requested after rooms are filled
|
||||
self.host.bridge.getPresenceStatuses(self.profile, callback=self._plug_profile_gotPresences)
|
||||
|
||||
|
|
@ -254,10 +254,10 @@ class QuickApp(object):
|
|||
self.registerSignal("progressFinished")
|
||||
self.registerSignal("progressError")
|
||||
self.registerSignal("actionResultExt", self.actionResultHandler)
|
||||
self.registerSignal("roomJoined", iface="plugin")
|
||||
self.registerSignal("roomLeft", iface="plugin")
|
||||
self.registerSignal("roomUserChangedNick", iface="plugin")
|
||||
self.registerSignal("roomNewSubject", iface="plugin")
|
||||
self.registerSignal("mucRoomJoined", iface="plugin")
|
||||
self.registerSignal("mucRoomLeft", iface="plugin")
|
||||
self.registerSignal("mucRoomUserChangedNick", iface="plugin")
|
||||
self.registerSignal("mucRoomNewSubject", iface="plugin")
|
||||
self.registerSignal("chatStateReceived", iface="plugin")
|
||||
self.registerSignal("psEvent", iface="plugin")
|
||||
|
||||
|
|
@ -548,7 +548,7 @@ class QuickApp(object):
|
|||
|
||||
self.callListeners('presence', entity, show, priority, statuses, profile=profile)
|
||||
|
||||
def roomJoinedHandler(self, room_jid_s, occupants, user_nick, subject, profile):
|
||||
def mucRoomJoinedHandler(self, room_jid_s, occupants, user_nick, subject, profile):
|
||||
"""Called when a MUC room is joined"""
|
||||
log.debug(u"Room [{room_jid}] joined by {profile}, users presents:{users}".format(room_jid=room_jid_s, profile=profile, users=occupants.keys()))
|
||||
room_jid = jid.JID(room_jid_s)
|
||||
|
|
@ -557,7 +557,7 @@ class QuickApp(object):
|
|||
self.contact_lists[profile].setSpecial(room_jid, C.CONTACT_SPECIAL_GROUP)
|
||||
# chat_widget.update()
|
||||
|
||||
def roomLeftHandler(self, room_jid_s, profile):
|
||||
def mucRoomLeftHandler(self, room_jid_s, profile):
|
||||
"""Called when a MUC room is left"""
|
||||
log.debug(u"Room [%(room_jid)s] left by %(profile)s" % {'room_jid': room_jid_s, 'profile': profile})
|
||||
room_jid = jid.JID(room_jid_s)
|
||||
|
|
@ -566,14 +566,14 @@ class QuickApp(object):
|
|||
self.widgets.deleteWidget(chat_widget)
|
||||
self.contact_lists[profile].removeContact(room_jid)
|
||||
|
||||
def roomUserChangedNickHandler(self, room_jid_s, old_nick, new_nick, profile):
|
||||
def mucRoomUserChangedNickHandler(self, room_jid_s, old_nick, new_nick, profile):
|
||||
"""Called when an user joined a MUC room"""
|
||||
room_jid = jid.JID(room_jid_s)
|
||||
chat_widget = self.widgets.getOrCreateWidget(quick_chat.QuickChat, room_jid, type_=C.CHAT_GROUP, profile=profile)
|
||||
chat_widget.changeUserNick(old_nick, new_nick)
|
||||
log.debug(u"user [%(old_nick)s] is now known as [%(new_nick)s] in room [%(room_jid)s]" % {'old_nick': old_nick, 'new_nick': new_nick, 'room_jid': room_jid})
|
||||
|
||||
def roomNewSubjectHandler(self, room_jid_s, subject, profile):
|
||||
def mucRoomNewSubjectHandler(self, room_jid_s, subject, profile):
|
||||
"""Called when subject of MUC room change"""
|
||||
room_jid = jid.JID(room_jid_s)
|
||||
chat_widget = self.widgets.getOrCreateWidget(quick_chat.QuickChat, room_jid, type_=C.CHAT_GROUP, profile=profile)
|
||||
|
|
|
|||
|
|
@ -114,3 +114,8 @@ class SkipHistory(Exception): # used in MessageReceivedTrigger to avoid history
|
|||
|
||||
class ParsingError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
# Something which need to be done is not available yet
|
||||
class NotReady(Exception):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -635,25 +635,25 @@ class Memory(object):
|
|||
return available
|
||||
|
||||
def _getMainResource(self, jid_s, profile_key):
|
||||
client = self.host.getClient(profile_key)
|
||||
jid_ = jid.JID(jid_s)
|
||||
return self.getMainResource(jid_, profile_key) or ""
|
||||
return self.getMainResource(client, jid_) or ""
|
||||
|
||||
def getMainResource(self, entity_jid, profile_key):
|
||||
def getMainResource(self, client, entity_jid):
|
||||
"""Return the main resource used by an entity
|
||||
|
||||
@param entity_jid: bare entity jid
|
||||
@param profile_key: %(doc_profile_key)s
|
||||
@return (unicode): main resource or None
|
||||
"""
|
||||
if entity_jid.resource:
|
||||
raise ValueError("getMainResource must be used with a bare jid (got {})".format(entity_jid))
|
||||
try:
|
||||
if self.host.plugins["XEP-0045"].isRoom(entity_jid, profile_key):
|
||||
if self.host.plugins["XEP-0045"].isJoinedRoom(client, entity_jid):
|
||||
return None # MUC rooms have no main resource
|
||||
except KeyError: # plugin not found
|
||||
pass
|
||||
try:
|
||||
resources = self.getAllResources(entity_jid, profile_key)
|
||||
resources = self.getAllResources(entity_jid, client.profile)
|
||||
except exceptions.UnknownEntityError:
|
||||
log.warning(u"Entity is not in cache, we can't find any resource")
|
||||
return None
|
||||
|
|
@ -662,7 +662,7 @@ class Memory(object):
|
|||
full_jid = copy.copy(entity_jid)
|
||||
full_jid.resource = resource
|
||||
try:
|
||||
presence_data = self.getEntityDatum(full_jid, "presence", profile_key)
|
||||
presence_data = self.getEntityDatum(full_jid, "presence", client.profile)
|
||||
except KeyError:
|
||||
log.debug(u"No presence information for {}".format(full_jid))
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ class Exp_Parrot(object):
|
|||
entity_type = "contact"
|
||||
if entity_type == 'chatroom':
|
||||
src_txt = from_jid.resource
|
||||
if src_txt == self.host.plugins["XEP-0045"].getRoomNick(from_jid.userhostJID(), profile):
|
||||
if src_txt == self.host.plugins["XEP-0045"].getRoomNick(client, from_jid.userhostJID()):
|
||||
#we won't repeat our own messages
|
||||
return True
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ PLUGIN_INFO = {
|
|||
}
|
||||
|
||||
|
||||
# FIXME: this plugin is broken, need to be fixed
|
||||
|
||||
class RoomGame(object):
|
||||
"""This class is used to help launching a MUC game.
|
||||
|
||||
|
|
@ -123,7 +125,7 @@ class RoomGame(object):
|
|||
host.trigger.add("MUC user joined", self.userJoinedTrigger)
|
||||
host.trigger.add("MUC user left", self.userLeftTrigger)
|
||||
|
||||
def _createOrInvite(self, room, other_players, profile):
|
||||
def _createOrInvite(self, room_jid, other_players, profile):
|
||||
"""
|
||||
This is called only when someone explicitly wants to play.
|
||||
|
||||
|
|
@ -131,22 +133,24 @@ class RoomGame(object):
|
|||
also its creation could be postponed until all the expected players
|
||||
join the room (in that case it will be created from userJoinedTrigger).
|
||||
@param room (wokkel.muc.Room): the room
|
||||
@param other_players (list[jid.JID]): list of the other players JID (bare)
|
||||
@param other_players (list[jid.JID]): list of the other players JID (bare)
|
||||
"""
|
||||
# FIXME: broken !
|
||||
raise NotImplementedError("To be fixed")
|
||||
client = self.host.getClient(profile)
|
||||
user_jid = self.host.getJidNStream(profile)[0]
|
||||
room_jid = room.occupantJID.userhostJID()
|
||||
nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid, profile)
|
||||
nick = self.host.plugins["XEP-0045"].getRoomNick(client, room_jid)
|
||||
nicks = [nick]
|
||||
if self._gameExists(room_jid):
|
||||
if not self._checkJoinAuth(room_jid, user_jid, nick):
|
||||
return
|
||||
nicks.extend(self._invitePlayers(room, other_players, nick, profile))
|
||||
nicks.extend(self._invitePlayers(room_jid, other_players, nick, profile))
|
||||
self._updatePlayers(room_jid, nicks, True, profile)
|
||||
else:
|
||||
self._initGame(room_jid, nick)
|
||||
(auth, waiting, missing) = self._checkWaitAuth(room, other_players)
|
||||
(auth, waiting, missing) = self._checkWaitAuth(room_jid, other_players)
|
||||
nicks.extend(waiting)
|
||||
nicks.extend(self._invitePlayers(room, missing, nick, profile))
|
||||
nicks.extend(self._invitePlayers(room_jid, missing, nick, profile))
|
||||
if auth:
|
||||
self.createGame(room_jid, nicks, profile)
|
||||
else:
|
||||
|
|
@ -300,15 +304,15 @@ class RoomGame(object):
|
|||
"""
|
||||
return []
|
||||
|
||||
def _invitePlayers(self, room, other_players, nick, profile):
|
||||
def _invitePlayers(self, room_jid, other_players, nick, profile):
|
||||
"""Invite players to a room, associated game may exist or not.
|
||||
|
||||
@param room (wokkel.muc.Room): the room
|
||||
@param other_players (list[jid.JID]): list of the players to invite
|
||||
@param nick (unicode): nick of the user who send the invitation
|
||||
@return: list[unicode] of room nicks for invited players who are already in the room
|
||||
"""
|
||||
room_jid = room.occupantJID.userhostJID()
|
||||
raise NotImplementedError("Need to be fixed !")
|
||||
# FIXME: this is broken and unsecure !
|
||||
if not self._checkInviteAuth(room_jid, nick):
|
||||
return []
|
||||
# TODO: remove invitation waiting for too long, using the time data
|
||||
|
|
@ -316,7 +320,7 @@ class RoomGame(object):
|
|||
nicks = []
|
||||
for player_jid in [player.userhostJID() for player in other_players]:
|
||||
# TODO: find a way to make it secure
|
||||
other_nick = self.host.plugins["XEP-0045"].getRoomNickOfUser(room, player_jid, secure=self.testing)
|
||||
other_nick = self.host.plugins["XEP-0045"].getRoomEntityNick(room_jid, player_jid, secure=self.testing)
|
||||
if other_nick is None:
|
||||
self.host.plugins["XEP-0249"].invite(player_jid, room_jid, {"game": self.name}, profile)
|
||||
else:
|
||||
|
|
@ -397,8 +401,9 @@ class RoomGame(object):
|
|||
@param profile_key (unicode): %(doc_profile_key)s
|
||||
@return: jid.JID (unique name for a new room to be created)
|
||||
"""
|
||||
client = self.host.getClient(profile_key)
|
||||
# FIXME: jid.JID must be used instead of strings
|
||||
room = self.host.plugins["XEP-0045"].getUniqueName(muc_service, profile_key=profile_key)
|
||||
room = self.host.plugins["XEP-0045"].getUniqueName(client, muc_service)
|
||||
return jid.JID("sat_%s_%s" % (self.name.lower(), room.userhost()))
|
||||
|
||||
def _prepareRoom(self, other_players=None, room_jid_s='', profile_key=C.PROF_KEY_NONE):
|
||||
|
|
@ -413,6 +418,8 @@ class RoomGame(object):
|
|||
@param room_jid (jid.JID): JID of the room, or None to generate a unique name
|
||||
@param profile_key (unicode): %(doc_profile_key)s
|
||||
"""
|
||||
# FIXME: need to be refactored
|
||||
client = self.host.getClient(profile_key)
|
||||
log.debug(_(u'Preparing room for %s game') % self.name)
|
||||
profile = self.host.memory.getProfileName(profile_key)
|
||||
if not profile:
|
||||
|
|
@ -421,21 +428,17 @@ class RoomGame(object):
|
|||
if other_players is None:
|
||||
other_players = []
|
||||
|
||||
def roomJoined(room):
|
||||
"""@param room: instance of wokkel.muc.Room"""
|
||||
self._createOrInvite(room, other_players, profile)
|
||||
|
||||
# Create/join the given room, or a unique generated one if no room is specified.
|
||||
if room_jid is None:
|
||||
room_jid = self.getUniqueName(profile_key=profile_key)
|
||||
else:
|
||||
if room_jid in self.host.plugins["XEP-0045"].clients[profile].joined_rooms:
|
||||
roomJoined(self.host.plugins["XEP-0045"].clients[profile].joined_rooms[room_jid])
|
||||
return defer.succeed(None)
|
||||
self.host.plugins["XEP-0045"].checkRoomJoined(client, room_jid)
|
||||
self._createOrInvite(client, room_jid, other_players)
|
||||
return defer.succeed(None)
|
||||
|
||||
user_jid = self.host.getJidNStream(profile)[0]
|
||||
d = self.host.plugins["XEP-0045"].join(room_jid, user_jid.user, {}, profile)
|
||||
return d.addCallback(roomJoined)
|
||||
return d.addCallback(lambda dummy: self._createOrInvite(client, room_jid, other_players))
|
||||
|
||||
def userJoinedTrigger(self, room, user, profile):
|
||||
"""This trigger is used to check if the new user can take part of a game, create the game if we were waiting for him or just update the players list.
|
||||
|
|
|
|||
|
|
@ -477,9 +477,10 @@ class Tarot(object):
|
|||
"""
|
||||
@param mess_elt: instance of twisted.words.xish.domish.Element
|
||||
"""
|
||||
client = self.host.getClient(profile)
|
||||
from_jid = jid.JID(mess_elt['from'])
|
||||
room_jid = jid.JID(from_jid.userhost())
|
||||
nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid, profile)
|
||||
nick = self.host.plugins["XEP-0045"].getRoomNick(client, room_jid)
|
||||
|
||||
game_elt = mess_elt.firstChildElement()
|
||||
game_data = self.games[room_jid]
|
||||
|
|
@ -522,7 +523,7 @@ class Tarot(object):
|
|||
# TODO: use proper XEP-0004 way for answering form
|
||||
player = elt['player']
|
||||
players_data[player]['contrat'] = unicode(elt)
|
||||
contrats = [players_data[player]['contrat'] for player in game_data['players']]
|
||||
contrats = [players_data[p]['contrat'] for p in game_data['players']]
|
||||
if contrats.count(None):
|
||||
# not everybody has choosed his contrat, it's next one turn
|
||||
player = self.__next_player(game_data)
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ class TextCommands(object):
|
|||
if mess_data['type'] == "groupchat":
|
||||
room = mess_data["to"].userhostJID()
|
||||
try:
|
||||
if self.host.plugins["XEP-0045"].isNickInRoom(room, entity, client.profile):
|
||||
if self.host.plugins["XEP-0045"].isNickInRoom(client, room, entity):
|
||||
entity = u"%s/%s" % (room, entity)
|
||||
except KeyError:
|
||||
log.warning("plugin XEP-0045 is not present")
|
||||
|
|
@ -322,7 +322,7 @@ class TextCommands(object):
|
|||
return False
|
||||
|
||||
if not target_jid.resource:
|
||||
target_jid.resource = self.host.memory.getMainResource(target_jid, client.profile)
|
||||
target_jid.resource = self.host.memory.getMainResource(client, target_jid)
|
||||
|
||||
whois_msg = [_(u"whois for %(jid)s") % {'jid': target_jid}]
|
||||
|
||||
|
|
|
|||
|
|
@ -276,10 +276,11 @@ class OTR(object):
|
|||
@param menu_data: %(menu_data)s
|
||||
@param profile: %(doc_profile)s
|
||||
"""
|
||||
client = self.host.getClient(profile)
|
||||
try:
|
||||
to_jid = jid.JID(menu_data['jid'])
|
||||
if not to_jid.resource:
|
||||
to_jid.resource = self.host.memory.getMainResource(to_jid, profile) # FIXME: temporary and unsecure, must be changed when frontends are refactored
|
||||
to_jid.resource = self.host.memory.getMainResource(client, to_jid) # FIXME: temporary and unsecure, must be changed when frontends are refactored
|
||||
except KeyError:
|
||||
log.error(_("jid key is not present !"))
|
||||
return defer.fail(exceptions.DataError)
|
||||
|
|
@ -294,10 +295,11 @@ class OTR(object):
|
|||
@param menu_data: %(menu_data)s
|
||||
@param profile: %(doc_profile)s
|
||||
"""
|
||||
client = self.host.getClient(profile)
|
||||
try:
|
||||
to_jid = jid.JID(menu_data['jid'])
|
||||
if not to_jid.resource:
|
||||
to_jid.resource = self.host.memory.getMainResource(to_jid, profile) # FIXME: temporary and unsecure, must be changed when frontends are refactored
|
||||
to_jid.resource = self.host.memory.getMainResource(client, to_jid) # FIXME: temporary and unsecure, must be changed when frontends are refactored
|
||||
except KeyError:
|
||||
log.error(_("jid key is not present !"))
|
||||
return defer.fail(exceptions.DataError)
|
||||
|
|
@ -311,10 +313,11 @@ class OTR(object):
|
|||
@param menu_data: %(menu_data)s
|
||||
@param profile: %(doc_profile)s
|
||||
"""
|
||||
client = self.host.getClient(profile)
|
||||
try:
|
||||
to_jid = jid.JID(menu_data['jid'])
|
||||
if not to_jid.resource:
|
||||
to_jid.resource = self.host.memory.getMainResource(to_jid, profile) # FIXME: temporary and unsecure, must be changed when frontends are refactored
|
||||
to_jid.resource = self.host.memory.getMainResource(client, to_jid) # FIXME: temporary and unsecure, must be changed when frontends are refactored
|
||||
except KeyError:
|
||||
log.error(_("jid key is not present !"))
|
||||
return defer.fail(exceptions.DataError)
|
||||
|
|
@ -381,10 +384,11 @@ class OTR(object):
|
|||
@param menu_data: %(menu_data)s
|
||||
@param profile: %(doc_profile)s
|
||||
"""
|
||||
client = self.host.getClient(profile)
|
||||
try:
|
||||
to_jid = jid.JID(menu_data['jid'])
|
||||
if not to_jid.resource:
|
||||
to_jid.resource = self.host.memory.getMainResource(to_jid, profile) # FIXME: temporary and unsecure, must be changed when frontends are refactored
|
||||
to_jid.resource = self.host.memory.getMainResource(client, to_jid) # FIXME: temporary and unsecure, must be changed when frontends are refactored
|
||||
except KeyError:
|
||||
log.error(_("jid key is not present !"))
|
||||
return defer.fail(exceptions.DataError)
|
||||
|
|
@ -467,7 +471,7 @@ class OTR(object):
|
|||
return True
|
||||
to_jid = copy.copy(mess_data['to'])
|
||||
if mess_data['type'] != 'groupchat' and not to_jid.resource:
|
||||
to_jid.resource = self.host.memory.getMainResource(to_jid, profile) # FIXME: it's dirty, but frontends don't manage resources correctly now, refactoring is planed
|
||||
to_jid.resource = self.host.memory.getMainResource(client, to_jid) # FIXME: it's dirty, but frontends don't manage resources correctly now, refactoring is planed
|
||||
otrctx = self.context_managers[profile].getContextForUser(to_jid)
|
||||
if mess_data['type'] != 'groupchat' and otrctx.state != potr.context.STATE_PLAINTEXT:
|
||||
if otrctx.state == potr.context.STATE_ENCRYPTED:
|
||||
|
|
@ -496,11 +500,12 @@ class OTR(object):
|
|||
return True
|
||||
|
||||
def _presenceReceivedTrigger(self, entity, show, priority, statuses, profile):
|
||||
client = self.host.getClient(profile)
|
||||
if show != C.PRESENCE_UNAVAILABLE:
|
||||
return True
|
||||
if not entity.resource:
|
||||
try:
|
||||
entity.resource = self.host.memory.getMainResource(entity, profile) # FIXME: temporary and unsecure, must be changed when frontends are refactored
|
||||
entity.resource = self.host.memory.getMainResource(client, entity) # FIXME: temporary and unsecure, must be changed when frontends are refactored
|
||||
except exceptions.UnknownEntityError:
|
||||
return True # entity was not connected
|
||||
if entity in self.context_managers[profile].contexts:
|
||||
|
|
|
|||
|
|
@ -63,44 +63,32 @@ CONFIG_SECTION = u'plugin muc'
|
|||
default_conf = {"default_muc": u'sat@chat.jabberfr.org'}
|
||||
|
||||
|
||||
class UnknownRoom(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class AlreadyJoinedRoom(Exception):
|
||||
pass
|
||||
|
||||
class NotReadyYet(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class XEP_0045(object):
|
||||
# TODO: this plugin is messy, need a big cleanup/refactoring
|
||||
|
||||
def __init__(self, host):
|
||||
log.info(_("Plugin XEP_0045 initialization"))
|
||||
self.host = host
|
||||
self.clients = {} # FIXME: should be moved to profile's client
|
||||
self._sessions = memory.Sessions()
|
||||
host.bridge.addMethod("mucJoin", ".plugin", in_sign='ssa{ss}s', out_sign='s', method=self._join, async=True)
|
||||
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("getRoomsJoined", ".plugin", in_sign='s', out_sign='a(sa{sa{ss}}ss)', 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.addMethod("getDefaultMUC", ".plugin", in_sign='', out_sign='s', method=self.getDefaultMUC)
|
||||
host.bridge.addSignal("roomJoined", ".plugin", signature='sa{sa{ss}}sss') # args: room_jid, occupants, user_nick, subject, profile
|
||||
host.bridge.addSignal("roomLeft", ".plugin", signature='ss') # args: room_jid, 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
|
||||
host.bridge.addMethod("mucNick", ".plugin", in_sign='sss', out_sign='', method=self._nick)
|
||||
host.bridge.addMethod("mucLeave", ".plugin", in_sign='ss', out_sign='', method=self._leave, async=True)
|
||||
host.bridge.addMethod("mucGetRoomsJoined", ".plugin", in_sign='s', out_sign='a(sa{sa{ss}}ss)', method=self._getRoomsJoined)
|
||||
host.bridge.addMethod("mucGetUniqueRoomName", ".plugin", in_sign='ss', out_sign='s', method=self._getUniqueName)
|
||||
host.bridge.addMethod("mucConfigureRoom", ".plugin", in_sign='ss', out_sign='s', method=self._configureRoom, async=True)
|
||||
host.bridge.addMethod("mucGetDefaultService", ".plugin", in_sign='', out_sign='s', method=self.getDefaultMUC)
|
||||
host.bridge.addSignal("mucRoomJoined", ".plugin", signature='sa{sa{ss}}sss') # args: room_jid, occupants, user_nick, subject, profile
|
||||
host.bridge.addSignal("mucRoomLeft", ".plugin", signature='ss') # args: room_jid, profile
|
||||
host.bridge.addSignal("mucRoomUserChangedNick", ".plugin", signature='ssss') # args: room_jid, old_nick, new_nick, profile
|
||||
host.bridge.addSignal("mucRoomNewSubject", ".plugin", signature='sss') # args: room_jid, subject, profile
|
||||
self.__submit_conf_id = host.registerCallback(self._submitConfiguration, with_data=True)
|
||||
host.importMenu((D_("MUC"), D_("configure")), self._configureRoomMenu, security_limit=0, help_string=D_("Configure Multi-User Chat room"), type_=C.MENU_ROOM)
|
||||
try:
|
||||
self.host.plugins[C.TEXT_CMDS].registerTextCommands(self)
|
||||
self.host.plugins[C.TEXT_CMDS].addWhoIsCb(self._whois, 100)
|
||||
txt_cmds = self.host.plugins[C.TEXT_CMDS]
|
||||
except KeyError:
|
||||
log.info(_("Text commands not available"))
|
||||
log.info(_(u"Text commands not available"))
|
||||
else:
|
||||
txt_cmds.registerTextCommands(self)
|
||||
txt_cmds.addWhoIsCb(self._whois, 100)
|
||||
|
||||
host.trigger.add("presence_available", self.presenceTrigger)
|
||||
host.trigger.add("MessageReceived", self.MessageReceivedTrigger, priority=1000000)
|
||||
|
|
@ -117,8 +105,8 @@ class XEP_0045(object):
|
|||
return False
|
||||
from_jid = jid.JID(message_elt['from'])
|
||||
room_jid = from_jid.userhostJID()
|
||||
if room_jid in self.clients[client.profile].joined_rooms:
|
||||
room = self.clients[client.profile].joined_rooms[room_jid]
|
||||
if room_jid in client._muc_client.joined_rooms:
|
||||
room = client._muc_client.joined_rooms[room_jid]
|
||||
if not room._room_ok:
|
||||
log.warning(u"Received non delayed message in a room before its initialisation: {}".format(message_elt.toXml()))
|
||||
room._cache.append(message_elt)
|
||||
|
|
@ -128,137 +116,129 @@ class XEP_0045(object):
|
|||
return False
|
||||
return True
|
||||
|
||||
def checkClient(self, profile):
|
||||
"""Check if the profile is connected and has used the MUC feature.
|
||||
|
||||
If profile was using MUC feature but is now disconnected, remove it from the client list.
|
||||
@param profile: profile to check
|
||||
@return: True if the profile is connected and has used the MUC feature, else False"""
|
||||
if not profile or profile not in self.clients or not self.host.isConnected(profile):
|
||||
log.error(_(u'Unknown or disconnected profile (%s)') % profile)
|
||||
if profile in self.clients:
|
||||
del self.clients[profile]
|
||||
return False
|
||||
return True
|
||||
|
||||
def getProfileAssertInRoom(self, room_jid, profile_key):
|
||||
"""Retrieve the profile name, assert that it's connected and participating in the given room.
|
||||
def checkRoomJoined(self, client, room_jid):
|
||||
"""Check that given room has been joined in current session
|
||||
|
||||
@param room_jid (JID): room JID
|
||||
@param profile_key (str): %(doc_profile_key)
|
||||
@return: the profile name
|
||||
"""
|
||||
profile = self.host.memory.getProfileName(profile_key)
|
||||
if not self.checkClient(profile):
|
||||
raise exceptions.ProfileUnknownError("Unknown or disconnected profile")
|
||||
if room_jid not in self.clients[profile].joined_rooms:
|
||||
raise UnknownRoom("This room has not been joined")
|
||||
return profile
|
||||
if room_jid not in client._muc_client.joined_rooms:
|
||||
raise exceptions.NotFound(_(u"This room has not been joined"))
|
||||
|
||||
def _joinCb(self, room, profile):
|
||||
def isJoinedRoom(self, client, room_jid):
|
||||
"""Tell if a jid is a known and joined room
|
||||
|
||||
@room_jid(jid.JID): jid of the room
|
||||
"""
|
||||
try:
|
||||
self.checkRoomJoined(client, room_jid)
|
||||
except exceptions.NotFound:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def _joinCb(self, room, client):
|
||||
"""Called when the user is in the requested room"""
|
||||
if room.locked:
|
||||
# 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
|
||||
print "room locked !"
|
||||
d = self.clients[profile].configure(room.roomJID, {})
|
||||
log.debug(_(u"room locked !"))
|
||||
d = client._muc_client.configure(room.roomJID, {})
|
||||
d.addErrback(lambda dummy: log.error(_(u'Error while configuring the room')))
|
||||
return room
|
||||
|
||||
def _joinEb(self, failure, room_jid, nick, password, profile):
|
||||
def _joinEb(self, failure, client, room_jid, nick, password):
|
||||
"""Called when something is going wrong when joining the room"""
|
||||
if hasattr(failure.value, "condition") and failure.value.condition == 'conflict':
|
||||
# we have a nickname conflict, we try again with "_" suffixed to current nickname
|
||||
nick += '_'
|
||||
return self.clients[profile].join(room_jid, nick, password).addCallbacks(self._joinCb, self._joinEb, callbackKeywords={'profile': profile}, errbackArgs=[room_jid, nick, password, profile])
|
||||
mess = D_("Error while joining the room %s" % room_jid.userhost())
|
||||
try:
|
||||
mess += " with condition '%s'" % failure.value.condition
|
||||
condition = failure.value.condition
|
||||
except AttributeError:
|
||||
pass
|
||||
msg_suffix = ''
|
||||
else:
|
||||
if condition == 'conflict':
|
||||
# we have a nickname conflict, we try again with "_" suffixed to current nickname
|
||||
nick += '_'
|
||||
return client.join(room_jid, nick, password).addCallbacks(self._joinCb, self._joinEb, callbackKeywords={client: client}, errbackArgs=[client, room_jid, nick, password])
|
||||
msg_suffix = ' with condition "{}"'.format(failure.value.condition)
|
||||
|
||||
mess = D_(u"Error while joining the room {room}{suffix}".format(
|
||||
room = room_jid.userhost(), suffix = msg_suffix))
|
||||
log.error(mess)
|
||||
self.host.bridge.newAlert(mess, D_("Group chat error"), "ERROR", profile)
|
||||
raise failure
|
||||
xmlui = xml_tools.note(mess, D_(u"Group chat error"), level=C.XMLUI_DATA_LVL_ERROR)
|
||||
self.host.actionNew({'xmlui': xmlui.toXml()}, profile=client.profile)
|
||||
|
||||
@staticmethod
|
||||
def _getOccupants(room):
|
||||
"""Get occupants of a room in a form suitable for bridge"""
|
||||
return {u.nick: {k:unicode(getattr(u,k) or '') for k in OCCUPANT_KEYS} for u in room.roster.values()}
|
||||
|
||||
def isRoom(self, entity_bare, profile_key):
|
||||
"""Tell if a bare entity is a MUC room.
|
||||
def _getRoomsJoined(self, profile_key=C.PROF_KEY_NONE):
|
||||
client = self.host.getClient(profile_key)
|
||||
return self.getRoomsJoined(client)
|
||||
|
||||
@param entity_bare (jid.JID): bare entity
|
||||
@param profile_key (unicode): %(doc_profile_key)s
|
||||
@return bool
|
||||
"""
|
||||
profile = self.host.memory.getProfileName(profile_key)
|
||||
return entity_bare in self.clients[profile].joined_rooms
|
||||
|
||||
def getRoomsJoined(self, profile_key=C.PROF_KEY_NONE):
|
||||
"""Return room where user is"""
|
||||
profile = self.host.memory.getProfileName(profile_key)
|
||||
def getRoomsJoined(self, client):
|
||||
"""Return rooms where user is"""
|
||||
result = []
|
||||
if not self.checkClient(profile):
|
||||
return result
|
||||
for room in self.clients[profile].joined_rooms.values():
|
||||
for room in client._muc_client.joined_rooms.values():
|
||||
if room._room_ok:
|
||||
result.append((room.roomJID.userhost(), self._getOccupants(room), room.nick, room.subject))
|
||||
return result
|
||||
|
||||
def getRoomNick(self, room_jid, profile_key=C.PROF_KEY_NONE):
|
||||
def getRoomNick(self, client, room_jid):
|
||||
"""return nick used in room by user
|
||||
|
||||
@param room_jid (jid.JID): JID of the room
|
||||
@profile_key: profile
|
||||
@return: nick or empty string in case of error"""
|
||||
profile = self.host.memory.getProfileName(profile_key)
|
||||
if not self.checkClient(profile) or room_jid not in self.clients[profile].joined_rooms:
|
||||
return ''
|
||||
return self.clients[profile].joined_rooms[room_jid].nick
|
||||
|
||||
def getRoomNickOfUser(self, room, user_jid, secure=True):
|
||||
"""Returns the nick of the given user in the room.
|
||||
|
||||
@param room (wokkel.muc.Room): the room
|
||||
@param user (jid.JID): bare JID of the user
|
||||
@param secure (bool): set to True for a secure check
|
||||
@return: unicode or None if the user didn't join the room.
|
||||
@return: nick or empty string in case of error
|
||||
"""
|
||||
for user in room.roster.values():
|
||||
if user.entity is not None:
|
||||
if user.entity.userhostJID() == user_jid.userhostJID():
|
||||
return user.nick
|
||||
elif not secure:
|
||||
# FIXME: this is NOT ENOUGH to check an identity!!
|
||||
# See in which conditions user.entity could be None.
|
||||
if user.nick == user_jid.user:
|
||||
return user.nick
|
||||
return None
|
||||
try:
|
||||
self.checkRoomJoined(client, room_jid)
|
||||
except exceptions.NotFound:
|
||||
return '' # FIXME: should not return empty string but raise the error
|
||||
return client._muc_client.joined_rooms[room_jid].nick
|
||||
|
||||
def getRoomNicksOfUsers(self, room, users=[], secure=True):
|
||||
"""Returns the nicks of the given users in the room.
|
||||
# FIXME: broken, to be removed !
|
||||
# def getRoomEntityNick(self, client, room_jid, entity_jid, =True):
|
||||
# """Returns the nick of the given user in the room.
|
||||
|
||||
@param room (wokkel.muc.Room): the room
|
||||
@param users (list[jid.JID]): list of users
|
||||
@param secure (True): set to True for a secure check
|
||||
@return: a couple (x, y) with:
|
||||
- x (list[unicode]): nicks of the users who are in the room
|
||||
- y (list[jid.JID]): JID of the missing users.
|
||||
"""
|
||||
nicks = []
|
||||
missing = []
|
||||
for user in users:
|
||||
nick = self.getRoomNickOfUser(room, user, secure)
|
||||
if nick is None:
|
||||
missing.append(user)
|
||||
else:
|
||||
nicks.append(nick)
|
||||
return nicks, missing
|
||||
# @param room (wokkel.muc.Room): the room
|
||||
# @param user (jid.JID): bare JID of the user
|
||||
# @param secure (bool): set to True for a secure check
|
||||
# @return: unicode or None if the user didn't join the room.
|
||||
# """
|
||||
# for user in room.roster.values():
|
||||
# if user.entity is not None:
|
||||
# if user.entity.userhostJID() == user_jid.userhostJID():
|
||||
# return user.nick
|
||||
# elif not secure:
|
||||
# # FIXME: this is NOT ENOUGH to check an identity!!
|
||||
# # See in which conditions user.entity could be None.
|
||||
# if user.nick == user_jid.user:
|
||||
# return user.nick
|
||||
# return None
|
||||
|
||||
# def getRoomNicksOfUsers(self, room, users=[], secure=True):
|
||||
# """Returns the nicks of the given users in the room.
|
||||
|
||||
# @param room (wokkel.muc.Room): the room
|
||||
# @param users (list[jid.JID]): list of users
|
||||
# @param secure (True): set to True for a secure check
|
||||
# @return: a couple (x, y) with:
|
||||
# - x (list[unicode]): nicks of the users who are in the room
|
||||
# - y (list[jid.JID]): JID of the missing users.
|
||||
# """
|
||||
# nicks = []
|
||||
# missing = []
|
||||
# for user in users:
|
||||
# nick = self.getRoomNickOfUser(room, user, secure)
|
||||
# if nick is None:
|
||||
# missing.append(user)
|
||||
# else:
|
||||
# nicks.append(nick)
|
||||
# return nicks, missing
|
||||
|
||||
def _configureRoom(self, room_jid_s, profile_key=C.PROF_KEY_NONE):
|
||||
d = self.configureRoom(jid.JID(room_jid_s), profile_key)
|
||||
client = self.host.getClient(profile_key)
|
||||
d = self.configureRoom(client, jid.JID(room_jid_s))
|
||||
d.addCallback(lambda xmlui: xmlui.toXml())
|
||||
return d
|
||||
|
||||
|
|
@ -268,6 +248,7 @@ class XEP_0045(object):
|
|||
@param menu_data: %(menu_data)s
|
||||
@param profile: %(doc_profile)s
|
||||
"""
|
||||
client = self.host.getClient(profile)
|
||||
try:
|
||||
room_jid = jid.JID(menu_data['room_jid'])
|
||||
except KeyError:
|
||||
|
|
@ -276,31 +257,31 @@ class XEP_0045(object):
|
|||
|
||||
def xmluiReceived(xmlui):
|
||||
return {"xmlui": xmlui.toXml()}
|
||||
return self.configureRoom(room_jid, profile).addCallback(xmluiReceived)
|
||||
return self.configureRoom(client, room_jid).addCallback(xmluiReceived)
|
||||
|
||||
def configureRoom(self, room_jid, profile_key=C.PROF_KEY_NONE):
|
||||
def configureRoom(self, client, room_jid):
|
||||
"""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.getProfileAssertInRoom(room_jid, profile_key)
|
||||
self.checkRoomJoined(client, room_jid)
|
||||
|
||||
def config2XMLUI(result):
|
||||
if not result:
|
||||
return ""
|
||||
session_id, session_data = self._sessions.newSession(profile=profile)
|
||||
session_id, session_data = self._sessions.newSession(profile=client.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 = client._muc_client.getConfiguration(room_jid)
|
||||
d.addCallback(config2XMLUI)
|
||||
return d
|
||||
|
||||
def _submitConfiguration(self, raw_data, profile):
|
||||
client = self.host.getClient(profile)
|
||||
try:
|
||||
session_data = self._sessions.profileGet(raw_data["session_id"], profile)
|
||||
except KeyError:
|
||||
|
|
@ -310,25 +291,17 @@ class XEP_0045(object):
|
|||
return defer.succeed({'xmlui': _dialog.toXml()})
|
||||
|
||||
data = xml_tools.XMLUIResult2DataFormResult(raw_data)
|
||||
d = self.clients[profile].configure(session_data['room_jid'], data)
|
||||
d = client._muc_client.configure(session_data['room_jid'], data)
|
||||
_dialog = xml_tools.XMLUI('popup', title=D_('Room configuration succeed'))
|
||||
_dialog.addText(D_("The new settings have been saved."))
|
||||
d.addCallback(lambda ignore: {'xmlui': _dialog.toXml()})
|
||||
del self._sessions[raw_data["session_id"]]
|
||||
return d
|
||||
|
||||
def isNickInRoom(self, room_jid, nick, profile):
|
||||
def isNickInRoom(self, client, room_jid, nick):
|
||||
"""Tell if a nick is currently present in a room"""
|
||||
profile = self.getProfileAssertInRoom(room_jid, profile)
|
||||
return self.clients[profile].joined_rooms[room_jid].inRoster(muc.User(nick))
|
||||
|
||||
def getRoomsSubjects(self, profile_key=C.PROF_KEY_NONE):
|
||||
"""Return received subjects of rooms"""
|
||||
# FIXME: to be removed
|
||||
profile = self.host.memory.getProfileName(profile_key)
|
||||
if not self.checkClient(profile):
|
||||
return []
|
||||
return self.clients[profile].rec_subjects.values()
|
||||
self.checkRoomJoined(client, room_jid)
|
||||
return client._muc_client.joined_rooms[room_jid].inRoster(muc.User(nick))
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def getMUCService(self, jid_=None, profile=C.PROF_KEY_NONE):
|
||||
|
|
@ -349,28 +322,28 @@ class XEP_0045(object):
|
|||
defer.returnValue(muc_service)
|
||||
|
||||
def _getUniqueName(self, muc_service="", profile_key=C.PROF_KEY_NONE):
|
||||
return self.getUniqueName(muc_service or None, profile_key).full()
|
||||
client = self.host.getClient(profile_key)
|
||||
return self.getUniqueName(client, muc_service or None).full()
|
||||
|
||||
def getUniqueName(self, muc_service=None, profile_key=C.PROF_KEY_NONE):
|
||||
def getUniqueName(self, client, muc_service=None):
|
||||
"""Return unique name for a room, avoiding collision
|
||||
|
||||
@param muc_service (jid.JID) : leave empty string to use the default service
|
||||
@return: jid.JID (unique room bare JID)
|
||||
"""
|
||||
# TODO: we should use #RFC-0045 10.1.4 when available here
|
||||
client = self.host.getClient(profile_key)
|
||||
room_name = uuid.uuid1()
|
||||
room_name = unicode(uuid.uuid4())
|
||||
if muc_service is None:
|
||||
try:
|
||||
muc_service = client.muc_service
|
||||
except AttributeError:
|
||||
raise NotReadyYet("Main server MUC service has not been checked yet")
|
||||
raise exceptions.NotReady(u"Main server MUC service has not been checked yet")
|
||||
if muc_service is None:
|
||||
log.warning(_("No MUC service found on main server"))
|
||||
raise exceptions.FeatureNotFound
|
||||
|
||||
muc_service = muc_service.userhost()
|
||||
return jid.JID("%s@%s" % (room_name, muc_service))
|
||||
return jid.JID(u"{}@{}".format(room_name, muc_service))
|
||||
|
||||
def getDefaultMUC(self):
|
||||
"""Return the default MUC.
|
||||
|
|
@ -380,19 +353,19 @@ class XEP_0045(object):
|
|||
return self.host.memory.getConfig(CONFIG_SECTION, 'default_muc', default_conf['default_muc'])
|
||||
|
||||
def join(self, client, room_jid, nick, options):
|
||||
def _errDeferred(exc_obj=Exception, txt='Error while joining room'):
|
||||
def _errDeferred(exc_obj=Exception, txt=u'Error while joining room'):
|
||||
d = defer.Deferred()
|
||||
d.errback(exc_obj(txt))
|
||||
return d
|
||||
|
||||
if room_jid in self.clients[client.profile].joined_rooms:
|
||||
log.warning(_(u'%(profile)s is already in room %(room_jid)s') % {'profile': client.profile, 'room_jid': room_jid.userhost()})
|
||||
return _errDeferred(AlreadyJoinedRoom, D_(u"The room has already been joined"))
|
||||
log.info(_(u"[%(profile)s] is joining room %(room)s with nick %(nick)s") % {'profile': client.profile, 'room': room_jid.userhost(), 'nick': nick})
|
||||
if room_jid in client._muc_client.joined_rooms:
|
||||
log.warning(_(u'{profile} is already in room {room_jid}').format(profile=client.profile, room_jid = room_jid.userhost()))
|
||||
return defer.fail(exceptions.ConflictError(_(u"The room has already been joined")))
|
||||
log.info(_(u"[{profile}] is joining room {room} with nick {nick}").format(profile=client.profile, room=room_jid.userhost(), nick=nick))
|
||||
|
||||
password = options["password"] if "password" in options else None
|
||||
|
||||
return self.clients[client.profile].join(room_jid, nick, password).addCallbacks(self._joinCb, self._joinEb, callbackKeywords={'profile': client.profile}, errbackArgs=[room_jid, nick, password, client.profile])
|
||||
return client._muc_client.join(room_jid, nick, password).addCallbacks(self._joinCb, self._joinEb, callbackKeywords={'client': client}, errbackArgs=[client, room_jid, nick, password])
|
||||
|
||||
def _join(self, room_jid_s, nick, options=None, profile_key=C.PROF_KEY_NONE):
|
||||
"""join method used by bridge
|
||||
|
|
@ -416,74 +389,72 @@ class XEP_0045(object):
|
|||
d = self.join(client, room_jid, nick, options)
|
||||
return d.addCallback(lambda room: room.roomJID.userhost())
|
||||
|
||||
def nick(self, room_jid, nick, profile_key):
|
||||
profile = self.getProfileAssertInRoom(room_jid, profile_key)
|
||||
return self.clients[profile].nick(room_jid, nick)
|
||||
def _nick(self, room_jid_s, nick, profile_key=C.PROF_KEY_NONE):
|
||||
client = self.host.getClient(profile_key)
|
||||
return self.nick(client, jid.JID(room_jid_s), nick)
|
||||
|
||||
def leave(self, room_jid, profile_key):
|
||||
profile = self.getProfileAssertInRoom(room_jid, profile_key)
|
||||
return self.clients[profile].leave(room_jid)
|
||||
|
||||
def subject(self, room_jid, subject, profile_key):
|
||||
profile = self.getProfileAssertInRoom(room_jid, profile_key)
|
||||
return self.clients[profile].subject(room_jid, subject)
|
||||
|
||||
def mucNick(self, room_jid_s, nick, profile_key=C.PROF_KEY_NONE):
|
||||
def nick(self, client, room_jid, nick):
|
||||
"""Change nickname in a room"""
|
||||
return self.nick(jid.JID(room_jid_s), nick, profile_key)
|
||||
self.checkRoomJoined(client, room_jid)
|
||||
return client._muc_client.nick(room_jid, nick)
|
||||
|
||||
def mucLeave(self, room_jid_s, profile_key=C.PROF_KEY_NONE):
|
||||
"""Leave a room"""
|
||||
return self.leave(jid.JID(room_jid_s), profile_key)
|
||||
def _leave(self, room_jid, profile_key):
|
||||
client = self.host.getClient(profile_key)
|
||||
return self.leave(client, jid.JID(room_jid))
|
||||
|
||||
def leave(self, client, room_jid):
|
||||
self.checkRoomJoined(client, room_jid)
|
||||
return client._muc_client.leave(room_jid)
|
||||
|
||||
def subject(self, client, room_jid, subject):
|
||||
self.checkRoomJoined(client, room_jid)
|
||||
return client._muc_client.subject(room_jid, subject)
|
||||
|
||||
def getHandler(self, profile):
|
||||
self.clients[profile] = SatMUCClient(self)
|
||||
return self.clients[profile]
|
||||
# create a MUC client and associate it with profile' session
|
||||
client = self.host.getClient(profile)
|
||||
muc_client = client._muc_client = SatMUCClient(self)
|
||||
return muc_client
|
||||
|
||||
def profileDisconnected(self, profile):
|
||||
try:
|
||||
del self.clients[profile]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def kick(self, nick, room_jid, options={}, profile_key=C.PROF_KEY_NONE):
|
||||
def kick(self, client, nick, room_jid, options=None):
|
||||
"""
|
||||
Kick a participant from the room
|
||||
@param nick (str): nick of the user to kick
|
||||
@param room_jid_s (JID): jid of the room
|
||||
@param options (dict): attribute with extra info (reason, password) as in #XEP-0045
|
||||
@param profile_key (str): %(doc_profile_key)s
|
||||
"""
|
||||
profile = self.getProfileAssertInRoom(room_jid, profile_key)
|
||||
return self.clients[profile].kick(room_jid, nick, reason=options.get('reason', None))
|
||||
if options is None:
|
||||
options = {}
|
||||
self.checkRoomJoined(client, room_jid)
|
||||
return client._muc_client.kick(room_jid, nick, reason=options.get('reason', None))
|
||||
|
||||
def ban(self, client, entity_jid, room_jid, options=None):
|
||||
"""Ban an entity from the room
|
||||
|
||||
def ban(self, entity_jid, room_jid, options={}, profile_key=C.PROF_KEY_NONE):
|
||||
"""
|
||||
Ban an entity from the room
|
||||
@param entity_jid (JID): bare jid of the entity to be banned
|
||||
@param room_jid_s (JID): jid of the room
|
||||
@param room_jid (JID): jid of the room
|
||||
@param options: attribute with extra info (reason, password) as in #XEP-0045
|
||||
@param profile_key (str): %(doc_profile_key)s
|
||||
"""
|
||||
assert(not entity_jid.resource)
|
||||
assert(not room_jid.resource)
|
||||
profile = self.getProfileAssertInRoom(room_jid, profile_key)
|
||||
return self.clients[profile].ban(room_jid, entity_jid, reason=options.get('reason', None))
|
||||
self.checkRoomJoined(client, room_jid)
|
||||
if options is None:
|
||||
options = {}
|
||||
assert not entity_jid.resource
|
||||
assert not room_jid.resource
|
||||
return client._muc_client.ban(room_jid, entity_jid, reason=options.get('reason', None))
|
||||
|
||||
def affiliate(self, client, entity_jid, room_jid, options):
|
||||
"""Change the affiliation of an entity
|
||||
|
||||
def affiliate(self, entity_jid, room_jid, options=None, profile_key=C.PROF_KEY_NONE):
|
||||
"""
|
||||
Change the affiliation of an entity
|
||||
@param entity_jid (JID): bare jid of the entity
|
||||
@param room_jid_s (JID): jid of the room
|
||||
@param options: attribute with extra info (reason, nick) as in #XEP-0045
|
||||
@param profile_key (str): %(doc_profile_key)s
|
||||
"""
|
||||
assert(not entity_jid.resource)
|
||||
assert(not room_jid.resource)
|
||||
assert('affiliation' in options)
|
||||
profile = self.getProfileAssertInRoom(room_jid, profile_key)
|
||||
self.checkRoomJoined(client, room_jid)
|
||||
assert not entity_jid.resource
|
||||
assert not room_jid.resource
|
||||
assert 'affiliation' in options
|
||||
# TODO: handles reason and nick
|
||||
return self.clients[profile].modifyAffiliationList(room_jid, [entity_jid], options['affiliation'])
|
||||
return client._muc_client.modifyAffiliationList(room_jid, [entity_jid], options['affiliation'])
|
||||
|
||||
# Text commands #
|
||||
|
||||
|
|
@ -508,7 +479,7 @@ class XEP_0045(object):
|
|||
"""
|
||||
if mess_data["unparsed"].strip():
|
||||
room_jid = self.host.plugins[C.TEXT_CMDS].getRoomJID(mess_data["unparsed"].strip(), mess_data["to"].host)
|
||||
nick = (self.getRoomNick(room_jid, client.profile) or
|
||||
nick = (self.getRoomNick(client, room_jid) or
|
||||
self.host.getClient(client.profile).jid.user)
|
||||
self.join(client, room_jid, nick, {})
|
||||
|
||||
|
|
@ -546,7 +517,7 @@ class XEP_0045(object):
|
|||
options = mess_data["unparsed"].strip().split()
|
||||
try:
|
||||
nick = options[0]
|
||||
assert(self.isNickInRoom(mess_data["to"], nick, client.profile))
|
||||
assert self.isNickInRoom(client, mess_data["to"], nick)
|
||||
except (IndexError, AssertionError):
|
||||
feedback = _(u"You must provide a member's nick to kick.")
|
||||
self.host.plugins[C.TEXT_CMDS].feedBack(client, feedback, mess_data)
|
||||
|
|
@ -639,7 +610,7 @@ class XEP_0045(object):
|
|||
|
||||
if subject:
|
||||
room = mess_data["to"]
|
||||
self.subject(room, subject, client.profile)
|
||||
self.subject(client, room, subject)
|
||||
|
||||
return False
|
||||
|
||||
|
|
@ -655,12 +626,12 @@ class XEP_0045(object):
|
|||
""" Add MUC user information to whois """
|
||||
if mess_data['type'] != "groupchat":
|
||||
return
|
||||
if target_jid.userhostJID() not in self.clients[client.profile].joined_rooms:
|
||||
if target_jid.userhostJID() not in client._muc_client.joined_rooms:
|
||||
log.warning(_("This room has not been joined"))
|
||||
return
|
||||
if not target_jid.resource:
|
||||
return
|
||||
user = self.clients[client.profile].joined_rooms[target_jid.userhostJID()].getUser(target_jid.resource)
|
||||
user = client._muc_client.joined_rooms[target_jid.userhostJID()].getUser(target_jid.resource)
|
||||
whois_msg.append(_("Nickname: %s") % user.nick)
|
||||
if user.entity:
|
||||
whois_msg.append(_("Entity: %s") % user.entity)
|
||||
|
|
@ -675,7 +646,7 @@ class XEP_0045(object):
|
|||
|
||||
def presenceTrigger(self, presence_elt, client):
|
||||
# XXX: shouldn't it be done by the server ?!!
|
||||
muc_client = self.clients[client.profile]
|
||||
muc_client = client._muc_client
|
||||
for room_jid, room in muc_client.joined_rooms.iteritems():
|
||||
elt = copy.deepcopy(presence_elt)
|
||||
elt['to'] = room_jid.userhost() + '/' + room.nick
|
||||
|
|
@ -683,7 +654,7 @@ class XEP_0045(object):
|
|||
return True
|
||||
|
||||
|
||||
class SatMUCClient (muc.MUCClient):
|
||||
class SatMUCClient(muc.MUCClient):
|
||||
implements(iwokkel.IDisco)
|
||||
|
||||
def __init__(self, plugin_parent):
|
||||
|
|
@ -823,7 +794,7 @@ class SatMUCClient (muc.MUCClient):
|
|||
log.info(_(u"Room ({room}) left ({profile})").format(
|
||||
room = room_jid_s, profile = self.parent.profile))
|
||||
self.host.memory.delEntityCache(room.roomJID, profile_key=self.parent.profile)
|
||||
self.host.bridge.roomLeft(room.roomJID.userhost(), self.parent.profile)
|
||||
self.host.bridge.mucRoomLeft(room.roomJID.userhost(), self.parent.profile)
|
||||
else:
|
||||
log.debug(_(u"user {nick} left room {room_id}").format(nick=user.nick, room_id=room.occupantJID.userhost()))
|
||||
extra = {'info_type': ROOM_USER_LEFT,
|
||||
|
|
@ -847,7 +818,7 @@ class SatMUCClient (muc.MUCClient):
|
|||
self.host.messageSendToBridge(mess_data, self.parent)
|
||||
|
||||
def userChangedNick(self, room, user, new_nick):
|
||||
self.host.bridge.roomUserChangedNick(room.roomJID.userhost(), user.nick, new_nick, self.parent.profile)
|
||||
self.host.bridge.mucRoomUserChangedNick(room.roomJID.userhost(), user.nick, new_nick, self.parent.profile)
|
||||
|
||||
def userUpdatedStatus(self, room, user, show, status):
|
||||
self.host.bridge.presenceUpdate(room.roomJID.userhost() + '/' + user.nick, show or '', 0, {C.PRESENCE_STATUSES_DEFAULT: status or ''}, self.parent.profile)
|
||||
|
|
@ -923,7 +894,7 @@ class SatMUCClient (muc.MUCClient):
|
|||
return muc.MUCClientProtocol.subject(self, room, subject)
|
||||
|
||||
def _historyCb(self, dummy, room):
|
||||
self.host.bridge.roomJoined(
|
||||
self.host.bridge.mucRoomJoined(
|
||||
room.roomJID.userhost(),
|
||||
XEP_0045._getOccupants(room),
|
||||
room.nick,
|
||||
|
|
@ -954,7 +925,7 @@ class SatMUCClient (muc.MUCClient):
|
|||
else:
|
||||
# the subject has been changed
|
||||
log.debug(_(u"New subject for room ({room_id}): {subject}").format(room_id = room.roomJID.full(), subject = subject))
|
||||
self.host.bridge.roomNewSubject(room.roomJID.userhost(), subject, self.parent.profile)
|
||||
self.host.bridge.mucRoomNewSubject(room.roomJID.userhost(), subject, self.parent.profile)
|
||||
|
||||
## disco ##
|
||||
|
||||
|
|
|
|||
|
|
@ -109,16 +109,18 @@ class XEP_0054(object):
|
|||
|
||||
return True
|
||||
|
||||
def isInRoom(self, entity_jid, profile):
|
||||
def isInRoom(self, client, entity_jid):
|
||||
"""Tell if an full jid is a member of a room
|
||||
|
||||
@param entity_jid(jid.JID): full jid of the entity
|
||||
@return (bool): True if the bare jid of the entity is a room jid
|
||||
"""
|
||||
try:
|
||||
return self.host.plugins['XEP-0045'].isRoom(entity_jid.userhostJID(), profile_key=profile)
|
||||
except KeyError:
|
||||
self.host.plugins['XEP-0045'].checkRoomJoined(client, entity_jid.userhostJID())
|
||||
except exceptions.NotFound:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def _fillCachedValues(self, profile):
|
||||
#FIXME: this is really suboptimal, need to be reworked
|
||||
|
|
@ -143,41 +145,39 @@ class XEP_0054(object):
|
|||
log.debug(u"Deleting profile cache for avatars")
|
||||
del self.cache[profile]
|
||||
|
||||
def updateCache(self, jid_, name, value, profile):
|
||||
def updateCache(self, client, jid_, name, value):
|
||||
"""update cache value
|
||||
|
||||
save value in memory in case of change
|
||||
@param jid_(jid.JID): jid of the owner of the vcard
|
||||
@param name(str): name of the item which changed
|
||||
@param value(unicode): new value of the item
|
||||
@param profile(unicode): profile which received the update
|
||||
"""
|
||||
if jid_.resource:
|
||||
if not self.isInRoom(jid_, profile):
|
||||
if not self.isInRoom(client, jid_):
|
||||
# VCard are retrieved with bare jid
|
||||
# but MUC room is a special case
|
||||
jid_ = jid.userhostJID()
|
||||
|
||||
self.host.memory.updateEntityData(jid_, name, value, profile_key=profile)
|
||||
self.host.memory.updateEntityData(jid_, name, value, profile_key=client.profile)
|
||||
if name in CACHED_DATA:
|
||||
jid_s = jid_.userhost()
|
||||
self.cache[profile].setdefault(jid_s, {})[name] = value
|
||||
self.cache[profile].force(jid_s)
|
||||
self.cache[client.profile].setdefault(jid_s, {})[name] = value
|
||||
self.cache[client.profile].force(jid_s)
|
||||
|
||||
def getCache(self, entity_jid, name, profile):
|
||||
def getCache(self, client, entity_jid, name):
|
||||
"""return cached value for jid
|
||||
|
||||
@param entity_jid: target contact
|
||||
@param name: name of the value ('nick' or 'avatar')
|
||||
@param profile: %(doc_profile)s
|
||||
@return: wanted value or None"""
|
||||
if entity_jid.resource:
|
||||
if not self.isInRoom(entity_jid, profile):
|
||||
if not self.isInRoom(client, entity_jid):
|
||||
# VCard are retrieved with bare jid
|
||||
# but MUC room is a special case
|
||||
entity_jid = jid.userhostJID()
|
||||
try:
|
||||
data = self.host.memory.getEntityData(entity_jid, [name], profile)
|
||||
data = self.host.memory.getEntityData(entity_jid, [name], client.profile)
|
||||
except exceptions.UnknownEntityError:
|
||||
return None
|
||||
return data.get(name)
|
||||
|
|
@ -217,7 +217,7 @@ class XEP_0054(object):
|
|||
return image_hash
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def vCard2Dict(self, vcard, target, profile):
|
||||
def vCard2Dict(self, client, vcard, target):
|
||||
"""Convert a VCard to a dict, and save binaries"""
|
||||
log.debug(_("parsing vcard"))
|
||||
dictionary = {}
|
||||
|
|
@ -227,7 +227,7 @@ class XEP_0054(object):
|
|||
dictionary['fullname'] = unicode(elem)
|
||||
elif elem.name == 'NICKNAME':
|
||||
dictionary['nick'] = unicode(elem)
|
||||
self.updateCache(target, 'nick', dictionary['nick'], profile)
|
||||
self.updateCache(client, target, 'nick', dictionary['nick'])
|
||||
elif elem.name == 'URL':
|
||||
dictionary['website'] = unicode(elem)
|
||||
elif elem.name == 'EMAIL':
|
||||
|
|
@ -239,7 +239,7 @@ class XEP_0054(object):
|
|||
if not dictionary["avatar"]: # can happen in case of e.g. empty photo elem
|
||||
del dictionary['avatar']
|
||||
else:
|
||||
self.updateCache(target, 'avatar', dictionary['avatar'], profile)
|
||||
self.updateCache(client, target, 'avatar', dictionary['avatar'])
|
||||
else:
|
||||
log.info(_('FIXME: [%s] VCard tag is not managed yet') % elem.name)
|
||||
|
||||
|
|
@ -248,56 +248,52 @@ class XEP_0054(object):
|
|||
# and we reset them
|
||||
for datum in CACHED_DATA.difference(dictionary.keys()):
|
||||
log.debug(u"reseting vcard datum [{datum}] for {entity}".format(datum=datum, entity=target.full()))
|
||||
self.updateCache(target, datum, '', profile)
|
||||
self.updateCache(client, target, datum, '')
|
||||
|
||||
defer.returnValue(dictionary)
|
||||
|
||||
def _VCardCb(self, answer, profile):
|
||||
def _VCardCb(self, answer, client):
|
||||
"""Called after the first get IQ"""
|
||||
log.debug(_("VCard found"))
|
||||
|
||||
if answer.firstChildElement().name == "vCard":
|
||||
_jid, steam = self.host.getJidNStream(profile)
|
||||
try:
|
||||
from_jid = jid.JID(answer["from"])
|
||||
except KeyError:
|
||||
from_jid = _jid.userhostJID()
|
||||
d = self.vCard2Dict(answer.firstChildElement(), from_jid, profile)
|
||||
d.addCallback(lambda data: self.host.bridge.actionResult("RESULT", answer['id'], data, profile))
|
||||
from_jid = client.jid.userhostJID()
|
||||
d = self.vCard2Dict(client, answer.firstChildElement(), from_jid)
|
||||
d.addCallback(lambda data: self.host.bridge.actionResult("RESULT", answer['id'], data, client.profile))
|
||||
else:
|
||||
log.error(_("FIXME: vCard not found as first child element"))
|
||||
self.host.bridge.actionResult("SUPPRESS", answer['id'], {}, profile) # FIXME: maybe an error message would be better
|
||||
self.host.bridge.actionResult("SUPPRESS", answer['id'], {}, client.profile) # FIXME: maybe an error message would be better
|
||||
|
||||
def _VCardEb(self, failure, profile):
|
||||
def _VCardEb(self, failure, client):
|
||||
"""Called when something is wrong with registration"""
|
||||
try:
|
||||
self.host.bridge.actionResult("SUPPRESS", failure.value.stanza['id'], {}, profile) # FIXME: maybe an error message would be better
|
||||
self.host.bridge.actionResult("SUPPRESS", failure.value.stanza['id'], {}, client.profile) # FIXME: maybe an error message would be better
|
||||
log.warning(_(u"Can't find VCard of %s") % failure.value.stanza['from'])
|
||||
self.updateCache(jid.JID(failure.value.stanza['from']), "avatar", '', profile)
|
||||
self.updateCache(client, jid.JID(failure.value.stanza['from']), "avatar", '')
|
||||
except (AttributeError, KeyError):
|
||||
# 'ConnectionLost' object has no attribute 'stanza' + sometimes 'from' key doesn't exist
|
||||
log.warning(_(u"Can't find VCard: %s") % failure.getErrorMessage())
|
||||
|
||||
def _getCard(self, target_s, profile_key=C.PROF_KEY_NONE):
|
||||
return self.getCard(jid.JID(target_s), profile_key)
|
||||
client = self.host.getClient(profile_key)
|
||||
return self.getCard(client, jid.JID(target_s))
|
||||
|
||||
def getCard(self, target, profile_key=C.PROF_KEY_NONE):
|
||||
def getCard(self, client, target):
|
||||
"""Ask server for VCard
|
||||
|
||||
@param target(jid.JID): jid from which we want the VCard
|
||||
@result: id to retrieve the profile
|
||||
"""
|
||||
current_jid, xmlstream = self.host.getJidNStream(profile_key)
|
||||
if not xmlstream:
|
||||
raise exceptions.ProfileUnknownError('Asking vcard for a non-existant or not connected profile ({})'.format(profile_key))
|
||||
profile = self.host.memory.getProfileName(profile_key)
|
||||
to_jid = target.userhostJID()
|
||||
log.debug(_(u"Asking for %s's VCard") % to_jid.userhost())
|
||||
reg_request = IQ(xmlstream, 'get')
|
||||
reg_request["from"] = current_jid.full()
|
||||
reg_request = client.IQ('get')
|
||||
reg_request["from"] = client.jid.full()
|
||||
reg_request["to"] = to_jid.userhost()
|
||||
reg_request.addElement('vCard', NS_VCARD)
|
||||
reg_request.send(to_jid.userhost()).addCallbacks(self._VCardCb, self._VCardEb, callbackArgs=[profile], errbackArgs=[profile])
|
||||
reg_request.send(to_jid.userhost()).addCallbacks(self._VCardCb, self._VCardEb, callbackArgs=[client], errbackArgs=[client])
|
||||
return reg_request["id"]
|
||||
|
||||
def getAvatarFile(self, avatar_hash):
|
||||
|
|
@ -354,7 +350,7 @@ class XEP_0054(object):
|
|||
def elementBuilt(result):
|
||||
"""Called once the image is at the right size/format, and the vcard set element is build"""
|
||||
set_avatar_elt, img_hash = result
|
||||
self.updateCache(client.jid.userhostJID(), 'avatar', img_hash, client.profile)
|
||||
self.updateCache(client, client.jid.userhostJID(), 'avatar', img_hash)
|
||||
return set_avatar_elt.send().addCallback(lambda ignore: client.presence.available()) # FIXME: should send the current presence, not always "available" !
|
||||
|
||||
d.addCallback(elementBuilt)
|
||||
|
|
@ -385,7 +381,7 @@ class XEP_0054_handler(XMPPHandler):
|
|||
@param presend(domish.Element): <presence/> stanza
|
||||
"""
|
||||
from_jid = jid.JID(presence['from'])
|
||||
if from_jid.resource and not self.plugin_parent.isInRoom(from_jid, self.parent.profile):
|
||||
if from_jid.resource and not self.plugin_parent.isInRoom(self.parent, from_jid):
|
||||
from_jid = from_jid.userhostJID()
|
||||
#FIXME: wokkel's data_form should be used here
|
||||
try:
|
||||
|
|
@ -401,12 +397,12 @@ class XEP_0054_handler(XMPPHandler):
|
|||
hash_ = str(photo_elt)
|
||||
if not hash_:
|
||||
return
|
||||
old_avatar = self.plugin_parent.getCache(from_jid, 'avatar', self.parent.profile)
|
||||
old_avatar = self.plugin_parent.getCache(self.parent, from_jid, 'avatar')
|
||||
filename = self.plugin_parent._getFilename(hash_)
|
||||
if not old_avatar or old_avatar != hash_:
|
||||
if os.path.exists(filename):
|
||||
log.debug(u"New avatar found for [{}], it's already in cache, we use it".format(from_jid.full()))
|
||||
self.plugin_parent.updateCache(from_jid, 'avatar', hash_, self.parent.profile)
|
||||
self.plugin_parent.updateCache(self.parent, from_jid, 'avatar', hash_)
|
||||
else:
|
||||
log.debug(u'New avatar found for [{}], requesting vcard'.format(from_jid.full()))
|
||||
self.plugin_parent.getCard(from_jid, self.parent.profile)
|
||||
|
|
|
|||
|
|
@ -309,18 +309,16 @@ class XEP_0085(object):
|
|||
@param profile_key (str): %(doc_profile_key)s
|
||||
"""
|
||||
# TODO: try to optimize this method which is called often
|
||||
profile = self.host.memory.getProfileName(profile_key)
|
||||
if profile is None:
|
||||
raise exceptions.ProfileUnknownError
|
||||
client = self.host.getClient(profile_key)
|
||||
to_jid = JID(to_jid_s)
|
||||
if self._isMUC(to_jid, profile):
|
||||
if self._isMUC(to_jid, client.profile):
|
||||
to_jid = to_jid.userhostJID()
|
||||
elif not to_jid.resource:
|
||||
to_jid.resource = self.host.memory.getMainResource(to_jid, profile)
|
||||
if not self._checkActivation(to_jid, forceEntityData=False, profile=profile):
|
||||
to_jid.resource = self.host.memory.getMainResource(client, to_jid)
|
||||
if not self._checkActivation(to_jid, forceEntityData=False, profile=client.profile):
|
||||
return
|
||||
try:
|
||||
self.map[profile][to_jid]._onEvent("composing")
|
||||
self.map[client.profile][to_jid]._onEvent("composing")
|
||||
except (KeyError, AttributeError):
|
||||
# no message has been sent/received since the notifications
|
||||
# have been enabled, it's better to wait for a first one
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
from sat.core.i18n import _
|
||||
from sat.core.constants import Const as C
|
||||
from sat.core import exceptions
|
||||
from sat.core.log import getLogger
|
||||
log = getLogger(__name__)
|
||||
from twisted.words.xish import domish
|
||||
|
|
@ -136,6 +137,7 @@ class XEP_0249(object):
|
|||
@param message: message element
|
||||
@profile: %(doc_profile)s
|
||||
"""
|
||||
client = self.host.getClient(profile)
|
||||
try:
|
||||
room_jid_s = message.firstChildElement()['jid']
|
||||
log.info(_(u'Invitation received for room %(room)s [%(profile)s]') % {'room': room_jid_s, 'profile': profile})
|
||||
|
|
@ -144,9 +146,14 @@ class XEP_0249(object):
|
|||
return
|
||||
from_jid_s = message["from"]
|
||||
room_jid = jid.JID(room_jid_s)
|
||||
if room_jid in self.host.plugins["XEP-0045"].clients[profile].joined_rooms:
|
||||
log.info(_("Invitation silently discarded because user is already in the room."))
|
||||
try:
|
||||
self.host.plugins["XEP-0045"].checkRoomJoined(client, room_jid)
|
||||
except exceptions.NotFound:
|
||||
pass
|
||||
else:
|
||||
log.info(_(u"Invitation silently discarded because user is already in the room."))
|
||||
return
|
||||
|
||||
autojoin = self.host.memory.getParamA(AUTOJOIN_NAME, AUTOJOIN_KEY, profile_key=profile)
|
||||
|
||||
def accept_cb(conf_id, accepted, data, profile):
|
||||
|
|
|
|||
Loading…
Reference in a new issue