Gateway API

Whilst the HTTP API is useful for writing and querying, it’s unsuitable for creating responsive bots that need to react to events as they happen. Discord provides a Gateway which allows for bots to receive all relevant events in real time.

Chiru implements a CSP-based gateway wrapper which handles all of the tricky parts of the connection (reconnecting, heartbeating, and dispatching) automatically, with the run_gateway_loop() function. This uses multiple channels to communicate between your bot and the inner workings of the gateway code.

# The gateway function is a ``NoReturn``, as it loops forever; it needs to be ran in its
# own separate task. This task should be bound to the lifetime of your bot.
async with anyio.create_task_group() as nursery:
    # Return type is Write/Read for this, so theirs is Read for Outbound, and Write for Inbound.
    outgoing_ours, outgoing_theirs = anyio.create_memory_object_stream[OutgoingGatewayEvent]()
    incoming_theirs, incoming_ours = anyio.create_memory_object_stream[IncomingGatewayEvent]()

    p = partial(
        run_gateway_loop,
        initial_url="wss://gateway.discord.gg/",
        token=BOT_TOKEN,
        shard_id=0,
        shard_count=1,
        outbound_channel=outgoing_theirs,
        inbound_channel=incoming_theirs,
    )
    nursery.start_soon(p)

    async for message in incoming_ours:
        print(message)
async chiru.gateway.conn.run_gateway_loop(*, initial_url, token, shard_id, shard_count, outbound_channel, inbound_channel, intents=4194303)

Runs the gateway loop forever. This should be ran in its own task.

Parameters:
  • initial_url (str) – The initial URL to connect to the gateway to. This will only be used for the first connection; all subsequent connections will use the URL returned in the READY packet.

  • token (str) – The Bot token to use when identifying.

  • shard_id (int) – The shard ID that this gateway will use.

  • shard_count (int) – The number of shards in total that will be spawned, including this one.

  • outbound_channel (MemoryObjectReceiveStream[OutgoingGatewayEvent]) –

    The channel that outbound gateway events will be read from. This is the mechanism for sending control messages such as presence updates or user-initiated closes through the gateway.

    Incoming messages will be buffered automatically across reconnects, with messages that have failed to send being retried after reconnection.

  • inbound_channel (MemoryObjectSendStream[IncomingGatewayEvent]) –

    The channel that incoming gateway events will be sent to.

    This channel should, ideally, have a buffer size of zero to prevent less important events from clogging up the channel (as they are sent without waiting, and simply discarded if nobody is listening).

  • intents (int) –

    The Gateway Intents configuration that should be used for incoming events. By default, this is set to all intents.

    Note that Chiru’s high-level functionality won’t work without privileged intents, and the gateway code will fail unrecoverably if privileged intents are requested but not available.

Return type:

NoReturn

Gateway Events

Gateway events are divided into two different types; incoming and outgoing. As the names suggest, incoming events are only ever received and outgoing events are only ever sent. These inherit from their appropriate base classes.

Voidable Events

Certain incoming gateway events are marked as voidable events. These are events that are primarily used for statistics or logging, and otherwise are largely not useful for most bots. These events will not block the event channel and will simply be discarded if nobody is listening to the channel.

Outgoing Events

class chiru.gateway.event.OutgoingGatewayEvent

Bases: object

Marker interface for outgoing events towards the Discord gateway.

final class chiru.gateway.event.GatewayMemberChunkRequest

Bases: OutgoingGatewayEvent

Requests the member chunk for the provided guild. One of user_ids or query must be passed.

guild_id: int

The ID of the guild that chunks are being requested for.

user_ids: list[int]

The IDs of the users to get member data for. This may be empty if this chunk request is for all users in the guild.

query: str | None

The username prefix to request a member chunk for. Ignored if user_ids is non-empty.

limit: int | None

The maximum number of members to return. Ignored if user_ids is passed.

presences: bool

If True, presence data will be included.

nonce: str | None

A 32 character nonce to identify this payload at the receiving end.

__init__(*, guild_id, user_ids=NOTHING, query=None, limit=None, presences=False, nonce=None)

Method generated by attrs for class GatewayMemberChunkRequest.

Incoming Events

class chiru.gateway.event.IncomingGatewayEvent

Bases: object

Marker interface for incoming events from the Discord gateway.

shard_id: int

The shard ID this event came from. Used to uniquely identify events during multi-shard situations.

__init__(*, shard_id)

Method generated by attrs for class IncomingGatewayEvent.

final class chiru.gateway.event.GatewayHello

Bases: IncomingGatewayEvent

The HELLO event from the gateway. This is a voidable event.

heartbeat_interval: float

The time, in seconds, between subsequent heartbeats.

__init__(*, shard_id, heartbeat_interval)

Method generated by attrs for class GatewayHello.

final class chiru.gateway.event.GatewayReconnectRequested

Bases: IncomingGatewayEvent

Published when the gateway has a reconnect requested by the other side. This is a voidable event.

__init__(*, shard_id)

Method generated by attrs for class GatewayReconnectRequested.

final class chiru.gateway.event.GatewayHeartbeatSent

Bases: IncomingGatewayEvent

Published when the gateway is sending a heartbeat. This is a voidable event.

heartbeat_count: int

The number of heartbeats that we have sent, including this one.

sequence: int

The sequence sent alongside this heartbeat.

__init__(*, shard_id, heartbeat_count, sequence)

Method generated by attrs for class GatewayHeartbeatSent.

final class chiru.gateway.event.GatewayHeartbeatAck

Bases: IncomingGatewayEvent

Published when the gateway has received a heartbeat ack. This is a voidable event.

heartbeat_ack_count: int

The number of heartbeat acks that we have received, including this one.

__init__(*, shard_id, heartbeat_ack_count)

Method generated by attrs for class GatewayHeartbeatAck.

final class chiru.gateway.event.GatewayInvalidateSession

Bases: IncomingGatewayEvent

Published when our IDENTIFY or RESUME failed. This is a voidable event.

resumable: bool

If we can resume after this or not.

__init__(*, shard_id, resumable)

Method generated by attrs for class GatewayInvalidateSession.

final class chiru.gateway.event.GatewayDispatch

Bases: IncomingGatewayEvent

A single dispatch event from the gateway.

event_name: str

The internal, Discord-provided name of the event being dispatched.

sequence: int

The sequence number for this dispatch.

body: Mapping[str, Any]

The raw event body for this dispatch.

__init__(*, shard_id, event_name, sequence, body)

Method generated by attrs for class GatewayDispatch.