Skip to navigation

SDK events

Subscribing to the Aegis event socket.
View as Markdown

aegis.music carries the events WebSocket. Subscribing is the only thing that opens it.

const off = aegis.music.on('trackStarted', ({ guildId, track }) => {
console.log(`${track.title} started in ${guildId}`)
})
off() // unsubscribes

Subscribing

on(event, listener)Fires every time. Returns an unsubscribe function
once(event, listener)Fires once, then unsubscribes itself
off(event, listener)Removes a listener by reference
listeningWhether the socket is currently open
disconnect()Closes permanently

The returned unsubscribe function and off do the same thing — use whichever reads better.

off needs the same function reference you subscribed with, which is why the returned function exists.

function onTrackStarted(event) { /* ... */ }
aegis.music.on('trackEnded', onTrackStarted)
aegis.music.off('trackEnded', onTrackStarted)

Events

EventPayload
trackStartedbotId, guildId, track
trackEndedbotId, guildId, reason
queueEmptiedbotId, guildId
playerClosedbotId, guildId, reason ('idle' | 'disconnected')
botStoppedbotId, reason

MUSIC_EVENTS holds the same list as a runtime array.

Payload types are enforced in both directions, so a typo or a field that does not belong to that event is a compile error:

aegis.music.on('queueEmptied', (data) => data.track)
// ^ Type 'queueEmptied' has no 'track'

Lifecycle

The socket opens lazily on the first subscription — constructing a client does not connect anything.

It closes when the last listener goes away, whether through off or the returned unsubscribe function. Nothing left to hear means nothing to keep open.

An unexpected close schedules a reconnect after 5 seconds, but only while a listener still exists. The delay is fixed: there is no backoff and no retry cap, so a socket that keeps failing will keep retrying every 5 seconds for as long as you are subscribed.

disconnect() is permanent. It marks the socket closed, and subscribing again afterwards will not reopen it. Treat it as shutting the client down for events, not as a pause.

Payload shape

Listeners receive the whole message, type field included — not just the parts that vary. A non-JSON frame is logged and skipped rather than thrown, and a listener that throws is isolated so the remaining listeners still run.

Custom sockets

The default socket uses the global WebSocket. If you need to supply your own implementation — in a test, or to add instrumentation — pass a factory:

new Aegis({
apiKey,
createSocket: (url, headers) => myWebSocket(url, headers),
})

The factory receives the resolved wss:// URL and the Authorization header, and must return something shaped like a WebSocket.

createSocket is accepted at runtime but is not declared on AegisOptions, so TypeScript rejects it as an excess property on an object literal. Cast the options object if you use it.