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

Change from many create_*_application_command requests to a single bulk_overwrite_*_application_commands request #34

Merged
31 changes: 31 additions & 0 deletions lib/nosedrum/storage.ex
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,29 @@ defmodule Nosedrum.Storage do
| {:error, :unknown_command}
| Nostrum.Api.error()

@doc """
Queues a new command to be registered under the given name or application command path. Queued commands are
added to the internal dispatch storage, and will be registered in bulk upon calling process_queue/1

If any command already exists, it will be overwritten.

## Return value
Returns `:ok` if successful, and `{:error, reason}` otherwise.
"""
@callback queue_command(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should update the documentation for this to read that it adds the command to the internal dispatch storage, but does not yet send it to Discord, and also that process_queued_commands should be used once all desired commands have been added.

Copy link
Contributor Author

@kshannoninnes kshannoninnes Apr 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be happy to. I'm new to contributing to open source, and relatively new to elixir compared to you guys, so if there's any steps other than just updating the doc comments, let me know.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, just updating the doc comment would be enough 🙂

name_or_path :: String.t() | application_command_path,
command_module :: module,
name_or_pid
) :: :ok | {:error, Nostrum.Error.ApiError.t()}

@doc """
Add a new command under the given name or application command path.

If the command already exists, it will be overwritten.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we document here that when many commands are being registered, it is recommended to use queue_command and process_queue_commands instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good idea.


When adding many commands, it is recommended to use queue_command, and to call process_queue once all
commands are queued for registration.

## Return value
Returns `:ok` if successful, and `{:error, reason}` otherwise.
"""
Expand All @@ -115,6 +133,19 @@ defmodule Nosedrum.Storage do
name_or_pid
) :: :ok | {:error, Nostrum.Error.ApiError.t()}

@doc """
Register all currently queued commands to discord, making them available for use

Global commands can take up to 1 hour to be made available. Guild commands are available immediately.

## Return value
Returns `:ok` if successful, and `{:error, reason}` otherwise.
"""
@callback process_queue(
scope :: command_scope,
name_or_pid
) :: :ok | {:error, Nostrum.Error.ApiError.t()}

@doc """
Responds to an Interaction with the given `t:Nosedrum.ApplicationCommand.response/0`.

Expand Down
55 changes: 55 additions & 0 deletions lib/nosedrum/storage/dispatcher.ex
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,26 @@ defmodule Nosedrum.Storage.Dispatcher do
end
end

@impl true
def process_queue(scope, id \\ __MODULE__) do
GenServer.call(id, {:process_queue, scope})
end

@impl true
def queue_command(path, command, id \\ __MODULE__) do
command_name =
if is_binary(path) do
path
else
path
|> Enum.take(1)
|> List.first()
|> unwrap_key()
end

GenServer.call(id, {:queue, command_name, command})
end

@impl true
def add_command(path, command, scope, id \\ __MODULE__) do
payload = build_payload(path, command)
Expand Down Expand Up @@ -76,6 +96,41 @@ defmodule Nosedrum.Storage.Dispatcher do
{:ok, init_arg}
end

def handle_call({:process_queue, :global}, _from, commands) do
command_list =
Enum.map(commands, fn {p, c} ->
build_payload(p, c)
end)

case Nostrum.Api.bulk_overwrite_global_application_commands(command_list) do
{:ok, _} = response ->
{:reply, response, commands}

error ->
{:reply, {:error, error}, commands}
end
end

def handle_call({:process_queue, guild_id}, _from, commands) do
command_list =
Enum.map(commands, fn {p, c} ->
build_payload(p, c)
end)

case Nostrum.Api.bulk_overwrite_guild_application_commands(guild_id, command_list) do
{:ok, _} = response ->
{:reply, response, commands}

error ->
{:reply, {:error, error}, commands}
end
end

@impl true
def handle_call({:queue, name, command}, _from, commands) do
{:reply, :ok, Map.put(commands, name, command)}
end

@impl true
def handle_call({:add, payload, name, command, :global}, _from, commands) do
case Nostrum.Api.create_global_application_command(payload) do
Expand Down
Loading