Nostrum.Consumer behaviour (nostrum v0.11.0-dev)

View Source

Consumer behaviour for gateway event handling.

Consuming gateway events

Events are first ingested by nostrum's cache. Afterwards, a new process is spawned to handle each event, which then calls the consumer callback module configured via Nostrum.Bot.bot_options/0.

Each event will be started in a separate task, outside of the shard session.

Listening to events

See the Nostrum.ConsumerGroup module if you wish to listen to events.

Example consumer

An example consumer could look as follows:

# Sourced from examples/event_consumer.ex
defmodule ExampleSupervisor do
  use Supervisor

  def start_link(args) do
    Supervisor.start_link(__MODULE__, args, name: __MODULE__)
  end

  @impl true
  def init(_init_arg) do
    bot_options = %{
      consumer: MyBot.Consumer,
      intents: [:direct_messages, :guild_messages, :message_content],
      wrapped_token: fn -> System.fetch_env!("BOT_TOKEN") end
    }

    children = [
      {Nostrum.Bot, bot_options}
    ]

    Supervisor.init(children, strategy: :one_for_one)
  end
end

defmodule MyBot.Consumer do
  @behaviour Nostrum.Consumer

  alias Nostrum.Api.Message

  def handle_event({:MESSAGE_CREATE, msg, _ws_state}) do
    case msg.content do
      "!sleep" ->
        Message.create(msg.channel_id, "Going to sleep...")
        # This won't stop other events from being handled.
        Process.sleep(3000)

      "!ping" ->
        Message.create(msg.channel_id, "pyongyang!")

      "!raise" ->
        # This won't crash the entire Consumer.
        raise "No problems here!"

      _ ->
        :ignore
    end
  end

  # Ignore any other events
  def handle_event(_), do: :ok
end

Summary

Types

Dispatched when a channel is created.

Dispatched when a channel is updated.

Dispatched when somebody leaves a guild.

Dispatched when a guild member is updated.

Dispatched when a role on a guild is updated.

Different from guild_integrations_update/0 in that more than only the guild_id is provided

Dispatched when a user adds a vote to a poll.

Dispatched when a user removes a vote from a poll.

Dispatched when a user's presence is updated.

Dispatched when a thread is created or when added to a private thread

Dispatched when a thread is deleted, if the thread was cached, contains the original thread, otherwise contains :noop

Dispatched when gaining access to a channel

Dispatched when a ThreadMember for the current user is updated

Dispatched when member(s) are added or removed from a thread

Dispatched when a user is updated.

Dispatched when async listening is enabled and another user is actively speaking

Dispatched when the bot is ready to begin sending audio after joining a voice channel

Dispatched when the bot starts or stops speaking

Callbacks

Callback used to handle events.

Types

auto_moderation_rule_create()

@type auto_moderation_rule_create() ::
  {:AUTO_MODERATION_RULE_CREATE, Nostrum.Struct.AutoModerationRule.t(),
   Nostrum.Struct.WSState.t()}

auto_moderation_rule_delete()

@type auto_moderation_rule_delete() ::
  {:AUTO_MODERATION_RULE_DELETE, Nostrum.Struct.AutoModerationRule.t(),
   Nostrum.Struct.WSState.t()}

auto_moderation_rule_execute()

@type auto_moderation_rule_execute() ::
  {:AUTO_MODERATION_RULE_EXECUTE,
   Nostrum.Struct.Event.AutoModerationRuleExecute.t(),
   Nostrum.Struct.WSState.t()}

auto_moderation_rule_update()

@type auto_moderation_rule_update() ::
  {:AUTO_MODERATION_RULE_UPDATE, Nostrum.Struct.AutoModerationRule.t(),
   Nostrum.Struct.WSState.t()}

channel_create()

@type channel_create() ::
  {:CHANNEL_CREATE, Nostrum.Struct.Channel.t(), Nostrum.Struct.WSState.t()}

Dispatched when a channel is created.

Starting from API and Gateway V8, this will never be sent for a DM.

channel_delete()

@type channel_delete() ::
  {:CHANNEL_DELETE, Nostrum.Struct.Channel.t(), Nostrum.Struct.WSState.t()}

channel_pins_ack()

@type channel_pins_ack() :: {:CHANNEL_PINS_ACK, map(), Nostrum.Struct.WSState.t()}

channel_pins_update()

@type channel_pins_update() ::
  {:CHANNEL_PINS_UPDATE, Nostrum.Struct.Event.ChannelPinsUpdate.t(),
   Nostrum.Struct.WSState.t()}

channel_update()

@type channel_update() ::
  {:CHANNEL_UPDATE,
   {old_channel :: Nostrum.Struct.Channel.t() | nil,
    new_channel :: Nostrum.Struct.Channel.t()}, Nostrum.Struct.WSState.t()}

Dispatched when a channel is updated.

old_channel will be nil when the pre-update channel could not be fetched from the cache.

event()

guild_audit_log_entry_create()

@type guild_audit_log_entry_create() ::
  {:GUILD_AUDIT_LOG_ENTRY_CREATE, Nostrum.Struct.Guild.AuditLogEntry.t(),
   Nostrum.Struct.WSState.t()}

guild_available()

@type guild_available() ::
  {:GUILD_AVAILABLE, new_guild :: Nostrum.Struct.Guild.t(),
   Nostrum.Struct.WSState.t()}

guild_ban_add()

@type guild_ban_add() ::
  {:GUILD_BAN_ADD, Nostrum.Struct.Event.GuildBanAdd.t(),
   Nostrum.Struct.WSState.t()}

guild_ban_remove()

@type guild_ban_remove() ::
  {:GUILD_BAN_REMOVE, Nostrum.Struct.Event.GuildBanRemove.t(),
   Nostrum.Struct.WSState.t()}

guild_create()

@type guild_create() ::
  {:GUILD_CREATE, new_guild :: Nostrum.Struct.Guild.t(),
   Nostrum.Struct.WSState.t()}

guild_delete()

@type guild_delete() ::
  {:GUILD_DELETE,
   {old_guild :: Nostrum.Struct.Guild.t(), unavailable :: boolean()},
   Nostrum.Struct.WSState.t()}

guild_emojis_update()

@type guild_emojis_update() ::
  {:GUILD_EMOJIS_UPDATE,
   {guild_id :: integer(), old_emojis :: [Nostrum.Struct.Emoji.t()],
    new_emojis :: [Nostrum.Struct.Emoji.t()]}, Nostrum.Struct.WSState.t()}

guild_integrations_update()

@type guild_integrations_update() ::
  {:GUILD_INTEGRATIONS_UPDATE, Nostrum.Struct.Event.GuildIntegrationsUpdate.t(),
   Nostrum.Struct.WSState.t()}

guild_member_add()

@type guild_member_add() ::
  {:GUILD_MEMBER_ADD,
   {guild_id :: integer(), new_member :: Nostrum.Struct.Guild.Member.t()},
   Nostrum.Struct.WSState.t()}

guild_member_remove()

@type guild_member_remove() ::
  {:GUILD_MEMBER_REMOVE,
   {guild_id :: integer(), old_member :: Nostrum.Struct.Guild.Member.t()},
   Nostrum.Struct.WSState.t()}

Dispatched when somebody leaves a guild.

In case the guild member intent is enabled but not the guild intent, nostrum may not cache the actual guild, and thus be unable to provide full information about members leaving guilds. In that case, this event receives the guild ID and a partial member object with the leaving user as provided by Discord, but no information about the user's state on the guild.

guild_member_update()

@type guild_member_update() ::
  {:GUILD_MEMBER_UPDATE,
   {guild_id :: integer(), old_member :: Nostrum.Struct.Guild.Member.t() | nil,
    new_member :: Nostrum.Struct.Guild.Member.t()}, Nostrum.Struct.WSState.t()}

Dispatched when a guild member is updated.

old_member will be nil when the pre-update member could not be fetched from the cache.

guild_members_chunk()

@type guild_members_chunk() ::
  {:GUILD_MEMBERS_CHUNK, map(), Nostrum.Struct.WSState.t()}

guild_role_create()

@type guild_role_create() ::
  {:GUILD_ROLE_CREATE,
   {guild_id :: integer(), new_role :: Nostrum.Struct.Guild.Role.t()},
   Nostrum.Struct.WSState.t()}

guild_role_delete()

@type guild_role_delete() ::
  {:GUILD_ROLE_DELETE,
   {guild_id :: integer(), old_role :: Nostrum.Struct.Guild.Role.t()},
   Nostrum.Struct.WSState.t()}

guild_role_update()

@type guild_role_update() ::
  {:GUILD_ROLE_UPDATE,
   {guild_id :: integer(), old_role :: Nostrum.Struct.Guild.Role.t() | nil,
    new_role :: Nostrum.Struct.Guild.Role.t()}, Nostrum.Struct.WSState.t()}

Dispatched when a role on a guild is updated.

old_role will be nil when the pre-update role could not be fetched from the cache.

guild_scheduled_event_create()

@type guild_scheduled_event_create() ::
  {:GUILD_SCHEDULED_EVENT_CREATE, Nostrum.Struct.Guild.ScheduledEvent.t(),
   Nostrum.Struct.WSState.t()}

guild_scheduled_event_delete()

@type guild_scheduled_event_delete() ::
  {:GUILD_SCHEDULED_EVENT_DELETE, Nostrum.Struct.Guild.ScheduledEvent.t(),
   Nostrum.Struct.WSState.t()}

guild_scheduled_event_update()

@type guild_scheduled_event_update() ::
  {:GUILD_SCHEDULED_EVENT_UPDATE, Nostrum.Struct.Guild.ScheduledEvent.t(),
   Nostrum.Struct.WSState.t()}

guild_scheduled_event_user_add()

@type guild_scheduled_event_user_add() ::
  {:GUILD_SCHEDULED_EVENT_USER_ADD,
   Nostrum.Struct.Event.GuildScheduledEventUserAdd.t(),
   Nostrum.Struct.WSState.t()}

guild_scheduled_event_user_remove()

@type guild_scheduled_event_user_remove() ::
  {:GUILD_SCHEDULED_EVENT_USER_REMOVE,
   Nostrum.Struct.Event.GuildScheduledEventUserRemove.t(),
   Nostrum.Struct.WSState.t()}

guild_stickers_update()

@type guild_stickers_update() ::
  {:GUILD_STICKERS_UPDATE,
   {guild_id :: integer(), old_stickers :: [Nostrum.Struct.Sticker.t()],
    new_stickers :: [Nostrum.Struct.Sticker.t()]}, Nostrum.Struct.WSState.t()}

guild_unavailable()

@type guild_unavailable() ::
  {:GUILD_UNAVAILABLE,
   unavailable_guild :: Nostrum.Struct.Guild.UnavailableGuild.t(),
   Nostrum.Struct.WSState.t()}

guild_update()

@type guild_update() ::
  {:GUILD_UPDATE,
   {old_guild :: Nostrum.Struct.Guild.t(),
    new_guild :: Nostrum.Struct.Guild.t()}, Nostrum.Struct.WSState.t()}

integration_create()

(since 0.5.1)
@type integration_create() ::
  {:INTEGRATION_CREATE, Nostrum.Struct.Guild.Integration.t(),
   Nostrum.Struct.WSState.t()}

integration_delete()

(since 0.5.1)
@type integration_delete() ::
  {:INTEGRATION_DELETE, Nostrum.Struct.Event.GuildIntegrationDelete.t(),
   Nostrum.Struct.WSState.t()}

integration_update()

(since 0.5.1)
@type integration_update() ::
  {:INTEGRATION_UPDATE, Nostrum.Struct.Guild.Integration.t(),
   Nostrum.Struct.WSState.t()}

Different from guild_integrations_update/0 in that more than only the guild_id is provided

interaction_create()

@type interaction_create() ::
  {:INTERACTION_CREATE, Nostrum.Struct.Interaction.t(),
   Nostrum.Struct.WSState.t()}

message_ack()

@type message_ack() :: {:MESSAGE_ACK, map(), Nostrum.Struct.WSState.t()}

message_create()

@type message_create() ::
  {:MESSAGE_CREATE, message :: Nostrum.Struct.Message.t(),
   Nostrum.Struct.WSState.t()}

message_delete()

@type message_delete() ::
  {:MESSAGE_DELETE, Nostrum.Struct.Event.MessageDelete.t(),
   Nostrum.Struct.WSState.t()}

message_delete_bulk()

@type message_delete_bulk() ::
  {:MESSAGE_DELETE_BULK, Nostrum.Struct.Event.MessageDeleteBulk.t(),
   Nostrum.Struct.WSState.t()}

message_poll_vote_add()

@type message_poll_vote_add() ::
  {:MESSAGE_POLL_VOTE_ADD, Nostrum.Struct.Event.PollVoteChange.t(),
   Nostrum.Struct.WSState.t()}

Dispatched when a user adds a vote to a poll.

message_poll_vote_remove()

@type message_poll_vote_remove() ::
  {:MESSAGE_POLL_VOTE_REMOVE, Nostrum.Struct.Event.PollVoteChange.t(),
   Nostrum.Struct.WSState.t()}

Dispatched when a user removes a vote from a poll.

message_reaction_add()

@type message_reaction_add() ::
  {:MESSAGE_REACTION_ADD, Nostrum.Struct.Event.MessageReactionAdd.t(),
   Nostrum.Struct.WSState.t()}

message_reaction_remove()

@type message_reaction_remove() ::
  {:MESSAGE_REACTION_REMOVE, Nostrum.Struct.Event.MessageReactionRemove.t(),
   Nostrum.Struct.WSState.t()}

message_reaction_remove_all()

@type message_reaction_remove_all() ::
  {:MESSAGE_REACTION_REMOVE_ALL,
   Nostrum.Struct.Event.MessageReactionRemoveAll.t(),
   Nostrum.Struct.WSState.t()}

message_reaction_remove_emoji()

@type message_reaction_remove_emoji() ::
  {:MESSAGE_REACTION_REMOVE_EMOJI,
   Nostrum.Struct.Event.MessageReactionRemoveEmoji.t(),
   Nostrum.Struct.WSState.t()}

message_update()

@type message_update() ::
  {:MESSAGE_UPDATE,
   {old_message :: Nostrum.Struct.Message.t() | nil,
    updated_message :: Nostrum.Struct.Message.t()}, Nostrum.Struct.WSState.t()}

presence_update()

@type presence_update() ::
  {:PRESENCE_UPDATE,
   {guild_id :: integer(), old_presence :: map() | nil, new_presence :: map()},
   Nostrum.Struct.WSState.t()}

Dispatched when a user's presence is updated.

old_presence will be nil when the pre-update presence could not be fetched from the cache.

ready()

@type ready() :: {:READY, Nostrum.Struct.Event.Ready.t(), Nostrum.Struct.WSState.t()}

resumed()

@type resumed() :: {:RESUMED, map(), Nostrum.Struct.WSState.t()}

thread_create()

@type thread_create() ::
  {:THREAD_CREATE, Nostrum.Struct.Channel.t(), Nostrum.Struct.WSState.t()}

Dispatched when a thread is created or when added to a private thread

thread_delete()

@type thread_delete() ::
  {:THREAD_DELETE, Nostrum.Struct.Channel.t() | :noop,
   Nostrum.Struct.WSState.t()}

Dispatched when a thread is deleted, if the thread was cached, contains the original thread, otherwise contains :noop

thread_list_sync()

@type thread_list_sync() ::
  {:THREAD_LIST_SYNC, Nostrum.Struct.Event.ThreadListSync.t(),
   Nostrum.Struct.WSState.t()}

Dispatched when gaining access to a channel

thread_member_update()

@type thread_member_update() ::
  {:THREAD_MEMBER_UPDATE, Nostrum.Struct.ThreadMember.t(),
   Nostrum.Struct.WSState.t()}

Dispatched when a ThreadMember for the current user is updated

thread_members_update()

@type thread_members_update() ::
  {:THREAD_MEMBERS_UPDATE, Nostrum.Struct.Event.ThreadMembersUpdate.t(),
   Nostrum.Struct.WSState.t()}

Dispatched when member(s) are added or removed from a thread

thread_update()

@type thread_update() ::
  {:THREAD_UPDATE,
   {old_thread :: Nostrum.Struct.Channel.t() | nil,
    new_thread :: Nostrum.Struct.Channel.t()}, Nostrum.Struct.WSState.t()}

typing_start()

@type typing_start() ::
  {:TYPING_START, Nostrum.Struct.Event.TypingStart.t(),
   Nostrum.Struct.WSState.t()}

user_settings_update()

@type user_settings_update() :: no_return()

user_update()

@type user_update() ::
  {:USER_UPDATE,
   {old_user :: Nostrum.Struct.User.t() | nil,
    new_user :: Nostrum.Struct.User.t()}, Nostrum.Struct.WSState.t()}

Dispatched when a user is updated.

old_user will be nil when the pre-update user could not be fetched from the cache.

voice_incoming_packet()

(since 0.6.0)
@type voice_incoming_packet() ::
  {:VOICE_INCOMING_PACKET, Nostrum.Voice.rtp_opus(),
   Nostrum.Struct.VoiceWSState.t()}

Dispatched when async listening is enabled and another user is actively speaking

The second tuple element is an Nostrum.Voice.rtp_opus/0, which is a tuple with RTP header information and an opus packet. While someone is actively talking, you can expect about 50 events per second per speaking user.

Note that the third tuple element is of type Nostrum.Struct.VoiceWSState.t/0 instead of Nostrum.Struct.WSState.t/0. That struct contains a Nostrum.Struct.VoiceWSState.ssrc_map/0 that can determine the speaking user based on the SSRC.

voice_ready()

(since 0.5.0)
@type voice_ready() ::
  {:VOICE_READY, Nostrum.Struct.Event.VoiceReady.t(),
   Nostrum.Struct.VoiceWSState.t()}

Dispatched when the bot is ready to begin sending audio after joining a voice channel

Note that the third tuple element is of type Nostrum.Struct.VoiceWSState.t/0 instead of Nostrum.Struct.WSState.t/0.

voice_server_update()

@type voice_server_update() ::
  {:VOICE_SERVER_UPDATE, Nostrum.Struct.Event.VoiceServerUpdate.t(),
   Nostrum.Struct.WSState.t()}

voice_speaking_update()

@type voice_speaking_update() ::
  {:VOICE_SPEAKING_UPDATE, Nostrum.Struct.Event.SpeakingUpdate.t(),
   Nostrum.Struct.VoiceWSState.t()}

Dispatched when the bot starts or stops speaking

Note that the third tuple element is of type Nostrum.Struct.VoiceWSState.t/0 instead of Nostrum.Struct.WSState.t/0.

voice_state_update()

@type voice_state_update() ::
  {:VOICE_STATE_UPDATE, Nostrum.Struct.Event.VoiceState.t(),
   Nostrum.Struct.WSState.t()}

webhooks_update()

@type webhooks_update() :: {:WEBHOOKS_UPDATE, map(), Nostrum.Struct.WSState.t()}

Callbacks

handle_event(event)

@callback handle_event(event()) :: any()

Callback used to handle events.

Event

event is a tuple describing the event. The tuple will include information in the following format:

{event_name, {event_payload(s)}, WSState.t}

For example, a message create will look like this

{:MESSAGE_CREATE, Nostrum.Struct.Message.t, WSState.t}

In some cases there will be multiple payloads when something is updated, so as to include the new and the old versions. In the event of there being two payloads, the old payload will always be first, followed by the new payload.

{:USER_UPDATE, {old_user :: Nostrum.Struct.User.t, new_user :: Nostrum.Struct.User.t}, WSState.t()}

Note that the availability of the old data depends on how nostrum's caching is configured. If the updated object cannot be found in the cache before the update, you will receive nothing.

For a full listing of events, please see Nostrum.Consumer.event/0.