Example #1
0
 async def puzzle(
     self,
     ctx,
     *,
     channel_or_query: typing.Optional[typing.Union[discord.TextChannel, str]]
 ):
     """Display current state of a puzzle.
     If no channel is provided, we default to the current puzzle channel."""
     puzzle = puzzboss_interface.SQL.get_puzzle_for_channel_fuzzy(
         ctx, channel_or_query, bot=self.bot
     )
     if puzzle:
         embed = build_puzzle_embed(puzzle, ctx.guild)
         await ctx.send(embed=embed)
         return
     if channel_or_query:
         await ctx.send(
             "Sorry, I couldn't find a puzzle for that query. "
             + "Please try again.\n"
             + "Usage: `!puzzle [query]`"
         )
         return
     if not discord_info.is_puzzle_channel(ctx.channel):
         await ctx.send(
             (
                 "`!puzzle` without any arguments tries to show the status "
                 + "of the puzzle channel you're currently in, "
                 + "but {0.mention} isn't recognized as a puzzle channel "
                 + "in Puzzleboss.\n"
                 + "Either go to that puzzle's channel and run `!puzzle` "
                 + "there, or run `!puzzle [query]`, with some substring "
                 + "or regex query for the puzzle's name."
             ).format(ctx.channel)
         )
Example #2
0
 async def joinus(self, ctx):
     """Invite folks to work on the puzzle on your voice channel.
     If you have joined one of the table voice channels, you can use
     this command to set that table as the solve location for this puzzle,
     and announce as such within the puzzle channel, so everyone can see it.
     """
     if not discord_info.is_puzzle_channel(ctx.channel):
         await ctx.send("Sorry, the !joinus command only works in puzzle channels.")
         return
     table = discord_info.get_table(ctx.author)
     puzzle = puzzboss_interface.SQL.get_puzzle_for_channel(
         ctx.channel, bot=self.bot
     )
     if not table:
         xyz = ""
         if puzzle["xyzloc"]:
             xyz = "\n\nFolks are already working on this puzzle in {}!".format(
                 xyzloc_mention(ctz.guild, puzzle["xyzloc"])
             )
         await ctx.send(
             "Sorry, you need to join one of the table voice chats "
             + "before you can use the !joinus command."
             + xyz
         )
         return
     if not puzzle:
         await ctx.send(
             "Sorry, I can't find this channel in the "
             + "Puzzleboss database, so !joinus won't work."
         )
         return
     await puzzboss_interface.REST.post(
         "/puzzles/{id}/xyzloc".format(**puzzle),
         {"xyzloc": table.name},
     )
     if discord_info.is_puzzboss(ctx.author):
         return
     solver = puzzboss_interface.SQL.get_solver_from_member(ctx.author, bot=self.bot)
     if not solver:
         return
     response = await puzzboss_interface.REST.post(
         "/solvers/{0}/puzz".format(solver["id"]),
         {"puzz": puzzle["id"]},
     )
     if response.status != 200:
         logging.error(
             "Failed to mark {} as working on {}".format(
                 solver["name"], puzzle["name"]
             )
         )
         return
     logging.info(
         "Marked {} as working on {}".format(solver["name"], puzzle["name"])
     )
Example #3
0
    def get_puzzle_for_channel_fuzzy(ctx, channel_or_query, bot=None):
        if not channel_or_query:
            if not is_puzzle_channel(ctx.channel):
                return None
            return SQL.get_puzzle_for_channel(ctx.channel, bot=bot)

        if isinstance(channel_or_query, discord.TextChannel):
            channel = channel_or_query
            return SQL.get_puzzle_for_channel(channel, bot=bot)

        query = channel_or_query
        try:
            regex = re.compile(query, re.IGNORECASE)
        except Exception as e:
            regex = re.compile(r"^$")
        query = query.replace(" ", "").lower()

        def puzzle_matches(name):
            if not name:
                return False
            if query in name.lower():
                return True
            return regex.search(name) is not None

        connection = SQL._get_db_connection(bot=bot)
        with connection.cursor() as cursor:
            cursor.execute(
                """
                SELECT
                    id,
                    name,
                    roundname AS round_name,
                    puzzle_uri,
                    drive_uri,
                    chat_channel_id AS channel_id,
                    status,
                    answer,
                    xyzloc,
                    comments,
                    cursolvers
                FROM puzzle_view
                """,
            )
            puzzles = cursor.fetchall()
            return next(
                (puzzle for puzzle in puzzles if puzzle_matches(puzzle["name"])),
                None,
            )
Example #4
0
    async def handle_workingon(self, payload):
        if payload.user_id == self.bot.user.id:
            return
        if not payload.guild_id:
            return

        emoji = str(payload.emoji)
        if emoji != "🧩":
            return

        guild = self.bot.get_guild(payload.guild_id)
        if not guild:
            return

        channel = guild.get_channel(payload.channel_id)

        message = await channel.fetch_message(payload.message_id)
        if not message:
            return
        if message.author != self.bot.user:
            return
        if "please click the 🧩 reaction" not in message.content.lower():
            return

        member = payload.member
        if not member:
            return
        if not discord_info.is_puzzle_channel(channel):
            return
        puzzle = puzzboss_interface.SQL.get_puzzle_for_channel(channel, bot=self.bot)
        if not puzzle:
            return
        solver = puzzboss_interface.SQL.get_solver_from_member(member, bot=self.bot)
        if not solver:
            return
        await puzzboss_interface.REST.post(
            "/solvers/{0}/puzz".format(solver["id"]),
            {"puzz": puzzle["id"]},
        )
        logging.info(
            "Marked {} as working on {}".format(solver["name"], puzzle["name"])
        )
Example #5
0
 async def here(self, ctx):
     """Lets folks know this is the puzzle you're working on now."""
     if not discord_info.is_puzzle_channel(ctx.channel):
         await ctx.send("Sorry, the !here command only works in puzzle channels.")
         return
     puzzle = puzzboss_interface.SQL.get_puzzle_for_channel(
         ctx.channel, bot=self.bot
     )
     solver = puzzboss_interface.SQL.get_solver_from_member(ctx.author, bot=self.bot)
     if not solver:
         await ctx.send(
             "Sorry, we can't find your wind-up-birds.org account. Please talk to "
             + "a @Role Verifier, then try again."
         )
         return
     response = await puzzboss_interface.REST.post(
         "/solvers/{0}/puzz".format(solver["id"]),
         {"puzz": puzzle["id"]},
     )
     if response.status != 200:
         await ctx.send(
             "Sorry, something went wrong. "
             + "Please use the Puzzleboss website to select your puzzle."
         )
         return
     logging.info(
         "Marked {} as working on {}".format(solver["name"], puzzle["name"])
     )
     message = await ctx.send(
         (
             "Thank you, {0.mention}, for marking yourself as working on this puzzle.\n"
             + "Everyone else: please click the 🧩 reaction "
             + "on this message to also indicate that you're working on this puzzle."
         ).format(ctx.author)
     )
     await message.add_reaction("🧩")