Event filtering
A client controls Dispatch traffic with Lazy Request subscriptions and the Identify ignored_events list. Guild availability, permissions and sharding also restrict delivery.
FiveCord has no intents field, no intent close code, and no privileged-intent approval. A client ported from a protocol that uses intents replaces its intent mask with those mechanisms.
The gates
Section titled “The gates”FiveCord evaluates a guild-scoped Dispatch against these gates in order.
| Gate | Name | What it decides |
|---|---|---|
| 1 | Guild availability | Whether the guild dispatches anything except Guild Update |
| 2 | Permission and visibility | Which sessions may see the event at all |
| 3 | Guild subscription state | Whether a passive session in a guild with more than 250 members still receives it, as Active and passive guilds lists |
| 4 | Session-level filters | Whether the shard filter, and then the ignored_events list, drops it inside the session after the guild has already chosen the recipients |
A guild with the UNAVAILABLE_FOR_EVERYONE or UNAVAILABLE_FOR_EVERYONE_BUT_STAFF feature fails gate 1. UNAVAILABLE_FOR_EVERYONE_BUT_STAFF decides what a session receives when it connects. A staff session receives the guild’s full state, and every other session receives an unavailable stub. Gate 1 has no staff exemption, so a staff session also receives nothing but Guild Update while the feature is set.
An account-scoped Dispatch skips gates 1 through 3 and is subject only to gate 4. Direct message traffic, relationship changes, and account record changes arrive that way.
Permission and visibility
Section titled “Permission and visibility”The guild resolves each event to one of these recipient sets.
| Event class | Events | Recipients |
|---|---|---|
| Channel-scoped | Channel Create, Channel Update, Channel Delete1, Message Create, Message Delete Bulk, Typing Start, Channel Pins Update, Webhooks Update | Sessions that can view the channel |
| Message-access filtered | Message Update, Message Delete, Message Reaction Add, Message Reaction Remove, Message Reaction Remove All, Message Reaction Remove Emoji | Sessions that can view the channel and can access that message |
| Invite | Invite Create, Invite Delete | Sessions holding MANAGE_CHANNELS on the invite’s channel |
| Audit log | Guild Audit Log Entry Create | Sessions holding VIEW_AUDIT_LOG in the guild |
| Guild-wide | Everything else | Every session connected to the guild |
1 Channel Delete is filtered against the guild state as it was before the deletion, so the session that could see the channel is the session that learns it is gone
Every one of those sets excludes a session that has not yet received the guild’s initial state.
Channel visibility is VIEW_CHANNEL on the channel, plus extensions. A category is visible when at least one of its children is visible. A user with a live voice connection in a channel keeps virtual access to it whenever the channel would otherwise stop being visible. That covers a role or overwrite change removing VIEW_CHANNEL, and a move into a channel the user cannot view. Virtual access is keyed by user, so it applies to every session of that user. It is dropped when the user’s voice connection to the channel ends.
Message access is READ_MESSAGE_HISTORY on the channel. Without that permission a session still receives events for messages newer than the guild’s message history cutoff. A guild that sets no cutoff offers no such fallback, so a session without READ_MESSAGE_HISTORY receives none of the message-access filtered events there.
Channel Update Bulk contains only channels the recipient can view. If none are visible, no event is sent.
Voice State Update takes its own path. The guild sends it straight to the sessions that can view the channel the voice state names, or, when the state names no channel, the channel the user just left. A voice state with no connection ID is not broadcast at all.
Excluding the acting session
Section titled “Excluding the acting session”Message Reaction Add and Message Reaction Remove accept a session_id on the originating HTTP request. FiveCord excludes that session from the resulting Dispatch and strips the field before it sends the payload. Every other mutation delivers its Dispatch to the acting session like any other eligible session.
Active and passive guilds
Section titled “Active and passive guilds”A user session is passive in every guild until Lazy Request marks that guild active: true. A bot session is never passive. A guild with 250 members or fewer is active for every session, so the rule below applies only to a passive user session in a guild with more than 250 members.
Such a session receives exactly this set:
- Guild Update
- Guild Delete
- Guild Role Update and Guild Role Update Bulk
- Channel Create, Channel Update, Channel Update Bulk, and Channel Delete
- Guild Audit Log Entry Create
- Passive Updates
- Message Create when the message mentions the session’s user
- Guild Member Update and Guild Member Remove when the subject is the session’s own user
Every other Dispatch the guild produces is suppressed:
- Message Update, Message Delete, and Message Delete Bulk
- Every reaction event
- Invite Create and Invite Delete
- Channel Pins Update
- Webhooks Update
- Guild Member Add
- Guild Role Create and Guild Role Delete
- Guild Ban Add and Guild Ban Remove
- Guild Emojis Update and Guild Stickers Update
Voice State Update never reaches this gate. It takes the separate path described above, so a passive session in a large guild still receives it for every channel it can view.
A message mentions the session’s user when the payload names that user in mentions, names one of that user’s roles in mention_roles, sets mention_here, or sets mention_everyone. The guild reads only the first 100 entries of mention_roles, so a message that mentions more roles than that can miss a passive recipient.
Every 30 seconds a passive session receives Passive Updates. The payload has the changed per-channel last_message_id watermarks and the changed voice states for the channels it can view, so the session keeps unread state and voice rosters correct without the suppressed message events. A cycle that finds nothing changed sends nothing.
Typing is decided separately
Section titled “Typing is decided separately”Typing Start never follows the rule above. When the session set typing for the guild through Lazy Request, that value alone decides delivery. Without an override the event follows the active state, so a passive session in a large guild does not receive it.
The override applies to every session, including a bot session. The only way for a bot to stop Typing Start in one guild and keep it in other guilds is to set typing to false for that guild.
Member lists
Section titled “Member lists”Guild Member List Update has its own subscription. A session receives it only for a channel it named in member_list_channels, and only while it can view that channel and holds VIEW_CHANNEL_MEMBERS on it. One session holds at most one member list subscription per guild.
Presence subscriptions
Section titled “Presence subscriptions”Presence Update skips gates 1 through 3 and is subject only to gate 4. A guild dispatches it only to a session that named the subject in the members array of a Lazy Request, that can view at least one channel the subject can view, and that does not belong to the subject.
A session that no longer shares a viewable channel with the subject is dropped from that subject’s subscriber set, so a client that regains access MUST resend members to restore delivery. Each members array replaces the session’s previous subscription set for that guild.
A bot session holds no friend or group direct message presence subscriptions, so a bot receives a presence through this guild path alone.
Ignored events
Section titled “Ignored events”Identify accepts ignored_events, an array of up to 256 Dispatch event names. FiveCord upper-cases and deduplicates the names at Identify. An absent field and a JSON null both mean the empty list. FiveCord closes the connection with 4002 and reason Invalid identify payload for any other value that is not an array of strings, and for any array of more than 256 entries. A Dispatch whose t appears in the list is dropped and never enters the replay buffer.
{ "op": 2, "d": { "token": "...", "properties": {"os": "Linux", "browser": "bot", "device": "bot"}, "ignored_events": ["TYPING_START", "PRESENCE_UPDATE"] }}Message Create is the one exception. FiveCord delivers it even when MESSAGE_CREATE is ignored, if the message names the session’s user in mentions, sets mention_here, or sets mention_everyone. A role mention does not defeat the list.
A suppressed Dispatch consumes no sequence number, so a client MUST NOT expect a gap in the sequence where the list dropped one.
The list is fixed for the lifetime of the session. Changing it requires a new Identify.
The shard filter
Section titled “The shard filter”A session that identified with a shard pair whose shard_id is not 0 drops every Dispatch that does not name a guild. A Dispatch names a guild through a non-empty guild_id, or through a non-empty id on a Guild Create, Guild Update, Guild Delete, or Guild Sync payload. Rate Limited, Guild Counts Update, and Channel Member Counts Update answer a command the session sent, and each passes the gate whatever its payload holds.
Account-level traffic, direct message traffic, relationship changes, and calls therefore never reach a session on a shard other than 0.
Sessions on shard 0, and sessions that identified without a shard pair, filter nothing at this gate. FiveCord still filters guilds by shard at Identify, as Sharding describes, so a shard 0 session is only ever connected to the guilds its shard owns.
What a bot should send
Section titled “What a bot should send”A bot session is never passive, so active changes nothing for it and a typical bot needs no Lazy Request at all. It shapes traffic with ignored_events and pulls members with Request Guild Members.
A bot that does not process typing or reactions saves the most by ignoring TYPING_START, MESSAGE_REACTION_ADD, and MESSAGE_REACTION_REMOVE. Ignoring PRESENCE_UPDATE saves a bot nothing, because a bot receives no presence until it subscribes to one.