Connection Methods

October 22, 2020 ยท View on GitHub

Connections can be made over two methods:

  • HTTP
  • WebSocket

Metadata

Andesite metadata is exposed by all default connection methods.

The current values are

nametypedescription
versionstringversion of the node
version-majorstringmajor version of the node
version-minorstringminor version of the node
version-revisionstringrevision version of the node
version-commitstringcommit hash of the node
version-buildintegerbuild number provided by the CI
node-regionstringregion defined in the config
node-idstringid defined in the config
enabled-sourceslist of stringslist of sources enabled in the config
loaded-pluginslist of stringslist of plugins loaded

Connection methods may choose to format these in a more idiomatic format.

HTTP

All requests must have an Authorization header or password query param with the password* defined in the config. Furthermore, all routes related to players, including the WebSocket routes, must have an User-Id header or user-id query param with the bot's id. For both of them, the header takes priority.

If an error happens, an error object is returned. Since these objects can get quite big, it's possible to enable a shorter version, which does not send stack frames, by providing a header named Andesite-Short-Errors or a query param named shortErrors. Their values can be anything, as long as they are present shorter error messages are returned.

Node metadata is exposed in response headers as dash (-) separated Title Case identifiers, prepended with Andesite-, eg version-major becomes Andesite-Version-Major. Lists have their values joined by a string, eg [a, b] becomes a,b.

* If the password isn't defined or is null this header may be omitted.

Player routes

routedescriptionreturns player
POST /player/voice-server-updateprovides a voice server update event
GET /player/:guild_idreturns the state of the player for that guildx
POST /player/:guild_id/playplays a track on the guild. Body must be a valid play payloadx
POST /player/:guild_id/stopstops playing audio on the guild.x
PATCH /player/:guild_id/mixerconfigures the mixer for the guild. Body must be a valid mixer update payloadx
PATCH /player/:guild_id/filtersconfigures the audio filters for the guild. Body must be a valid filter update payloadx
PATCH /player/:guild_id/pauseupdate pause state of the player. Body must be a valid pause payloadx
PATCH /player/:guild_id/seekupdate the track position. Body must be a valid seek payloadx
PATCH /player/:guild_id/volumeupdate volume of the player. Body must be a valid volume payloadx
PATCH /player/:guild_idupdate the player. Body must be a valid update payloadx
DELETE /player/:guild_iddestroys the player

Other routes

routedescription
GET /statsreturns stats about the node
GET /stats/lavalinkreturns lavalink compatible stats about the node
GET /loadtracksloads tracks from the identifier query param. Returns a loaded tracks response
GET /decodetrackreturns metadata for a track in the track query param. Returns a track info object
POST /decodetrackreturns metadata for a track in the track body property. Returns a track info object
POST /decodetracksreturns metadata for the tracks in the request body. Returns an array of track info objects

WebSocket

  • The regular websocket is available on the /websocket route.
  • A (mostly*) lavalink compatible websocket is available by default on the / route.

Websocket authorization is the same as HTTP.

The metadata payload sent on connection start provides the metadata, instead of providing it through HTTP headers. The values are sent with lowerCamelCase keys and the appropriate json types. Lists are converted into arrays, other values are sent as-is.

All payloads must be valid json objects. If parsing fails, the socket is closed with code 4001. Both text and binary frames are accepted, as long as the data is valid UTF 8.

All payloads must have an op key, which must be a string. This restriction does not apply to custom handling of payloads done by plugins.

Responses from the server will always contain an op

Payloads can override the User-Id header by providing an userId field. This override is valid only for that payload. All responses will have an userId field containing either the id provided in the override or the id provided in the headers during the websocket handshake.

Valid ops are:

opdescription
voice-server-updateprovides a voice server update. Payload must also be a valid voice server update object
playplays a track on the guild. Payload must also be a valid play object
mixerconfigures the mixer for the guild. Payload must also be a valid mixer update object
stopstops playing on the guild
pauseupdates the pause state on the guild. Payload must also be a valid pause object
seekupdates the track position. Payload must also be a valid seek object
volumeupdates the volume on the guild. Payload must also be a valid volume object
filtersupdates the player audio filters. Payload must also be a valid filter update object
updateupdates the player. Payload must also be a valid update object
destroydestroys the player. Resulting player update event will have a destroyed key with value of true
get-playerreturns the player state
get-statsreturns node stats
pingused to calculate the ping and/or get the user id used in the handshake header. sends the received payload back

Additionally, WebSockets offer a replay system, so events fired after a connection was closed can be replayed. During websocket connection, the server will send a header Andesite-Connection-Id. After the websocket connection is established, clients can send an event-buffer payload to enable buffering. When a connection is closed, events will be buffered for up to the timeout specified in the event-buffer payload. After that, all buffered events are discarded and buffering will stop. To get the missed events, clients must reconnect with a Andesite-Resume-Id header containing the value returned by the Andesite-Connection-Id received earlier. All IDs are single use and reconnects must save the new ID returned. To disable buffering, simply send an event-buffer payload with timeout of 0.

All commands that directly interact with players (updating it, changing it's state, etc) send a player update as a response.

Events that may be sent by the websocket are:

  • Connection ID (connection-id op, not sent on lavalink compat)
keytypedescription
idstringID of the connection
  • Metadata (metadata op, not sent on lavalink compat)
keytypedescription
dataobjectmap of metadata key to value. Values may be integers, strings or arrays of strings
  • Player Update (player-update op, playerUpdate on lavalink compat)
keytypedescription
userIdstringID of the user that owns the player
guildIdstringID of the guild that owns the player
stateplayerState of the player
  • Event (event op)
keytypedescription
typestringOne of TrackStartEvent, TrackEndEvent, TrackExceptionEvent, TrackStuckEvent, WebSocketClosedEvent
userIdstringID of the user affected by this event
guildIdstringID of the guild affected by this event

Additional event-specific data is also included:

  • reason (string), code (integer), byRemote (boolean) for WebSocketClosedEvent

  • track (string) for TrackStartEvent

  • track (string), reason (string), mayStartNext (boolean) for TrackEndEvent

  • track (string), error (string), exception(short error) for TrackExceptionEvent

  • track (string), thresholdMs (integer) for TrackStuckEvent

  • Pong (pong op)

keytypedescription
userIdstringdefault user ID for this connection, provided on the ws handshake
  • Stats (stats op)
keytypedescription
userIdstringdefault user ID for this connection, provided on the ws handshake
statsobjectmap containing the node stats

* Lavalink resumes are not supported.

Browser

The WebSocket endpoints can be accessed from a browser with a few small changes to how the connection is established.

The password must be provided as a websocket extension or query param.

The user id must be provided as a query param.

var ws = new WebSocket("ws://my.node/websocket?user-id=1234&password=youshallnotpass")

or

var ws = new WebSocket("ws://my.node/websocket?user-id=1234", "andesite-password:youshallnotpass")

After the connection is established, the API is identical to regular websockets.

Entities

Loaded Track(s)

keytypedescription
loadTypestringtype* of the response
trackstrack info[]/nullloaded tracks
playlistInfoplaylist info/nullmetadata of the loaded playlist
causeerror/nullerror that happened while loading tracks
severitystring/nullseverity of the error

* Type may be one of

  • TRACK_LOADED - tracks will only have one track, playlistInfo, cause and severity will be null.
  • SEARCH_RESULT - cause and severity will be null.
  • PLAYLIST_LOADED - cause and severity will be null.
  • NO_MATCHES - all other fields will be null.
  • LOAD_FAILED - tracks and playlistInfo will be null.

Playlist Info

keytypedescription
namestringname of the playlist
selectedTrackinteger/nullindex of the selected track in the tracks array, or null if no track is selected

Track Info

keytypedescription
trackstringbase64 encoded track
infotrack metadatametadata of the track

Track Metadata

keytypedescription
classstringclass name of the lavaplayer track
titlestringtitle of the track
authorstringauthor of the track
lengthintegerduration of the track, in milliseconds
identifierstringidentifier of the track
uristringuri of the track
isStreambooleanwhether or not the track is a livestream
isSeekablebooleanwhether or not the track supports seeking
positionintegercurrent position of the track

Player

keytypedescription
timestringcurrent unix timestamp on the node
positioninteger/nullposition of the current playing track, or null if nothing is playing
pausedbooleanwhether or not the player is paused
volumeintegerthe volume of the player
filtersobjectmap of filter name -> filter settings for each filter present
mixerobjectmap of mixer player id -> mixer player
mixerEnabledbooleanwhether or not the mixer is the current source of audio

Mixer Player

keytypedescription
timestringcurrent unix timestamp on the node
positioninteger/nullposition of the current playing track, or null if nothing is playing
pausedbooleanwhether or not the player is paused
volumeintegerthe volume of the player
filtersobjectmap of filter name -> filter settings for each filter present

Voice Server Update

keytypedescription
sessionIdstringsession ID for the current user in the event's guild
guildIdstringID of the guild
eventvoice-server-updatevoice server update event sent by discord

Play

keytypedescription
trackstringbase64 encoded lavaplayer track. If null, the player is stopped. Only use null for mixer players, for regular players use stop instead.
startinteger/nulltimestamp, in milliseconds, to start the track
endinteger/nulltimestamp, in milliseconds, to end the track
pauseboolean/nullwhether or not to pause the player
volumeinteger/nullvolume to set on the player
noReplacebooleanif true and a track is already playing/paused, this command is ignored

Pause

keytypedescription
pausebooleanwhether or not to pause the player

Seek

keytypedescription
positionintegertimestamp to set the current track to, in milliseconds

Volume

keytypedescription
volumeintegervolume to set on the player

Filter update

keytypedescription
equalizerequalizer/nullconfigures the equalizer
karaokekaraoke/nullconfigures the karaoke filter
timescaletimescale/nullconfigures the timescale filter
tremolotremolo/nullconfigures the tremolo filter
vibratovibrato/nullconfigures the vibrato filter
volumevolume/nullconfigures the volume filter

Update

keytypedescription
pauseboolean/nullwhether or not to pause the player
positioninteger/nulltimestamp to set the current track to, in milliseconds
volumeinteger/nullvolume to set on the player
filtersfilter update/nullconfiguration for the filters

Mixer Update

keytypedescription
enableboolean/nullif present, controls whether or not the mixer should be used
playersobjectmap of player id to play/update payloads for each mixer source

Event Buffer

keytypedescription
timeoutintegertimeout for event buffering, in milliseconds

Error

keytypedescription
classstringclass of the error
messagestring/nullmessage of the error
stackstack frame[]stacktrace of the error
causeerror/nullcause of the error
suppressederror[]suppressed errors

Stack Frame

keytypedescription
classLoaderstring/nullname of the classloader
moduleNamestring/nullname of the module
moduleVersionstring/nullversion of the module
classNamestringname of the class
methodNamestringname of the method
fileNamestring/nullname of the source file
lineNumberinteger/nullline in the source file
prettystringpretty printed version of this frame, as it would appear on Throwable#printStackTrace

Filters

Equalizer

keytypedescription
bandsband[]array of bands to configure

Band

keytypedescriptiondefault
bandinteger (0-14)band number to configure-
gainfloat ([-0.25, 1.0])value to set for the band0

Karaoke

keytypedefault
levelfloat1
monoLevelfloat1
filterBandfloat220
filterWidthfloat100

Timescale

keytypedescriptiondefault
speedfloat (> 0)speed to play music at1
pitchfloat (> 0)pitch to set1
ratefloat (> 0)rate to set1

Tremolo

keytypedefault
frequency (> 0)float2
depth (0 < x <= 1)float0.5

Vibrato

keytypedefault
frequency (0 < x <= 14)float2
depth (0 < x <= 1)float0.5

Volume {#update}

keytypedefault
volumefloat1