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) )
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"]) )
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, )
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"]) )
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("🧩")