# cmd_discord.py from discord.ext import commands from cmd_common import common_commands as cc from modules.permissions import has_permission from modules.utility import handle_help_command from modules.utility import monitor_cmds def setup(bot, db_conn=None, log=None): """ Attach commands to the Discord bot, store references to db/log. """ @monitor_cmds(bot.log) @bot.hybrid_command(name="available", description="List commands available to you") async def available(ctx): available_cmds = [] for command in bot.commands: try: # This will return True if the command's checks pass for the given context. if await command.can_run(ctx): available_cmds.append(command.name) except commands.CheckFailure: # The command's checks did not pass. pass except Exception as e: # In case some commands fail unexpectedly during checks. bot.log(f"Error checking command {command.name}: {e}", "ERROR") if available_cmds: await ctx.send("Available commands: " + ", ".join(sorted(available_cmds))) else: await ctx.send("No commands are available to you at this time.") @monitor_cmds(bot.log) @bot.hybrid_command(name="greet", description="Make me greet you") async def cmd_greet(ctx): result = cc.greet(ctx.author.display_name, "Discord") await ctx.send(result) @monitor_cmds(bot.log) @bot.hybrid_command(name="ping", description="Check my uptime") async def cmd_ping(ctx): result = cc.ping() await ctx.send(result) @monitor_cmds(bot.log) @bot.hybrid_command(name="howl", description="Attempt a howl") async def cmd_howl(ctx): response = cc.handle_howl_command(ctx) await ctx.send(response) # @monitor_cmds(bot.log) # @bot.hybrid_command(name="reload", description="Dynamically reload commands (INOP)") # async def cmd_reload(ctx): # """ Dynamically reloads Discord commands. """ # try: # import cmd_discord # import importlib # importlib.reload(cmd_discord) # cmd_discord.setup(bot) # await ctx.send("Commands reloaded on first try!") # except Exception as e: # try: # await bot.reload_extension("cmd_discord") # await ctx.send("Commands reloaded on second try!") # except Exception as e: # try: # await bot.unload_extension("cmd_discord") # await bot.load_extension("cmd_discord") # await ctx.send("Commands reloaded on third try!") # except Exception as e: # await ctx.send(f"Fallback reload failed: {e}") @monitor_cmds(bot.log) @bot.hybrid_command(name="hi", description="Dev command for testing permissions system") async def cmd_hi(ctx): user_id = str(ctx.author.id) user_roles = [role.name.lower() for role in ctx.author.roles] # Normalize to lowercase if not has_permission("hi", user_id, user_roles, "discord"): await ctx.send("You don't have permission to use this command.") return await ctx.send("Hello there!") # @monitor_cmds(bot.log) # @bot.hybrid_command(name="quote", description="Interact with the quotes system") # async def cmd_quote(ctx, query: str = None): # """ # !quote # !quote add # !quote remove # !quote # """ # if not bot.db_conn: # return await ctx.send("Database is unavailable, sorry.") # args = query.split() # # Send to our shared logic # await cc.handle_quote_command( # db_conn=bot.db_conn, # log_func=bot.log, # is_discord=True, # ctx=ctx, # args=list(args), # get_twitch_game_for_channel=None # None for Discord # ) @monitor_cmds(bot.log) @bot.hybrid_group(name="quote", description="Interact with the quotes system", with_app_command=True) async def cmd_quote(ctx, query: str = None): """ Usage: !quote -> get a random quote !quote -> get a specific quote by number As a slash command, leave the query blank for a random quote or type a number. """ if not bot.db_conn: return await ctx.send("Database is unavailable, sorry.") # Only process the base command if no subcommand was invoked. # When query is provided, split it into arguments (for a specific quote lookup). args = query.split() if query else [] await cc.handle_quote_command( db_conn=bot.db_conn, log_func=bot.log, is_discord=True, ctx=ctx, args=args, get_twitch_game_for_channel=None # None for Discord ) @cmd_quote.command(name="add", description="Add a quote") async def cmd_quote_add(ctx, *, text: str): """ Usage: !quote add As a slash command, type /quote add text: """ if not bot.db_conn: return await ctx.send("Database is unavailable, sorry.") args = ["add", text] await cc.handle_quote_command( db_conn=bot.db_conn, log_func=bot.log, is_discord=True, ctx=ctx, args=args, get_twitch_game_for_channel=None ) @cmd_quote.command(name="remove", description="Remove a quote by number") async def cmd_quote_remove(ctx, id: int): """ Usage: !quote remove As a slash command, type /quote remove id: """ if not bot.db_conn: return await ctx.send("Database is unavailable, sorry.") args = ["remove", str(id)] await cc.handle_quote_command( db_conn=bot.db_conn, log_func=bot.log, is_discord=True, ctx=ctx, args=args, get_twitch_game_for_channel=None ) @monitor_cmds(bot.log) @bot.hybrid_command(name="help", description="Get information about commands") async def cmd_help(ctx, cmd_name: str = None): """ e.g. !help !help quote """ await handle_help_command(ctx, cmd_name, bot, is_discord=True, log_func=bot.log) ###################### # The following log entry must be last in the file to verify commands loading as they should ###################### # Debug: Print that commands are being registered try: command_names = [cmd.name for cmd in bot.commands] # Extract command names bot.log(f"Registering commands for Discord: {command_names}", "DEBUG") except Exception as e: bot.log(f"An error occured while printing registered commands for Discord: {e}", "WARNING")