Discord

The DiscordInteractions and DiscordInteractionsBlueprint classes manage a collection of Command s for you.

DiscordInteractions

Generally, the first thing you want to do in your application is create your Flask app and then your DiscordInteractions object:

from flask import Flask
from flask_discord_interactions import DiscordInteractions

app = Flask(__name__)
discord = DiscordInteractions(app)

Then, you need to provide your authentication information for Discord. You must provide:

  • Client ID of your application

  • Public Key assigned to your application (used to authenticate incoming webhooks from Discord)

  • Client Secret of your application (used to request an OAuth2 token and register application commands)

For a more tutorial-style explanation of this, see Bot Setup Tutorial.

import os

app.config["DISCORD_CLIENT_ID"] = os.environ["DISCORD_CLIENT_ID"]
app.config["DISCORD_PUBLIC_KEY"] = os.environ["DISCORD_PUBLIC_KEY"]
app.config["DISCORD_CLIENT_SECRET"] = os.environ["DISCORD_CLIENT_SECRET"]

Next, define your commands using the DiscordInteractions.command() decorator and DiscordInteractions.command_group() function. For more information about defining commands, see Command.

@discord.command()
def ping(ctx):
    "Respond with a friendly 'pong'!"
    return "Pong!"

Next, set the URL path that your app will listen for Discord Interactions on. This is the part that you will enter into the Discord Developer Portal.

You could use the root URL "/", but you might want to pick a different path like "/interactions". That way, you can serve your bot’s website at "/" from the same Flask app.

discord.set_route("/interactions")

Note

If you want to use Flask-Discord-Interactions with Quart instead, you should use DiscordInteractions.set_route_async(). This functions similarly, but it registers the route handler as an async function, allowing it to await your function handlers. For details, see Using Asyncio with Quart.

Finally, you need to register the commands with Discord. DiscordInteractions.update_commands() will automatically get the list of currently registered commands, delete any that are no longer defined, update any that have changed, and register any newly-defined ones. Note that this may take a while due to Discord rate-limiting, especially if you are running your bot for the first time.

You can optionally pass in a guild_id parameter. This will register the commands in a specific guild instead of registering them globally. This is the recommended approach for testing, since registering new global commands can take up to 1 hour.

discord.update_commands(guild_id=os.environ["TESTING_GUILD"])

Note

If you’d like to deploy your bot in an environment with multiple workers, you might experience an issue where each worker tries to update your commands at the same time, causing you to be rate-limited. You should read the page on Pitfalls with Multiple Workers for information and advice relating to this issue.

Now, like any other Flask app, all that’s left to do is:

if __name__ == '__main__':
    app.run()

Running this code should serve your app locally. For production, your app can be deployed like any other Flask app (using gunicorn, etc).

Full API

class flask_discord_interactions.DiscordInteractions(app: Optional[Flask] = None)

Bases: DiscordInteractionsBlueprint

Handles registering a collection of Command s, receiving incoming interaction data, and sending/editing/deleting messages via webhook.

Parameters:

app (Flask) – The Flask application to bind to.

add_autocomplete_handler(handler: Callable, command_name: str)

Add a handler for an incoming autocomplete request.

Parameters:
  • handler (Callable) – The function to call to handle the incoming autocomplete request.

  • command_name (str) – The name of the command to autocomplete.

add_command(command: Callable, name: Optional[str] = None, description: Optional[str] = None, *, options: Optional[List[Option]] = None, annotations: Optional[Dict[str, str]] = None, type: int = 1, default_member_permissions: Optional[int] = None, dm_permission: Optional[bool] = None, name_localizations: Optional[Dict[str, str]] = None, description_localizations: Optional[Dict[str, str]] = None)

Create and add a new ApplicationCommand.

Parameters:
  • command (Callable) – Function to execute when the command is run.

  • name (str) – The name of the command, as displayed in the Discord client.

  • name_localizations (Dict[str, str]) – A dictionary of localizations for the name of the command.

  • description (str) – The description of the command.

  • description_localizations (Dict[str, str]) – A dictionary of localizations for the description of the command.

  • options (List[Option]) – A list of options for the command, overriding the function’s keyword arguments.

  • annotations (Dict[str, str]) – If options is not provided, descriptions for each of the options defined in the function’s keyword arguments.

  • type (int) – The class:.ApplicationCommandType of the command.

  • default_member_permissions (int) – A permission integer defining the required permissions a user must have to run the command.

  • dm_permission (bool) – Indicates whether the command can be used in DMs.

add_custom_handler(handler: Callable, custom_id: Optional[str] = None)

Add a handler for an incoming interaction with the specified custom ID.

Parameters:
  • handler (Callable) – The function to call to handle the incoming interaction.

  • custom_id (str) – The custom ID to respond to. If not specified, the ID will be generated randomly.

Returns:

The custom ID that the handler will respond to.

Return type:

str

static auth_headers(app: Flask)

Get the Authorization header required for HTTP requests to the Discord API.

Parameters:

app (Flask) – The Flask app with the relevant access token.

Returns:

The Authorization header.

Return type:

Dict[str, str]

static build_permission_overwrite_url(self, command: Optional[Command] = None, *, guild_id: str, command_id: Optional[str] = None, token: Optional[str] = None, app: Optional[Flask] = None, application_id: Optional[str] = None, base_url: Optional[str] = None)

Build the URL for getting or setting permission overwrites for a specific guild and command.

command(name: Optional[str] = None, description: Optional[str] = None, *, options: Optional[List[Option]] = None, annotations: Optional[Dict[str, str]] = None, type: int = 1, default_member_permissions: Optional[int] = None, dm_permission: Optional[bool] = None, name_localizations: Optional[Dict[str, str]] = None, description_localizations: Optional[Dict[str, str]] = None)

Decorator to create a new Command.

Parameters:
  • name (str) – The name of the command, as displayed in the Discord client.

  • name_localizations (Dict[str, str]) – A dictionary of localizations for the name of the command.

  • description (str) – The description of the command.

  • description_localizations (Dict[str, str]) – A dictionary of localizations for the description of the command.

  • options (List[Option]) – A list of options for the command, overriding the function’s keyword arguments.

  • annotations (Dict[str, str]) – If options is not provided, descriptions for each of the options defined in the function’s keyword arguments.

  • type (int) – The ApplicationCommandType of the command.

  • default_member_permissions (int) – A permission integer defining the required permissions a user must have to run the command

  • dm_permission (bool) – Indicates whether the command can be used in DMs

Return type:

Callable[Callable, Command]

command_group(name: str, description: str = 'No description', *, is_async: bool = False, default_member_permissions: Optional[int] = None, dm_permission: Optional[bool] = None, name_localizations: Optional[Dict[str, str]] = None, description_localizations: Optional[Dict[str, str]] = None)

Create a new SlashCommandGroup (which can contain multiple subcommands)

Parameters:
  • name (str) – The name of the command group, as displayed in the Discord client.

  • name_localizations (Dict[str, str]) – A dictionary of localizations for the name of the command group.

  • description (str) – The description of the command group.

  • description_localizations (Dict[str, str]) – A dictionary of localizations for the description of the command group.

  • is_async (bool) – Whether the subgroup should be considered async (if subcommands get an AsyncContext instead of a Context.)

  • default_member_permissions (int) – A permission integer defining the required permissions a user must have to run the command

  • dm_permission (bool) – Indicates whether the command canbe used in DMs

Returns:

The newly created command group.

Return type:

SlashCommandGroup

custom_handler(custom_id: Optional[str] = None)

Returns a decorator to register a handler for a custom ID.

Parameters:

custom_id – The custom ID to respond to. If not specified, the ID will be generated randomly.

Return type:

Callable[Callable, str]

fetch_token()

Fetch an OAuth2 token from Discord using the CLIENT_ID and CLIENT_SECRET with the applications.commands.update scope. This can be used to register new application commands.

Parameters:

app – The Flask app with the relevant config (client ID and secret).

get_permission_overwrites(*, guild_id: str, command_id: str = None, token: str = None, app: Flask = None, application_id: str = None, base_url: str = None)

Get the list of permission overwrites in a specific guild for a specific command. You must supply a Bearer token from a user with “Manage Roles” and “Manage Server” permissions in the given guild.

If the token is omitted, the bot’s token will be used. Note that this only works if the bot’s developer account is an admin in the guild. This is handy for small bots on your own servers, but you shouldn’t rely on this for anything you want others to use in their servers.

There are a many ways to call this method, here are a few:

# Without the app or instance, useful in a background worker
DiscordInteractions.get_permission_overwrites(
    guild_id=...,
    command_id=...,
    token=...,
    application_id=...,
    base_url=...,
)

# With the instance and app passed in, useful in an app-factory project
discord.get_permission_overwrites(
    guild_id=...,
    command=...,
    token=...,
    app=...,
)

# With the instance and a bound app, using an implicit token
# useful in most small projects
discord.get_permission_overwrites(
    guild_id=...,
    command=...,
)
Parameters:
  • command (Command) – The Command to retrieve permissions for.

  • guild_id (str) – The ID of the guild to retrieve permissions from.

  • command_id (str) – The ID of the command to retrieve permissions for.

  • token (str) – A bearer token from an admin of the guild (not including the leading Bearer word). If omitted, the bot’s token will be used instead.

  • app (Flask) – The Flask app with the relevant Discord application ID.

  • application_id (str) – The ID of the Discord application to retrieve permissions from.

  • base_url (str) – The base URL of the Discord API.

Returns:

A list of permission overwrites for the given command.

Return type:

List[Permission]

handle_request()

Verify the signature in the incoming request and return the Message result from the given command.

Returns:

The resulting message from the command.

Return type:

Message

init_app(app: Flask)

Initialize a Flask app with Discord-specific configuration and attributes.

Parameters:

app (Flask) – The Flask app to initialize.

register_blueprint(blueprint: DiscordInteractionsBlueprint, app: Optional[Flask] = None)

Register a DiscordInteractionsBlueprint to this DiscordInteractions class. Updates this instance’s list of Command s using the blueprint’s list of Command s.

Parameters:
run_autocomplete(data: dict)

Run the corresponding autocomplete handler given incoming interaction data.

Parameters:

data – Incoming interaction data.

Returns:

The result of the autocomplete handler.

Return type:

AutocompleteResult

run_command(data: dict)

Run the corresponding Command given incoming interaction data.

Parameters:

data – Incoming interaction data.

Returns:

The resulting message from the command.

Return type:

Message

run_handler(data: dict, *, allow_modal: bool = True)

Run the corresponding custom ID handler given incoming interaction data.

Parameters:

data – Incoming interaction data.

Returns:

The resulting message.

Return type:

Message

set_permission_overwrites(command: Command = None, *, guild_id: str, command_id: str = None, token: str = None, app: Flask = None, application_id: str = None, base_url: str = None)

Overwrite the list of permission overwrites in a specific guild for a specific command. You must supply a Bearer token from a user with “Manage Roles” and “Manage Server” permissions in the given guild.

This method requires access to the application ID and base URL. For convenience, it can be called as either an instance method (using the bound app’s configuration) or a static method.

Parameters:
  • command (Command) – The Command to retrieve permissions for.

  • guild_id (str) – The ID of the guild to retrieve permissions from.

  • command_id (str) – The ID of the command to retrieve permissions for.

  • token (str) – A bearer token from an admin of the guild (not including the leading Bearer word). If omitted, the bot’s token will be used instead.

  • app (Flask) – The Flask app with the relevant Discord application ID.

  • application_id (str) – The ID of the Discord application to retrieve permissions from.

  • base_url (str) – The base URL of the Discord API.

set_route(route: str, app: Optional[Flask] = None)

Add a route handler to the Flask app that handles incoming interaction data.

If you are using Quart, you should use DiscordInteractions.set_route_async() instead.

Parameters:
  • route (str) – The URL path to receive interactions on.

  • app (Flask) – The Flask app to add the route to.

set_route_async(route: str, app: Optional[Flask] = None)

Add a route handler to a Quart app that handles incoming interaction data using asyncio.

This function also sets up the aiohttp ClientSession that is used for sending followup messages, etc.

Parameters:
  • route (str) – The URL path to receive interactions on.

  • app (Flask) – The Quart app to add the route to.

throttle(response: Response)

Throttle the number of HTTP requests made to Discord using the X-RateLimit headers https://discord.com/developers/docs/topics/rate-limits

Parameters:

response (requests.Response) – Response object from a previous HTTP request

update_commands(app: Optional[Flask] = None, guild_id: Optional[str] = None)

Update the list of commands registered with Discord. This method will overwrite all existing commands.

Make sure you aren’t calling this every time a new worker starts! You will run into rate-limiting issues if multiple workers attempt to register commands simultaneously. Read Pitfalls with Multiple Workers for more info.

Parameters:
  • app (Flask) – The Flask app with the relevant Discord access token.

  • guild_id (str) – The ID of the Discord guild to register commands to. If omitted, the commands are registered globally.

verify_signature(request)

Verify the signature sent by Discord with incoming interactions.

Parameters:

request – The request to verify the signature of.

Blueprints

Similarly to Flask, you can use Blueprints to split your bot’s commands across multiple files. You can’t use Flask Blueprints for this, because all interactions from Discord are sent to the same URL. However, this library provides a DiscordInteractionsBlueprint class which you can use similarly to a Flask blueprint.

Here’s an example of a simple echo bot split into two files.

echo.py
from flask_discord_interactions import DiscordInteractionsBlueprint

bp = DiscordInteractionsBlueprint()

@bp.command()
def echo(ctx, text: str):
    "Repeat a string"
    return f"*Echooo!!!* {text}"
main.py
import os

from flask import Flask
from flask_discord_interactions import DiscordInteractions

from echo import bp as echo_bp

app = Flask(__name__)
discord = DiscordInteractions(app)

app.config["DISCORD_CLIENT_ID"] = os.environ["DISCORD_CLIENT_ID"]
app.config["DISCORD_PUBLIC_KEY"] = os.environ["DISCORD_PUBLIC_KEY"]
app.config["DISCORD_CLIENT_SECRET"] = os.environ["DISCORD_CLIENT_SECRET"]

discord.register_blueprint(echo_bp)


discord.set_route("/interactions")
discord.update_commands(guild_id=os.environ["TESTING_GUILD"])

if __name__ == '__main__':
    app.run()

As your app grows, Blueprints are a great way to keep things organized. Note that you can also use the DiscordInteractionsBlueprint.command_group() method to create a command group, just like with the DiscordInteractions object.

Full API

class flask_discord_interactions.DiscordInteractionsBlueprint

Represents a collection of ApplicationCommand s.

Useful for splitting a bot across multiple files.

add_autocomplete_handler(handler: Callable, command_name: str)

Add a handler for an incoming autocomplete request.

Parameters:
  • handler (Callable) – The function to call to handle the incoming autocomplete request.

  • command_name (str) – The name of the command to autocomplete.

add_command(command: Callable, name: Optional[str] = None, description: Optional[str] = None, *, options: Optional[List[Option]] = None, annotations: Optional[Dict[str, str]] = None, type: int = 1, default_member_permissions: Optional[int] = None, dm_permission: Optional[bool] = None, name_localizations: Optional[Dict[str, str]] = None, description_localizations: Optional[Dict[str, str]] = None)

Create and add a new ApplicationCommand.

Parameters:
  • command (Callable) – Function to execute when the command is run.

  • name (str) – The name of the command, as displayed in the Discord client.

  • name_localizations (Dict[str, str]) – A dictionary of localizations for the name of the command.

  • description (str) – The description of the command.

  • description_localizations (Dict[str, str]) – A dictionary of localizations for the description of the command.

  • options (List[Option]) – A list of options for the command, overriding the function’s keyword arguments.

  • annotations (Dict[str, str]) – If options is not provided, descriptions for each of the options defined in the function’s keyword arguments.

  • type (int) – The class:.ApplicationCommandType of the command.

  • default_member_permissions (int) – A permission integer defining the required permissions a user must have to run the command.

  • dm_permission (bool) – Indicates whether the command can be used in DMs.

add_custom_handler(handler: Callable, custom_id: Optional[str] = None)

Add a handler for an incoming interaction with the specified custom ID.

Parameters:
  • handler (Callable) – The function to call to handle the incoming interaction.

  • custom_id (str) – The custom ID to respond to. If not specified, the ID will be generated randomly.

Returns:

The custom ID that the handler will respond to.

Return type:

str

command(name: Optional[str] = None, description: Optional[str] = None, *, options: Optional[List[Option]] = None, annotations: Optional[Dict[str, str]] = None, type: int = 1, default_member_permissions: Optional[int] = None, dm_permission: Optional[bool] = None, name_localizations: Optional[Dict[str, str]] = None, description_localizations: Optional[Dict[str, str]] = None)

Decorator to create a new Command.

Parameters:
  • name (str) – The name of the command, as displayed in the Discord client.

  • name_localizations (Dict[str, str]) – A dictionary of localizations for the name of the command.

  • description (str) – The description of the command.

  • description_localizations (Dict[str, str]) – A dictionary of localizations for the description of the command.

  • options (List[Option]) – A list of options for the command, overriding the function’s keyword arguments.

  • annotations (Dict[str, str]) – If options is not provided, descriptions for each of the options defined in the function’s keyword arguments.

  • type (int) – The ApplicationCommandType of the command.

  • default_member_permissions (int) – A permission integer defining the required permissions a user must have to run the command

  • dm_permission (bool) – Indicates whether the command can be used in DMs

Return type:

Callable[Callable, Command]

command_group(name: str, description: str = 'No description', *, is_async: bool = False, default_member_permissions: Optional[int] = None, dm_permission: Optional[bool] = None, name_localizations: Optional[Dict[str, str]] = None, description_localizations: Optional[Dict[str, str]] = None)

Create a new SlashCommandGroup (which can contain multiple subcommands)

Parameters:
  • name (str) – The name of the command group, as displayed in the Discord client.

  • name_localizations (Dict[str, str]) – A dictionary of localizations for the name of the command group.

  • description (str) – The description of the command group.

  • description_localizations (Dict[str, str]) – A dictionary of localizations for the description of the command group.

  • is_async (bool) – Whether the subgroup should be considered async (if subcommands get an AsyncContext instead of a Context.)

  • default_member_permissions (int) – A permission integer defining the required permissions a user must have to run the command

  • dm_permission (bool) – Indicates whether the command canbe used in DMs

Returns:

The newly created command group.

Return type:

SlashCommandGroup

custom_handler(custom_id: Optional[str] = None)

Returns a decorator to register a handler for a custom ID.

Parameters:

custom_id – The custom ID to respond to. If not specified, the ID will be generated randomly.

Return type:

Callable[Callable, str]