core, plugin XEP-0115: discovery refactoring:

- hashing algorithm of XEP-0115 has been including in core
    - our own hash is still calculated by XEP-0115 and can be regenerated with XEP_0115.recalculateHash
    - old discovery methods have been removed. Now the following methods are used:
        - hasFeature: tell if a feature is available for an entity
        - getDiscoInfos: self explaining
        - getDiscoItems: self explaining
        - findServiceEntities: return all available items of an entity which given (category, type)
        - findFeaturesSet: search for a set of features in entity + entity's items
      all these methods are asynchronous, and manage cache automatically
    - XEP-0115 manage in a better way hashes, and now use a trigger for presence instead of monkey patch
    - new FeatureNotFound exception, when we want to do something which is not available
    - refactored client initialisation sequence, removed client.initialized Deferred
    - added constant APP_URL
    - test_plugin_xep_0033.py has been temporarly deactivated, the time to adapt it
    - lot of cleaning
This commit is contained in:
Goffi 2014-03-28 18:07:22 +01:00
commit 95678d7967

View file

@ -362,6 +362,7 @@ class RoomGame(object):
def _checkWaitAuth(self, room, other_players, verbose=False):
"""Check if we must wait for other players before starting the game.
@param room: wokkel.muc.Room instance
@param other_players: list of players JID userhosts without the referee
@param verbose: display debug message
@ -383,17 +384,20 @@ class RoomGame(object):
debug(_("Still waiting for %(users)s before starting the game %(game)s in %(room)s") % {'users': result[2], 'game': self.name, 'room': room.occupantJID.userhost()})
return result
def getUniqueName(self, muc_service="", profile_key=C.PROF_KEY_NONE):
"""
def getUniqueName(self, muc_service=None, profile_key=C.PROF_KEY_NONE):
"""Generate unique room name
@param muc_service: you can leave empty to autofind the muc service
@param profile_key
@param profile_key: %(doc_profile_key)s
@return: a unique name for a new room to be created
"""
# FIXME: jid.JID must be used instead of strings
room = self.host.plugins["XEP-0045"].getUniqueName(muc_service, profile_key=profile_key)
return "sat_%s_%s" % (self.name.lower(), room) if room != "" else ""
return "sat_%s_%s" % (self.name.lower(), room.full())
def prepareRoom(self, other_players=None, room_jid_s=None, profile_key=C.PROF_KEY_NONE):
"""Prepare the room for a game: create it if it doesn't exist and invite players.
@param other_players: list for other players JID userhosts
@param room_jid_s: JID userhost of the room, or None to generate a unique name
@param profile_key
@ -410,28 +414,22 @@ class RoomGame(object):
"""@param room: instance of wokkel.muc.Room"""
self._createOrInvite(room, [JID(player).userhost() for player in other_players], profile)
def afterClientInit(room_jid_s):
"""Create/join the given room, or a unique generated one if no room is specified.
@param room_jids: userhost of the room to join
"""
if room_jid_s is not None and room_jid_s != "": # a room name has been specified
if room_jid_s in self.host.plugins["XEP-0045"].clients[profile].joined_rooms:
roomJoined(self.host.plugins["XEP-0045"].clients[profile].joined_rooms[room_jid_s])
return
else:
room_jid_s = self.getUniqueName(profile_key=profile_key)
if room_jid_s == "":
return
user_jid = self.host.getJidNStream(profile)[0]
d = self.host.plugins["XEP-0045"].join(JID(room_jid_s), user_jid.user, {}, profile)
d.addCallback(roomJoined)
client = self.host.getClient(profile)
client.client_initialized.addCallback(lambda ignore: afterClientInit(room_jid_s))
# Create/join the given room, or a unique generated one if no room is specified.
if room_jid_s is not None and room_jid_s != "": # a room name has been specified
if room_jid_s in self.host.plugins["XEP-0045"].clients[profile].joined_rooms:
roomJoined(self.host.plugins["XEP-0045"].clients[profile].joined_rooms[room_jid_s])
return
else:
room_jid_s = self.getUniqueName(profile_key=profile_key)
if room_jid_s == "":
return
user_jid = self.host.getJidNStream(profile)[0]
d = self.host.plugins["XEP-0045"].join(JID(room_jid_s), user_jid.user, {}, profile)
return d.addCallback(roomJoined)
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.
"""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.
@room: wokkel.muc.Room object. room.roster is a dict{wokkel.muc.User.nick: wokkel.muc.User}
@user: wokkel.muc.User object. user.nick is a unicode and user.entity a JID
@return: True to not interrupt the main process.
@ -463,6 +461,7 @@ class RoomGame(object):
def userLeftTrigger(self, room, user, profile):
"""This trigger is used to update or stop the game when a user leaves.
@room: wokkel.muc.Room object. room.roster is a dict{wokkel.muc.User.nick: wokkel.muc.User}
@user: wokkel.muc.User object. user.nick is a unicode and user.entity a JID
@return: True to not interrupt the main process.
@ -491,13 +490,13 @@ class RoomGame(object):
return True
def _checkCreateGameAndInit(self, room_jid_s, profile):
"""Check if that profile can create the game. If the game can be created
but is not initialized yet, this method will also do the initialization.
"""Check if that profile can create the game. If the game can be created but is not initialized yet, this method will also do the initialization.
@param room_jid_s: room userhost
@param profile
@return: a couple (create, sync) with:
- create: set to True to allow the game creation
- sync: set to True to advice a game synchronization
- create: set to True to allow the game creation
- sync: set to True to advice a game synchronization
"""
user_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid_s, profile)
if not user_nick:
@ -516,12 +515,14 @@ class RoomGame(object):
return True, False
def createGame(self, room_jid_s, nicks=None, profile_key=C.PROF_KEY_NONE):
"""Create a new game - this can be called directly from a frontend
and skips all the checks and invitation system, but the game must
not exist and all the players must be in the room already.
"""Create a new game.
This can be called directly from a frontend and skips all the checks and invitation system,
but the game must not exist and all the players must be in the room already.
@param room_jid: JID userhost of the room
@param nicks: list of players nicks in the room (referee included, in first position)
@param profile_key: %(doc_profile_key)s"""
@param profile_key: %(doc_profile_key)s
"""
debug(_("Creating %(game)s game in room %(room)s") % {'game': self.name, 'room': room_jid_s})
profile = self.host.memory.getProfileName(profile_key)
if not profile:
@ -545,6 +546,7 @@ class RoomGame(object):
def playerReady(self, player, referee, profile_key=C.PROF_KEY_NONE):
"""Must be called when player is ready to start a new game
@param player: the player nick in the room
@param referee: referee userhost
"""
@ -558,10 +560,11 @@ class RoomGame(object):
def newRound(self, room_jid, data, profile):
"""Launch a new round (reinit the user data)
@param room_jid: room userhost
@param data: a couple (common_data, msg_elts) with:
- common_data: backend initialization data for the new round
- msg_elts: dict to map each user to his specific initialization message
- common_data: backend initialization data for the new round
- msg_elts: dict to map each user to his specific initialization message
@param profile
"""
debug(_('new round for %s game') % self.name)
@ -585,6 +588,7 @@ class RoomGame(object):
def _createGameElt(self, to_jid):
"""Create a generic domish Element for the game messages
@param to_jid: JID of the recipient
@return: the created element
"""
@ -597,10 +601,11 @@ class RoomGame(object):
def _createStartElement(self, players=None, name="started"):
"""Create a domish Element listing the game users
@param players: list of the players
@param name: element name:
- "started" to signal the players that the game has been started
- "players" to signal the list of players when the game is not started yet
- "started" to signal the players that the game has been started
- "players" to signal the list of players when the game is not started yet
@return the create element
"""
started_elt = domish.Element((None, name))
@ -616,15 +621,16 @@ class RoomGame(object):
return started_elt
def _sendElements(self, to_jid, data, profile=None):
"""
""" TODO
@param to_jid: recipient JID
@param data: list of (elem, attr, content) with:
- elem: domish.Element, unicode or a couple:
- domish.Element to be directly added as a child to the message
- unicode name or couple (uri, name) to create a new domish.Element
and add it as a child to the message (see domish.Element.addElement)
- attrs: dictionary of attributes for the new child
- content: unicode that is appended to the child content
- elem: domish.Element, unicode or a couple:
- domish.Element to be directly added as a child to the message
- unicode name or couple (uri, name) to create a new domish.Element
and add it as a child to the message (see domish.Element.addElement)
- attrs: dictionary of attributes for the new child
- content: unicode that is appended to the child content
@param profile: the profile from which the message is sent
@return: a Deferred instance
"""
@ -646,12 +652,13 @@ class RoomGame(object):
return defer.succeed(None)
def send(self, to_jid, elem=None, attrs=None, content=None, profile=None):
"""
""" TODO
@param to_jid: recipient JID
@param elem: domish.Element, unicode or a couple:
- domish.Element to be directly added as a child to the message
- unicode name or couple (uri, name) to create a new domish.Element
and add it as a child to the message (see domish.Element.addElement)
- domish.Element to be directly added as a child to the message
- unicode name or couple (uri, name) to create a new domish.Element
and add it as a child to the message (see domish.Element.addElement)
@param attrs: dictionary of attributes for the new child
@param content: unicode that is appended to the child content
@param profile: the profile from which the message is sent