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.
- static auth_headers(app: Flask)¶
Get the Authorization header required for HTTP requests to the Discord API.
- 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 aContext
.)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:
- 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
andCLIENT_SECRET
with theapplications.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:
- 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 ofCommand
s using the blueprint’s list ofCommand
s.- Parameters:
blueprint (DiscordInteractionsBlueprint) – The
DiscordInteractionsBlueprint
to addCommand
s from.app (Flask) – The Flask app with the relevant Discord commands.
- 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:
- 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:
- 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:
- 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.
from flask_discord_interactions import DiscordInteractionsBlueprint
bp = DiscordInteractionsBlueprint()
@bp.command()
def echo(ctx, text: str):
"Repeat a string"
return f"*Echooo!!!* {text}"
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.
- 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 aContext
.)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: