comparison sat/plugins/plugin_misc_room_game.py @ 3028:ab2696e34d29

Python 3 port: /!\ this is a huge commit /!\ starting from this commit, SàT is needs Python 3.6+ /!\ SàT maybe be instable or some feature may not work anymore, this will improve with time This patch port backend, bridge and frontends to Python 3. Roughly this has been done this way: - 2to3 tools has been applied (with python 3.7) - all references to python2 have been replaced with python3 (notably shebangs) - fixed files not handled by 2to3 (notably the shell script) - several manual fixes - fixed issues reported by Python 3 that where not handled in Python 2 - replaced "async" with "async_" when needed (it's a reserved word from Python 3.7) - replaced zope's "implements" with @implementer decorator - temporary hack to handle data pickled in database, as str or bytes may be returned, to be checked later - fixed hash comparison for password - removed some code which is not needed anymore with Python 3 - deactivated some code which needs to be checked (notably certificate validation) - tested with jp, fixed reported issues until some basic commands worked - ported Primitivus (after porting dependencies like urwid satext) - more manual fixes
author Goffi <goffi@goffi.org>
date Tue, 13 Aug 2019 19:08:41 +0200
parents 003b8b4b56a7
children 9d0df638c8b4
comparison
equal deleted inserted replaced
3027:ff5bcb12ae60 3028:ab2696e34d29
1 #!/usr/bin/env python2 1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*- 2 # -*- coding: utf-8 -*-
3 3
4 # SAT: a jabber client 4 # SAT: a jabber client
5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) 5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org)
6 6
25 from twisted.words.protocols.jabber import jid 25 from twisted.words.protocols.jabber import jid
26 from twisted.words.xish import domish 26 from twisted.words.xish import domish
27 from twisted.internet import defer 27 from twisted.internet import defer
28 from time import time 28 from time import time
29 from wokkel import disco, iwokkel 29 from wokkel import disco, iwokkel
30 from zope.interface import implements 30 from zope.interface import implementer
31 import copy 31 import copy
32 32
33 try: 33 try:
34 from twisted.words.protocols.xmlstream import XMPPHandler 34 from twisted.words.protocols.xmlstream import XMPPHandler
35 except ImportError: 35 except ImportError:
62 62
63 For examples of messages sequences, please look in sub-classes. 63 For examples of messages sequences, please look in sub-classes.
64 """ 64 """
65 65
66 # Values for self.invite_mode (who can invite after the game creation) 66 # Values for self.invite_mode (who can invite after the game creation)
67 FROM_ALL, FROM_NONE, FROM_REFEREE, FROM_PLAYERS = xrange(0, 4) 67 FROM_ALL, FROM_NONE, FROM_REFEREE, FROM_PLAYERS = range(0, 4)
68 # Values for self.wait_mode (for who we should wait before creating the game) 68 # Values for self.wait_mode (for who we should wait before creating the game)
69 FOR_ALL, FOR_NONE = xrange(0, 2) 69 FOR_ALL, FOR_NONE = range(0, 2)
70 # 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)
71 ALL, INVITED, NONE = xrange(0, 3) 71 ALL, INVITED, NONE = range(0, 3)
72 # 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)
73 ASK, FORCE = xrange(0, 2) 73 ASK, FORCE = range(0, 2)
74 74
75 MESSAGE = "/message" 75 MESSAGE = "/message"
76 REQUEST = '%s/%s[@xmlns="%s"]' 76 REQUEST = '%s/%s[@xmlns="%s"]'
77 77
78 def __init__(self, host): 78 def __init__(self, host):
216 auth = True 216 auth = True
217 break 217 break
218 218
219 if not auth and (verbose or _DEBUG): 219 if not auth and (verbose or _DEBUG):
220 log.debug( 220 log.debug(
221 _(u"%(user)s not allowed to join the game %(game)s in %(room)s") 221 _("%(user)s not allowed to join the game %(game)s in %(room)s")
222 % { 222 % {
223 "user": user_jid.userhost() or nick, 223 "user": user_jid.userhost() or nick,
224 "game": self.name, 224 "game": self.name,
225 "room": room_jid.userhost(), 225 "room": room_jid.userhost(),
226 } 226 }
375 auth = self.isReferee(room_jid, nick) 375 auth = self.isReferee(room_jid, nick)
376 elif self.invite_mode == self.FROM_PLAYERS: 376 elif self.invite_mode == self.FROM_PLAYERS:
377 auth = self.isPlayer(room_jid, nick) 377 auth = self.isPlayer(room_jid, nick)
378 if not auth and (verbose or _DEBUG): 378 if not auth and (verbose or _DEBUG):
379 log.debug( 379 log.debug(
380 _(u"%(user)s not allowed to invite for the game %(game)s in %(room)s") 380 _("%(user)s not allowed to invite for the game %(game)s in %(room)s")
381 % {"user": nick, "game": self.name, "room": room_jid.userhost()} 381 % {"user": nick, "game": self.name, "room": room_jid.userhost()}
382 ) 382 )
383 return auth 383 return auth
384 384
385 def isReferee(self, room_jid, nick): 385 def isReferee(self, room_jid, nick):
429 ) 429 )
430 result = (len(nicks) == len(other_players), nicks, missing) 430 result = (len(nicks) == len(other_players), nicks, missing)
431 if not result[0] and (verbose or _DEBUG): 431 if not result[0] and (verbose or _DEBUG):
432 log.debug( 432 log.debug(
433 _( 433 _(
434 u"Still waiting for %(users)s before starting the game %(game)s in %(room)s" 434 "Still waiting for %(users)s before starting the game %(game)s in %(room)s"
435 ) 435 )
436 % { 436 % {
437 "users": result[2], 437 "users": result[2],
438 "game": self.name, 438 "game": self.name,
439 "room": room.occupantJID.userhost(), 439 "room": room.occupantJID.userhost(),
467 @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
468 @param profile_key (unicode): %(doc_profile_key)s 468 @param profile_key (unicode): %(doc_profile_key)s
469 """ 469 """
470 # FIXME: need to be refactored 470 # FIXME: need to be refactored
471 client = self.host.getClient(profile_key) 471 client = self.host.getClient(profile_key)
472 log.debug(_(u"Preparing room for %s game") % self.name) 472 log.debug(_("Preparing room for %s game") % self.name)
473 profile = self.host.memory.getProfileName(profile_key) 473 profile = self.host.memory.getProfileName(profile_key)
474 if not profile: 474 if not profile:
475 log.error(_("Unknown profile")) 475 log.error(_("Unknown profile"))
476 return defer.succeed(None) 476 return defer.succeed(None)
477 if other_players is None: 477 if other_players is None:
513 if self.wait_mode == self.FOR_ALL: 513 if self.wait_mode == self.FOR_ALL:
514 # considering the last batch of invitations 514 # considering the last batch of invitations
515 batch = len(self.invitations[room_jid]) - 1 515 batch = len(self.invitations[room_jid]) - 1
516 if batch < 0: 516 if batch < 0:
517 log.error( 517 log.error(
518 u"Invitations from %s to play %s in %s have been lost!" 518 "Invitations from %s to play %s in %s have been lost!"
519 % (profile_nick, self.name, room_jid.userhost()) 519 % (profile_nick, self.name, room_jid.userhost())
520 ) 520 )
521 return True 521 return True
522 other_players = self.invitations[room_jid][batch][1] 522 other_players = self.invitations[room_jid][batch][1]
523 (auth, nicks, __) = self._checkWaitAuth(room, other_players) 523 (auth, nicks, __) = self._checkWaitAuth(room, other_players)
570 - sync: set to True to advice a game synchronization 570 - sync: set to True to advice a game synchronization
571 """ 571 """
572 user_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid, profile) 572 user_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid, profile)
573 if not user_nick: 573 if not user_nick:
574 log.error( 574 log.error(
575 u"Internal error: profile %s has not joined the room %s" 575 "Internal error: profile %s has not joined the room %s"
576 % (profile, room_jid.userhost()) 576 % (profile, room_jid.userhost())
577 ) 577 )
578 return False, False 578 return False, False
579 if self._gameExists(room_jid): 579 if self._gameExists(room_jid):
580 is_referee = self.isReferee(room_jid, user_nick) 580 is_referee = self.isReferee(room_jid, user_nick)
581 if self._gameExists(room_jid, started=True): 581 if self._gameExists(room_jid, started=True):
582 log.info( 582 log.info(
583 _(u"%(game)s game already created in room %(room)s") 583 _("%(game)s game already created in room %(room)s")
584 % {"game": self.name, "room": room_jid.userhost()} 584 % {"game": self.name, "room": room_jid.userhost()}
585 ) 585 )
586 return False, is_referee 586 return False, is_referee
587 elif not is_referee: 587 elif not is_referee:
588 log.info( 588 log.info(
589 _(u"%(game)s game in room %(room)s can only be created by %(user)s") 589 _("%(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} 590 % {"game": self.name, "room": room_jid.userhost(), "user": user_nick}
591 ) 591 )
592 return False, False 592 return False, False
593 else: 593 else:
594 self._initGame(room_jid, user_nick) 594 self._initGame(room_jid, user_nick)
605 @param room_jid (jid.JID): JID of the room 605 @param room_jid (jid.JID): JID of the room
606 @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)
607 @param profile_key (unicode): %(doc_profile_key)s 607 @param profile_key (unicode): %(doc_profile_key)s
608 """ 608 """
609 log.debug( 609 log.debug(
610 _(u"Creating %(game)s game in room %(room)s") 610 _("Creating %(game)s game in room %(room)s")
611 % {"game": self.name, "room": room_jid} 611 % {"game": self.name, "room": room_jid}
612 ) 612 )
613 profile = self.host.memory.getProfileName(profile_key) 613 profile = self.host.memory.getProfileName(profile_key)
614 if not profile: 614 if not profile:
615 log.error(_(u"profile %s is unknown") % profile_key) 615 log.error(_("profile %s is unknown") % profile_key)
616 return 616 return
617 (create, sync) = self._checkCreateGameAndInit(room_jid, profile) 617 (create, sync) = self._checkCreateGameAndInit(room_jid, profile)
618 if nicks is None: 618 if nicks is None:
619 nicks = [] 619 nicks = []
620 if not create: 620 if not create:
641 @param player: the player nick in the room 641 @param player: the player nick in the room
642 @param referee_jid (jid.JID): JID of the referee 642 @param referee_jid (jid.JID): JID of the referee
643 """ 643 """
644 profile = self.host.memory.getProfileName(profile_key) 644 profile = self.host.memory.getProfileName(profile_key)
645 if not profile: 645 if not profile:
646 log.error(_(u"profile %s is unknown") % profile_key) 646 log.error(_("profile %s is unknown") % profile_key)
647 return 647 return
648 log.debug(u"new player ready: %s" % profile) 648 log.debug("new player ready: %s" % profile)
649 # 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
650 self.send(referee_jid, "player_ready", {"player": player_nick}, profile=profile) 650 self.send(referee_jid, "player_ready", {"player": player_nick}, profile=profile)
651 651
652 def newRound(self, room_jid, data, profile): 652 def newRound(self, room_jid, data, profile):
653 """Launch a new round (reinit the user data) 653 """Launch a new round (reinit the user data)
656 @param data: a couple (common_data, msg_elts) with: 656 @param data: a couple (common_data, msg_elts) with:
657 - common_data: backend initialization data for the new round 657 - common_data: backend initialization data for the new round
658 - 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
659 @param profile 659 @param profile
660 """ 660 """
661 log.debug(_(u"new round for %s game") % self.name) 661 log.debug(_("new round for %s game") % self.name)
662 game_data = self.games[room_jid] 662 game_data = self.games[room_jid]
663 players = game_data["players"] 663 players = game_data["players"]
664 players_data = game_data["players_data"] 664 players_data = game_data["players_data"]
665 game_data["stage"] = "init" 665 game_data["stage"] = "init"
666 666
761 761
762 def getHandler(self, client): 762 def getHandler(self, client):
763 return RoomGameHandler(self) 763 return RoomGameHandler(self)
764 764
765 765
766 @implementer(iwokkel.IDisco)
766 class RoomGameHandler(XMPPHandler): 767 class RoomGameHandler(XMPPHandler):
767 implements(iwokkel.IDisco)
768 768
769 def __init__(self, plugin_parent): 769 def __init__(self, plugin_parent):
770 self.plugin_parent = plugin_parent 770 self.plugin_parent = plugin_parent
771 self.host = plugin_parent.host 771 self.host = plugin_parent.host
772 772