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

Some commands cause bot to redeclare commands on every launch #851

Open
jiamingc opened this issue Jan 23, 2024 · 0 comments
Open

Some commands cause bot to redeclare commands on every launch #851

jiamingc opened this issue Jan 23, 2024 · 0 comments

Comments

@jiamingc
Copy link

Description

If a bot has a slash command that meets these criteria, then the bot will redeclare all commands on every launch:

  1. The command is in a command group
  2. The command has no options

This is adding some friction to my development flow, due to the rate limit on command registration API.

Reproduction

import os

import hikari
import tanjun

TOKEN = os.environ["TOKEN"]
GUILD_ID = int(os.environ["GUILD_ID"])

test_group = tanjun.slash_command_group("test", "test")

@test_group.add_command
@tanjun.as_slash_command("test", "asdf")
async def test(ctx: tanjun.abc.SlashContext) -> None:
    await ctx.respond("test")

component = tanjun.Component().add_slash_command(test_group)

bot = hikari.GatewayBot(token=TOKEN)
tanjun.Client.from_gateway_bot(
    bot, declare_global_commands=GUILD_ID
).add_component(component)

bot.run()

Every time I run this bot, I get the log line:

I 2024-01-22 19:16:39,429 hikari.tanjun.clients: Bulk declaring 1 guild <GUILD_ID> application commands

If I add an option to test, the bot will instead skip the command declaration after the first run:

I 2024-01-22 19:16:43,572 hikari.tanjun.clients: Skipping bulk declare for guild <GUILD_ID> application commands since they're already declared

Cause

When Tanjun starts up, it queries Discord for the currently declared commands to see if anything has changed:

Tanjun/tanjun/clients.py

Lines 1540 to 1541 in 25413f2

registered_commands = await self._rest.fetch_application_commands(application, guild=guild)
if _internal.cmp_all_commands(registered_commands, builders):

The query will return something like this for test_group in the example above:

{
  "name": "test_group",
  "options": [
    {
      "name": "test",
      "options": None,
      ...
    },
  ],
  ...
}

The internal command builder test_group something like this instead:

{
  "name": "test_group",
  "options": [
    {
      "name": "test",
      "options": [],
      ...
    },
  ],
  ...
}

The options for the two representations will eventually compared in this line:

return len(opts) == len(other_opts) and all(itertools.starmap(operator.eq, zip(opts, other_opts)))

Since they're compared directly, the discrepancy in the subcommand option representation isn't taken into account, and the check fails.

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

1 participant