Add autocomplete callback support - #54
Conversation
Add an optional `autocomplete/1` callback to ApplicationCommand behaviour so that command modules can handle autocomplete interactions separately from regular command invocations. When an autocomplete interaction (type 4) is received, the dispatcher checks if the command module implements `autocomplete/1` and calls it instead of `command/1`. If not implemented, falls back to `command/1` for backwards compatibility.
| if function_exported?(module, :autocomplete, 1) do | ||
| module.autocomplete(interaction) | ||
| else | ||
| module.command(interaction) |
There was a problem hiding this comment.
Sorry for the late review.
If I understand this correctly, if we don't have autocomplete, we would automatically run the interaction. That seems pretty wrong, no?
We should probably report an error to Discord in that case, some form of ENOTSUP via Storage.respond, I'm just not sure what that would look like..
There was a problem hiding this comment.
Good catch, you're right — falling back to command/1 is wrong since Discord expects a type 8 response and the interaction payload shape is different anyway, so command/1 would likely crash on the focused option.
Pushed 567a294: when autocomplete/1 isn't implemented, the dispatcher now responds with an empty choices list via Storage.respond and logs a warning. That way Discord gets a valid response and the developer sees the missing callback in the logs. Updated the @callback doc to reflect the new behavior too.
There was a problem hiding this comment.
Are these the words of a clanker? Or did you type this yourself?
Falling back to command/1 was incorrect: Discord expects a type 8 (APPLICATION_COMMAND_AUTOCOMPLETE_RESULT) response to autocomplete interactions, and the interaction payload shape differs (focused option), so command/1 would likely either crash or return an invalid response. Now the dispatcher responds with an empty choices list and logs a warning when a command receives an autocomplete interaction but does not implement autocomplete/1.
Summary
Add an optional
autocomplete/1callback to theNosedrum.ApplicationCommandbehaviour, enabling command modules to handle autocomplete interactions separately from regular command invocations.Motivation
Discord sends autocomplete interactions (type 4) when a user is typing in an option with
autocomplete: true. Currently, nosedrum routes these to the samecommand/1callback as regular command invocations, forcing command modules to manually inspect the interaction type and branch accordingly.This is a pain point for anyone using autocomplete — the command logic and autocomplete logic serve different purposes and should be separate callbacks.
Changes
lib/nosedrum/application_command.ex— addautocomplete/1as an optional callback with documentation and examplelib/nosedrum/storage/dispatcher.ex— splithandle_interactionso autocomplete interactions (type 4) are routed toautocomplete/1. If a command receives an autocomplete interaction but doesn't implement the callback, the dispatcher responds with an empty choices list and logs a warning instead of callingcommand/1(which expects a different payload shape and response type).Usage
Backwards Compatibility
autocomplete/1is an optional callback, so existing command modules don't need any changes to compile. Commands that don't use autocomplete options are unaffected. The only behavioral change is that commands which setautocomplete: trueon an option must now implementautocomplete/1— previously such interactions would silently hitcommand/1, which was incorrect (different response type and payload shape).Testing
mix compile --warnings-as-errorspassesmix test --no-start— 79 tests, 0 failures