Mercurial > libervia-backend
comparison sat/plugins/plugin_misc_room_game.py @ 2624:56f94936df1e
code style reformatting using black
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 27 Jun 2018 20:14:46 +0200 |
parents | 26edcf3a30eb |
children | 378188abe941 |
comparison
equal
deleted
inserted
replaced
2623:49533de4540b | 2624:56f94936df1e |
---|---|
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | 19 |
20 from sat.core.i18n import _ | 20 from sat.core.i18n import _ |
21 from sat.core.constants import Const as C | 21 from sat.core.constants import Const as C |
22 from sat.core.log import getLogger | 22 from sat.core.log import getLogger |
23 | |
23 log = getLogger(__name__) | 24 log = getLogger(__name__) |
24 from twisted.words.protocols.jabber import jid | 25 from twisted.words.protocols.jabber import jid |
25 from twisted.words.xish import domish | 26 from twisted.words.xish import domish |
26 from twisted.internet import defer | 27 from twisted.internet import defer |
27 from time import time | 28 from time import time |
28 from wokkel import disco, iwokkel | 29 from wokkel import disco, iwokkel |
29 from zope.interface import implements | 30 from zope.interface import implements |
30 import copy | 31 import copy |
32 | |
31 try: | 33 try: |
32 from twisted.words.protocols.xmlstream import XMPPHandler | 34 from twisted.words.protocols.xmlstream import XMPPHandler |
33 except ImportError: | 35 except ImportError: |
34 from wokkel.subprotocols import XMPPHandler | 36 from wokkel.subprotocols import XMPPHandler |
35 | 37 |
42 C.PI_TYPE: "MISC", | 44 C.PI_TYPE: "MISC", |
43 C.PI_PROTOCOLS: [], | 45 C.PI_PROTOCOLS: [], |
44 C.PI_DEPENDENCIES: ["XEP-0045", "XEP-0249"], | 46 C.PI_DEPENDENCIES: ["XEP-0045", "XEP-0249"], |
45 C.PI_MAIN: "RoomGame", | 47 C.PI_MAIN: "RoomGame", |
46 C.PI_HANDLER: "no", # handler MUST be "no" (dynamic inheritance) | 48 C.PI_HANDLER: "no", # handler MUST be "no" (dynamic inheritance) |
47 C.PI_DESCRIPTION: _("""Base class for MUC games""") | 49 C.PI_DESCRIPTION: _("""Base class for MUC games"""), |
48 } | 50 } |
49 | 51 |
50 | 52 |
51 # FIXME: this plugin is broken, need to be fixed | 53 # FIXME: this plugin is broken, need to be fixed |
54 | |
52 | 55 |
53 class RoomGame(object): | 56 class RoomGame(object): |
54 """This class is used to help launching a MUC game. | 57 """This class is used to help launching a MUC game. |
55 | 58 |
56 Bridge methods callbacks: _prepareRoom, _playerReady, _createGame | 59 Bridge methods callbacks: _prepareRoom, _playerReady, _createGame |
67 # Values for self.join_mode (who can join the game - NONE means solo game) | 70 # Values for self.join_mode (who can join the game - NONE means solo game) |
68 ALL, INVITED, NONE = xrange(0, 3) | 71 ALL, INVITED, NONE = xrange(0, 3) |
69 # Values for ready_mode (how to turn a MUC user into a player) | 72 # Values for ready_mode (how to turn a MUC user into a player) |
70 ASK, FORCE = xrange(0, 2) | 73 ASK, FORCE = xrange(0, 2) |
71 | 74 |
72 MESSAGE = '/message' | 75 MESSAGE = "/message" |
73 REQUEST = '%s/%s[@xmlns="%s"]' | 76 REQUEST = '%s/%s[@xmlns="%s"]' |
74 | 77 |
75 def __init__(self, host): | 78 def __init__(self, host): |
76 """For other plugin to dynamically inherit this class, it is necessary to not use __init__ but _init_. | 79 """For other plugin to dynamically inherit this class, it is necessary to not use __init__ but _init_. |
77 The subclass itself must be initialized this way: | 80 The subclass itself must be initialized this way: |
163 @param referee_nick (unicode): nickname of the referee | 166 @param referee_nick (unicode): nickname of the referee |
164 """ | 167 """ |
165 # Important: do not add the referee to 'players' yet. For a | 168 # Important: do not add the referee to 'players' yet. For a |
166 # <players /> message to be emitted whenever a new player is joining, | 169 # <players /> message to be emitted whenever a new player is joining, |
167 # it is necessary to not modify 'players' outside of _updatePlayers. | 170 # it is necessary to not modify 'players' outside of _updatePlayers. |
168 referee_jid = jid.JID(room_jid.userhost() + '/' + referee_nick) | 171 referee_jid = jid.JID(room_jid.userhost() + "/" + referee_nick) |
169 self.games[room_jid] = {'referee': referee_jid, 'players': [], 'started': False, 'status': {}} | 172 self.games[room_jid] = { |
173 "referee": referee_jid, | |
174 "players": [], | |
175 "started": False, | |
176 "status": {}, | |
177 } | |
170 self.games[room_jid].update(copy.deepcopy(self.game_init)) | 178 self.games[room_jid].update(copy.deepcopy(self.game_init)) |
171 self.invitations.setdefault(room_jid, []) | 179 self.invitations.setdefault(room_jid, []) |
172 | 180 |
173 def _gameExists(self, room_jid, started=False): | 181 def _gameExists(self, room_jid, started=False): |
174 """Return True if a game has been initialized/started. | 182 """Return True if a game has been initialized/started. |
175 @param started: if False, the game must be initialized to return True, | 183 @param started: if False, the game must be initialized to return True, |
176 otherwise it must be initialized and started with createGame. | 184 otherwise it must be initialized and started with createGame. |
177 @return: True if a game is initialized/started in that room""" | 185 @return: True if a game is initialized/started in that room""" |
178 return room_jid in self.games and (not started or self.games[room_jid]['started']) | 186 return room_jid in self.games and (not started or self.games[room_jid]["started"]) |
179 | 187 |
180 def _checkJoinAuth(self, room_jid, user_jid=None, nick="", verbose=False): | 188 def _checkJoinAuth(self, room_jid, user_jid=None, nick="", verbose=False): |
181 """Checks if this profile is allowed to join the game. | 189 """Checks if this profile is allowed to join the game. |
182 | 190 |
183 The parameter nick is used to check if the user is already | 191 The parameter nick is used to check if the user is already |
207 if nick in [invited.user for invited in invitations[1]]: | 215 if nick in [invited.user for invited in invitations[1]]: |
208 auth = True | 216 auth = True |
209 break | 217 break |
210 | 218 |
211 if not auth and (verbose or _DEBUG): | 219 if not auth and (verbose or _DEBUG): |
212 log.debug(_(u"%(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()}) | 220 log.debug( |
221 _(u"%(user)s not allowed to join the game %(game)s in %(room)s") | |
222 % { | |
223 "user": user_jid.userhost() or nick, | |
224 "game": self.name, | |
225 "room": room_jid.userhost(), | |
226 } | |
227 ) | |
213 return auth | 228 return auth |
214 | 229 |
215 def _updatePlayers(self, room_jid, nicks, sync, profile): | 230 def _updatePlayers(self, room_jid, nicks, sync, profile): |
216 """Update the list of players and signal to the room that some players joined the game. | 231 """Update the list of players and signal to the room that some players joined the game. |
217 If sync is True, the news players are synchronized with the game data they have missed. | 232 If sync is True, the news players are synchronized with the game data they have missed. |
222 @param profile (unicode): %(doc_profile)s | 237 @param profile (unicode): %(doc_profile)s |
223 """ | 238 """ |
224 if nicks == []: | 239 if nicks == []: |
225 return | 240 return |
226 # this is better than set(nicks).difference(...) as it keeps the order | 241 # this is better than set(nicks).difference(...) as it keeps the order |
227 new_nicks = [nick for nick in nicks if nick not in self.games[room_jid]['players']] | 242 new_nicks = [ |
243 nick for nick in nicks if nick not in self.games[room_jid]["players"] | |
244 ] | |
228 if len(new_nicks) == 0: | 245 if len(new_nicks) == 0: |
229 return | 246 return |
230 | 247 |
231 def setStatus(status): | 248 def setStatus(status): |
232 for nick in new_nicks: | 249 for nick in new_nicks: |
233 self.games[room_jid]['status'][nick] = status | 250 self.games[room_jid]["status"][nick] = status |
234 | 251 |
235 sync = sync and self._gameExists(room_jid, True) and len(self.games[room_jid]['players']) > 0 | 252 sync = ( |
236 setStatus('desync' if sync else 'init') | 253 sync |
237 self.games[room_jid]['players'].extend(new_nicks) | 254 and self._gameExists(room_jid, True) |
255 and len(self.games[room_jid]["players"]) > 0 | |
256 ) | |
257 setStatus("desync" if sync else "init") | |
258 self.games[room_jid]["players"].extend(new_nicks) | |
238 self._synchronizeRoom(room_jid, [room_jid], profile) | 259 self._synchronizeRoom(room_jid, [room_jid], profile) |
239 if sync: | 260 if sync: |
240 setStatus('init') | 261 setStatus("init") |
241 | 262 |
242 def _synchronizeRoom(self, room_jid, recipients, profile): | 263 def _synchronizeRoom(self, room_jid, recipients, profile): |
243 """Communicate the list of players to the whole room or only to some users, | 264 """Communicate the list of players to the whole room or only to some users, |
244 also send the synchronization data to the players who recently joined the game. | 265 also send the synchronization data to the players who recently joined the game. |
245 @param room_jid (jid.JID): JID of the room | 266 @param room_jid (jid.JID): JID of the room |
247 - room JID | 268 - room JID |
248 - room JID + "/" + user nick | 269 - room JID + "/" + user nick |
249 @param profile (unicode): %(doc_profile)s | 270 @param profile (unicode): %(doc_profile)s |
250 """ | 271 """ |
251 if self._gameExists(room_jid, started=True): | 272 if self._gameExists(room_jid, started=True): |
252 element = self._createStartElement(self.games[room_jid]['players']) | 273 element = self._createStartElement(self.games[room_jid]["players"]) |
253 else: | 274 else: |
254 element = self._createStartElement(self.games[room_jid]['players'], name="players") | 275 element = self._createStartElement( |
276 self.games[room_jid]["players"], name="players" | |
277 ) | |
255 elements = [(element, None, None)] | 278 elements = [(element, None, None)] |
256 | 279 |
257 sync_args = [] | 280 sync_args = [] |
258 sync_data = self._getSyncData(room_jid) | 281 sync_data = self._getSyncData(room_jid) |
259 for nick in sync_data: | 282 for nick in sync_data: |
260 user_jid = jid.JID(room_jid.userhost() + '/' + nick) | 283 user_jid = jid.JID(room_jid.userhost() + "/" + nick) |
261 if user_jid in recipients: | 284 if user_jid in recipients: |
262 user_elements = copy.deepcopy(elements) | 285 user_elements = copy.deepcopy(elements) |
263 for child in sync_data[nick]: | 286 for child in sync_data[nick]: |
264 user_elements.append((child, None, None)) | 287 user_elements.append((child, None, None)) |
265 recipients.remove(user_jid) | 288 recipients.remove(user_jid) |
266 else: | 289 else: |
267 user_elements = [(child, None, None) for child in sync_data[nick]] | 290 user_elements = [(child, None, None) for child in sync_data[nick]] |
268 sync_args.append(([user_jid, user_elements], {'profile': profile})) | 291 sync_args.append(([user_jid, user_elements], {"profile": profile})) |
269 | 292 |
270 for recipient in recipients: | 293 for recipient in recipients: |
271 self._sendElements(recipient, elements, profile=profile) | 294 self._sendElements(recipient, elements, profile=profile) |
272 for args, kwargs in sync_args: | 295 for args, kwargs in sync_args: |
273 self._sendElements(*args, **kwargs) | 296 self._sendElements(*args, **kwargs) |
281 be sent by self._synchronizeRoom for the game to be synchronized. | 304 be sent by self._synchronizeRoom for the game to be synchronized. |
282 """ | 305 """ |
283 if not self._gameExists(room_jid): | 306 if not self._gameExists(room_jid): |
284 return {} | 307 return {} |
285 data = {} | 308 data = {} |
286 status = self.games[room_jid]['status'] | 309 status = self.games[room_jid]["status"] |
287 nicks = [nick for nick in status if status[nick] == 'desync'] | 310 nicks = [nick for nick in status if status[nick] == "desync"] |
288 if force_nicks is None: | 311 if force_nicks is None: |
289 force_nicks = [] | 312 force_nicks = [] |
290 for nick in force_nicks: | 313 for nick in force_nicks: |
291 if nick not in nicks: | 314 if nick not in nicks: |
292 nicks.append(nick) | 315 nicks.append(nick) |
314 raise NotImplementedError("Need to be fixed !") | 337 raise NotImplementedError("Need to be fixed !") |
315 # FIXME: this is broken and unsecure ! | 338 # FIXME: this is broken and unsecure ! |
316 if not self._checkInviteAuth(room_jid, nick): | 339 if not self._checkInviteAuth(room_jid, nick): |
317 return [] | 340 return [] |
318 # TODO: remove invitation waiting for too long, using the time data | 341 # TODO: remove invitation waiting for too long, using the time data |
319 self.invitations[room_jid].append((time(), [player.userhostJID() for player in other_players])) | 342 self.invitations[room_jid].append( |
343 (time(), [player.userhostJID() for player in other_players]) | |
344 ) | |
320 nicks = [] | 345 nicks = [] |
321 for player_jid in [player.userhostJID() for player in other_players]: | 346 for player_jid in [player.userhostJID() for player in other_players]: |
322 # TODO: find a way to make it secure | 347 # TODO: find a way to make it secure |
323 other_nick = self.host.plugins["XEP-0045"].getRoomEntityNick(room_jid, player_jid, secure=self.testing) | 348 other_nick = self.host.plugins["XEP-0045"].getRoomEntityNick( |
349 room_jid, player_jid, secure=self.testing | |
350 ) | |
324 if other_nick is None: | 351 if other_nick is None: |
325 self.host.plugins["XEP-0249"].invite(player_jid, room_jid, {"game": self.name}, profile) | 352 self.host.plugins["XEP-0249"].invite( |
353 player_jid, room_jid, {"game": self.name}, profile | |
354 ) | |
326 else: | 355 else: |
327 nicks.append(other_nick) | 356 nicks.append(other_nick) |
328 return nicks | 357 return nicks |
329 | 358 |
330 def _checkInviteAuth(self, room_jid, nick, verbose=False): | 359 def _checkInviteAuth(self, room_jid, nick, verbose=False): |
337 """ | 366 """ |
338 auth = False | 367 auth = False |
339 if self.invite_mode == self.FROM_ALL or not self._gameExists(room_jid): | 368 if self.invite_mode == self.FROM_ALL or not self._gameExists(room_jid): |
340 auth = True | 369 auth = True |
341 elif self.invite_mode == self.FROM_NONE: | 370 elif self.invite_mode == self.FROM_NONE: |
342 auth = not self._gameExists(room_jid, started=True) and self.isReferee(room_jid, nick) | 371 auth = not self._gameExists(room_jid, started=True) and self.isReferee( |
372 room_jid, nick | |
373 ) | |
343 elif self.invite_mode == self.FROM_REFEREE: | 374 elif self.invite_mode == self.FROM_REFEREE: |
344 auth = self.isReferee(room_jid, nick) | 375 auth = self.isReferee(room_jid, nick) |
345 elif self.invite_mode == self.FROM_PLAYERS: | 376 elif self.invite_mode == self.FROM_PLAYERS: |
346 auth = self.isPlayer(room_jid, nick) | 377 auth = self.isPlayer(room_jid, nick) |
347 if not auth and (verbose or _DEBUG): | 378 if not auth and (verbose or _DEBUG): |
348 log.debug(_(u"%(user)s not allowed to invite for the game %(game)s in %(room)s") % {'user': nick, 'game': self.name, 'room': room_jid.userhost()}) | 379 log.debug( |
380 _(u"%(user)s not allowed to invite for the game %(game)s in %(room)s") | |
381 % {"user": nick, "game": self.name, "room": room_jid.userhost()} | |
382 ) | |
349 return auth | 383 return auth |
350 | 384 |
351 def isReferee(self, room_jid, nick): | 385 def isReferee(self, room_jid, nick): |
352 """Checks if the player with this nick is the referee for the game in this room" | 386 """Checks if the player with this nick is the referee for the game in this room" |
353 @param room_jid (jid.JID): room JID | 387 @param room_jid (jid.JID): room JID |
354 @param nick: user nick in the room | 388 @param nick: user nick in the room |
355 @return: True if the user is the referee of the game in this room | 389 @return: True if the user is the referee of the game in this room |
356 """ | 390 """ |
357 if not self._gameExists(room_jid): | 391 if not self._gameExists(room_jid): |
358 return False | 392 return False |
359 return jid.JID(room_jid.userhost() + '/' + nick) == self.games[room_jid]['referee'] | 393 return ( |
394 jid.JID(room_jid.userhost() + "/" + nick) == self.games[room_jid]["referee"] | |
395 ) | |
360 | 396 |
361 def isPlayer(self, room_jid, nick): | 397 def isPlayer(self, room_jid, nick): |
362 """Checks if the user with this nick is a player for the game in this room. | 398 """Checks if the user with this nick is a player for the game in this room. |
363 @param room_jid (jid.JID): JID of the room | 399 @param room_jid (jid.JID): JID of the room |
364 @param nick: user nick in the room | 400 @param nick: user nick in the room |
366 """ | 402 """ |
367 if not self._gameExists(room_jid): | 403 if not self._gameExists(room_jid): |
368 return False | 404 return False |
369 # Important: the referee is not in the 'players' list right after | 405 # Important: the referee is not in the 'players' list right after |
370 # the game initialization, that's why we do also check with isReferee | 406 # the game initialization, that's why we do also check with isReferee |
371 return nick in self.games[room_jid]['players'] or self.isReferee(room_jid, nick) | 407 return nick in self.games[room_jid]["players"] or self.isReferee(room_jid, nick) |
372 | 408 |
373 def _checkWaitAuth(self, room, other_players, verbose=False): | 409 def _checkWaitAuth(self, room, other_players, verbose=False): |
374 """Check if we must wait for other players before starting the game. | 410 """Check if we must wait for other players before starting the game. |
375 | 411 |
376 @param room (wokkel.muc.Room): the room | 412 @param room (wokkel.muc.Room): the room |
386 elif len(room.roster) < len(other_players): | 422 elif len(room.roster) < len(other_players): |
387 # do not check the players until we may actually have them all | 423 # do not check the players until we may actually have them all |
388 result = (False, [], other_players) | 424 result = (False, [], other_players) |
389 else: | 425 else: |
390 # TODO: find a way to make it secure | 426 # TODO: find a way to make it secure |
391 (nicks, missing) = self.host.plugins["XEP-0045"].getRoomNicksOfUsers(room, other_players, secure=False) | 427 (nicks, missing) = self.host.plugins["XEP-0045"].getRoomNicksOfUsers( |
428 room, other_players, secure=False | |
429 ) | |
392 result = (len(nicks) == len(other_players), nicks, missing) | 430 result = (len(nicks) == len(other_players), nicks, missing) |
393 if not result[0] and (verbose or _DEBUG): | 431 if not result[0] and (verbose or _DEBUG): |
394 log.debug(_(u"Still waiting for %(users)s before starting the game %(game)s in %(room)s") % {'users': result[2], 'game': self.name, 'room': room.occupantJID.userhost()}) | 432 log.debug( |
433 _( | |
434 u"Still waiting for %(users)s before starting the game %(game)s in %(room)s" | |
435 ) | |
436 % { | |
437 "users": result[2], | |
438 "game": self.name, | |
439 "room": room.occupantJID.userhost(), | |
440 } | |
441 ) | |
395 return result | 442 return result |
396 | 443 |
397 def getUniqueName(self, muc_service=None, profile_key=C.PROF_KEY_NONE): | 444 def getUniqueName(self, muc_service=None, profile_key=C.PROF_KEY_NONE): |
398 """Generate unique room name | 445 """Generate unique room name |
399 | 446 |
404 client = self.host.getClient(profile_key) | 451 client = self.host.getClient(profile_key) |
405 # FIXME: jid.JID must be used instead of strings | 452 # FIXME: jid.JID must be used instead of strings |
406 room = self.host.plugins["XEP-0045"].getUniqueName(client, muc_service) | 453 room = self.host.plugins["XEP-0045"].getUniqueName(client, muc_service) |
407 return jid.JID("sat_%s_%s" % (self.name.lower(), room.userhost())) | 454 return jid.JID("sat_%s_%s" % (self.name.lower(), room.userhost())) |
408 | 455 |
409 def _prepareRoom(self, other_players=None, room_jid_s='', profile_key=C.PROF_KEY_NONE): | 456 def _prepareRoom( |
457 self, other_players=None, room_jid_s="", profile_key=C.PROF_KEY_NONE | |
458 ): | |
410 room_jid = jid.JID(room_jid_s) if room_jid_s else None | 459 room_jid = jid.JID(room_jid_s) if room_jid_s else None |
411 other_players = [jid.JID(player).userhostJID() for player in other_players] | 460 other_players = [jid.JID(player).userhostJID() for player in other_players] |
412 return self.prepareRoom(other_players, room_jid, profile_key) | 461 return self.prepareRoom(other_players, room_jid, profile_key) |
413 | 462 |
414 def prepareRoom(self, other_players=None, room_jid=None, profile_key=C.PROF_KEY_NONE): | 463 def prepareRoom(self, other_players=None, room_jid=None, profile_key=C.PROF_KEY_NONE): |
418 @param room_jid (jid.JID): JID of the room, or None to generate a unique name | 467 @param room_jid (jid.JID): JID of the room, or None to generate a unique name |
419 @param profile_key (unicode): %(doc_profile_key)s | 468 @param profile_key (unicode): %(doc_profile_key)s |
420 """ | 469 """ |
421 # FIXME: need to be refactored | 470 # FIXME: need to be refactored |
422 client = self.host.getClient(profile_key) | 471 client = self.host.getClient(profile_key) |
423 log.debug(_(u'Preparing room for %s game') % self.name) | 472 log.debug(_(u"Preparing room for %s game") % self.name) |
424 profile = self.host.memory.getProfileName(profile_key) | 473 profile = self.host.memory.getProfileName(profile_key) |
425 if not profile: | 474 if not profile: |
426 log.error(_("Unknown profile")) | 475 log.error(_("Unknown profile")) |
427 return defer.succeed(None) | 476 return defer.succeed(None) |
428 if other_players is None: | 477 if other_players is None: |
436 self._createOrInvite(client, room_jid, other_players) | 485 self._createOrInvite(client, room_jid, other_players) |
437 return defer.succeed(None) | 486 return defer.succeed(None) |
438 | 487 |
439 user_jid = self.host.getJidNStream(profile)[0] | 488 user_jid = self.host.getJidNStream(profile)[0] |
440 d = self.host.plugins["XEP-0045"].join(room_jid, user_jid.user, {}, profile) | 489 d = self.host.plugins["XEP-0045"].join(room_jid, user_jid.user, {}, profile) |
441 return d.addCallback(lambda dummy: self._createOrInvite(client, room_jid, other_players)) | 490 return d.addCallback( |
491 lambda dummy: self._createOrInvite(client, room_jid, other_players) | |
492 ) | |
442 | 493 |
443 def userJoinedTrigger(self, room, user, profile): | 494 def userJoinedTrigger(self, room, user, profile): |
444 """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. | 495 """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. |
445 | 496 |
446 @room: wokkel.muc.Room object. room.roster is a dict{wokkel.muc.User.nick: wokkel.muc.User} | 497 @room: wokkel.muc.Room object. room.roster is a dict{wokkel.muc.User.nick: wokkel.muc.User} |
449 """ | 500 """ |
450 room_jid = room.occupantJID.userhostJID() | 501 room_jid = room.occupantJID.userhostJID() |
451 profile_nick = room.occupantJID.resource | 502 profile_nick = room.occupantJID.resource |
452 if not self.isReferee(room_jid, profile_nick): | 503 if not self.isReferee(room_jid, profile_nick): |
453 return True # profile is not the referee | 504 return True # profile is not the referee |
454 if not self._checkJoinAuth(room_jid, user.entity if user.entity else None, user.nick): | 505 if not self._checkJoinAuth( |
506 room_jid, user.entity if user.entity else None, user.nick | |
507 ): | |
455 # user not allowed but let him know that we are playing :p | 508 # user not allowed but let him know that we are playing :p |
456 self._synchronizeRoom(room_jid, [jid.JID(room_jid.userhost() + '/' + user.nick)], profile) | 509 self._synchronizeRoom( |
510 room_jid, [jid.JID(room_jid.userhost() + "/" + user.nick)], profile | |
511 ) | |
457 return True | 512 return True |
458 if self.wait_mode == self.FOR_ALL: | 513 if self.wait_mode == self.FOR_ALL: |
459 # considering the last batch of invitations | 514 # considering the last batch of invitations |
460 batch = len(self.invitations[room_jid]) - 1 | 515 batch = len(self.invitations[room_jid]) - 1 |
461 if batch < 0: | 516 if batch < 0: |
462 log.error(u"Invitations from %s to play %s in %s have been lost!" % (profile_nick, self.name, room_jid.userhost())) | 517 log.error( |
518 u"Invitations from %s to play %s in %s have been lost!" | |
519 % (profile_nick, self.name, room_jid.userhost()) | |
520 ) | |
463 return True | 521 return True |
464 other_players = self.invitations[room_jid][batch][1] | 522 other_players = self.invitations[room_jid][batch][1] |
465 (auth, nicks, dummy) = self._checkWaitAuth(room, other_players) | 523 (auth, nicks, dummy) = self._checkWaitAuth(room, other_players) |
466 if auth: | 524 if auth: |
467 del self.invitations[room_jid][batch] | 525 del self.invitations[room_jid][batch] |
483 profile_nick = room.occupantJID.resource | 541 profile_nick = room.occupantJID.resource |
484 if not self.isReferee(room_jid, profile_nick): | 542 if not self.isReferee(room_jid, profile_nick): |
485 return True # profile is not the referee | 543 return True # profile is not the referee |
486 if self.isPlayer(room_jid, user.nick): | 544 if self.isPlayer(room_jid, user.nick): |
487 try: | 545 try: |
488 self.games[room_jid]['players'].remove(user.nick) | 546 self.games[room_jid]["players"].remove(user.nick) |
489 except ValueError: | 547 except ValueError: |
490 pass | 548 pass |
491 if len(self.games[room_jid]['players']) == 0: | 549 if len(self.games[room_jid]["players"]) == 0: |
492 return True | 550 return True |
493 if self.wait_mode == self.FOR_ALL: | 551 if self.wait_mode == self.FOR_ALL: |
494 # allow this user to join the game again | 552 # allow this user to join the game again |
495 user_jid = user.entity.userhostJID() | 553 user_jid = user.entity.userhostJID() |
496 if len(self.invitations[room_jid]) == 0: | 554 if len(self.invitations[room_jid]) == 0: |
511 - create: set to True to allow the game creation | 569 - create: set to True to allow the game creation |
512 - sync: set to True to advice a game synchronization | 570 - sync: set to True to advice a game synchronization |
513 """ | 571 """ |
514 user_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid, profile) | 572 user_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid, profile) |
515 if not user_nick: | 573 if not user_nick: |
516 log.error(u'Internal error: profile %s has not joined the room %s' % (profile, room_jid.userhost())) | 574 log.error( |
575 u"Internal error: profile %s has not joined the room %s" | |
576 % (profile, room_jid.userhost()) | |
577 ) | |
517 return False, False | 578 return False, False |
518 if self._gameExists(room_jid): | 579 if self._gameExists(room_jid): |
519 is_referee = self.isReferee(room_jid, user_nick) | 580 is_referee = self.isReferee(room_jid, user_nick) |
520 if self._gameExists(room_jid, started=True): | 581 if self._gameExists(room_jid, started=True): |
521 log.info(_(u"%(game)s game already created in room %(room)s") % {'game': self.name, 'room': room_jid.userhost()}) | 582 log.info( |
583 _(u"%(game)s game already created in room %(room)s") | |
584 % {"game": self.name, "room": room_jid.userhost()} | |
585 ) | |
522 return False, is_referee | 586 return False, is_referee |
523 elif not is_referee: | 587 elif not is_referee: |
524 log.info(_(u"%(game)s game in room %(room)s can only be created by %(user)s") % {'game': self.name, 'room': room_jid.userhost(), 'user': user_nick}) | 588 log.info( |
589 _(u"%(game)s game in room %(room)s can only be created by %(user)s") | |
590 % {"game": self.name, "room": room_jid.userhost(), "user": user_nick} | |
591 ) | |
525 return False, False | 592 return False, False |
526 else: | 593 else: |
527 self._initGame(room_jid, user_nick) | 594 self._initGame(room_jid, user_nick) |
528 return True, False | 595 return True, False |
529 | 596 |
537 but the game must not exist and all the players must be in the room already. | 604 but the game must not exist and all the players must be in the room already. |
538 @param room_jid (jid.JID): JID of the room | 605 @param room_jid (jid.JID): JID of the room |
539 @param nicks (list[unicode]): list of players nicks in the room (referee included, in first position) | 606 @param nicks (list[unicode]): list of players nicks in the room (referee included, in first position) |
540 @param profile_key (unicode): %(doc_profile_key)s | 607 @param profile_key (unicode): %(doc_profile_key)s |
541 """ | 608 """ |
542 log.debug(_(u"Creating %(game)s game in room %(room)s") % {'game': self.name, 'room': room_jid}) | 609 log.debug( |
610 _(u"Creating %(game)s game in room %(room)s") | |
611 % {"game": self.name, "room": room_jid} | |
612 ) | |
543 profile = self.host.memory.getProfileName(profile_key) | 613 profile = self.host.memory.getProfileName(profile_key) |
544 if not profile: | 614 if not profile: |
545 log.error(_(u"profile %s is unknown") % profile_key) | 615 log.error(_(u"profile %s is unknown") % profile_key) |
546 return | 616 return |
547 (create, sync) = self._checkCreateGameAndInit(room_jid, profile) | 617 (create, sync) = self._checkCreateGameAndInit(room_jid, profile) |
549 nicks = [] | 619 nicks = [] |
550 if not create: | 620 if not create: |
551 if sync: | 621 if sync: |
552 self._updatePlayers(room_jid, nicks, True, profile) | 622 self._updatePlayers(room_jid, nicks, True, profile) |
553 return | 623 return |
554 self.games[room_jid]['started'] = True | 624 self.games[room_jid]["started"] = True |
555 self._updatePlayers(room_jid, nicks, False, profile) | 625 self._updatePlayers(room_jid, nicks, False, profile) |
556 if self.player_init: | 626 if self.player_init: |
557 # specific data to each player (score, private data) | 627 # specific data to each player (score, private data) |
558 self.games[room_jid].setdefault('players_data', {}) | 628 self.games[room_jid].setdefault("players_data", {}) |
559 for nick in nicks: | 629 for nick in nicks: |
560 # The dict must be COPIED otherwise it is shared between all users | 630 # The dict must be COPIED otherwise it is shared between all users |
561 self.games[room_jid]['players_data'][nick] = copy.deepcopy(self.player_init) | 631 self.games[room_jid]["players_data"][nick] = copy.deepcopy( |
632 self.player_init | |
633 ) | |
562 | 634 |
563 def _playerReady(self, player_nick, referee_jid_s, profile_key=C.PROF_KEY_NONE): | 635 def _playerReady(self, player_nick, referee_jid_s, profile_key=C.PROF_KEY_NONE): |
564 self.playerReady(player_nick, jid.JID(referee_jid_s), profile_key) | 636 self.playerReady(player_nick, jid.JID(referee_jid_s), profile_key) |
565 | 637 |
566 def playerReady(self, player_nick, referee_jid, profile_key=C.PROF_KEY_NONE): | 638 def playerReady(self, player_nick, referee_jid, profile_key=C.PROF_KEY_NONE): |
571 """ | 643 """ |
572 profile = self.host.memory.getProfileName(profile_key) | 644 profile = self.host.memory.getProfileName(profile_key) |
573 if not profile: | 645 if not profile: |
574 log.error(_(u"profile %s is unknown") % profile_key) | 646 log.error(_(u"profile %s is unknown") % profile_key) |
575 return | 647 return |
576 log.debug(u'new player ready: %s' % profile) | 648 log.debug(u"new player ready: %s" % profile) |
577 # TODO: we probably need to add the game and room names in the sent message | 649 # TODO: we probably need to add the game and room names in the sent message |
578 self.send(referee_jid, 'player_ready', {'player': player_nick}, profile=profile) | 650 self.send(referee_jid, "player_ready", {"player": player_nick}, profile=profile) |
579 | 651 |
580 def newRound(self, room_jid, data, profile): | 652 def newRound(self, room_jid, data, profile): |
581 """Launch a new round (reinit the user data) | 653 """Launch a new round (reinit the user data) |
582 | 654 |
583 @param room_jid: room userhost | 655 @param room_jid: room userhost |
584 @param data: a couple (common_data, msg_elts) with: | 656 @param data: a couple (common_data, msg_elts) with: |
585 - common_data: backend initialization data for the new round | 657 - common_data: backend initialization data for the new round |
586 - msg_elts: dict to map each user to his specific initialization message | 658 - msg_elts: dict to map each user to his specific initialization message |
587 @param profile | 659 @param profile |
588 """ | 660 """ |
589 log.debug(_(u'new round for %s game') % self.name) | 661 log.debug(_(u"new round for %s game") % self.name) |
590 game_data = self.games[room_jid] | 662 game_data = self.games[room_jid] |
591 players = game_data['players'] | 663 players = game_data["players"] |
592 players_data = game_data['players_data'] | 664 players_data = game_data["players_data"] |
593 game_data['stage'] = "init" | 665 game_data["stage"] = "init" |
594 | 666 |
595 common_data, msg_elts = copy.deepcopy(data) if data is not None else (None, None) | 667 common_data, msg_elts = copy.deepcopy(data) if data is not None else (None, None) |
596 | 668 |
597 if isinstance(msg_elts, dict): | 669 if isinstance(msg_elts, dict): |
598 for player in players: | 670 for player in players: |
599 to_jid = jid.JID(room_jid.userhost() + "/" + player) # FIXME: gof: | 671 to_jid = jid.JID(room_jid.userhost() + "/" + player) # FIXME: gof: |
600 elem = msg_elts[player] if isinstance(msg_elts[player], domish.Element) else None | 672 elem = ( |
673 msg_elts[player] | |
674 if isinstance(msg_elts[player], domish.Element) | |
675 else None | |
676 ) | |
601 self.send(to_jid, elem, profile=profile) | 677 self.send(to_jid, elem, profile=profile) |
602 elif isinstance(msg_elts, domish.Element): | 678 elif isinstance(msg_elts, domish.Element): |
603 self.send(room_jid, msg_elts, profile=profile) | 679 self.send(room_jid, msg_elts, profile=profile) |
604 if common_data is not None: | 680 if common_data is not None: |
605 for player in players: | 681 for player in players: |
610 | 686 |
611 @param to_jid: JID of the recipient | 687 @param to_jid: JID of the recipient |
612 @return: the created element | 688 @return: the created element |
613 """ | 689 """ |
614 type_ = "normal" if to_jid.resource else "groupchat" | 690 type_ = "normal" if to_jid.resource else "groupchat" |
615 elt = domish.Element((None, 'message')) | 691 elt = domish.Element((None, "message")) |
616 elt["to"] = to_jid.full() | 692 elt["to"] = to_jid.full() |
617 elt["type"] = type_ | 693 elt["type"] = type_ |
618 elt.addElement(self.ns_tag) | 694 elt.addElement(self.ns_tag) |
619 return elt | 695 return elt |
620 | 696 |
630 started_elt = domish.Element((None, name)) | 706 started_elt = domish.Element((None, name)) |
631 if players is None: | 707 if players is None: |
632 return started_elt | 708 return started_elt |
633 idx = 0 | 709 idx = 0 |
634 for player in players: | 710 for player in players: |
635 player_elt = domish.Element((None, 'player')) | 711 player_elt = domish.Element((None, "player")) |
636 player_elt.addContent(player) | 712 player_elt.addContent(player) |
637 player_elt['index'] = str(idx) | 713 player_elt["index"] = str(idx) |
638 idx += 1 | 714 idx += 1 |
639 started_elt.addChild(player_elt) | 715 started_elt.addChild(player_elt) |
640 return started_elt | 716 return started_elt |
641 | 717 |
642 def _sendElements(self, to_jid, data, profile=None): | 718 def _sendElements(self, to_jid, data, profile=None): |
685 | 761 |
686 def getHandler(self, client): | 762 def getHandler(self, client): |
687 return RoomGameHandler(self) | 763 return RoomGameHandler(self) |
688 | 764 |
689 | 765 |
690 class RoomGameHandler (XMPPHandler): | 766 class RoomGameHandler(XMPPHandler): |
691 implements(iwokkel.IDisco) | 767 implements(iwokkel.IDisco) |
692 | 768 |
693 def __init__(self, plugin_parent): | 769 def __init__(self, plugin_parent): |
694 self.plugin_parent = plugin_parent | 770 self.plugin_parent = plugin_parent |
695 self.host = plugin_parent.host | 771 self.host = plugin_parent.host |
696 | 772 |
697 def connectionInitialized(self): | 773 def connectionInitialized(self): |
698 self.xmlstream.addObserver(self.plugin_parent.request, self.plugin_parent.room_game_cmd, profile=self.parent.profile) | 774 self.xmlstream.addObserver( |
699 | 775 self.plugin_parent.request, |
700 def getDiscoInfo(self, requestor, target, nodeIdentifier=''): | 776 self.plugin_parent.room_game_cmd, |
777 profile=self.parent.profile, | |
778 ) | |
779 | |
780 def getDiscoInfo(self, requestor, target, nodeIdentifier=""): | |
701 return [disco.DiscoFeature(self.plugin_parent.ns_tag[0])] | 781 return [disco.DiscoFeature(self.plugin_parent.ns_tag[0])] |
702 | 782 |
703 def getDiscoItems(self, requestor, target, nodeIdentifier=''): | 783 def getDiscoItems(self, requestor, target, nodeIdentifier=""): |
704 return [] | 784 return [] |