#Any way to import commands from a folder without breaking script?

1 messages · Page 1 of 1 (latest)

sinful violetBOT
#

Hey! Once your issue is solved, press the button below to close this thread!

compact moth
#

Hi all!

Just so you know, I'm new to Discord bot development and this is my first Discord bot. I organised the commands inside a "commands" folder but when it comes to using them they throw a KeyError which I have not been able to find a fix for.

main.py

import os

from interactions import Client, Intents, listen

bot = Client(
    token="REDACTED",
    intents=Intents.DEFAULT,
)
guild_ids = [REDACTED]
colors = [
    0x2ECC71,  # Green
    0x3498DB,  # Blue
    0xE74C3C,  # Red
    0xF1C40F,  # Yellow
    0x9B59B6,  # Purple
]

# List all command files in the "commands" folder
command_files = [file for file in os.listdir("commands") if file.endswith(".py")]

# Import each command module and pass the bot instance
for file in command_files:
    module_name = file[:-3]  # Remove the ".py" extension
    command_module = __import__(f"commands.{module_name}", fromlist=[module_name])
    command_module.setup(bot, colors)  # Pass the bot instance to the command module


@listen()
async def on_ready():
    print(f"{bot.user} is Ready | Owner: {bot.owner}")


bot.start()

An example command, commands/ping.py

import random
import datetime

from interactions import Embed, slash_command, SlashContext


def setup(bot, colors):
    @slash_command(name="ping", description="Pong!")
    async def ping(ctx: SlashContext):
        embed = Embed(
            title="Ping Test",
            description=f":ping_pong: Pong! ({bot.latency * 1000}ms)",
            color=random.choice(colors),
            timestamp=datetime.datetime.now(),
        )
        await ctx.send(embeds=embed)

Error thrown upon usage:

Task exception was never retrieved
future: <Task finished name='Task-52' coro=<Client._dispatch_interaction() done, defined at C:\Users\zeesh\AppData\Local\Programs\Python\Python310\lib\site-packages\interactions\client\client.py:1773> exception=KeyError('ping')>
Traceback (most recent call last):
  File "C:\Users\zeesh\AppData\Local\Programs\Python\Python310\lib\site-packages\interactions\client\client.py", line 1798, in _dispatch_interaction
    if ctx.command:
  File "C:\Users\zeesh\AppData\Local\Programs\Python\Python310\lib\site-packages\interactions\models\internal\context.py", line 329, in command
    return self.client._interaction_lookup[self._command_name]
KeyError: 'ping'
winter valve
#

That is not how you use different files, use extensions!

sinful violetBOT
#

Extensions are an easy way of organzing and scaling your bot into different files. Check out this guide for more information.

compact moth
#

Ah okay sure, testing that right now.

compact moth
# winter valve That is not how you use different files, use extensions!

So I tried to use this with the ping command but I ended up getting the same error.

For context my main.py is now:

import os, random, datetime, requests, glob

from importlib import import_module
from commands.data.plugins import failedEmbed
from interactions import (
    Client,
    Intents,
    listen,
    Embed,
    slash_command,
    modal_callback,
    SlashContext,
    Modal,
    ModalContext,
    ShortText,
    slash_option,
    OptionType,
    ParagraphText,
) # I'll remove the unused ones later

bot = Client(
    token="REDACTED",
    intents=Intents.DEFAULT | Intents.GUILDS,
)
guild_ids = [REDACTED]

command_filenames = glob.glob("commands/*.py")
command_names = [
    filename.removesuffix(".py").replace("/", ".") for filename in command_filenames
]
for command in command_names:
    bot.load_extension(command)


@listen()
async def on_ready():
    print(f"{bot.user} is Ready | Owner: {bot.owner}\n")

    for guild_id in guild_ids:
        server = bot.get_guild(guild_id)
        server_name = server.name if server else "Unknown Server"
        # Print server name and member count
        print(f"Server: {server_name}")


bot.start()

And my commands/ping.py is now:

import random
import datetime

from interactions import Embed, slash_command, SlashContext


def setup(bot):
    @slash_command(name="ping", description="Pong!")
    async def ping(ctx: SlashContext):
        embed = Embed(
            title="Ping Test",
            description=f":ping_pong: Pong! ({bot.latency * 1000}ms)",
            color=random.choice(colors),
            timestamp=datetime.datetime.now(),
        )
        await ctx.send(embeds=embed)

I'm still confused on how to properly use this as upon running the command from the bot the same error happens.

#

Just wondering, do I need to add classes for each extension as shown in the docs?

winter valve
#

yes

#

you need to have subclasses of Extension, not this setup() function, that will not work

compact moth
#

Got it.

#

Thank you for the help