# cmd_discord.py import discord from discord.ext import commands from typing import Optional from discord import app_commands from cmd_common import common_commands as cc from modules.permissions import has_permission from modules.utility import handle_help_command import globals import os import json import random # Retrieve primary guild info if needed (for logging or other purposes) primary_guild = globals.constants.primary_discord_guild() # e.g., {"object": discord.Object(id=1234567890), "id": 1234567890} def setup(bot): """ Attach commands to the Discord bot and register textual commands. This function loads configuration data, then registers several commands: - sync_commands: (OWNER ONLY) Manually syncs the bot’s command tree. - available: Lists commands available to the user. - help: Provides detailed help information for commands. - greet: Makes the bot greet the user. - ping: Checks the bot's uptime and latency. - howl: Makes the bot attempt a howl. - hi: A development command to test permission handling. - quote: Interact with the quotes system (multiple subcommands supported). All commands here are invoked with your text command prefix (e.g. "!") """ config_data = globals.load_config_file() @bot.command(name='funfact', aliases=['fun-fact']) async def funfact_command(ctx, *keywords): # keywords is a tuple of strings from the command arguments. fact = cc.get_fun_fact(list(keywords)) # Reply to the invoking user. await ctx.reply(fact) # ------------------------------------------------------------------------- # TEXTUAL COMMAND: quote # ------------------------------------------------------------------------- @bot.command(name="quote") async def cmd_quote_text(ctx, *, arg_str: str = ""): """ Handle the '!quote' command with multiple subcommands. Usage: - !quote -> Retrieves a random (non-removed) quote. - !quote -> Retrieves a specific quote by its ID. - !quote add -> Adds a new quote and replies with its quote number. - !quote remove -> Removes the specified quote. - !quote restore -> Restores a previously removed quote. - !quote info -> Displays stored information about the quote. - !quote search [keywords] -> Searches for the best matching quote. - !quote latest -> Retrieves the latest (most recent) non-removed quote. """ if not globals.init_db_conn: await ctx.reply("Database is unavailable, sorry.") return args = arg_str.split() if arg_str else [] globals.log(f"'quote' command initiated with arguments: {args}", "DEBUG") result = await cc.handle_quote_command( db_conn=globals.init_db_conn, is_discord=True, ctx=ctx, args=args, get_twitch_game_for_channel=None ) globals.log(f"'quote' result: {result}", "DEBUG") if hasattr(result, "to_dict"): await ctx.reply(embed=result) else: await ctx.reply(result) # ------------------------------------------------------------------------- # TEXTUAL COMMAND: howl # ------------------------------------------------------------------------- @bot.command(name="howl") async def cmd_howl_text(ctx): """ Handle the '!howl' command. Usage: - !howl -> Attempts a howl. - !howl stat -> Looks up howling stats for a user (defaults to self if not provided). """ result = cc.handle_howl_command(ctx) await ctx.reply(result) # ------------------------------------------------------------------------- # TEXTUAL COMMAND: help # ------------------------------------------------------------------------- @bot.command(name="help") async def cmd_help_text(ctx, *, command: str = ""): """ Get help information about commands. Usage: - !help -> Provides a list of all commands with brief descriptions. - !help -> Provides detailed help information for the specified command. """ result = await handle_help_command(ctx, command, bot, is_discord=True) await ctx.reply(result) # ------------------------------------------------------------------------- # SLASH COMMAND: help # ------------------------------------------------------------------------- @bot.tree.command(name="help", description="Get information about commands", guild=primary_guild["object"]) @app_commands.describe(command="The command to get help info about. Defaults to 'help'") async def cmd_help_slash(interaction: discord.Interaction, command: Optional[str] = ""): result = await handle_help_command(interaction, command, bot, is_discord=True) await interaction.response.send_message(result) # ------------------------------------------------------------------------- # TEXTUAL COMMAND: ping # ------------------------------------------------------------------------- @bot.command(name="ping") async def cmd_ping_text(ctx): """ Check the bot's uptime and latency. Usage: - !ping -> Returns the bot's uptime along with its latency in milliseconds. """ result = cc.ping() latency = round(float(bot.latency) * 1000) result += f" (*latency: {latency}ms*)" await ctx.reply(result) # ------------------------------------------------------------------------- # Final logging: list registered commands. # ------------------------------------------------------------------------- try: command_names = [cmd.name for cmd in bot.commands] # Extract command names globals.log(f"Registering commands for Discord: {command_names}", "DEBUG") except Exception as e: globals.log(f"An error occurred while printing registered commands for Discord: {e}", "WARNING")