Client

Client

Discord.ClientType.
Client(
    token::String;
    prefix::String="",
    presence::Union{Dict, NamedTuple}=Dict(),
    strategies::Dict{DataType, <:CacheStrategy}=Dict(),
    version::Int=6,
) -> Client

A Discord bot. Clients can connect to the gateway, respond to events, and make REST API calls to perform actions such as sending/deleting messages, kicking/banning users, etc.

Bot Token

A bot token can be acquired by creating a new application here. Make sure not to hardcode the token into your Julia code! Use an environment variable or configuration file instead.

Command Prefix

The prefix keyword specifies the command prefix, which is used by commands added with add_command!. It can be changed later, both globally and on a per-guild basis, with set_prefix!.

Presence

The presence keyword sets the bot's presence upon connection. It also sets defaults for future calls to set_game. The schema here must be followed.

Cache Control

By default, most data that comes from Discord is cached for later use. However, to avoid memory leakage, not all of it is kept forever. The default setings are to keep everything but Messages, which are deleted after 6 hours, forever. Although the default settings are sufficient for most workloads, you can specify your own strategies per type with the strategies keyword. Keys can be any of the following:

For potential values, see CacheStrategy.

The cache can also be disabled/enabled permanently and temporarily as a whole with enable_cache! and disable_cache!.

API Version

The version keyword chooses the Version of the Discord API to use. Using anything but 6 is not officially supported by the Discord.jl developers.

Sharding

Sharding is handled automatically. The number of available processes is the number of shards that are created. See the sharding example for more details.

source
Discord.enable_cache!Function.
enable_cache!(c::Client)
enable_cache!(f::Function c::Client)

Enable the cache. do syntax is also accepted.

source
disable_cache!(c::Client)
disable_cache!(f::Function, c::Client)

Disable the cache. do syntax is also accepted.

source
Discord.meFunction.
me(c::Client) -> Nullable{User}

Get the Client's bot user.

source

Gateway

Base.openFunction.
open(c::Client; delay::Period=Second(7))

Connect a Client to the Discord gateway.

The delay keyword is the time between shards connecting. It can be increased from its default if you are using multiple shards and frequently experiencing invalid sessions upon connection.

source
Base.isopenFunction.
isopen(c::Client) -> Bool

Determine whether the Client is connected to the gateway.

source
Base.closeFunction.
close(c::Client)

Disconnect the Client from the gateway.

source
Base.waitFunction.
wait(c::Client)

Wait for an open Client to close.

source
request_guild_members(
    c::Client,
    guilds::Union{Integer, Vector{<:Integer};
    query::AbstractString="",
    limit::Int=0,
) -> Bool

Request offline guild members of one or more Guilds. GuildMembersChunk events are sent by the gateway in response. More details here.

source
update_voice_state(
    c::Client,
    guild::Integer,
    channel::Nullable{Integer},
    mute::Bool,
    deaf::Bool,
) -> Bool

Join, move, or disconnect from a voice channel. A VoiceStateUpdate event is sent by the gateway in response. More details here.

source
Discord.update_statusFunction.
update_status(
    c::Client,
    since::Nullable{Int},
    activity::Nullable{Activity},
    status::Union{PresenceStatus, AbstractString},
    afk::Bool,
) -> Bool

Indicate a presence or status update. A PresenceUpdate event is sent by the gateway in response. More details here.

source
heartbeat_ping(c::Client) -> Nullable{Period}

Get the Client's ping time to the gateway. If the client is not connected, or no heartbeats have been sent/acknowledged, nothing is returned.

source

Event Handlers

See Events for more details.

Discord.add_handler!Function.
add_handler!(
    c::Client,
    [T::Type{<:AbstractEvent}],
    handler::Function;
    tag::Symbol=gensym(),
    predicate::Function=alwaystrue,
    fallback::Function=donothing,
    priority::Int=100,
    count::Nullable{Int}=nothing,
    timeout::Nullable{Period}=nothing,
    until::Function=alwaysfalse,
    wait::Bool=false,
    compile::Bool=false,
    kwargs...,
) -> Nullable{Vector{Any}}

Add an event handler. do syntax is also accepted.

Handler Function

The handler function does the real work and must take two arguments: A Client and an AbstractEvent (or a subtype). If an event type T is supplied, then the handler is registered for that event. Otherwise, the second argument of the handler must be annotated, and the type annotation determines what events will invoke the handler. Union types are also accepted to register handlers for multiple events.

Handler Tag

The tag keyword gives a label to the handler, which can be used to remove it with delete_handler!.

Predicate/Fallback Functions

The predicate keyword specifies a predicate function. The handler will only run if this function returns true. Otherwise, a fallback function, specified by the fallback keyword, is run. Their signatures should match that of the handler.

Handler Priority

The priority keyword indicates the handler's priority relative to other handlers for the same event. Handlers with higher values execute before those with lower ones.

Handler Expiry

Handlers can have multiple types of expiries. The count keyword sets the number of times a handler is run before expiring. The timeout keyword determines how long the handler remains active. The until keyword takes a function which is called on the handler's previous results (in a Vector), and if it returns true, the handler expires. These keywords can be combined; the first condition to be met causes the handler to expire.

Blocking Handlers + Result Collection

To collect results from a handler, set the wait keyword along with n, timeout, and/or until. The call will block until the handler expires, at which point the return value of each invocation is returned in a Vector.

Forcing Precompilation

Handler functions are precompiled without running them, but it's not always successful, especially if your functions are not type-safe. If the compile keyword is set, precompilation is forced by running the predicate and handler on a randomized input. Any trailing keywords are passed to the constructors of the event and its fields.

Examples

Basic "hello world" with explicit event type:

add_handler!(c, MessageCreate, (c, e) -> println(e.message.content); tag=:print)

Adding a handler with a predicate and fallback:

handler(::Client, e::ChannelCreate) = println(e.channel.name)
predicate(::Client, e::ChannelCreate) = length(e.channel.name) < 10
fallback(::Client, ::ChannelCreate) = println("channel name too long")
add_handler!(c, handler; predicate=predicate, fallback=fallback)

Assigning maximum priority to a handler:

handler(:::Client, ::MessageCreate) = println("this runs before any other handlers!")
add_handler!(c, handler; priority=typemax(Int))

Adding a handler with various expiry conditions:

handler(::Client, e::ChannelCreate) = e.channel.name
until(results::Vector{Any}) = "foo" in results
add_handler!(c, handler; count=10, timeout=Minute(1), until=until)

Aggregating results of a handler:

handler(::Client, e::MessageCreate) = e.message.content
msgs = add_handler!(c, handler; count=5, wait=true)

Forcing precompilation:

handler(::Client, e::MessageDelete) = @show e
add_handler!(c, handler; compile=true, id=0xff)
source
add_handler!(c::Client, m::Module; kwargs...)

Add all of the event handlers defined in a module. Any function you wish to use as a handler must be exported. Only functions with correct, annotated type signatures (see above) are used.

Note

If you set keywords, they are applied to all of the handlers in the module. For example, if you add two handlers for the same event type with the same tag, one of them will be immediately overwritten.

source
delete_handler!(c::Client, T::Type{<:AbstractEvent}, tag::Symbol)
delete_handler!(c::Client, T::Type{<:AbstractEvent})

Delete event handlers. If no tag is supplied, all handlers for the event are deleted. Using the tagless method is generally not recommended because it also clears default handlers which maintain the client state. If you do want to delete a default handler, use DEFAULT_HANDLER_TAG.

source

Tag assigned to default handlers, which you can use to delete them.

source

Bot Commands

Discord.add_command!Function.
add_command!(
    c::Client,
    name::Symbol,
    handler::Function;
    help::AbstractString="",
    parsers::Vector=[],
    separator::StringOrChar=' ',
    pattern::Regex=defaultpattern(name, length(parsers), separator),
    allowed::Vector{<:Integer}=Snowflake[],
    permissions::Integer=PERM_NONE,
    cooldown::Nullable{Period}=nothing,
    fallback_parsers::Function=donothing,
    fallback_allowed::Function=donothing,
    fallback_permissions::Function=donothing,
    fallback_cooldown::Function=donothing,
    priority::Int=100,
    count::Nullable{Int}=nothing,
    timeout::Nullable{Period}=nothing,
    compile::Bool=false,
    kwargs...,
)

Add a text command handler. do syntax is also accepted.

Handler Function

The handler function must accept a Client and a Message. Additionally, it can accept any number of additional arguments, which are captured from pattern and parsed with parsers (see below).

Command Pattern

The pattern keyword specifies how to invoke the command. The given Regex must match the message contents after having removed the command prefix. By default, it's the command name with as many wildcard capture groups as there are parsers, separated by the separator keyword (a space character by default).

Command Help

The help keyword specifies a help string which can be used by add_help!.

Argument Parsing

The parsers keyword sets the parsers of the command arguments, and can contain both types and functions. If pattern contains captures, then they are run through the parsers before being passed into the handler. For repeating arguments, see Splat.

Authorization + Required Permissions

The allowed keyword specifies Users or Roles (by ID) that are allowed to use the command. The permissions keyword sets the minimum permissions that command callers must have.

Rate Limiting

The cooldown keyword sets the rate at which a user can invoke the command. The default of nothing indicates no limit.

Fallback Functions

The fallback_* keywords specify functions to be run whenever a command is called but cannot be run, such as failed argument parsing, missing permissions, or rate limiting. They should accept a Client and a Message.

Additional keyword arguments are a subset of those to add_handler!.

Examples

Basic echo command with a help string:

add_command!(c, :echo, (c, m) -> reply(c, m, m.content); help="repeat a message")

The same, but excluding the command part:

add_command!(c, :echo, (c, m, msg) -> reply(c, m, msg); pattern=r"^echo (.+)")

Parsing a subtraction expression with custom parsers and separator:

add_command!(
    c, :sub, (c, m, a, b) -> reply(c, m, string(a - b));
    parsers=[Float64, Float64], separator='-',
)

Splatting some comma-separated numbers with a parsing fallback function:

add_command!(
    c, :sum, (c, m, xs...) -> reply(c, m, string(sum(collect(xs))));
    parsers=[Splat(Float64, ',')],
    fallback_parsers=(c, m) -> reply(c, m, "Args must be numbers."),
)
source
add_command!(c::Client, m::Module; compile::Bool=false; kwargs...)

Add all of the bot commands defined in a module. To set up commands to be included, see @command.

source
Discord.@commandMacro.
@command name=name handler=handler kwargs...

Mark a function as a bot command to be collected by add_command! (from a module). Supported keywords are identical to add_command!.

Example

module Commands
using Discord
echo(c::Client, m::Message, noprefix::AbstractString) = reply(c, m, noprefix)
@command name=:echo handler=echo help="Echo a message" pattern=r"^echo (.+)"
end
c = Client("token")
add_command!(c, Commands)
source
delete_command!(c::Client, name::Symbol)

Delete a command.

source
Discord.add_help!Function.
add_help!(
    c::Client;
    pattern::Regex=r"^help(?: (.+))?",
    help::AbstractString="Show this help message",
    nohelp::AbstractString="No help provided",
    nocmd::AbstractString="Command not found",
)

Add a help command. This can be called at any time, new commands will be included automatically.

Keywords

  • separator::StringOrChar: Separator between commands.
  • pattern::Regex: The command pattern (see add_command!).
  • help::AbstractString: Help for the help command.
  • nohelp::AbstractString: Help for commands without their own help string.
  • nocmd::AbstractString: Help for commands that aren't found.
source
Discord.set_prefix!Function.
set_prefix!(c::Client, prefix::StringOrChar)
set_prefix!(c::Client, prefix::StringOrChar, guild::Union{Guild, Integer})

Set Client's command prefix. If a Guild or its ID is supplied, then the prefix only applies to that guild.

source
Discord.SplatType.
Splat(func::Base.Callable=identity, split::StringOrChar=' ') -> Splat

Collect a variable number of arguments from one capture group with a single parser.

source

Caching

A method of handling cache insertion and eviction.

source
CacheForever() -> CacheForever

Store everything and never evict items from the cache.

source
CacheNever() -> CacheNever

Don't store anything in the cache.

source
CacheTTL(ttl::Period) -> CacheTTL

Evict items from the cache after ttl has elapsed.

source
CacheLRU(size::Int) -> CacheLRU

Evict the least recently used item from the cache when there are more than size items.

source
CacheFilter(f::Function) -> CacheFilter

Only store value v at key k if f(v) === true (k is always v.id).

source