diff src/plugins/plugin_misc_room_game.py @ 1359:83127a4c89ce frontends_multi_profiles

plugins room_game, quiz, radiocol, tarot: use JID instead of unicode in many methods + class attributes
author souliane <souliane@mailoo.org>
date Wed, 11 Mar 2015 12:36:22 +0100
parents 83ed877541e3
children 069ad98b360d
line wrap: on
line diff
--- a/src/plugins/plugin_misc_room_game.py	Wed Mar 11 12:35:21 2015 +0100
+++ b/src/plugins/plugin_misc_room_game.py	Wed Mar 11 12:36:22 2015 +0100
@@ -21,7 +21,7 @@
 from sat.core.constants import Const as C
 from sat.core.log import getLogger
 log = getLogger(__name__)
-from twisted.words.protocols.jabber.jid import JID
+from twisted.words.protocols.jabber import jid
 from twisted.words.xish import domish
 from twisted.internet import defer
 from time import time
@@ -51,7 +51,7 @@
 class RoomGame(object):
     """This class is used to help launching a MUC game.
 
-    Bridge methods callbacks: prepareRoom, playerReady, createGame
+    Bridge methods callbacks: _prepareRoom, _playerReady, _createGame
     Triggered methods: userJoinedTrigger, userLeftTrigger
     Also called from subclasses: newRound
 
@@ -107,7 +107,7 @@
         self.game_init = game_init
         self.player_init = player_init
         self.games = {}
-        self.invitations = {}  # list of couple (x, y) with x the time and y a list of users
+        self.invitations = {}  # values are a couple (x, y) with x the time and y a list of users
 
         # These are the default settings, which can be overwritten by child class after initialization
         self.invite_mode = self.FROM_PLAYERS if self.player_init == {} else self.FROM_NONE
@@ -126,129 +126,134 @@
     def _createOrInvite(self, room, other_players, profile):
         """
         This is called only when someone explicitly wants to play.
+
         The game will not be created if one already exists in the room,
         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: instance of wokkel.muc.Room
-        @param other_players: list for other players JID userhosts
+        @param room (wokkel.muc.Room): the room
+        @param other_players (list[jid.JID]): list of the other players JID (bare) 
         """
         user_jid = self.host.getJidNStream(profile)[0]
-        room_jid_s = room.occupantJID.userhost()
-        nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid_s, profile)
+        room_jid = room.occupantJID.userhostJID()
+        nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid, profile)
         nicks = [nick]
-        if self._gameExists(room_jid_s):
-            if not self._checkJoinAuth(room_jid_s, user_jid.userhost(), 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))
-            self._updatePlayers(room_jid_s, nicks, True, profile)
+            self._updatePlayers(room_jid, nicks, True, profile)
         else:
-            self._initGame(room_jid_s, nick)
+            self._initGame(room_jid, nick)
             (auth, waiting, missing) = self._checkWaitAuth(room, other_players)
             nicks.extend(waiting)
             nicks.extend(self._invitePlayers(room, missing, nick, profile))
             if auth:
-                self.createGame(room_jid_s, nicks, profile)
+                self.createGame(room_jid, nicks, profile)
             else:
-                self._updatePlayers(room_jid_s, nicks, False, profile)
+                self._updatePlayers(room_jid, nicks, False, profile)
+
+    def _initGame(self, room_jid, referee_nick):
+        """
 
-    def _initGame(self, room_jid_s, referee_nick):
-        """Important: do not add the referee to 'players' yet. For a
-        <players /> message to be emitted whenever a new player is joining,
-        it is necessary to not modify 'players' outside of _updatePlayers.
+        @param room_jid (jid.JID): JID of the room
+        @param referee_nick (unicode): nickname of the referee
         """
-        referee = room_jid_s + '/' + referee_nick
-        self.games[room_jid_s] = {'referee': referee, 'players': [], 'started': False, 'status': {}}
-        self.games[room_jid_s].update(copy.deepcopy(self.game_init))
-        self.invitations.setdefault(room_jid_s, [])
+        # Important: do not add the referee to 'players' yet. For a
+        # <players /> message to be emitted whenever a new player is joining,
+        # it is necessary to not modify 'players' outside of _updatePlayers.
+        referee_jid = jid.JID(room_jid.userhost() + '/' + referee_nick)
+        self.games[room_jid] = {'referee': referee_jid, 'players': [], 'started': False, 'status': {}}
+        self.games[room_jid].update(copy.deepcopy(self.game_init))
+        self.invitations.setdefault(room_jid, [])
 
-    def _gameExists(self, room_jid_s, started=False):
+    def _gameExists(self, room_jid, started=False):
         """Return True if a game has been initialized/started.
         @param started: if False, the game must be initialized to return True,
         otherwise it must be initialized and started with createGame.
         @return: True if a game is initialized/started in that room"""
-        return room_jid_s in self.games and (not started or self.games[room_jid_s]['started'])
+        return room_jid in self.games and (not started or self.games[room_jid]['started'])
 
-    def _checkJoinAuth(self, room_jid_s, user_jid_s=None, nick="", verbose=False):
+    def _checkJoinAuth(self, room_jid, user_jid=None, nick="", verbose=False):
         """Checks if this profile is allowed to join the game.
+
         The parameter nick is used to check if the user is already
         a player in that game. When this method is called from
         userJoinedTrigger, nick is also used to check the user
         identity instead of user_jid_s (see TODO comment below).
-        @param room_jid_s: the room hosting the game
-        @param user_jid_s: JID userhost of the user
-        @param nick: nick of the user
+        @param room_jid (jid.JID): the JID of the room hosting the game
+        @param user_jid (jid.JID): JID of the user
+        @param nick (unicode): nick of the user
         @return: True if this profile can join the game
         """
         auth = False
-        if not self._gameExists(room_jid_s):
+        if not self._gameExists(room_jid):
             auth = False
-        elif self.join_mode == self.ALL or self.isPlayer(room_jid_s, nick):
+        elif self.join_mode == self.ALL or self.isPlayer(room_jid, nick):
             auth = True
         elif self.join_mode == self.INVITED:
-            user_jid_s = JID(user_jid_s).userhost()
             # considering all the batches of invitations
-            for invitations in self.invitations[room_jid_s]:
-                if user_jid_s is not None:
-                    if user_jid_s in invitations[1]:
+            for invitations in self.invitations[room_jid]:
+                if user_jid is not None:
+                    if user_jid.userhostJID() in invitations[1]:
                         auth = True
                         break
                 else:
                     # TODO: that's not secure enough but what to do if
                     # wokkel.muc.User's 'entity' attribute is not set?!
-                    if nick in [JID(invited).user for invited in invitations[1]]:
+                    if nick in [invited.user for invited in invitations[1]]:
                         auth = True
                         break
 
         if not auth and (verbose or _DEBUG):
-            log.debug(_("%(user)s not allowed to join the game %(game)s in %(room)s") % {'user': user_jid_s or nick, 'game': self.name, 'room': room_jid_s})
+            log.debug(_("%(user)s not allowed to join the game %(game)s in %(room)s") % {'user': user_jid.userhost() or nick, 'game': self.name, 'room': room_jid.userhost()})
         return auth
 
-    def _updatePlayers(self, room_jid_s, nicks, sync, profile):
+    def _updatePlayers(self, room_jid, nicks, sync, profile):
         """Update the list of players and signal to the room that some players joined the game.
         If sync is True, the news players are synchronized with the game data they have missed.
-        Remark: self.games[room_jid_s]['players'] should not be modified outside this method.
-        @param room_jid_s: room userhost
-        @param nicks: list of players nicks in the room (referee included, in first position)
-        @param sync: set to True to send synchronization data to the new players
-        @param profile
+        Remark: self.games[room_jid]['players'] should not be modified outside this method.
+        @param room_jid (jid.JID): JID of the room
+        @param nicks (list[unicode]): list of players nicks in the room (referee included, in first position)
+        @param sync (bool): set to True to send synchronization data to the new players
+        @param profile (unicode): %(doc_profile)s
         """
         if nicks == []:
             return
         # this is better than set(nicks).difference(...) as it keeps the order
-        new_nicks = [nick for nick in nicks if nick not in self.games[room_jid_s]['players']]
+        new_nicks = [nick for nick in nicks if nick not in self.games[room_jid]['players']]
         if len(new_nicks) == 0:
             return
 
         def setStatus(status):
             for nick in new_nicks:
-                self.games[room_jid_s]['status'][nick] = status
+                self.games[room_jid]['status'][nick] = status
 
-        sync = sync and self._gameExists(room_jid_s, True) and len(self.games[room_jid_s]['players']) > 0
+        sync = sync and self._gameExists(room_jid, True) and len(self.games[room_jid]['players']) > 0
         setStatus('desync' if sync else 'init')
-        self.games[room_jid_s]['players'].extend(new_nicks)
-        self._synchronizeRoom(room_jid_s, [JID(room_jid_s)], profile)
+        self.games[room_jid]['players'].extend(new_nicks)
+        self._synchronizeRoom(room_jid, [room_jid], profile)
         if sync:
             setStatus('init')
 
-    def _synchronizeRoom(self, room_jid_s, recipients, profile):
+    def _synchronizeRoom(self, room_jid, recipients, profile):
         """Communicate the list of players to the whole room or only to some users,
         also send the synchronization data to the players who recently joined the game.
-        @param room_jid_s: room userhost
-        @recipients: list of JIDs, the recipients of the message could be:
-        - room JID
-        - room JID + "/" + user nick
-        @param profile
+        @param room_jid (jid.JID): JID of the room
+        @recipients (list[jid.JID]): list of JIDs, the recipients of the message could be:
+            - room JID
+            - room JID + "/" + user nick
+        @param profile (unicode): %(doc_profile)s
         """
-        if self._gameExists(room_jid_s, started=True):
-            element = self._createStartElement(self.games[room_jid_s]['players'])
+        if self._gameExists(room_jid, started=True):
+            element = self._createStartElement(self.games[room_jid]['players'])
         else:
-            element = self._createStartElement(self.games[room_jid_s]['players'], name="players")
+            element = self._createStartElement(self.games[room_jid]['players'], name="players")
         elements = [(element, None, None)]
 
         sync_args = []
-        sync_data = self._getSyncData(room_jid_s)
+        sync_data = self._getSyncData(room_jid)
         for nick in sync_data:
-            user_jid = JID(room_jid_s + '/' + nick)
+            user_jid = jid.JID(room_jid.userhost() + '/' + nick)
             if user_jid in recipients:
                 user_elements = copy.deepcopy(elements)
                 for child in sync_data[nick]:
@@ -263,18 +268,18 @@
         for args, kwargs in sync_args:
             self._sendElements(*args, **kwargs)
 
-    def _getSyncData(self, room_jid_s, force_nicks=None):
+    def _getSyncData(self, room_jid, force_nicks=None):
         """The synchronization data are returned for each player who
         has the state 'desync' or if he's been contained by force_nicks.
-        @param room_jid_s: room userhost
+        @param room_jid (jid.JID): JID of the room
         @param force_nicks: force the synchronization for this list of the nicks
         @return: a mapping between player nicks and a list of elements to
         be sent by self._synchronizeRoom for the game to be synchronized.
         """
-        if not self._gameExists(room_jid_s):
+        if not self._gameExists(room_jid):
             return {}
         data = {}
-        status = self.games[room_jid_s]['status']
+        status = self.games[room_jid]['status']
         nicks = [nick for nick in status if status[nick] == 'desync']
         if force_nicks is None:
             force_nicks = []
@@ -282,14 +287,14 @@
             if nick not in nicks:
                 nicks.append(nick)
         for nick in nicks:
-            elements = self.getSyncDataForPlayer(room_jid_s, nick)
+            elements = self.getSyncDataForPlayer(room_jid, nick)
             if elements:
                 data[nick] = elements
         return data
 
-    def getSyncDataForPlayer(self, room_jid_s, nick):
+    def getSyncDataForPlayer(self, room_jid, nick):
         """This method may (and should probably) be overwritten by a child class.
-        @param room_jid_s: room userhost
+        @param room_jid (jid.JID): JID of the room
         @param nick: the nick of the player to be synchronized
         @return: a list of elements to synchronize this player with the game.
         """
@@ -297,20 +302,19 @@
 
     def _invitePlayers(self, room, other_players, nick, profile):
         """Invite players to a room, associated game may exist or not.
-        @param room: wokkel.muc.Room instance
-        @param other_players: list of JID userhosts to invite
-        @param nick: nick of the user who send the invitation
-        @return: list of room nicks for invited players who are already in the room
+
+        @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()
-        room_jid_s = room.occupantJID.userhost()
-        if not self._checkInviteAuth(room_jid_s, nick):
+        if not self._checkInviteAuth(room_jid, nick):
             return []
         # TODO: remove invitation waiting for too long, using the time data
-        players_jids = [JID(player) for player in other_players]
-        self.invitations[room_jid_s].append((time(), [player.userhost() for player in players_jids]))
+        self.invitations[room_jid].append((time(), [player.userhostJID() for player in other_players]))
         nicks = []
-        for player_jid in [player.userhostJID() for player in players_jids]:
+        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)
             if other_nick is None:
@@ -319,58 +323,59 @@
                 nicks.append(other_nick)
         return nicks
 
-    def _checkInviteAuth(self, room_jid_s, nick, verbose=False):
+    def _checkInviteAuth(self, room_jid, nick, verbose=False):
         """Checks if this user is allowed to invite players
-        @param room_jid_s: room userhost
+
+        @param room_jid (jid.JID): JID of the room
         @param nick: user nick in the room
         @param verbose: display debug message
         @return: True if the user is allowed to invite other players
         """
         auth = False
-        if self.invite_mode == self.FROM_ALL or not self._gameExists(room_jid_s):
+        if self.invite_mode == self.FROM_ALL or not self._gameExists(room_jid):
             auth = True
         elif self.invite_mode == self.FROM_NONE:
-            auth = not self._gameExists(room_jid_s, started=True) and self.isReferee(room_jid_s, nick)
+            auth = not self._gameExists(room_jid, started=True) and self.isReferee(room_jid, nick)
         elif self.invite_mode == self.FROM_REFEREE:
-            auth = self.isReferee(room_jid_s, nick)
+            auth = self.isReferee(room_jid, nick)
         elif self.invite_mode == self.FROM_PLAYERS:
-            auth = self.isPlayer(room_jid_s, nick)
+            auth = self.isPlayer(room_jid, nick)
         if not auth and (verbose or _DEBUG):
-            log.debug(_("%(user)s not allowed to invite for the game %(game)s in %(room)s") % {'user': nick, 'game': self.name, 'room': room_jid_s})
+            log.debug(_("%(user)s not allowed to invite for the game %(game)s in %(room)s") % {'user': nick, 'game': self.name, 'room': room_jid.userhost()})
         return auth
 
-    def isReferee(self, room_jid_s, nick):
+    def isReferee(self, room_jid, nick):
         """Checks if the player with this nick is the referee for the game in this room"
-        @param room_jid_s: room userhost
+        @param room_jid (jid.JID): room JID
         @param nick: user nick in the room
         @return: True if the user is the referee of the game in this room
         """
-        if not self._gameExists(room_jid_s):
+        if not self._gameExists(room_jid):
             return False
-        return room_jid_s + '/' + nick == self.games[room_jid_s]['referee']
+        return jid.JID(room_jid.userhost() + '/' + nick) == self.games[room_jid]['referee']
 
-    def isPlayer(self, room_jid_s, nick):
+    def isPlayer(self, room_jid, nick):
         """Checks if the user with this nick is a player for the game in this room.
-        @param room_jid_s: room userhost
+        @param room_jid (jid.JID): JID of the room
         @param nick: user nick in the room
         @return: True if the user is a player of the game in this room
         """
-        if not self._gameExists(room_jid_s):
+        if not self._gameExists(room_jid):
             return False
         # Important: the referee is not in the 'players' list right after
         # the game initialization, that's why we do also check with isReferee
-        return nick in self.games[room_jid_s]['players'] or self.isReferee(room_jid_s, nick)
+        return nick in self.games[room_jid]['players'] or self.isReferee(room_jid, nick)
 
     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
+        @param room (wokkel.muc.Room): the room
+        @param other_players (list[jid.JID]): list of the players without the referee
+        @param verbose (bool): display debug message
         @return: (x, y, z) with:
-        x: False if we must wait, True otherwise
-        y: the nicks of the players that have been checked and confirmed
-        z: the players that have not been checked or that are missing
+            x: False if we must wait, True otherwise
+            y: the nicks of the players that have been checked and confirmed
+            z: the JID of the players that have not been checked or that are missing
         """
         if self.wait_mode == self.FOR_NONE or other_players == []:
             result = (True, [], other_players)
@@ -388,20 +393,25 @@
     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: %(doc_profile_key)s
-        @return: a unique name for a new room to be created
+        @param muc_service (jid.JID): you can leave empty to autofind the muc service
+        @param profile_key (unicode): %(doc_profile_key)s
+        @return: jid.JID (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.full())
+        return jid.JID("sat_%s_%s" % (self.name.lower(), room.userhost()))
 
-    def prepareRoom(self, other_players=None, room_jid_s=None, profile_key=C.PROF_KEY_NONE):
+    def _prepareRoom(self, other_players=None, room_jid_s='', profile_key=C.PROF_KEY_NONE):
+        room_jid = jid.JID(room_jid_s) if room_jid_s else None
+        other_players = [jid.JID(player).userhostJID() for player in other_players]
+        return self.prepareRoom(other_players, room_jid, profile_key)
+
+    def prepareRoom(self, other_players=None, room_jid=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
+        @param other_players (list[JID]): list of other players JID (bare)
+        @param room_jid (jid.JID): JID of the room, or None to generate a unique name
+        @param profile_key (unicode): %(doc_profile_key)s
         """
         log.debug(_('Preparing room for %s game') % self.name)
         profile = self.host.memory.getProfileName(profile_key)
@@ -413,19 +423,18 @@
 
         def roomJoined(room):
             """@param room: instance of wokkel.muc.Room"""
-            self._createOrInvite(room, [JID(player).userhost() for player in other_players], profile)
+            self._createOrInvite(room, other_players, profile)
 
         # 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 defer.succeed(None)
+        if room_jid is None:
+            room_jid = self.getUniqueName(profile_key=profile_key)
         else:
-            room_jid_s = self.getUniqueName(profile_key=profile_key)
-            if room_jid_s == "":
+            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)
+
         user_jid = self.host.getJidNStream(profile)[0]
-        d = self.host.plugins["XEP-0045"].join(JID(room_jid_s), user_jid.user, {}, profile)
+        d = self.host.plugins["XEP-0045"].join(room_jid, user_jid.user, {}, profile)
         return d.addCallback(roomJoined)
 
     def userJoinedTrigger(self, room, user, profile):
@@ -435,29 +444,29 @@
         @user: wokkel.muc.User object. user.nick is a unicode and user.entity a JID
         @return: True to not interrupt the main process.
         """
-        room_jid_s = room.occupantJID.userhost()
+        room_jid = room.occupantJID.userhostJID()
         profile_nick = room.occupantJID.resource
-        if not self.isReferee(room_jid_s, profile_nick):
+        if not self.isReferee(room_jid, profile_nick):
             return True  # profile is not the referee
-        if not self._checkJoinAuth(room_jid_s, user.entity.userhost() if user.entity else None, user.nick):
+        if not self._checkJoinAuth(room_jid, user.entity if user.entity else None, user.nick):
             # user not allowed but let him know that we are playing :p
-            self._synchronizeRoom(room_jid_s, [JID(room_jid_s + '/' + user.nick)], profile)
+            self._synchronizeRoom(room_jid, [jid.JID(room_jid.userhost() + '/' + user.nick)], profile)
             return True
         if self.wait_mode == self.FOR_ALL:
             # considering the last batch of invitations
-            batch = len(self.invitations[room_jid_s]) - 1
+            batch = len(self.invitations[room_jid]) - 1
             if batch < 0:
-                log.error("Invitations from %s to play %s in %s have been lost!" % (profile_nick, self.name, room_jid_s))
+                log.error("Invitations from %s to play %s in %s have been lost!" % (profile_nick, self.name, room_jid.userhost()))
                 return True
-            other_players = self.invitations[room_jid_s][batch][1]
+            other_players = self.invitations[room_jid][batch][1]
             (auth, nicks, dummy) = self._checkWaitAuth(room, other_players)
             if auth:
-                del self.invitations[room_jid_s][batch]
+                del self.invitations[room_jid][batch]
                 nicks.insert(0, profile_nick)  # add the referee
-                self.createGame(room_jid_s, nicks, profile_key=profile)
+                self.createGame(room_jid, nicks, profile_key=profile)
                 return True
         # let the room know that a new player joined
-        self._updatePlayers(room_jid_s, [user.nick], True, profile)
+        self._updatePlayers(room_jid, [user.nick], True, profile)
         return True
 
     def userLeftTrigger(self, room, user, profile):
@@ -467,89 +476,95 @@
         @user: wokkel.muc.User object. user.nick is a unicode and user.entity a JID
         @return: True to not interrupt the main process.
         """
-        room_jid_s = room.occupantJID.userhost()
+        room_jid = room.occupantJID.userhostJID()
         profile_nick = room.occupantJID.resource
-        if not self.isReferee(room_jid_s, profile_nick):
+        if not self.isReferee(room_jid, profile_nick):
             return True  # profile is not the referee
-        if self.isPlayer(room_jid_s, user.nick):
+        if self.isPlayer(room_jid, user.nick):
             try:
-                self.games[room_jid_s]['players'].remove(user.nick)
+                self.games[room_jid]['players'].remove(user.nick)
             except ValueError:
                 pass
-            if len(self.games[room_jid_s]['players']) == 0:
-                del self.games[room_jid_s]  # finish the game
+            if len(self.games[room_jid]['players']) == 0:
                 return True
             if self.wait_mode == self.FOR_ALL:
                 # allow this user to join the game again
-                user_jid_s = user.entity.userhost()
-                if len(self.invitations[room_jid_s]) == 0:
-                    self.invitations[room_jid_s].append((time(), [user_jid_s]))
+                user_jid = user.entity.userhostJID()
+                if len(self.invitations[room_jid]) == 0:
+                    self.invitations[room_jid].append((time(), [user_jid]))
                 else:
                     batch = 0  # add to the first batch of invitations
-                    if user_jid_s not in self.invitations[room_jid_s][batch][1]:
-                        self.invitations[room_jid_s][batch][1].append(user_jid_s)
+                    if user_jid not in self.invitations[room_jid][batch][1]:
+                        self.invitations[room_jid][batch][1].append(user_jid)
         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.
+    def _checkCreateGameAndInit(self, room_jid, 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.
 
-        @param room_jid_s: room userhost
+        @param room_jid (jid.JID): JID of the room
         @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
         """
-        user_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid_s, profile)
+        user_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid, profile)
         if not user_nick:
-            log.error('Internal error: profile %s has not joined the room %s' % (profile, room_jid_s))
+            log.error('Internal error: profile %s has not joined the room %s' % (profile, room_jid.userhost()))
             return False, False
-        if self._gameExists(room_jid_s):
-            is_referee = self.isReferee(room_jid_s, user_nick)
-            if self._gameExists(room_jid_s, started=True):
-                log.warning(_("%(game)s game already created in room %(room)s") % {'game': self.name, 'room': room_jid_s})
+        if self._gameExists(room_jid):
+            is_referee = self.isReferee(room_jid, user_nick)
+            if self._gameExists(room_jid, started=True):
+                log.warning(_("%(game)s game already created in room %(room)s") % {'game': self.name, 'room': room_jid.userhost()})
                 return False, is_referee
             elif not is_referee:
-                log.warning(_("%(game)s game in room %(room)s can only be created by %(user)s") % {'game': self.name, 'room': room_jid_s, 'user': user_nick})
+                log.warning(_("%(game)s game in room %(room)s can only be created by %(user)s") % {'game': self.name, 'room': room_jid.userhost(), 'user': user_nick})
                 return False, False
         else:
-            self._initGame(room_jid_s, user_nick)
+            self._initGame(room_jid, user_nick)
         return True, False
 
-    def createGame(self, room_jid_s, nicks=None, profile_key=C.PROF_KEY_NONE):
+    def _createGame(self, room_jid_s, nicks=None, profile_key=C.PROF_KEY_NONE):
+        self.createGame(jid.JID(room_jid_s), nicks, profile_key)
+
+    def createGame(self, room_jid, 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.
-        @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 room_jid (jid.JID): JID of the room
+        @param nicks (list[unicode]): list of players nicks in the room (referee included, in first position)
+        @param profile_key (unicode): %(doc_profile_key)s
         """
-        log.debug(_("Creating %(game)s game in room %(room)s") % {'game': self.name, 'room': room_jid_s})
+        log.debug(_("Creating %(game)s game in room %(room)s") % {'game': self.name, 'room': room_jid})
         profile = self.host.memory.getProfileName(profile_key)
         if not profile:
             log.error(_("profile %s is unknown") % profile_key)
             return
-        (create, sync) = self._checkCreateGameAndInit(room_jid_s, profile)
+        (create, sync) = self._checkCreateGameAndInit(room_jid, profile)
         if nicks is None:
             nicks = []
         if not create:
             if sync:
-                self._updatePlayers(room_jid_s, nicks, True, profile)
+                self._updatePlayers(room_jid, nicks, True, profile)
             return
-        self.games[room_jid_s]['started'] = True
-        self._updatePlayers(room_jid_s, nicks, False, profile)
+        self.games[room_jid]['started'] = True
+        self._updatePlayers(room_jid, nicks, False, profile)
         if self.player_init:
             # specific data to each player (score, private data)
-            self.games[room_jid_s].setdefault('players_data', {})
+            self.games[room_jid].setdefault('players_data', {})
             for nick in nicks:
                 # The dict must be COPIED otherwise it is shared between all users
-                self.games[room_jid_s]['players_data'][nick] = copy.deepcopy(self.player_init)
+                self.games[room_jid]['players_data'][nick] = copy.deepcopy(self.player_init)
 
-    def playerReady(self, player, referee, profile_key=C.PROF_KEY_NONE):
+    def _playerReady(self, player_nick, referee_jid_s, profile_key=C.PROF_KEY_NONE):
+        self.playerReady(player_nick, jid.JID(referee_jid_s), profile_key)
+
+    def playerReady(self, player_nick, referee_jid, 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
+        @param referee_jid (jid.JID): JID of the referee
         """
         profile = self.host.memory.getProfileName(profile_key)
         if not profile:
@@ -557,7 +572,7 @@
             return
         log.debug('new player ready: %s' % profile)
         # TODO: we probably need to add the game and room names in the sent message
-        self.send(JID(referee), 'player_ready', {'player': player}, profile=profile)
+        self.send(referee_jid, 'player_ready', {'player': player_nick}, profile=profile)
 
     def newRound(self, room_jid, data, profile):
         """Launch a new round (reinit the user data)
@@ -569,7 +584,7 @@
         @param profile
         """
         log.debug(_('new round for %s game') % self.name)
-        game_data = self.games[room_jid.userhost()]
+        game_data = self.games[room_jid]
         players = game_data['players']
         players_data = game_data['players_data']
         game_data['stage'] = "init"
@@ -578,7 +593,7 @@
 
         if isinstance(msg_elts, dict):
             for player in players:
-                to_jid = JID(room_jid.userhost() + "/" + player)  # FIXME: gof:
+                to_jid = jid.JID(room_jid.userhost() + "/" + player)  # FIXME: gof:
                 elem = msg_elts[player] if isinstance(msg_elts[player], domish.Element) else None
                 self.send(to_jid, elem, profile=profile)
         elif isinstance(msg_elts, domish.Element):