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
| Variant | Discord event | What it carries, when it fires |
|---|---|---|
Ready(user, guild_count) | READY | the bot’s own user; guild_count counts the guilds READY listed, which arrive as GuildCreate moments later |
MessageCreate(message) | MESSAGE_CREATE | the full message object |
MessageUpdate(update) | MESSAGE_UPDATE | the PARTIAL message: ids always present, other fields may be absent — see tadpole/model/message’s update_decoder |
MessageDelete(id, channel_id, guild_id) | MESSAGE_DELETE | ids only; guild_id is None in DMs |
Resumed | RESUMED | no payload modeled: RESUMED’s d is a trace list |
GuildCreate(guild) | GUILD_CREATE | the full guild object |
GuildDelete(unavailable) | GUILD_DELETE | the unavailable: true stub — only the id is guaranteed |
Unknown(name, raw) | any other name | the event name and the raw frame JSON, untouched |
Nothing here crashes a bot
- Any name tadpole does not model — new Discord events included —
decodes to
Unknownanddecodesucceeds. Known events this slice does not model are also data, not errors. - A modeled event whose payload no longer matches decodes to
Error(DecodeFailed)fromdecode— but the shard never forwards that failure. It converts it toUnknown(name, raw)and keeps running, so a handler seesUnknown, never a decode error. decodeis public for direct callers (tests, replay tools), who get the failure honestly instead:DecodeFailednames the event and the JSON path, and only fires for the six modeled events —Resumedand every unmodeled name cannot fail.
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
tadpole/bot— where events are deliveredtadpole/model/message— the two message shapes behind MESSAGE_CREATE/UPDATEtadpole/gateway/shard— the actor that decodes and forwards
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.
-
ResumedRESUMED: the session resumed and replayed missed events. No payload worth modeling: RESUMED’s
dis 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: trueobject 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.