Example #1
0
class MyClient(discord.Client):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.boggle_game = None
        self.boggle_submission = False
        self.taskboard = None
        self.boggle_time = 150
        self.english_words = fetch_english_words("words_dictionary.json")
        self.delete_queue = []

    def string_of_boggle(self):
        def emojid_padded(face):
            place = face[0].lower()
            return f" :regional_indicator_{place}: "

        rows = ("".join(
            emojid_padded(face)
            for face in self.boggle_game.board_list()[i:i + 4])
                for i in [0, 4, 8, 12])
        return ". \n" + "\n".join(rows)

    async def cancel_board(self):
        """Cancels the current board, and deletes all messages associated with it.
        For instance, the board itself is deleted."""
        self.taskboard.cancel()
        self.taskboard = None
        self.boggle_submission = False
        for msg in self.delete_queue:
            await msg.delete()
        self.delete_queue = []

    async def run_board(self, message):
        self.delete_queue.append(await message.channel.send(
            self.string_of_boggle(), delete_after=self.boggle_time))
        self.boggle_submission = True
        await asyncio.sleep(self.boggle_time)
        self.delete_queue.append(await message.channel.send(
            "Submit your answers now (you have 2 minutes)", delete_after=120))
        await asyncio.sleep(120)
        self.boggle_submission = False
        return

    async def on_message(self, message):
        if message.author.id == self.user.id:
            return

        content = message.content.lower()

        if content.startswith("$boggle"):
            args = re.split(r"\s+", content.strip())[1:]
            user_name = message.guild.get_member(
                message.author.id).display_name
            if args == ['start']:
                if self.boggle_game is None:
                    self.boggle_game = Boggle(message.author.id,
                                              self.english_words)
                    await message.channel.send(self.boggle_game.greeting())
                else:
                    await message.channel.send(
                        "There's already a running game.\
                     End that game before starting a new one.")
                return

            if args == ['join']:
                if self.boggle_game.new_player(message.author.id):
                    await message.channel.send(
                        f"Welcome to the game {user_name}")
                    return
                await message.channel.send(
                    f"{user_name}, you're already in the game.")
            if self.boggle_game is None:
                await message.channel.send("Soz bud. There ain't a game.")
                return

            if args == ['flip', 'off', 'question', 'master']:
                if self.boggle_game.gm == message.author.id:
                    await message.channel.send("Don't be rude to yourself.")
                    return

                self.boggle_game.kick_player(self.boggle_game.gm)
                self.boggle_game.gm = message.author.id
                await message.channel.send(
                    f"{message.guild.get_member(self.boggle_game.gm).display_name} is now the game master."
                )
                return

            if args == ['end']:
                self.boggle_game = None
                await message.channel.send("I have ended the game, hotshots.")
                return

            if message.author.id != self.boggle_game.gm:
                await message.channel.send("\n".join([
                    "Either your command is wrong, or you aren't the game master.",
                    "If the game master has run off, use '$boggle flip off question master' to take control"
                ]))
                return

            if args == ['roll']:

                if self.boggle_submission:
                    return

                self.boggle_game.roll()

                self.taskboard = asyncio.ensure_future(self.run_board(message))

                return

            if args == ['abort']:
                if self.taskboard is not None:
                    await self.cancel_board()
                    await message.channel.send("Current game is cancelled.")
                return

            if args == ['show']:
                await message.channel.send(self.string_of_boggle())
                return

            if args[0] == 'allow':
                self.boggle_game.allow(args[1:])
                return

            if args == ['confirm']:
                self.boggle_game.confirm()
                return

            if args == ['scores']:
                scores = self.boggle_game.scores()
                await message.channel.send("\n".join(
                    f"{message.guild.get_member(user_id).display_name}: {score}"
                    for user_id, score in scores.items()))
                return

            if args[0] == 'kick' and len(args) == 2:
                kickee_id = list(
                    filter(lambda mem: mem.display_name.lower() == args[1],
                           message.guild.members))[0].id
                self.boggle_game.kick_player(kickee_id)
                return

            if args == ['text']:
                await message.channel.send(self.boggle_game.string_of_board())
                return

        if self.boggle_submission \
            and self.boggle_game is not None \
                and self.boggle_game.is_playing(message.author.id):

            users_words = [
                word for word in re.split(r"\s+", message.content.strip())
                if word.isalpha()
            ]
            summary = self.boggle_game.input_words(message.author.id,
                                                   users_words)

            if summary is not None:

                def display(ws):
                    return ', '.join(sorted(ws))

                to_send = ".\nRESULTS\n=======\n\n"
                for p_r in summary:
                    user_id = p_r.id
                    user_name = message.guild.get_member(user_id).display_name

                    points = p_r.calculate_points()
                    name = f"{user_name}: scored {points}"
                    get_points = f"Got points for: {display(p_r.get_points_words)}" if p_r.get_points_words else None
                    others_got = f"Other people got: {display(p_r.others_got_words)}" if p_r.others_got_words else None
                    not_on_board = f"You can't even make: {display(p_r.not_on_board_words)}" if p_r.not_on_board_words else None
                    not_in_dict = f"Not in the dictionary: {display(p_r.not_english_words)}" if p_r.not_english_words else None
                    to_send += "\n".join(
                        filter(None, (name, get_points, others_got,
                                      not_on_board, not_in_dict)))
                    to_send += "\n\n\n"

                await message.channel.send(to_send)
                self.boggle_submission = False
                if self.taskboard is not None:
                    await self.cancel_board()