def add_user_to_game(self, user, game, subtle_message=False): if len(game.players) >= game.max_player_count: banter = ":warning: game's full, rip {0}".format(format_user(user)) if subtle_message: self.update_game_message(game, banter) else: self.send_message(banter) return if not game.add_player(user): banter = "you're already in the '{}' game {}".format( game.description, format_user(user)) else: banter = self.load_banter("joined", { "s": format_user(user), "d": game.description }, for_user=user, in_channel=game.channel) self.history_sync() if not subtle_message: self.send_message(banter) self.update_game_message(game, banter if subtle_message else None) self.save()
def maybe_cancel_game(self, message, rest): user = message.user if len(rest) == 0: user_games = self.games_created_by(message.user) if len(user_games) == 1: game = user_games[0] else: self.send_too_many_owned_games_message(user_games, "cancel") return else: try: when = parse_time(rest) except ValueError: self.send_message( ":warning: scrubadubdub, when's this game you want to cancel?" .format(rest)) return game = self.game_occuring_at(when) if not game: self.send_game_not_found(when, user) return if game.creator != user: self.send_message( ":warning: scrubadubdub, only {} can cancel the {} {}".format( format_user(game.creator), when_str(game.when), game.description)) return self.games = filter(lambda g: g != game, self.games) rip_players = game.pretty_players(with_creator=False) rip_players_message = " (just burn some time on kimble instead {})".format(rip_players) \ if len(rip_players) else "" self.send_message( ":candle: {}'s {} ({}) has been flown out by {}{}".format( game.channel, game.description, when_str(game.when), format_user(user), rip_players_message)) newtext = game.message.text + "\n:warning: Cancelled :warning: :candle::candle:" self.update_message(newtext, original_message=game.message) self.history.cancel_game(game) self.save()
def stat_for_user(user_stats): user, users_stats = user_stats def get_stat_value(stat): value = users_stats[stat] # maybe highlight the value, if it was the latest if last_updated_user_stat: last_u, last_s = last_updated_user_stat if user == last_u and stat == last_s: return "[{}]".format(value) return value if UserOption.mute in self.user_options[user]: # we won't be @ing this user user_name = user user_padding = 0 else: padding_for_slackat = -2 user_name = format_user(user) user_padding = format_user_padding( user) + padding_for_slackat return [(user_padding, user_name)] \ + map(get_stat_value, allstats)
def maybe_new_game(self, user, channel, rest): """ Attempts to create a new game from freeform text Returns True on parse success (even if game creation failed) """ parsed = parse_game_initiation(rest, channel) if not parsed: return False when, desc, max_player_count, play_time, mode = parsed if len(desc) == 0: desc = "big game" game = self.game_overlapping(when, play_time) if game: self.send_duplicate_game_message(game) return True banter = self.load_banter("created", {"s": format_user(user)}, for_user=user, in_channel=channel) message = Game.create_message(banter, desc, when, max_player_count, mode, channel) posted_message = self.send_message(message) game = self.new_game(when, desc, channel, user, \ posted_message, max_player_count, play_time, mode) self.add_user_to_game(user, game, subtle_message=True) return True
def send_game_not_found(self, when, user): if random.randint(0, 1) == 0: self.send_message(":warning: {0}, there isnae game at {1}".format( format_user(user), when_str(when))) else: self.send_message( ":warning: scrubadubdub, there's no game at {}".format( when_str(when)))
def remove_user_from_game(self, user, game, subtle_message=False): if game.remove_player(user): banter = ":candle: {}".format(format_user(user)) else: if subtle_message: # don't say anything - they're silently removing their failed join-attmept-emoji return banter = ":warning: you're not in the {} game {} (\"{}\")".format( when_str(game.when), format_user(user), game.description) self.history_sync() if not subtle_message: self.send_message(banter) self.update_game_message(game, banter if subtle_message else None) self.save()
def handle_stats_request(self, message, rest, type=StatRequest.stats): anchor_message = True channel_name = None year = None k_factor = None history_length = None if len(rest): parsed = parse_stats_request(rest) if not parsed: self.send_message( ":warning: ere {}: \"{} [year] [channel]\"".format( type, format_user(message.user))) return channel_name, year, k_factor, history_length = parsed anchor_message = (channel_name is None or channel_name == message.channel.name) \ and (year is None or year.year == datetime.date.today().year) if not channel_name: channel_name = message.channel.name if type == StatRequest.elo: rankings = self.history.summary_elo(channel_name, year=year, k_factor=k_factor) if history_length: ranking_values = map( lambda ranking: [ ranking.getName(), ranking.games_played, ranking.getFormattedRanking(), ranking.getHistory(history_length) ], rankings.values()) ranking_values.sort(key=lambda x: (x[1] > 10, x[2]), reverse=True) table = generate_table( ['Player', 'Games Played', 'Ranking', 'Form'], ranking_values) else: ranking_values = map( lambda ranking: [ ranking.getName(), ranking.games_played, ranking.getFormattedRanking() ], rankings.values()) ranking_values.sort(key=lambda x: (x[1] > 10, x[2]), reverse=True) table = generate_table(['Player', 'Games Played', 'Ranking'], ranking_values) self.send_message(table) else: stats = self.history.summary_stats(channel_name, year=year) self.update_stats_table(channel_name, stats, force_new=True, anchor_message=anchor_message) self.latest_stats_table[channel_name].year = year
def handle_imminent_games(self): scheduled_games = filter(lambda g: g.state == GameStates.scheduled, self.games) active_games = filter(lambda g: g.state == GameStates.active, self.games) self.update_game_states() # keep games until end-of-day (to allow late entrants, etc) self.games = filter(lambda g: g.state != GameStates.dead, self.games) imminent_games = filter(lambda g: g.state == GameStates.active, scheduled_games) just_finished_games = filter(lambda g: g.state == GameStates.finished, active_games) for g in imminent_games: if len(g.players) == 0: banter = "big game ({0}) about to kick off at {1}, no one wants to play?".format( g.description, when_str(g.when)) else: banter = self.load_banter( "kickoff", { "s": g.pretty_players(), "t": when_str(g.when), "d": g.description, }) suggested_teams = suggest_teams(g) if suggested_teams: banter += "\n{}".format(suggested_teams) nextgame = self.game_straight_after(g, threshold=GAME_FOLLOWON_TIME) if nextgame: nextgame_banter = self.load_banter( "follow-on", { "s": format_user(nextgame.creator), "d": nextgame.description, "c": nextgame.channel, }) banter += "\n({})".format(nextgame_banter) self.send_message(banter, to_channel=g.channel) for g in just_finished_games: msg = vote_message(g) if msg: self.update_game_message(g, msg)
def handle_game_reaction(self, game, reacting_user, emoji, removed): now = datetime.datetime.today() join_emojis = ["+1", "thumbsup", "plus1" "heavy_plus_sign"] if emoji in join_emojis: if now < game.endtime(): if removed: self.remove_user_from_game(reacting_user, game, subtle_message=True) else: self.add_user_to_game(reacting_user, game, subtle_message=True) else: self.update_game_message( game, "game's over {}, can't {}".format( format_user(reacting_user), "flyout" if removed else "flyin"))
def handle_command(self, message, command, rest): if len(command.strip()) == 0 and len(rest) == 0: self.send_dialect_reply(message) return if command.lower() in PS4Bot_commands: PS4Bot_commands[command.lower()][1](self, message, rest) return # attempt to parse a big game, if unsuccessful, show usage: if not self.maybe_new_game(message.user, message.channel.name, command + " " + rest): self.send_message(( ":warning: Hew {}, here's what I listen to: `{} {}`, " + "or try adding a :+1: to a game invite (or typing `+:+1:` as a response)." ).format( format_user(message.user), self.botname, "/".join(command for command, (show, _) in PS4Bot_commands.iteritems() if show)))
def replace_user(match): id = match.group(1) name = lookup_user(self.slackconnection, id) if name: return format_user(name) return match.group(0)
def scrub_entry(player, i): return ":{}: {}".format(number_emojis[i], format_user(player))
def send_thanks_reply(self, message, rest): reply = self.load_banter("thanked", {"s": format_user(message.user)}, for_user=message.user, in_channel=message.channel.name) self.send_message(reply)
def send_dialect_reply(self, message): reply = self.load_banter("dialect", {"u": format_user(message.user)}, for_user=message.user, in_channel=message.channel.name) self.send_message(reply)
def maybe_scuttle_game(self, message, rest): tokens = rest.split(" ") if len(tokens) >= 3 and tokens[-2] == "to": str_to = tokens[-1] str_from = " ".join(tokens[:-2]) elif len(tokens) == 1: str_from = None str_to = tokens[0] else: self.send_scuttle_usage() return try: when_desc = None when_to = parse_time(str_to) except ValueError: self.send_scuttle_usage() return try: when_from = parse_time(str_from) if str_from else None except ValueError: when_desc = str_from if when_desc: game_to_move = None for g in self.games: if g.description == when_desc: if game_to_move: self.send_message( ":warning: scrubadubdub - there's multiple games called \"{}\"" .format(when_desc)) return game_to_move = g elif when_from: # we've been given an explicit game to move game_to_move = self.game_occuring_at(when_from) if not game_to_move: self.send_game_not_found(when_from, message.user) return else: # no explicit game to move, if the user has just one, move it created_games = self.games_created_by(message.user) if len(created_games) != 1: self.send_too_many_owned_games_message(created_games, "scuttle") return game_to_move = created_games[0] if game_to_move.creator != message.user: self.send_message( ":warning: scrubadubdub, only {} can scuttle the {} {}".format( format_user(game_to_move.creator), when_str(game_to_move.when), game_to_move.description)) return game_in_slot = self.game_overlapping(when_to, game_to_move.play_time, ignoring=game_to_move) if game_in_slot: self.send_duplicate_game_message(game_in_slot) return old_when = game_to_move.when banter = self.load_banter("created", {"s": format_user(message.user)}, for_user=message.user, in_channel=game_to_move.channel) game_to_move.update_when(when_to, banter) self.update_game_message( game_to_move, "moved by {} to {}".format(format_user(message.user), when_str(when_to))) pretty_players = game_to_move.pretty_players(with_creator=False) self.send_message( ":alarm_clock: {}{} moved from {} to {} by {}".format( pretty_players + " - " if len(pretty_players) else "", game_to_move.description, when_str(old_when), when_str(when_to), format_user(message.user))) self.save()