diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..4529e15 --- /dev/null +++ b/.flake8 @@ -0,0 +1,8 @@ +[flake8] +exclude = + .git, + __pycache__, + .venv, + venv, + build, + dist diff --git a/bot.py b/bot.py index b20f884..d546774 100644 --- a/bot.py +++ b/bot.py @@ -212,13 +212,8 @@ async def _safe_ctx_send(message: str) -> None: async def on_app_command_error(self, interaction: discord.Interaction, error: app_commands.AppCommandError): """Handle slash command errors.""" - # Silence unknown slash/app commands - # app_commands doesn't expose a simple CommandNotFound class in some versions, so be conservative - try: - from discord import app_commands as _appc - # In later versions, AppCommandError subclasses may exist; ignore generic NotFound-like errors - except Exception: - _appc = None + # Silence unknown slash/app commands. + # `app_commands` doesn't expose a stable CommandNotFound across versions, so be conservative. # If it's a cooldown, inform user if isinstance(error, app_commands.CommandOnCooldown): diff --git a/cogs/afk.py b/cogs/afk.py index da31df9..1820557 100644 --- a/cogs/afk.py +++ b/cogs/afk.py @@ -168,7 +168,6 @@ async def set_afk_command(self, ctx: commands.Context, *, reason: Optional[str] # Check if user is already AFK was_afk = self.is_afk(ctx.author.id) if was_afk: - old_info = self.get_afk_info(ctx.author.id) action_text = "updated" else: action_text = "set" diff --git a/cogs/codebuddy_leaderboard.py b/cogs/codebuddy_leaderboard.py index 58dd8d3..95cfd32 100644 --- a/cogs/codebuddy_leaderboard.py +++ b/cogs/codebuddy_leaderboard.py @@ -28,7 +28,6 @@ async def before_weekly_reset(self): @app_commands.command(name="codeweek", description="Show the weekly coding leaderboard") async def codeweek(self, interaction: discord.Interaction): """Display the weekly leaderboard.""" - start_time = datetime.datetime.now() try: # Immediate simple response first embed = discord.Embed( @@ -126,7 +125,6 @@ async def codeweek(self, interaction: discord.Interaction): @commands.command(name="codeweek", aliases=["cw", "cwlb"]) async def codeweek_prefix(self, ctx): """Display the weekly leaderboard.""" - start_time = datetime.datetime.now() try: # Immediate simple response first embed = discord.Embed( @@ -202,7 +200,6 @@ async def codeweek_prefix(self, ctx): @app_commands.command(name="codestreak", description="Show the coding streak leaderboard") async def codestreak(self, interaction: discord.Interaction): """Display the streak leaderboard.""" - start_time = datetime.datetime.now() try: # Immediate simple response first embed = discord.Embed( @@ -307,7 +304,6 @@ async def codestreak(self, interaction: discord.Interaction): @commands.command(name="codestreak", aliases=["cs", "cslb"]) async def codestreak_prefix(self, ctx): """Display the streak leaderboard.""" - start_time = datetime.datetime.now() try: # Immediate simple response first embed = discord.Embed( diff --git a/cogs/help.py b/cogs/help.py index 0b74a63..d274c15 100644 --- a/cogs/help.py +++ b/cogs/help.py @@ -85,8 +85,6 @@ def __init__(self, bot: commands.Bot): ) ] - # Track if we've added the Quiz category - quiz_added = False quiz_command_count = 0 # Cogs to merge into Misc (kept lightweight) @@ -292,7 +290,7 @@ def _create_category_embed(self, cog_name: str) -> discord.Embed: else: embed.description = "No commands available in this category." - embed.set_footer(text=f"Use ?helpmenu for detailed help") + embed.set_footer(text="Use ?helpmenu for detailed help") return embed # Handle special Misc category that combines multiple cogs @@ -365,7 +363,7 @@ def _create_category_embed(self, cog_name: str) -> discord.Embed: else: embed.description = "No commands available in this category." - embed.set_footer(text=f"Use ?helpmenu for detailed help") + embed.set_footer(text="Use ?helpmenu for detailed help") return embed # Find the cog (case-insensitive) @@ -452,7 +450,7 @@ def _create_category_embed(self, cog_name: str) -> discord.Embed: else: embed.description = "No commands available in this category." - embed.set_footer(text=f"Use ?helpmenu for detailed help") + embed.set_footer(text="Use ?helpmenu for detailed help") return embed diff --git a/cogs/misc.py b/cogs/misc.py index 1235fdf..7c46807 100644 --- a/cogs/misc.py +++ b/cogs/misc.py @@ -351,9 +351,7 @@ async def bug_report(self, ctx: commands.Context, *, bug: str): """Report a bug to the support server.""" # Support server channel ID SUPPORT_CHANNEL_ID = 1452739906525728828 - - # Get interaction for hybrid command - interaction = ctx.interaction or ctx + user = ctx.author guild = ctx.guild diff --git a/cogs/rockpaperscissors.py b/cogs/rockpaperscissors.py index bc9b561..487bf3c 100644 --- a/cogs/rockpaperscissors.py +++ b/cogs/rockpaperscissors.py @@ -192,7 +192,7 @@ def format_message(self, cancelled=False): winner = self.game.players[winner_id] body = f"\n{winner.mention} has **won!**\n\n" else: - body = f"Draw!\n\n" + body = "Draw!\n\n" body += f"{self.format_player_line_endgame(0)}\n{self.format_player_line_endgame(1)}" if rounds: body += f"\n\n{rounds}" diff --git a/cogs/staff_applications.py b/cogs/staff_applications.py index 1ce3ea1..a6850bd 100644 --- a/cogs/staff_applications.py +++ b/cogs/staff_applications.py @@ -487,10 +487,6 @@ async def on_interaction(self, interaction: discord.Interaction): # But to make it work, I need to respond. # If the view was attached via `add_view`, it handles it. If not, this global listener does. - parts = custom_id.split(':') - action = parts[1] - user_id = int(parts[2]) - # We need to recreate the modal logic here manually since the View instance is lost # But `send_modal` needs a Modal instance. # Checking if the interaction was already handled (if View was attached)? diff --git a/cogs/starboard.py b/cogs/starboard.py index 4e26ac8..af27f91 100644 --- a/cogs/starboard.py +++ b/cogs/starboard.py @@ -284,7 +284,7 @@ async def starboard_setup(self, ctx: commands.Context, channel: discord.TextChan embed = create_success_embed( " Starboard Setup Complete!", - f"Your modern starboard system is now active and ready to showcase your community's best messages!" + "Your modern starboard system is now active and ready to showcase your community's best messages!" ) embed.color = 0x00FF7F # Spring green embed.add_field(name=" Channel", value=channel.mention, inline=True) @@ -465,7 +465,7 @@ async def starboard_stats(self, ctx: commands.Context): embed = discord.Embed( title="⭐ Starboard Statistics", - description=f"Here's how your server is shining!", + description="Here's how your server is shining!", color=color ) @@ -916,7 +916,7 @@ async def update_starboard_message(self, message: discord.Message, star_count: i async with aiosqlite.connect(self.database_path) as db: await db.execute("DELETE FROM starred_messages WHERE starboard_message_id = ?", (starboard_msg_id,)) await db.commit() - except Exception as e: + except Exception: self.logger.exception(f"Error updating starboard message {starboard_msg_id} for original {message.id}") async def remove_starboard_message(self, starboard_msg_id: int, settings: Dict): @@ -930,7 +930,7 @@ async def remove_starboard_message(self, starboard_msg_id: int, settings: Dict): await starboard_msg.delete() except discord.NotFound: pass # Already deleted - except Exception as e: + except Exception: self.logger.exception(f"Error removing starboard message {starboard_msg_id}") async def create_starboard_embed(self, message: discord.Message, star_count: int, settings: Dict) -> discord.Embed: @@ -952,7 +952,8 @@ async def create_starboard_embed(self, message: discord.Message, star_count: int content = content[:1500] + "..." # Highlight the message by using a block quote style in the description - description = f"> {content.replace('\n', '\n> ')}" + quoted_content = content.replace("\n", "\n> ") + description = f"> {quoted_content}" embed = discord.Embed( description=description, diff --git a/cogs/tickets.py b/cogs/tickets.py index d3e8f26..86fbc53 100644 --- a/cogs/tickets.py +++ b/cogs/tickets.py @@ -180,7 +180,7 @@ async def _restore_persistent_views(self): # Fetch the message to ensure it exists try: - message = await channel.fetch_message(message_id) + await channel.fetch_message(message_id) # Create and attach the persistent view view = TicketPanelView(self) # The view is automatically registered due to persistent custom_id @@ -1090,9 +1090,9 @@ async def ticket_log_setup(self, ctx, channel: Optional[discord.TextChannel] = N embed.add_field( name="ℹ️ Information", value="Ticket actions (create, close, claim) will be logged to this channel.\n\n" - f"• **Change it:** `/ticketlog #new-channel`\n" - f"• **Disable custom:** `/ticketlog-disable`\n" - f"• **Quick disable:** Rename this channel", + "• **Change it:** `/ticketlog #new-channel`\n" + "• **Disable custom:** `/ticketlog-disable`\n" + "• **Quick disable:** Rename this channel", inline=False ) else: @@ -1265,10 +1265,10 @@ async def ticket_support_role(self, ctx, role: Optional[discord.Role] = None): ) embed.add_field( name="ℹ️ Information", - value=f"This role will be pinged when new tickets are created.\n\n" - f"• **Change it:** `/ticketsupport @new-role`\n" - f"• **Remove it:** `/ticketsupport-disable`\n" - f"• **Set via panel:** `/ticketpanel #channel @role`", + value="This role will be pinged when new tickets are created.\n\n" + "• **Change it:** `/ticketsupport @new-role`\n" + "• **Remove it:** `/ticketsupport-disable`\n" + "• **Set via panel:** `/ticketpanel #channel @role`", inline=False ) else: @@ -1670,10 +1670,10 @@ async def ticket_report_role(self, ctx, role: Optional[discord.Role] = None): ) embed.add_field( name="ℹ️ Information", - value=f"This role will be pinged when report tickets are created.\n\n" - f"• **Change it:** `/ticketreport @new-role`\n" - f"• **Remove it:** `/ticketreport-disable`\n" - f"• **Set via panel:** `/ticketpanel report_role:@role`", + value="This role will be pinged when report tickets are created.\n\n" + "• **Change it:** `/ticketreport @new-role`\n" + "• **Remove it:** `/ticketreport-disable`\n" + "• **Set via panel:** `/ticketpanel report_role:@role`", inline=False ) else: @@ -1809,10 +1809,10 @@ async def ticket_partner_role(self, ctx, role: Optional[discord.Role] = None): ) embed.add_field( name="ℹ️ Information", - value=f"This role will be pinged when partnership tickets are created.\n\n" - f"• **Change it:** `/ticketpartner @new-role`\n" - f"• **Remove it:** `/ticketpartner-disable`\n" - f"• **Set via panel:** `/ticketpanel partner_role:@role`", + value="This role will be pinged when partnership tickets are created.\n\n" + "• **Change it:** `/ticketpartner @new-role`\n" + "• **Remove it:** `/ticketpartner-disable`\n" + "• **Set via panel:** `/ticketpanel partner_role:@role`", inline=False ) else: diff --git a/utils/codebuddy_database.py b/utils/codebuddy_database.py index c87441c..e24c497 100644 --- a/utils/codebuddy_database.py +++ b/utils/codebuddy_database.py @@ -445,8 +445,6 @@ async def increment_quest_quiz_count(user_id: int): Increment the quiz count for today's quest. Returns True if quest was completed with this quiz. """ - today = datetime.date.today() - async with aiosqlite.connect(DB_PATH) as db: # Get current progress progress = await get_daily_quest_progress(user_id) @@ -481,8 +479,6 @@ async def mark_quest_voted(user_id: int): Mark that the user has voted today. Returns True if quest was completed with this vote. """ - today = datetime.date.today() - async with aiosqlite.connect(DB_PATH) as db: # Get current progress progress = await get_daily_quest_progress(user_id) diff --git a/utils/codingquestions.py b/utils/codingquestions.py index a372083..6a699d0 100644 --- a/utils/codingquestions.py +++ b/utils/codingquestions.py @@ -18,7 +18,7 @@ def get_random_question(): """Returns a non repeating randomized question""" - global _index, _question_pool + global _index if _index >= len(_question_pool): random.shuffle(_question_pool) @@ -28,6 +28,8 @@ def get_random_question(): _index += 1 return fix_question(q) + + def fix_question(question): """Randomizes options while keeping the correct answer accurate.""" # Extract answer text.