def AddChatRoom(request, game_state): """Add a new chat room. Use the chatRoomId to make a new chat room. Add the chatRoomId to the game's list of chat rooms. Validation: Args: chatRoomId: Id to use for this chat room. groupId: name: Chat room name, can be updated. withAdmins: bool, used by the client. Firebase entries: /chatRooms/%(chatRoomId) /games/%(gameId)/chatRooms """ helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'chatRoomId': '!ChatRoomId', 'groupId': 'GroupId', 'withAdmins': 'Boolean', 'name': 'String' }) chat_room_id = request['chatRoomId'] game_id = request['gameId'] chat_room = {k: request[k] for k in ('groupId', 'name', 'withAdmins', 'gameId')} game_state.put('/chatRooms', chat_room_id, chat_room) game_state.put('/games/%s/chatRooms' % game_id, chat_room_id, True)
def AckChatMessage(request, game_state): """Ack a chat message which sets the ack to the timestamp of that message. Validation: Player is in the chat room (via the group). Args: chatRoomId: Chat room to send the message to. playerId: Player sending the message. messageId: Unique ID to use for the message. Firebase entries: /chatRooms/%(chatRoomId)/acks """ valid_args = ['chatRoomId', 'playerId'] required_args = list(valid_args) required_args.extend(['messageId']) helpers.ValidateInputs(request, game_state, required_args, valid_args) chat = request['chatRoomId'] messageId = request['messageId'] playerId = request['playerId'] group = helpers.ChatToGroup(game_state, chat) message = game_state.get('/chatRooms/%s/messages' % chat, messageId) if message is None: raise InvalidInputError('That message ID is not valid.') if not game_state.get('/groups/%s/players' % group, playerId): raise InvalidInputError('You are not a member of that chat room.') game_state.put('/chatRooms/%s/acks' % chat, playerId, message['time'])
def AddLife(request, game_state): """Add a new player life. Validation: Args: playerId: The player who gets the new life. Firebase entry: /playersPublic/%(playerId)/lives /lives/%(lifeCode) """ helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'playerId': 'PlayerId', 'lifeCode': '?String', 'lifeId': '?!LifeId' }) player_id = request['playerId'] game_id = helpers.PlayerToGame(game_state, player_id) life_id = request['lifeId'] or 'life-%s' % random.randint(0, 2**52) life_code = request['lifeCode'] or RandomWords(3) public_life = { 'time': int(time.time()), } private_life = { 'code': life_code, } game_state.put('/playersPublic/%s/lives' % player_id, life_code, public_life), game_state.put('/playersPrivate/%s/lives' % player_id, life_code, private_life)
def AddRewards(request, game_state): """Add a set of rewards. Firebase entries: /rewards/%(rewardId) /rewardCategories/%(rcID)/rewards/%(rewardId) """ helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'rewardCategoryId': 'RewardCategoryId', 'count': 'Number' }) reward_category_id = request['rewardCategoryId'] reward_category = game_state.get('/rewardCategories/%s' % reward_category_id, None) for i in range(request['count']): reward_id = 'reward-%s' % random.randint(0, 2**52) reward_data = { 'gameId': request['gameId'], 'rewardCategoryId': reward_category_id, 'code': '%s-%s' % (reward_category['shortName'], RandomWords(3)), 'playerId': None } AddRewardToDb(game_state, reward_category_id, reward_id, reward_data)
def AddGameAdmin(request, game_state): """Add an admin to a game. Validation: Args: gameId: userId: Firebase entries: /games/%(gameId)/adminUsers """ helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'userId': 'UserId' }) game = request['gameId'] user = request['userId'] if game_state.get('/games/%s/adminUsers' % game, user): raise InvalidInputError('User %s is already an admin.' % user) game_state.put('/games/%s/adminUsers/' % game, user, True)
def UpdateRewardCategory(request, game_state): """Update an existing reward group. Firebase entries: /rewardCategories/%(rewardCategoryId) """ helpers.ValidateInputs(request, game_state, { 'rewardCategoryId': 'RewardCategoryId', 'gameId': 'GameId', 'name': '|String', 'shortName': '|String', 'points': '|Number', 'limitPerPlayer': '|Number', 'badgeUrl': '|String', 'description': '|String', }) reward_category_id = request['rewardCategoryId'] reward_category_data = {} for k in ('name', 'points', 'limitPerPlayer', 'badgeUrl', 'description'): if k in request: reward_category_data[k] = request[k] game_state.patch('/rewardCategories/%s' % reward_category_id, reward_category_data)
def UpdateGame(request, game_state): """Update a game entry. Firebase entries: /games/%(gameId) """ valid_args = ['gameId'] required_args = list(valid_args) helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'name': '|String', 'rulesHtml': '|String', 'faqHtml': '|String', 'stunTimer': '|Number', 'startTime': '|Timestamp', 'endTime': '|Timestamp', 'registrationEndTime': '|Timestamp', }) put_data = {} for property in ['name', 'rulesHtml', 'faqHtml', 'stunTimer', 'active', 'startTime', 'endTime', 'registrationEndTime']: if property in request: put_data[property] = request[property] game_state.patch('/games/%s' % request['gameId'], put_data)
def DeleteMission(request, game_state): helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'missionId': 'MissionId' }) game_state.delete('/missions', request['missionId']) game_state.delete('/games/%s/missions' % request['gameId'], request['missionId'])
def SendChatMessage(request, game_state): """Record a chat message. Validation: Player is in the chat room (via the group). The messageId is not used yet in this chat rom. Args: chatRoomId: Chat room to send the message to. messageId: Unique ID to use for the message. message: The message to send. Firebase entries: /chatRooms/%(chatRoomId)/messages """ helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'chatRoomId': 'ChatRoomId', 'messageId': '!MessageId', 'message': 'String', 'playerId': 'PlayerId', 'image': Optional({ 'url': 'String' }), 'location': Optional({ 'latitude': 'Number', 'longitude': 'Number', }), }) chat = request['chatRoomId'] messageId = request['messageId'] group = helpers.ChatToGroup(game_state, chat) if game_state.get('/chatRooms/%s/messages' % chat, messageId): raise InvalidInputError('That message ID was already used.') if not game_state.get('/groups/%s/players' % group, request['playerId']): raise InvalidInputError('You are not a member of that chat room.') # TODO Scan message for any @all or @player to turn into notifications. put_data = { 'playerId': request['playerId'], 'message': request['message'], 'time': int(time.time()) } if 'image' in request: put_data['image'] = { 'url': request['image']['url'] } if 'location' in request: put_data['location'] = { 'latitude': request['location']['latitude'], 'longitude': request['location']['longitude'] } game_state.put('/chatRooms/%s/messages' % chat, messageId, put_data)
def JoinHorde(request, game_state): helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'playerId': 'PlayerId', }) player_id = request['playerId'] player = game_state.get('/playersPublic', player_id) if player['allegiance'] != 'undeclared': raise InvalidInputError('Already have an allegiance!') SetPlayerAllegiance(game_state, player_id, allegiance=constants.ZOMBIE, can_infect=True)
def SendNotification(request, game_state): """Queue a notification to be sent. Validation: notificationId does not exist. groupId or playerId exists. Args: notificationId: Queued Notification id to create. message: Message to send to client. previewMessage: Short preview of the message comments. If empty, one will be generated. app: Whether to send as a push notification to the iOS/Android/Web clients. vibrate: Whether the notification should vibrate on iOS/Android. sound: Whether the notification should play a sound on iOS/Android. destination: URL that notification should open when clicked. sendTime: When to spawn notifications from this template. UNIX timestamp. playerId: Player id to send message to. Cannot be mixed with groupId. groupId: Who to send the notifications to. Cannot be mixed with playerId. icon: An icon code to show. Firebase entries: /notifications/%(notificationId) """ valid_args = ['!notificationId'] if 'groupId' in request and 'playerId' not in request: valid_args.append('groupId') elif 'playerId' in request and 'groupId' not in request: valid_args.append('playerId') else: raise InvalidInputError('Must include either a playerId or a groupId') required_args = list(valid_args) required_args.extend(['message', 'app', 'vibrate', 'sound', 'destination', 'sendTime', 'groupId', 'icon']) helpers.ValidateInputs(request, game_state, required_args, valid_args) current_time = int(time.time()) if 'sendTime' in request and current_time > int(request['sendTime']): raise InvalidInputError('sendTime must not be in the past!') if 'previewMessage' not in request: request['previewMessage'] = textwrap.wrap(request['message'], 100)[0] put_data = {} properties = ['message', 'app', 'vibrate', 'sound', 'destination', 'sendTime', 'groupId', 'playerId', 'icon', 'previewMessage'] for property in properties: if property in request: put_data[property] = request[property] game_state.put('/notifications', request['notificationId'], put_data)
def SetAdminContact(request, game_state): """Update a game entry. Firebase entries: /games/%(gameId)/a """ helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'playerId': 'PlayerId', }) put_data = {'adminContactPlayerId': request['playerId']} game_state.patch('/games/%s' % request['gameId'], put_data)
def UpdateChatRoom(request, game_state): """Update a chat room. Firebase entries: /chatRooms/%(chatRoomId) """ helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'chatRoomId': 'ChatRoomId', 'name': '|String', }) put_data = {'name': request['name']} game_state.patch('/chatRooms/%s' % request['chatRoomId'], put_data)
def UpdateNotification(request, game_state): """Update a queued notification. Validation: notificationId exists. Args: notificationId: Queued Notification id to create. message: Message to send to client. previewMessage: Short preview of the message conents. Optional. app: Whether to send as a push notification to the iOS/Android/Web clients. vibrate: Whether the notification should vibrate on iOS/Android. sound: Whether the notification should play a sound on iOS/Android. destination: URL that notification should open when clicked. sendTime: When to spawn notifications from this template. UNIX timestamp. playerId: Player id to send message to. groupId: Who to send the notifications to. icon: An icon code to show. Firebase entries: /notifications/%(notificationId) """ valid_args = ['notificationId'] required_args = list(valid_args) helpers.ValidateInputs(request, game_state, required_args, valid_args) put_data = {} properties = ['message', 'app', 'vibrate', 'sound', 'destination', 'sendTime', 'groupId', 'playerId', 'icon'] current_time = int(time.time()) if 'sendTime' in request and current_time > int(request['sendTime']): raise InvalidInputError('sendTime must not be in the past!') notification = game_state.get('/notifications', request['notificationId']) # This shouldn't happen since we validated this above... if not notification: raise InvalidInputError('notificationId must exist!') if current_time > int(notification['sendTime']) or 'sent' in notification: raise InvalidInputError('Cannot modify sent notification.') for property in properties: if property in request: put_data[property] = request[property] game_state.patch('/notifications/%s' % request['notificationId'], put_data)
def AddReward(request, game_state): """Add a new reward to an existing category. Validation: Args: rewardId: rewardCategoryId: code: The code that the player can use to claim this reward. Must start with the reward category's shortName. For example, "epicinfection-purple-roller-strike" is a reward for the reward category that has shortName "epicinfection". Firebase entries: /rewards/%(rewardId) /rewardCategories/%(rcID)/rewards/%(rewardId) """ helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'rewardId': '!RewardId', 'rewardCategoryId': 'RewardCategoryId', 'code': '?String' }) game_id = request['gameId'] reward_id = request['rewardId'] reward_category_id = request['rewardCategoryId'] reward_category = game_state.get('/rewardCategories/%s' % reward_category_id, None) reward_code = request['code'] or '%s-%s' % (reward_category['shortName'], RandomWords(3)) if helpers.RewardCodeToRewardId(game_state, game_id, reward_code, False) is not None: raise InvalidInputError('Reward with that code already exists!') reward_category_short_name = reward_category['shortName'] if reward_code.split('-')[0] != reward_category_short_name: raise InvalidInputError('Reward code must start with category\'s shortName. code: "%s", shortName: "%s"' % (reward_code, reward_category_short_name)) reward_data = { 'rewardCategoryId': reward_category_id, 'code': reward_code, 'playerId': None, } AddRewardToDb(game_state, reward_category_id, reward_id, reward_data)
def AddRewardCategory(request, game_state): """Add a new reward group. Validation: rewardCategoryId is of valid form. Args: rewardCategoryId: reward type, eg rewardCategory-foo gameId: The game ID. eg game-1 name: Name of the reward, such as "Epic Infection" shortName: The shortname for the reward category, will serve as a seed for generating the reward codes, and will appear at the front of the reward codes. Example "epicinfection" limitPerPlayer: (int) how many a player can claim points: (int) points the reward is worth Firebase entries: /rewardCategories/%(rewardCategoryId) """ helpers.ValidateInputs(request, game_state, { 'rewardCategoryId': '!RewardCategoryId', 'gameId': 'GameId', 'name': 'String', 'shortName': 'String', 'points': 'Number', 'limitPerPlayer': 'Number', 'badgeImageUrl': '?String', 'description': 'String', }) game = request['gameId'] reward_category_id = request['rewardCategoryId'] reward_category_data = { 'gameId': game, 'claimed': 0, 'shortName': request['shortName'], 'name': request['name'], 'points': int(request['points']), 'badgeImageUrl': request['badgeImageUrl'], 'limitPerPlayer': request['limitPerPlayer'], } game_state.put('/rewardCategories', reward_category_id, reward_category_data) game_state.put('/games/%s/rewardCategories' % game, reward_category_id, True)
def JoinResistance(request, game_state): helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'playerId': 'PlayerId', 'lifeCode': '?String', 'lifeId': '?!LifeId', }) player_id = request['playerId'] life_code = request['lifeCode'] player = game_state.get('/playersPublic', player_id) if player['allegiance'] != 'undeclared': raise InvalidInputError('Already have an allegiance!') AddLife(request, game_state) SetPlayerAllegiance(game_state, player_id, allegiance=constants.HUMAN, can_infect=False)
def AssignGun(request, game_state): """Assign a gun to a given player. Firebase entries: /guns/%(gunId) """ helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'gunId': 'GunId', 'playerId': '|?PlayerId', }) update = {} if 'playerId' in request: update['playerId'] = request['playerId'] or '' if 'label' in request: update['label'] = request['label'] game_state.patch('/guns/%s' % request['gunId'], update)
def RegisterUserDevice(request, game_state): """Register a user device to a userId. Validation: userId must exist. Args: userId: User id to associate with. deviceToken: Ionic device token. Firebase entries: /users/%(userId)/deviceToken """ helpers.ValidateInputs(request, game_state, { 'userId': 'UserId', 'deviceToken': 'String', }) put_data = {'deviceToken': request['deviceToken']} game_state.patch('/users/%s', put_data)
def Register(request, game_state): """Register a new user in the DB. Validation: Args: userId: Unique userId added to the user list. name: A name to use to reference a player. Firebase entries: /users/%(userId) """ helpers.ValidateInputs(request, game_state, { 'userId': 'String' }) user_id = request['userId'] if game_state.get('/users', user_id) is None: data = {'a': True} game_state.put('/users', request['userId'], data)
def AddGame(request, game_state): """Add a new game. Validation: gameId must be valid format. Args: gameId: adminUserId: name: rulesHtml: static HTML containing the rule doc. stunTimer: Firebase entries: /games/%(gameId) """ helpers.ValidateInputs(request, game_state, { 'gameId': '!GameId', 'adminUserId': 'UserId', 'active': 'Boolean', 'name': 'String', 'rulesHtml': 'String', 'faqHtml': 'String', 'stunTimer': 'Number', 'startTime': 'Timestamp', 'endTime': 'Timestamp', 'registrationEndTime': 'Timestamp', }) put_data = { 'name': request['name'], 'active': request['active'], 'rulesHtml': request['rulesHtml'], 'faqHtml': request['faqHtml'], 'stunTimer': request['stunTimer'], 'startTime': request['startTime'], 'endTime': request['endTime'], 'registrationEndTime': request['registrationEndTime'], } game_state.put('/games', request['gameId'], put_data) game_state.put('/games/%s/adminUsers' % request['gameId'], request['adminUserId'], True)
def AddGun(request, game_state): """Add a new gun to the DB. Firebase entries: /guns/%(gunId)/ """ helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'gunId': '!GunId', 'label': 'String' }) game_id = request['gameId'] gun_id = request['gunId'] game_state.put('/guns', gun_id, { 'gameId': request['gameId'], 'playerId': '', 'label': request['label'] }) game_state.put('/games/%s/guns' % game_id, gun_id, True)
def MarkNotificationSeen(request, game_state): """Updates the notification's seenTime. Validation: notificationId must exist. playerId must exist. Args: notificationId: Notification Id to update. playerId: Player who saw notification. Firebase entries: /playersPrivate/%(playerId)/notifications/%(notificationId) """ valid_args = ['notificationId', 'playerId'] required_args = list(valid_args) helpers.ValidateInputs(request, game_state, required_args, valid_args) put_data = { 'time': int(time.time()) } game_state.patch('/player/%s/notifications/%s' % ( request['playerId'], request['notificationId']), put_data)
def AddGroup(request, game_state): """Add a new player group. Firebase entries: /groups/%(groupId) /groups/%(groupId)/players/%(playerId) /games/%(gameId)/groups/%(groupId) """ helpers.ValidateInputs(request, game_state, { 'groupId': '!GroupId', 'gameId': 'GameId', 'ownerPlayerId': '?PlayerId', 'allegianceFilter': 'String', 'name': 'String', 'autoRemove': 'Boolean', 'autoAdd': 'Boolean', 'canAddOthers': 'Boolean', 'canRemoveOthers': 'Boolean', 'canAddSelf': 'Boolean', 'canRemoveSelf': 'Boolean' }) group_id = request['groupId'] owner_player_id = request['ownerPlayerId'] group = { 'ownerPlayerId': owner_player_id, 'gameId': request['gameId'], 'allegianceFilter': request['allegianceFilter'], 'name': request['name'], 'autoRemove': request['autoRemove'], 'autoAdd': request['autoAdd'], 'canAddOthers': request['canAddOthers'], 'canRemoveOthers': request['canRemoveOthers'], 'canAddSelf': request['canAddSelf'], 'canRemoveSelf': request['canRemoveSelf'], } game_state.put('/groups', group_id, group) game_state.put('/games/%s/groups/' % request['gameId'], request['groupId'], True)
def AddMission(request, game_state): """Add a new mission. Firebase entries: /game/%(gameId)/missions /missions/%(missionId) """ helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'missionId': '!MissionId', 'groupId': 'GroupId', 'rsvpersGroupId': 'GroupId', 'name': 'String', 'beginTime': 'Timestamp', 'endTime': 'Timestamp', 'detailsHtml': 'String' }) mission_data = {k: request[k] for k in ['name', 'beginTime', 'endTime', 'detailsHtml', 'groupId', 'rsvpersGroupId', 'gameId']} game_state.put('/missions', request['missionId'], mission_data) game_state.put('/games/%s/missions' % request['gameId'], request['missionId'], True)
def UpdateMission(request, game_state): """Update details of a mission. Firebase entries: /missions/%(missionId) """ helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'missionId': 'MissionId', 'name': '|String', 'beginTime': '|Timestamp', 'endTime': '|Timestamp', 'detailsHtml': '|String' }) mission_id = request['missionId'] put_data = {} for property in ['name', 'beginTime', 'endTime', 'detailsHtml']: if property in request: put_data[property] = request[property] game_state.patch('/missions/%s' % mission_id, put_data)
def UpdateGroup(request, game_state): """Update a group entry. Firebase entries: /groups/%(groupId) """ helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'groupId': 'GroupId', 'ownerPlayerId': '|PlayerId', 'name': '|String', 'autoAdd': '|Boolean', 'autoRemove': '|Boolean', 'canAddOthers': '|Boolean', 'canRemoveOthers': '|Boolean', 'canAddSelf': '|Boolean', 'canRemoveSelf': '|Boolean' }) put_data = {} for property in ['name', 'autoAdd', 'autoRemove', 'canAddOthers', 'canRemoveOthers', 'canAddSelf', 'canRemoveSelf', 'ownerPlayerId']: if property in request: put_data[property] = request[property] game_state.patch('/groups/%s' % request['groupId'], put_data)
def Infect(request, game_state): """Infect a player via life code. Infect a human and gets points. Args: playerId: The person doing the infecting. lifeCode: The life code being taken/infected, makes to the victom. Validation: Valid IDs. Infector can infect or is self-infecting. Infectee is human. Firebase entries: /games/%(gameId)/players/%(playerId) /groups/%(groupId) indirectly """ helpers.ValidateInputs(request, game_state, { 'infectionId': '!InfectionId', 'gameId': 'GameId', 'infectorPlayerId': 'PlayerId', 'victimLifeCode': '?String', 'victimPlayerId': '?PlayerId', }) game_id = request['gameId'] infector_player_id = request['infectorPlayerId'] infection_id = request['infectionId'] victim_life_code = request['victimLifeCode'] victim_player_id = helpers.LifeCodeToPlayerId(game_state, game_id, victim_life_code) infector_player = helpers.GetWholePlayer(game_state, infector_player_id) victim_player = helpers.GetWholePlayer(game_state, victim_player_id) print "Infector %s is infecting %s" % (infector_player_id, victim_player_id) print "infector:" print infector_player # Both players must be in the same game. if helpers.PlayerToGame(game_state, victim_player_id) != game_id: raise InvalidInputError('Those players are not part of the same game!') # The infector must be able to infect or be doing a self-infect if infector_player_id != victim_player_id and not infector_player['canInfect']: raise InvalidInputError('You cannot infect another player at the present time.') # The victim must be human to be infected if victim_player['allegiance'] != constants.HUMAN: raise InvalidInputError('Your victim is not human and cannot be infected.') # Add points and an infection entry for a successful infection if infector_player_id != victim_player_id: helpers.AddPoints(game_state, infector_player_id, constants.POINTS_INFECT) infect_path = '/playersPublic/%s/infections' % victim_player_id infect_data = { 'infectorId': infector_player_id, 'time': int(time.time()), } game_state.put(infect_path, infection_id, infect_data) # If secret zombie, set the victim to secret zombie and the infector to zombie # Else set the victom to zombie if infector_player_id != victim_player_id and infector_player['allegiance'] == constants.HUMAN: logging.warn('Secret infection') SetPlayerAllegiance(game_state, victim_player_id, allegiance=constants.HUMAN, can_infect=True) SetPlayerAllegiance(game_state, infector_player_id, allegiance=constants.ZOMBIE, can_infect=True) else: logging.warn('Normal infection') SetPlayerAllegiance(game_state, victim_player_id, allegiance=constants.ZOMBIE, can_infect=True) # DO NOT BLINDLY COPY THIS # Returning game data from the server (other than an error message or a success boolean) # is risky for the client; the client has to be careful about race conditions when reading # data returned from the server. In this case, this playerId response will likely reach # the client before firebase tells the client that this player was zombified. return victim_player_id
def RemovePlayerFromGroup(request, game_state): """Remove a player from a group. Either a member of the group or the admin adds a player. Validation: * Player doing the removing is a member of the group AND the group supports removing or The player is the group owner. * playerToAddId is in the group. * Both players and the groupId all point to the same game. Args: groupId: The group to remove a player from. playerId: The player doing the removing (unless an admin). playerToAddId: The player being removed. Firebase entries: /groups/%(groupId)/players/%(playerId) /playersPrivate/%(playerId)/chatRooms/ /playersPrivate/%(playerId)/missions/ """ helpers.ValidateInputs(request, game_state, { 'groupId': 'GroupId', 'gameId': 'GameId', 'playerToRemoveId': 'PlayerId', 'actingPlayerId': '?PlayerId' }) requesting_player_id = request['requestingPlayerId'] requesting_user_id = request['requestingUserId'] acting_player_id = request['actingPlayerId'] group_id = request['groupId'] player_to_remove_id = request['playerToRemoveId'] game_id = request['gameId'] if helpers.IsAdmin(game_state, game_id, requesting_user_id): pass elif acting_player_id is not None: pass else: raise InvalidInputError('Only a player or an admin can call this method!') if game_id != helpers.PlayerToGame(game_state, player_to_remove_id): raise InvalidInputError('Other player is not in the same game as you.') if game_id != helpers.GroupToGame(game_state, group_id): raise InvalidInputError('That group is not part of your active game.') # Validate otherPlayer is in the group if not game_state.get('/groups/%s/players' % group_id, player_to_remove_id): raise InvalidInputError('Other player is not in the chat.') # Player must be admin or the owner or (be in the group and group allows adding). if helpers.IsAdmin(game_state, game_id, requesting_user_id): pass elif acting_player_id == game_state.get('/groups/%s' % group_id, 'ownerPlayerId'): pass else: # Validate player is in the chat room. if not game_state.get('/groups/%s/players' % group_id, acting_player_id): raise InvalidInputError('You are not a member of that group nor an owner.') # Validate players are allowed to remove other players. if not game_state.get('/groups/%s' % group_id, 'canRemoveOthers'): raise InvalidInputError('Players are not allowed to remove from this group.') RemovePlayerFromGroupInner(game_state, group_id, player_to_remove_id)
def UpdatePlayer(request, game_state): """Update player properties. Firebase entries: /playersPrivate/%(playerId) /playersPublic/%(playerId) """ helpers.ValidateInputs(request, game_state, { 'gameId': 'GameId', 'playerId': 'PlayerId', 'active': '|Boolean', 'name': '|String', 'needGun': '|Boolean', 'profileImageUrl': '|?String', 'gotEquipment': '|Boolean', 'notes': '|String', 'wantToBeSecretZombie': '|Boolean', 'notificationSettings': { 'sound': '|Boolean', 'vibrate': '|Boolean', }, 'volunteer': { 'advertising': '|Boolean', 'logistics': '|Boolean', 'communications': '|Boolean', 'moderator': '|Boolean', 'cleric': '|Boolean', 'sorcerer': '|Boolean', 'admin': '|Boolean', 'photographer': '|Boolean', 'chronicler': '|Boolean', 'server': '|Boolean', 'client': '|Boolean', 'android': '|Boolean', 'ios': '|Boolean' } }) player_id = request['playerId'] public_update = {} for property in ['active', 'name', 'profileImageUrl']: if property in request: public_update[property] = request[property] volunteer_update = {} if 'volunteer' in request: for property in constants.PLAYER_VOLUNTEER_ARGS: if property in request['volunteer']: volunteer_update[property] = request['volunteer'][property] notification_settings_update = {} if 'notificationSettings' in request: for property in ['vibrate', 'sound']: if property in request['notificationSettings']: notification_settings_update[property] = request['notificationSettings'][property] private_update = {} for property in ['needGun', 'gotEquipment', 'notes', 'wantToBeSecretZombie']: if property in request: private_update[property] = request[property] game_state.patch('/playersPrivate/%s' % player_id, private_update) game_state.patch('/playersPrivate/%s/volunteer' % player_id, volunteer_update) game_state.patch('/playersPrivate/%s/notificationSettings' % player_id, notification_settings_update) game_state.patch('/playersPublic/%s' % player_id, public_update)