Core API

This page defines the public top-level exports from sonolink.

Client

class sonolink.Client(client: DpyClientProto, *, node_cls: type[N] = ..., framework: Literal['discord.py'] = ...)[source]
class sonolink.Client(client: PycordClientProto, *, node_cls: type[N] = ..., framework: Literal['pycord'] = ...)
class sonolink.Client(client: DisnakeClientProto, *, node_cls: type[N] = ..., framework: Literal['disnake'] = ...)
class sonolink.Client(client: NextcordClientProto, *, node_cls: type[N] = ..., framework: Literal['nextcord'] = ...)
class sonolink.Client(client: Any, *, node_cls: type[N] = ..., framework: None = ...)

Represents a SonoLink client.

A client helps you manage all Node connections and players.

Parameters:
  • client (discord.Client (discord.py) | discord.Client (py-cord) | disnake.Client) – The Discord client this SonoLink client is attached to.

  • node_cls (type[Node]) – The class to use when creating new nodes. Defaults to Node.

  • framework (str | None) – The Discord framework to use. Accepted values are "discord.py", "pycord", "disnake" and "nextcord". When None, the framework is detected automatically from whichever library is installed. If no supported framework is found, a RuntimeError is raised. If multiple are present, the one already imported is preferred; if that is ambiguous, the first available is used and a warning is logged. Defaults to None.

Raises:

RuntimeError – No supported Discord framework meeting the minimum version requirements was found, or a sonolink.Client is already attached to the given Discord client.

clear_nodes() None[source]

Clears all Nodes from this Client.

async close() None[source]

Gracefully closes all Node connections and cleans up internal resources.

This will stop all active players and close the underlying websocket and HTTP sessions.

create_node(*, host: str, port: int, password: str, id: str | None = None, retries: int | None = None, resume_timeout: float = 60.0, cache_settings: CacheSettings | None = None, inactivity_settings: InactivitySettings | None = None, session: SessionType | None = None) N[source]
create_node(*, uri: str, password: str, id: str | None = None, retries: int | None = None, resume_timeout: float = 60.0, cache_settings: CacheSettings | None = None, inactivity_settings: InactivitySettings | None = None, session: SessionType | None = None) N

Creates a Node attached to this client.

Parameters:
  • password (str) – The password of the node.

  • uri (str | None) –

    The URI the node will connect to. You should only provide the base URI without any routes, as the library will do it for you. This is mutually exclusive with providing host and port.

    Changed in version 1.1.0: This is optional now to accommodate users who prefer providing host and port separately.

  • host (str | None) –

    The host of the node. This is mutually exclusive with providing uri.

    Added in version 1.1.0.

  • port (int | None) –

    The port of the node. This is mutually exclusive with providing uri.

    Added in version 1.1.0.

  • id (str | None) – The ID of this node. This is used internally to identify this node. If None is passed, it is generated automatically.

  • retries (int | None) – The amount of retries to attempt when connecting or reconnecting this node. Whenever the limit is reached, it closes the node automatically. If this is set to None, it retries indefinitely. Defaults to None.

  • resume_timeout (float) – The maximum amount of seconds a resume can take before closing the node. Defaults to 60.0.

  • cache_settings (CacheSettings | None) – The search result caching configuration. Defaults to CacheSettings.default().

  • inactivity_settings (InactivitySettings | None) – The inactivity configuration for all players connected to this node. If None is passed, it uses InactivitySettings.default().

  • session (aiohttp.ClientSession | curl_cffi.AsyncSession | None) – The session this node should use. If None is provided, creates one. Defaults to None.

  • auto_reconnect (bool) –

    Whether the node should attempt to reconnect automatically after an unexpected disconnect. Defaults to True.

    versionadded:: 1.2.0

Raises:

ValueError – Invalid combination of parameters. You must provide either uri or both host and port, but not all three.

Returns:

The node that was created.

Return type:

Node

async decode_track(encoded: str) Playable[source]

Decodes a track from its encoded data using the best Node available, obtained with Client.get_best_node().

When a track is fetched, the encoded data can be found under sonolink.rest.schemas.Track.encoded.

Parameters:

encoded (str) – The encoded data to resolve the track from.

Returns:

The decoded resolved track.

Return type:

sonolink.models.Playable

async decode_tracks(*encoded: str) list[Playable][source]

Bulk decode encoded tracks using the best Node available, obtained with Client.get_best_node().

Parameters:

*encoded (str) – The encoded data for each track to be decoded.

Returns:

The decoded resolved tracks.

Return type:

list[Playable]

get_best_node() N[source]

Returns the best available Node based on current load and connectivity.

Returns:

The node with the lowest penalty that is currently connected.

Return type:

Node

Raises:

RuntimeError – No nodes are currently connected to handle the request.

get_node(id: str, /) N | None[source]

Retrieves a Node by its ID.

Added in version 1.1.0.

Parameters:

id (str) – The ID of the node to retrieve.

Returns:

The node if found, otherwise None.

Return type:

Node | None

remove_node(identifier: str, /) None[source]

Removes a Node from this client.

Parameters:

identifier (str) – The ID of the node to remove.

async search_track(query: str, *, source: TrackSourceType | str = TrackSourceType.YOUTUBE) SearchResult[source]

Searches for query in the best Node available, obtained with Client.get_best_node().

Parameters:
  • query (str) – The query to search. This can be a full URL, or headed by hosts specified by any plugin.

  • source (TrackSourceType | str) – The source to search from. This is, essentially, providing a host to query. The library provides default source types under TrackSourceType, but custom ones can be passed with a raw string.

Returns:

The search result.

Return type:

SearchResult

async start() None[source]

Connects all registered nodes to their respective Lavalink servers.

This method should typically be called after the discord client is logged in, often within the setup_hook (discord.py) or on_connect (py-cord, disnake and nextcord) event.

property framework: Literal['discord.py', 'pycord', 'disnake', 'nextcord']

The Discord framework used by this client ("discord.py", "pycord", "disnake", or "nextcord").

property nodes: list[N]

The active nodes attached to this client.

Node

class sonolink.Node(*, client: Client[Any], uri: str, password: str, id: str | None = None, retries: int | None = None, resume_timeout: float = 60, cache_settings: CacheSettings | None = None, inactivity_settings: InactivitySettings, session: SessionType | None = None, auto_reconnect: bool = True)[source]

Represents a connectable Node.

Parameters:
  • client (sonolink.Client) – The SonoLink client this node is attached to.

  • uri (str) – The base URI for the Lavalink node. Do not include REST or websocket routes.

  • password (str) – The Lavalink server password used for both HTTP and websocket authentication.

  • id (str | None) – The identifier used to track this node inside the client. If None is passed, a random identifier is generated.

  • retries (int | None) – How many reconnect attempts should be made before the node gives up. If None is passed, reconnect attempts are unlimited.

  • resume_timeout (float) – The number of seconds Lavalink should keep a resumable session alive.

  • cache_settings (sonolink.models.CacheSettings | None) – Settings used for the node’s search-result cache. If None is passed, default cache settings are used.

  • inactivity_settings (sonolink.models.InactivitySettings) – Default inactivity behavior applied to players managed by this node.

  • session (aiohttp.ClientSession | curl_cffi.AsyncSession | None) – Optional pre-existing HTTP session to reuse for this node’s REST and websocket transport. If None is passed, the library creates one.

  • auto_reconnect (bool) – Whether the node should attempt to reconnect automatically after an unexpected disconnect.

async cleanup() None[source]

A function that may be overridden in order to add custom clean-up logic to a node.

This is automatically called by the library.

async close() None[source]

Closes the connection to this node.

All Players connected to it will stop playing.

This also closes all HTTP and WS sessions and connections.

This dispatches a on_node_close event.

async connect() None[source]

Connects this node.

This can only be done when the node has been attached to a pool.

create_player(*, volume: int | None = None, paused: bool | None = None, filters: Filters | None = None, queue_mode: QueueMode = QueueMode.NORMAL, autoplay_settings: AutoPlaySettings | None = None, history_settings: HistorySettings | None = None) Player[source]

Creates a player with extra configuration bound to this node.

Parameters:
  • volume (int | None) – The volume of the player, in percentage from 0 to 1000. Defaults to None.

  • paused (bool | None) – Whether the player should start paused. Defaults to None.

  • filters (Filters | None) – The filters to apply to the player. Defaults to None.

  • queue_mode (QueueMode) – The playback strategy for the queue. Defaults to QueueMode.NORMAL.

  • autoplay_settings (AutoPlaySettings | None) – The autoplay settings to set to this player. Defaults to None.

  • history_settings (HistorySettings | None) – The history settings to set to this player. Defaults to None.

Returns:

The player. This can be passed to the cls= kwarg on

Return type:

Player

async decode_track(encoded: str) Playable[source]

Decodes a track from its encoded data.

When a track is fetched, the encoded data can be found under sonolink.rest.schemas.Track.encoded.

Parameters:

encoded (str) – The encoded data to resolve the track from.

Returns:

The decoded resolved track.

Return type:

sonolink.models.Playable

async decode_tracks(*encoded: str) list[Playable][source]

Bulk decodes encoded tracks.

Parameters:

*encoded (str) – The encoded data for each track to be decoded.

Returns:

The decoded resolved tracks.

Return type:

list[Playable]

async disconnect_player(guild_id: int) None[source]

Force disconnects a player from this node connected to the provided guild ID.

Parameters:

guild_id (int) – The guild ID to disconnect the player from.

async fetch_info() ServerInfo[source]

Fetches the Lavalink server info this node is connected to.

Returns:

The server info.

Return type:

sonolink.models.ServerInfo

async fetch_player(guild_id: int) PlayerInfo[source]

Fetches a player from this node connected to the provided guild ID.

Usually, you should use Node.get_player instead of this method.

Parameters:

guild_id (int) – The guild ID the player is connected to.

Returns:

The player connected to the guild ID.

Return type:

PlayerInfo

async fetch_players() list[PlayerInfo][source]

Fetches all the players that are connected to this node.

This performs a fresh REST request for the current player states on the node.

Returns:

The players connected to this node.

Return type:

list[PlayerInfo]

get_player(guild_id: int, /) BasePlayer | None[source]

Gets a player connected to this node.

async reconnect() None[source]

Reconnects this node.

This can only be done when the node has been attached to a pool.

Added in version 1.2.0.

async search_track(query: str, *, source: TrackSourceType | str | None = None) SearchResult[source]

Searches for query in this Node.

Parameters:
  • query (str) – The query to search. This can be a full URL, or headed by hosts specified by any plugin.

  • source (TrackSourceType | str | None) – The source to search from. This is, essentially, providing a host to query. The library provides default source types under TrackSourceType, but custom ones can be passed with a raw string.

Returns:

The search result.

Return type:

SearchResult

async send(method: Literal['GET', 'POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS'], path: str, *, headers: Mapping[str, str] | None = None, params: Mapping[str, str] | None = None, json: dict[str, Any] | None = None, data: Any | None = None) dict[str, Any] | list[Any] | str | bytes | None[source]

Method for doing manual requests to the Lavalink node.

Warning

Usually you wouldn’t use this method. Please use the built in methods of Client, Node and Player, unless you need to send specific plugin data to Lavalink.

Using this method may have unwanted side effects on your players and/or nodes.

Parameters:
  • method (str | None) – The method to use when making this request. Available methods are “GET”, “POST”, “PATCH”, “PUT”, “DELETE” and “OPTIONS”. Defaults to “GET”.

  • path (str) – The path to make this request to. E.g. “stats”, which will translate to “/v4/stats”. Do not include the base URI of the node here or the “/v4” prefix.

  • headers (Mapping | None) – An optional dict of headers to send with this request. This is merged with the default headers used for the node, so you don’t have to include authentication headers here. E.g. {"X-Thing": "Value"}.

  • params (Mapping | None) – An optional dict of query parameters to send with your request. If you include your query parameters in the path parameter, do not pass them here as well. E.g. {"thing": 1, "other": 2} would equate to “?thing=1&other=2”.

  • json (dict | None) – The optional JSON data to send along with your request.

  • data (Any | None) – The optional data to send along with your request.

Returns:

The response body returned by Lavalink, if any. This can be a dict (if the response is a JSON object), a list (if the response is a JSON array), a string (if the response is text) or bytes (if the response is binary). If the response has no body or the request is out of lavalink’s control, None is returned.

Return type:

dict | list | str | bytes | None

Raises:
  • msgspec.DecodeError – The response body could not be decoded.

  • sonolink.HTTPException – An error occurred while making the request.

property client: Client[Any] | None

The client this node is attached to.

property id: str

The ID of this node.

property inactivity_settings: InactivitySettings

The inactivity configuration for all players on this node.

property is_connected: bool

Whether the Node is connected and Players can be attached to it.

property password: str

The password of the node.

resume_timeout: float

The maximum amount of seconds a resume can take before closing the node.

retries: int | None

The amount of retries to attempt when connecting or reconnecting this node.

property session_id: str

The current session ID for this node.

Raises:

RuntimeError – The node is not connected or has no active session.

property stats: StatsResponse | None

The latest stats received from the Lavalink node.

property uri: str

The URI this node connects to. This can only be changed while the node is disconnected.

Player

class sonolink.Player(client: Any, channel: Any)[source]
class sonolink.Player(*, node: Node | None = None, queue_mode: QueueMode = QueueMode.NORMAL, autoplay_settings: AutoPlaySettings | None = None, history_settings: HistorySettings | None = None, volume: int | None = None, paused: bool | None = None, filters: Filters | None = None, **kwargs: Any)

A dynamic proxy class for SonoLink players.

Automatically resolves the appropriate BasePlayer implementation for the detected or configured Discord library backend (discord.py, py-cord, disnake, or nextcord) at instantiation time.

The framework is resolved from the SONOLINK_FRAMEWORK environment variable, or detected automatically from whichever supported library is installed. If no supported framework is found, a RuntimeError is raised. If multiple are present, the one already imported is preferred; if that is ambiguous, the first available is used and a warning is logged.

There are two primary ways to create a player:

  1. Class-pass — pass the class itself to the voice channel’s connect method. The library will instantiate it directly:

    player = await voice_channel.connect(cls=Player)
    
  2. Instance-pass — construct a pre-configured instance and pass it instead. The library will call player(client, channel) which hits the concrete adapter’s __call__():

    player = Player(node=some_node, volume=80)
    await voice_channel.connect(cls=player)
    
Parameters:
  • node (Node | None) – The Lavalink node to associate with this player. If None, an available node is resolved from the client’s node pool at connection time.

  • queue_mode (QueueMode) – The initial queue looping mode. Defaults to QueueMode.NORMAL.

  • autoplay_settings (AutoPlaySettings | None) – AutoPlay configuration. None uses the default configuration. History must be enabled when AutoPlay is active.

  • history_settings (HistorySettings | None) – History configuration. None uses the default configuration.

  • volume (int | None) – Initial volume in the range 01000. Defaults to 100.

  • paused (bool | None) – Whether the player should start in a paused state. Defaults to False.

  • filters (Filters | None) – Initial audio filters. Defaults to an empty Filters instance.

guild

The guild this player is attached to. The concrete type depends on the underlying Discord library (e.g. discord.Guild (discord.py), discord.Guild (py-cord), disnake.Guild (disnake), or nextcord.Guild (nextcord)).

channel

The voice channel this player is currently connected to. The concrete type depends on the underlying Discord library.

Type:

Any

client

The Discord client instance driving this player. The concrete type depends on the underlying Discord library.

Type:

Any

cleanup() None[source]

Cleans the internal state of the Player. This is automatically called by the library when failures or disconnects occur.

If this is overridden, it must call the original cleanup.

async connect(*, timeout: float = 10.0, reconnect: bool = False, self_deaf: bool = False, self_mute: bool = False) None

Connect this player to its assigned voice channel.

Called automatically by libraries after the player is instantiated. Manual invocation is not normally required.

Parameters:
  • timeout (float) – Seconds to wait for the Discord gateway handshake before raising. Defaults to 10.0.

  • reconnect (bool) – Whether to attempt reconnection on failure. Defaults to False.

  • self_deaf (bool) – Whether to join the channel self-deafened. Defaults to False.

  • self_mute (bool) – Whether to join the channel self-muted. Defaults to False.

async disconnect(*, force: bool = False) None

Disconnect this player, destroy it on the Lavalink node, and clean up all internal state.

Parameters:

force (bool) – If True, proceeds even if the player is not currently connected. Defaults to False.

get_connection_state() PlayerConnectionState

Return a PlayerConnectionState instance for this player.

Override this method to supply a custom connection state subclass with additional metadata relevant to your application.

Return type:

PlayerConnectionState

async move_to(node: Node, /) None

Migrate this player to a different Lavalink node without interrupting playback.

Parameters:

node (Node) – The destination node.

async on_voice_server_update(data: Any) None[source]

Handle a VOICE_SERVER_UPDATE payload from the Discord gateway.

This provides the voice server token and endpoint required by the Lavalink node to establish or re-establish the audio stream. This method should be called by the library-specific subclass in response to the corresponding gateway event.

The data dictionary is passed as a raw mapping so that this base class remains decoupled from any specific library’s type aliases. Subclasses may cast it to the appropriate typed dict for their library (e.g., discord.types.voice.VoiceServerUpdate, disnake.types.voice.VoiceServerUpdate).

Parameters:

data (Any) – The raw VOICE_SERVER_UPDATE payload received from the Discord gateway.

async on_voice_state_update(data: Any) None[source]

Handle a VOICE_STATE_UPDATE payload from the Discord gateway.

This provides the session ID and channel ID required for the voice connection handshake with the Lavalink node. This method should be called by the library-specific subclass in response to the corresponding gateway event.

The data dictionary is passed as a raw mapping so that this base class remains decoupled from any specific library’s type aliases. Subclasses may cast it to the appropriate typed dict for their library (e.g., discord.types.voice.GuildVoiceState, disnake.types.voice.GuildVoiceState).

Parameters:

data (Any) – The raw VOICE_STATE_UPDATE payload received from the Discord gateway.

async pause() None

Set the pause state of the player.

Raises:

RuntimeError – If the player is not connected to a node or an active session.

async play(track: Playable, /, *, start: int = 0, end: int | None = None, volume: int | None = None, paused: bool | None = None) Playable

Begin playback of the specified track.

If a track is already playing, it is stopped and the currently playing track is added to history (if history is enabled) before the new track starts.

Parameters:
  • track (Playable) – The track to play.

  • start (int) – The position in milliseconds at which to begin playback. Defaults to 0.

  • end (int | None) – The position in milliseconds at which to stop playback. If None, the track plays to completion. Defaults to None.

  • volume (int | None) – Override the player volume for this track only. If None, the current player volume is used. Defaults to None.

  • paused (bool | None) – If True, the track begins in a paused state. If None, the player’s current pause state is preserved. Defaults to None.

Returns:

The track that was dispatched to the Lavalink node for playback.

Return type:

Playable

async previous() Playable

Return to the most recently played track in the history.

The current track is pushed back to the front of the queue so it can be reached again via skip(). The historical track then begins playing immediately.

Returns:

The historical track that is now playing.

Return type:

Playable

Raises:
  • RuntimeError – If the player is not connected to a node or an active session.

  • HistoryEmpty – If there is no previous track in the history.

async resume() None

Resume playback if the player is currently paused.

Raises:

RuntimeError – If the player is not connected to a node or an active session.

async seek(position: int, /) None

Seek to an arbitrary position within the current track.

Parameters:

position (int) – The target position in milliseconds. Must be within the bounds of the current track’s duration.

Raises:

RuntimeError – If the player is not connected to a node or an active session.

async set_filters(filters: Filters, /, *, seek: bool = False) None

Apply a new set of audio filters to this player.

Parameters:
  • filters (Filters) – The Filters instance to apply.

  • seek (bool) – If True, the player seeks to the current position immediately after applying filters. This forces Lavalink to process the audio through the new filter chain without a audible delay. Defaults to False.

Raises:

RuntimeError – If the player is not connected to a node or an active session.

async set_volume(value: int, /) None

Set the player’s output volume.

Parameters:

value (int) – The desired volume level, in the range 01000. 100 is the default (unmodified) level.

Raises:
  • ValueError – If value is outside the range 01000.

  • RuntimeError – If the player is not connected to a node or an active session.

async skip() Playable | None

Skip the currently playing track and advance to the next one in the queue.

If the queue is empty and AutoPlay is enabled, a related track may be fetched automatically. If neither a queued nor an AutoPlay track is available, playback stops and None is returned.

Returns:

The track that began playing after the skip, or None if the player stopped due to an empty queue with no AutoPlay fallback.

Return type:

Playable | None

Raises:
  • RuntimeError – If the player is not connected to a node or an active session.

  • QueueEmpty – If the queue is empty and AutoPlay is disabled or yields no results.

async stop(*, clear_queue: bool = False, clear_history: bool = False) None

Stop the currently playing track.

This sends a stop request to the Lavalink node and resets the player’s internal position tracking and current track reference.

Parameters:
  • clear_queue (bool) – If True, all pending tracks in the queue are removed. Defaults to False.

  • clear_history (bool) – If True, the playback history is cleared. Defaults to False.

Raises:

RuntimeError – If the player is not connected to a node or an active session.

async update(*, queue_mode: QueueMode | None = None, autoplay_settings: AutoPlaySettings | None = None, history_settings: HistorySettings | None = None, volume: int | None = None, filters: Filters | None = None) None

Update the player’s configuration in-place.

Added in version 1.1.0.

Parameters:
  • queue_mode (QueueMode | None) – The new queue looping mode. If None, the current mode is preserved.

  • autoplay_settings (AutoPlaySettings | None) – New AutoPlay configuration. If None, the current settings are preserved.

  • history_settings (HistorySettings | None) – New history configuration. If None, the current settings are preserved.

  • volume (int | None) – New volume in the range 01000. If None, the current volume is preserved.

  • filters (Filters | None) – New audio filters. If None, the current filters are preserved.

property autoplay: AutoPlayMode

The current AutoPlayMode for this player.

When AutoPlay is enabled, the player will automatically fetch and enqueue related tracks when the queue is exhausted.

Raises:

RuntimeError – When setting, if the player’s history is disabled (history is required for AutoPlay to function).

property autoplay_settings: AutoPlaySettings

The current AutoPlaySettings for this player.

Can be mutated directly to update individual fields, or replaced entirely.

Added in version 1.1.0.

Return type:

AutoPlaySettings

channel: Any
client: Any
property current: Playable | None

The track that is currently playing, or None if the player is idle.

Return type:

Playable | None

property filters: Filters

The Filters currently applied to this player.

To apply new filters, use set_filters() rather than mutating this object directly, so that the updated state is dispatched to the Lavalink node.

Return type:

Filters

property guild: Any

The guild this player is associated with.

The concrete return type is the guild class of the underlying Discord library (e.g. discord.Guild, disnake.Guild).

Raises:

RuntimeError – If the player has not yet been attached to a guild.

property history_settings: HistorySettings

The current HistorySettings for this player’s queue.

Can be mutated directly to update individual fields, or replaced entirely.

Added in version 1.1.0.

Return type:

HistorySettings

property node: Node

The Node this player is currently attached to.

Raises:

RuntimeError – If the player is not currently attached to a node.

property paused: bool

Whether the player is currently paused.

Return type:

bool

property position: int

The estimated current playback position in milliseconds.

When the player is paused or has not yet started, this returns the last known position. Otherwise, it is calculated by interpolating the time elapsed since the last state update received from the Lavalink node.

Returns:

Position in milliseconds.

Return type:

int

property queue: Queue

The Queue associated with this player.

The queue manages both upcoming tracks and playback history. Tracks can be added with queue.put() / queue.put_wait() and inspected or manipulated via the queue’s public API.

Return type:

Queue

property queue_mode: QueueMode

The current QueueMode for this player’s queue.

Added in version 1.1.0.

Return type:

QueueMode

property volume: int

The current volume of the player as an integer in the range 01000.

100 represents the default (unmodified) volume. Values above 100 amplify the audio and may introduce distortion.

Return type:

int