Nostrum.Bot (nostrum v0.11.0-dev)
View SourceSupervisor for a bot along with all its associated components.
Usage
In your supervisor tree, write:
bot_options = %{
consumer: MyBot.Consumer,
# This is an example and includes privileged intents, but
# should provide a useful set of intents for bots. Feel
# free to adjust this as you see fit.
intents: [
:direct_messages,
:guild_bans,
:guild_members,
:guild_message_reactions,
:guild_messages,
:guilds,
:message_content
],
wrapped_token: fn -> System.fetch_env!("BOT_TOKEN") end,
}
children = [
{Nostrum.Bot, bot_options}
]
See bot_options/0
for which options you can configure here.
You may also configure supervisor_options/0
, which allow you
to customize the options we start the Supervisor
with by defining
your child in the form {Nostrum.Bot, {bot_options, supervisor_options}}
,
but the default supervisor_options/0
should suit most needs.
Migration guide
If you are still using the old way of deploying nostrum, please do the following:
Remove the
:nostrum
,:token
configuration option. nostrum will then assume that you are starting it as part of your own supervision tree, and automatic startup via the application is disabled.Remove your consumer from your application supervisor tree.
In your supervisor tree, add the
bot_options
described above, and addNostrum.Bot
to your supervisor tree as described above. For the:intents
setting, cut the value you previously had in yourconfig.exs
and use it here. Do the same with:num_shards
, renaming it to:shards
on thebot_options
map. You can then remove the old config values.In your consumer, change
use Nostrum.Consumer
to@behaviour Nostrum.Consumer
.In your consumer, add a default event handling clause for unmatched events at the end of the module, such as:
def handle_event(_), do: :ok
Multiple Bots
Nostrum allows you to start multiple bots under your supervision tree. If you are
calling a function that interacts with an API specific to a bot - Rest, Cache, Voice, etc. -
nostrum needs to determine which bot to call it for. It does this with a bot Registry
and process dictionaries so that you don't have to pass an additional argument to every
function.
Inside the handle_event/1
callback in your consumer, the calling process already
has the context of the bot that generated the event for any API calls that follow.
If you have a single bot running and need to call an API asynchronously, i.e. not as a response to a gateway event in your consumer, nostrum will automatically determine the bot.
However, if you have multiple bots running and you need to make unprompted bot calls, you will need to assist nostrum by setting the process's context in one of three ways:
Nostrum.Bot.with_bot(MyBot, fn -> ... end)
to wrap the API function callsuse Nostrum.Bot, name: MyBot
at the top of the module where the API-calling functions are definedNostrum.Bot.set_bot_name(MyBot)
dynamically before each API call
You are free to call API functions from newly-spawned tasks as nostrum will search the process dictionaries of a few generations of calling processes to find the bot context.
Note that, unless explicitly configured otherwise (see bot_options/0
), nostrum uses
the user ID from the bot's token as the bot name. If you wish to dynamically determine
the user ID from the token, use Nostrum.Token.decode_token!/1
.
Summary
Types
Options to start a bot with.
Which gateway intents to request.
Unique name for the bot.
Options to pass to the bot's supervisor.
Functions
Returns all running bots
Manually set the bot name in the calling process's context
Call a function with the context of the provided bot
Types
@type bot_options() :: %{ :consumer => module(), :intents => :all | :nonprivileged | [atom()], :wrapped_token => (-> String.t()), optional(:name) => name(), optional(:shards) => :auto | :manual | (num_shards :: pos_integer()) | {lowest :: pos_integer(), highest :: pos_integer(), total :: pos_integer()}, optional(:request_guild_members) => boolean(), optional(:ffmpeg) => String.t(), optional(:youtubedl) => String.t(), optional(:streamlink) => String.t(), optional(:audio_timeout) => pos_integer(), optional(:audio_frames_per_burst) => pos_integer(), optional(:voice_auto_connect) => boolean(), optional(:voice_encryption_mode) => Nostrum.Voice.Crypto.cipher(), optional(:log_full_events) => boolean(), optional(:log_dispatch_events) => boolean(), optional(:force_http1) => boolean() }
Options to start a bot with.
Required fields
:consumer
: A module implementing theNostrum.Consumer
behaviour that should be called for each event.:intents
: Which gateway intents to request. See the Gateway Intents documentation for more details.:wrapped_token
: A function that takes no arguments and returns the bot token to use. This is wrapped to prevent exposure of the token in stacktraces.
Optional fields
:name
: Unique name for your bot. Defaults to the integer bot id encoded into the token.:shards
: Shards that should be started with this bot. Possible values::auto
uses the suggested amount of shards as provided by Discord. This value is the default.:manual
do not automatically spawn shards. In this case, it is your responsibility to spawn shards manually, see the manual sharding documentation.pos_integer()
: A number of shards to run. nostrum will warn if this is not the recommended amount.{lowest, highest, total}
starts shardslowest
tohighest
.total
should contain the total amount of shards that your bot is expected to have. Useful for splitting a single bot across multiple nodes, see the multi-node documentation for further information.
Global config override fields
The following fields will override global config values if provided. More information on globally configuring these options and their defaults may be found here.
:request_guild_members
:ffmpeg
:youtubedl
:streamlink
:audio_timeout
:audio_frames_per_burst
:voice_auto_connect
:voice_encryption_mode
:log_full_events
:log_dispatch_events
:force_http1
@type intents() :: :all | :nonprivileged | [atom()]
Which gateway intents to request.
A full reference can be found either on Discord or on our Gateway Intents documentation.
Unique name for the bot.
@type supervisor_options() :: [Supervisor.init_option()]
Options to pass to the bot's supervisor.
By default, we set the strategy: :one_for_one
. No other options are set by
nostrum.
Functions
@spec child_spec(options()) :: Supervisor.child_spec()
@spec fetch_all_bots() :: [%{name: name(), pid: pid(), bot_options: bot_options()}]
Returns all running bots
Manually set the bot name in the calling process's context
Call a function with the context of the provided bot
Nostrum.Bot.with_bot(ReticentBot, fn ->
Nostrum.Api.Message.create(channel_id, "Hi...")
end)
Nostrum.Bot.with_bot(SillyGoofyBot, fn ->
Nostrum.Api.Message.create(channel_id, "Heyyy :)")
end, :keep)
# Context is still set to SillyGoofyBot
Nostrum.Api.Message.create(channel_id, "Me again :)")
Parameters
name
- Name of the bot to run the function asfunction
- Zero arity function to executenext
- What to do with the process's bot context after the function:reset
- Reset the values to what they were before (default):clear
- Set the values tonil
:keep
- Keep the provided bot's context in this process's dictionary