Example #1
0
    def add_user_to_game(self, user, game, subtle_message = False):
        try:
            game.add_player(user)
            errormsg = None
        except PlayerAlreadyPresent:
            errormsg = "you're already in the '{}' game {}".format(game.description, format_user(user))
        except GameFull:
            errormsg = ":warning: game's full, rip {}".format(format_user(user))

        if errormsg:
            if subtle_message:
                self.update_game_message(game, errormsg)
            else:
                self.send_message(errormsg)
            return

        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()
Example #2
0
    def handle_stats_request(self, message, rest):
        anchor_message = True
        channel_name = None
        year = None
        parameters = empty_parameters()

        if len(rest):
            parsed = parse_stats_request(rest)
            if not parsed:
                self.send_message(":warning: ere {}: \"stats [year] [channel]\"".format(
                    format_user(message.user)))
                return
            channel_name, year, parameters = 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

        try:
            stats = self.history.summary_stats(channel_name, year = year, parameters = parameters)

            self.update_stats_table(channel_name, stats, force_new = True, anchor_message = anchor_message)
            self.latest_stats_table[channel_name].year = year
            self.latest_stats_table[channel_name].parameters = parameters
        except OverflowError as e:
            self.send_message(":warning: overflow calculating elo stats, sort yerselves out")
Example #3
0
            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)
Example #4
0
 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)
Example #5
0
 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)
Example #6
0
    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, gametype_from_channel(channel))
        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
Example #7
0
    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, gametype_from_channel(message.channel.name))
            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()
Example #8
0
    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()
Example #9
0
 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"))
Example #10
0
    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_for_channel(message.channel.name),
                "/".join(command for command, (show, _) in PS4Bot_commands.iteritems() if show)
            ))
Example #11
0
    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)
Example #12
0
    def maybe_scuttle_game(self, message, rest):
        tokens = rest.split(" ")
        gametype = gametype_from_channel(message.channel.name)

        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, gametype)
            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, gametype, 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()
Example #13
0
 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)))