tadpole/gateway/events

Typed gateway events: the Event type a handler receives, one variant per modeled Discord event plus Unknown for everything else. decode maps a dispatch frame’s name + raw payload to one variant; anything tadpole does not model yet lands in Unknown with the raw payload intact, so new Discord events degrade to data instead of crashing a bot. Stability: Growing.

When you reach for this

Indirectly, always: tadpole/bot delivers these to your handler, and matching on the variants is how a bot reacts to anything. Directly, when testing decoders or replaying captured payloads: decode takes the event name and the raw frame JSON.

Variant to Discord event

VariantDiscord eventWhat it carries, when it fires
Ready(user, guild_count)READYthe bot’s own user; guild_count counts the guilds READY listed, which arrive as GuildCreate moments later
MessageCreate(message)MESSAGE_CREATEthe full message object
MessageUpdate(update)MESSAGE_UPDATEthe PARTIAL message: ids always present, other fields may be absent — see tadpole/model/message’s update_decoder
MessageDelete(id, channel_id, guild_id)MESSAGE_DELETEids only; guild_id is None in DMs
ResumedRESUMEDno payload modeled: RESUMED’s d is a trace list
GuildCreate(guild)GUILD_CREATEthe full guild object
GuildDelete(unavailable)GUILD_DELETEthe unavailable: true stub — only the id is guaranteed
Unknown(name, raw)any other namethe event name and the raw frame JSON, untouched

Nothing here crashes a bot

Example

import tadpole/gateway/events

fn describe(event: events.Event) -> String {
  case event {
    events.MessageCreate(message) -> message.content
    events.Unknown(name, _raw) -> "unmodeled: " <> name
    _ -> ""
  }
}

See also

Types

pub type Event {
  Ready(ready_user: user.User, guild_count: Int)
  MessageCreate(message: message.Message)
  MessageUpdate(update: message.MessageUpdate)
  MessageDelete(
    id: ids.MessageId,
    channel_id: ids.ChannelId,
    guild_id: option.Option(ids.GuildId),
  )
  Resumed
  GuildCreate(guild: guild.Guild)
  GuildDelete(unavailable: guild.UnavailableGuild)
  Unknown(name: String, raw: String)
}

Constructors

  • Ready(ready_user: user.User, guild_count: Int)

    The bot’s own user plus how many guilds READY listed. Those guilds arrive as GUILD_CREATE moments later; until then they are unavailable.

  • MessageCreate(message: message.Message)

    MESSAGE_CREATE: a new message, decoded to the full model.

  • MessageUpdate(update: message.MessageUpdate)

    MESSAGE_UPDATE: the partial payload — ids always present, most fields may be absent. See tadpole/model/message’s MessageUpdate.

  • MessageDelete(
      id: ids.MessageId,
      channel_id: ids.ChannelId,
      guild_id: option.Option(ids.GuildId),
    )

    MESSAGE_DELETE: ids only, no content. guild_id is None for DMs.

  • Resumed

    RESUMED: the session resumed and replayed missed events. No payload worth modeling: RESUMED’s d is a trace list.

  • GuildCreate(guild: guild.Guild)

    GUILD_CREATE: a guild the bot can see, delivered per guild after READY (and again on outages resolving).

  • GuildDelete(unavailable: guild.UnavailableGuild)

    GUILD_DELETE: the payload shape is the unavailable: true object GUILD_DELETE carries; only the guild id is guaranteed.

  • Unknown(name: String, raw: String)

    Any event this version does not model, known or not. Name and raw payload are kept so callers can log, count, or hand-off; nothing here is ever a crash.

Values

pub fn decode(
  event_name: String,
  payload: String,
) -> Result(Event, error.TadpoleError)

Decode one dispatched gateway event. payload is the full frame JSON as frame.parse saw it — envelope and all, d included — because the shard never re-parses.

Modeled events decode to their variant and fail with DecodeFailed (event filled in) when Discord’s payload does not match. Every other name — including known events this slice does not model — decodes to Unknown and never fails. RESUMED never fails either: it carries no data, so any payload is accepted.

Search Document