Discord Client

AA contains a web client for interacting with the Discord API. This client can be used independently from an installed Discord service in AA.

Location: allianceauth.services.modules.discord.discord_client

client

Client for interacting with the Discord API.

class DiscordApiStatusCode(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Status code returned from the Discord API.

UNKNOWN_MEMBER = 10007
class DiscordClient(access_token: str, redis: Redis = None, is_rate_limited: bool = True)[source]

This class provides a web client for interacting with the Discord API.

The client has rate limiting that supports concurrency. This means it is able to ensure the API rate limit is not violated, even when used concurrently, e.g. with multiple parallel celery tasks.

In addition the client support proper API backoff.

Synchronization of rate limit infos across multiple processes is implemented with Redis and thus requires Redis as Django cache backend.

The cache is shared across all clients and processes (also using Redis).

All durations are in milliseconds.

Most errors from the API will raise a requests.HTTPError.

Parameters:
  • access_token – Discord access token used to authenticate all calls to the API

  • redis – Redis instance to be used.

  • is_rate_limited – Set to False to turn off rate limiting (use with care). If not specified will try to use the Redis instance from the default Django cache backend.

Raises:

ValueError – No access token provided

__init__(access_token: str, redis: Redis = None, is_rate_limited: bool = True) None[source]
property access_token: str

Discord access token.

add_guild_member(guild_id: int, user_id: int, access_token: str, role_ids: list = None, nick: str = None) bool | None[source]

Adds a user to the guild.

Returns:

  • True when a new user was added

  • None if the user already existed

  • False when something went wrong or raises exception

add_guild_member_role(guild_id: int, user_id: int, role_id: int) bool | None[source]

Adds a role to a guild member

Returns: - True when successful - None if member does not exist - False otherwise

create_guild_role(guild_id: int, role_name: str, **kwargs) Role | None[source]

Create a new guild role with the given name.

See official documentation for additional optional parameters.

Note that Discord allows the creation of multiple roles with the same name, so to avoid duplicates it’s important to check existing roles before creating new one

Parameters:
  • guild_id – Discord ID of the guild

  • role_name – Name of new role to create

Returns:

new role on success

current_user() User[source]

Fetch user belonging to the current access_token.

delete_guild_role(guild_id: int, role_id: int) bool[source]

Delete a guild role.

guild_infos(guild_id: int) Guild[source]

Fetch all basic infos about this guild.

Parameters:

guild_id – Discord ID of the guild

guild_member(guild_id: int, user_id: int) GuildMember | None[source]

Fetch info for a guild member.

Parameters:
  • guild_id – Discord ID of the guild

  • user_id – Discord ID of the user

Returns:

guild member or None if the user is not a member of the guild

guild_member_roles(guild_id: int, user_id: int) RolesSet | None[source]

Fetch the current guild roles of a guild member.

Args: - guild_id: Discord guild ID - user_id: Discord user ID

Returns: - Member roles - None if user is not a member of the guild

guild_name(guild_id: int, use_cache: bool = True) str[source]

Fetch the name of this guild (cached).

Parameters:
  • guild_id – Discord ID of the guild

  • use_cache – When set to False will force an API call to get the server name

Returns:

Name of the server or an empty string if something went wrong.

guild_roles(guild_id: int, use_cache: bool = True) Set[Role][source]

Fetch all roles for this guild.

Parameters:
  • guild_id – Discord ID of the guild

  • use_cache – If is set to False it will always hit the API to retrieve fresh data and update the cache.

Returns:

property is_rate_limited: bool

Wether this instance is rate limited.

match_or_create_role_from_name(guild_id: int, role_name: str, guild_roles: RolesSet = None) Tuple[Role, bool][source]

Fetch or create Discord role matching the given name.

Will try to match with existing roles names Non-existing roles will be created, then created flag will be True

Parameters:
  • guild_id – ID of guild

  • role_name – strings defining name of a role

  • guild_roles – All known guild roles as RolesSet object. Helps to void redundant lookups of guild roles when this method is used multiple times.

Returns:

Tuple of Role and created flag

match_or_create_roles_from_names(guild_id: int, role_names: Iterable[str]) List[Tuple[Role, bool]][source]

Fetch or create Discord roles matching the given names (cached).

Will try to match with existing roles names Non-existing roles will be created, then created flag will be True

Parameters:
  • guild_id – ID of guild

  • role_names – list of name strings each defining a role

Returns:

List of tuple of Role and created flag

match_or_create_roles_from_names_2(guild_id: int, role_names: Iterable[str]) RolesSet[source]

Fetch or create Discord role matching the given name.

Wrapper for match_or_create_role_from_name()

Returns:

Roles as RolesSet object.

match_role_from_name(guild_id: int, role_name: str) Role | None[source]

Fetch Discord role matching the given name (cached).

Parameters:
  • guild_id – Discord ID of the guild

  • role_name – Name of role

Returns:

Matching role or None if no match is found

modify_guild_member(guild_id: int, user_id: int, role_ids: List[int] = None, nick: str = None) bool | None[source]

Set properties of a guild member.

Parameters:
  • guild_id – Discord ID of the guild

  • user_id – Discord ID of the user

  • roles_id – New list of role IDs (if provided)

  • nick – New nickname (if provided)

Returns
  • True when successful

  • None if user is not a member of this guild

  • False otherwise

remove_guild_member(guild_id: int, user_id: int) bool | None[source]

Remove a member from a guild.

Parameters:
  • guild_id – Discord ID of the guild

  • user_id – Discord ID of the user

Returns:

  • True when successful

  • None if member does not exist

  • False otherwise

remove_guild_member_role(guild_id: int, user_id: int, role_id: int) bool | None[source]

Remove a role to a guild member

Parameters:
  • guild_id – Discord ID of the guild

  • user_id – Discord ID of the user

  • role_id – Discord ID of role to be removed

Returns:

  • True when successful

  • None if member does not exist

  • False otherwise

models

Implementation of Discord objects used by this client.

Note that only those objects and properties are implemented, which are needed by AA.

Names and types are mirrored from the API whenever possible. Discord’s snowflake type (used by Discord IDs) is implemented as int.

class User(id: int, username: str, discriminator: str)[source]

A user on Discord.

id: int
username: str
discriminator: str
classmethod from_dict(data: dict) User[source]

Create object from dictionary as received from the API.

__init__(id: int, username: str, discriminator: str) None
class Role(id: int, name: str, managed: bool = False)[source]

A role on Discord.

id: int
name: str
managed: bool = False
asdict() dict[source]

Convert object into a dictionary representation.

classmethod from_dict(data: dict) Role[source]

Create object from dictionary as received from the API.

classmethod sanitize_name(role_name: str) str[source]

Shorten too long names if necessary.

__init__(id: int, name: str, managed: bool = False) None
class Guild(id: int, name: str, roles: FrozenSet[Role])[source]

A guild on Discord.

id: int
name: str
roles: FrozenSet[Role]
classmethod from_dict(data: dict) Guild[source]

Create object from dictionary as received from the API.

__init__(id: int, name: str, roles: FrozenSet[Role]) None
class GuildMember(roles: FrozenSet[int], nick: str = None, user: User = None)[source]

A member of a guild on Discord.

roles: FrozenSet[int]
nick: str = None
user: User = None
classmethod from_dict(data: dict) GuildMember[source]

Create object from dictionary as received from the API.

classmethod sanitize_nick(nick: str) str[source]

Sanitize a nick, i.e. shorten too long strings if necessary.

__init__(roles: FrozenSet[int], nick: str = None, user: User = None) None

exceptions

Custom exceptions for the Discord Client package.

exception DiscordApiBackoff(retry_after: int)[source]

Exception signaling we need to backoff from sending requests to the API for now.

Parameters:

retry_after – time to retry after in milliseconds

__init__(retry_after: int)[source]
property retry_after_seconds

Time to retry after in seconds.

exception DiscordClientException[source]

Base Exception for the Discord client.

exception DiscordRateLimitExhausted(retry_after: int)[source]

Exception signaling that the total number of requests allowed under the current rate limit have been exhausted and weed to wait until next reset.

exception DiscordTooManyRequestsError(retry_after: int)[source]

API has responded with a 429 Too Many Requests Error. Need to backoff for now.

settings

Settings for the Discord client.

To overwrite a default set the variable in your local Django settings, e.g:

DISCORD_GUILD_NAME_CACHE_MAX_AGE = 7200
DISCORD_API_BASE_URL = 'https://discord.com/api/'

Base URL for all API calls. Must end with /.

DISCORD_API_TIMEOUT_CONNECT = 5

Low level connect timeout for requests to the Discord API in seconds.

DISCORD_API_TIMEOUT_READ = 30

Low level read timeout for requests to the Discord API in seconds.

DISCORD_DISABLE_ROLE_CREATION = False

Turns off creation of new roles. In case the rate limit for creating roles is exhausted, this setting allows the Discord service to continue to function and wait out the reset. Rate limit is about 250 per 48 hrs.

DISCORD_GUILD_NAME_CACHE_MAX_AGE = 86400

How long the Discord guild names retrieved from the server are caches locally in seconds.

DISCORD_OAUTH_BASE_URL = 'https://discord.com/api/oauth2/authorize'

Base authorization URL for Discord Oauth.

DISCORD_OAUTH_TOKEN_URL = 'https://discord.com/api/oauth2/token'

Base authorization URL for Discord Oauth.

DISCORD_ROLES_CACHE_MAX_AGE = 3600

How long Discord roles retrieved from the server are caches locally in seconds.