Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Properly registering a slash command with the API #9

Closed
hpenney2 opened this issue Dec 16, 2020 · 3 comments
Closed

Properly registering a slash command with the API #9

hpenney2 opened this issue Dec 16, 2020 · 3 comments

Comments

@hpenney2
Copy link
Contributor

hpenney2 commented Dec 16, 2020

Hi, I recently started using this extension to try out Discord's new slash commands feature. I noticed my commands weren't showing up in the Discord client when entering / into the chat box, so I went through the issues and found #3 and #4.

Leastrio said in #4:

You need to either use the libs built in way or send a post request to discords api, https://discord.com/developers/docs/interactions/slash-commands#create-guild-application-command

I noticed the lib has discord_slash.utils.manage_commands which contains methods for adding slash commands with the Discord API, I assume this is what Leastrio was referring to. However, I don't understand how to use this in junction with my slash.slash() decorated functions or really just the lib in general. This leads to me to have questions like, "How do I link a command to a function? What's the purpose of slash.slash()'s parameters if they're seemingly overwritten by discord_slash.utils.manage_commands.add_slash_command?"

All help is appreciated, thank you!

@hpenney2 hpenney2 changed the title Properly registering a slash command Properly registering a slash command with the API Dec 16, 2020
@hpenney2
Copy link
Contributor Author

hpenney2 commented Dec 16, 2020

If you're curious, here's my code at the moment. I haven't implemented any calls to discord_slash.utils.manage_commands.add_slash_command or anything similar yet because I still don't understand how it works. (that's why I made this issue, after all)

import discord
import logging
from discord.ext import commands
from discord_slash import SlashCommand
from discord_slash.model import SlashContext
from time import sleep

logging.basicConfig(level=logging.INFO, format="[%(asctime)s] %(levelname)s %(name)s | %(message)s")

bot = commands.Bot(command_prefix="!", intents=discord.Intents.default())
slash = SlashCommand(bot)


allowedIds = [396395639791026196]


@slash.slash(name="test", description="Sends a test message.", guild_ids=allowedIds)
async def _test(ctx: SlashContext):
    embed = discord.Embed(title="Here's an embed.",
                          color=0xeb4034)
    await ctx.send(3, content="This is a test. Only you can see this.",
                   embeds=[embed], hidden=True)


@bot.event
async def on_ready():
    print(f"Logged in as {bot.user.name} with ID {bot.user.id}")
    print(f"{len(slash.commands)} command(s) are registered.")


sleep(0.5)
bot.run("token")

@eunwoo1104
Copy link
Contributor

Well, slash() decorator and discord_slash.utils.manage_commands.add_slash_command is completely different.
slash() Decorator is for registering command in your bot, and add_slash_command is for registering command at Discord API. Since only using slash() decorator doesn't register your command to Discord (for now), utility function is created to help people registering commands to Discord API.

@hpenney2
Copy link
Contributor Author

hpenney2 commented Dec 17, 2020

After I figured out how the registering system worked, I made a short script that contains functions for auto-registering commands. I have this in slashutils.py, then I just import it to my main script and call addToAPI when on_ready is fired, and call removeFromAPI on my stop command. This could possibly be used to develop the auto-register feature for this extension.

import discord_slash
import discord_slash.utils.manage_commands
import aiohttp
from typing import Tuple


async def addToAPI(SlashCommand: discord_slash.SlashCommand, botId, botToken: str):
    """Adds all commands that are registered in SlashCommand to Discord."""
    commands = SlashCommand.commands

    print("Adding commands to the API...")
    if len(commands) <= 0:
        print("No commands are registered, cancelled.")
        return

    for cmd, info in commands.items():
        if info["guild_ids"] is not None:
            for guild in info["guild_ids"]:
                print(f"Adding command '{cmd}' to guild {guild}")
                await discord_slash.utils.manage_commands.add_slash_command(botId, botToken, guild, cmd,
                                                                            info["description"], info["api_options"])
        else:
            print(f"Adding global command '{cmd}'")
            await discord_slash.utils.manage_commands.add_slash_command(botId, botToken, None, cmd,
                                                                        info["description"], info["api_options"])
    print("Done adding commands.")


async def _getCommands(botId, botToken: str, guildsWithCommands=None) -> Tuple[list, dict]:
    """Retrives all global and guild specific commands that are registered on Discord."""
    if guildsWithCommands is None:
        guildsWithCommands = []
    url = f"https://discord.com/api/v8/applications/{botId}/commands"
    async with aiohttp.ClientSession() as session:
        async with session.get(url, headers={"Authorization": f"Bot {botToken}"}) as resp:
            globalCmds = await resp.json()
        guildCmds = {}
        for guildId in guildsWithCommands:
            url = f"https://discord.com/api/v8/applications/{botId}/guilds/{guildId}/commands"
            async with session.get(url, headers={"Authorization": f"Bot {botToken}"}) as resp:
                guildCmds[guildId] = await resp.json()
    return globalCmds, guildCmds


async def removeFromAPI(botId, botToken: str, guildsWithCommands: list):
    """Removes all commands that are registered to the bot on Discord."""
    globalCmds, guildCmds = await _getCommands(botId, botToken, guildsWithCommands)

    print("Removing commands to the API...")
    if len(globalCmds) <= 0 and len(guildCmds) <= 0:
        print("No commands are registered, cancelled.")
        return

    for guild, cmds in guildCmds.items():
        for cmd in cmds:
            print(f"Removing command '{cmd['name']}' from guild {guild}")
            await discord_slash.utils.manage_commands.remove_slash_command(botId, botToken, guild, cmd["id"])

    for cmd in globalCmds:
        print(f"Removing global command '{cmd['name']}'")
        await discord_slash.utils.manage_commands.remove_slash_command(botId, botToken, None, cmd["id"])
    print("Done removing commands.")

@ghost ghost mentioned this issue Mar 13, 2021
i0bs pushed a commit that referenced this issue Dec 20, 2021
* test #1

* test #2

* test #3

* test #4

* test #5

* test #6

* test #7

* test #8

* test #9

* test #10

* test #11

* test #12

* almost final

* final formatted
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants