Shoukaku

repository·master·Indexed 43 days ago

https://github.com/shipgirlproject/shoukaku

A stable TypeScript/JavaScript wrapper for Lavalink designed for Discord bot applications. It provides a consistent interface for managing Lavalink nodes and includes connectors for popular libraries such as Discord.js (v13.x.x & v14.x.x), Eris (0.15.x, 0.16.x, 0.17.x), Oceanic.JS (1.0.x), and Seyfert (0.1.x). Version 5.0.0-dev.0 supports custom node resolvers, clustering, and sharding.

Tokens
12.9K
Snippets
48
Records
64
Agent score
55%

What's inside Shoukaku

  1. Implement Clustering and Sharding with Shoukaku

    master

    When scaling large Discord bots using clustering or sharding, you can run one independent Shoukaku instance per cluster.

    For Shoukaku to function correctly in a clustered environment, the only requirement is that the specific cluster/instance has the ability to receive events from the Discord Websocket.

  2. Implement a custom nodeResolver

    master

    When multiple Lavalink nodes are configured, Shoukaku uses a nodeResolver to decide which node should handle an action. You can provide your own logic by passing a nodeResolver function in the Shoukaku options object during initialization. The resolver receives the current list of nodes and the connection context.

    const shoukaku = new Shoukaku(new Connectors.DiscordJS(client), [{ ...yourNodeOptions }], {
    	...yourShoukakuOptions,
    	nodeResolver: (nodes, connection) => getYourIdealNode(nodes, connection),
    });
  3. Resolve nodes in Shoukaku v4

    master

    Node resolving is now configurable. Instead of calling shoukaku.getNode(), you should use the nodeResolver function provided in your Shoukaku options, passing the current nodes as an argument.

    You can also supply a custom node resolver in your configuration to implement your own logic for selecting the ideal node based on nodes and connection data.

    // Standard way to get a node in v4
    const node = shoukaku.options.nodeResolver(shoukaku.nodes);
    
    // Custom node resolver configuration
    const ShoukakuOptions = {
    	...yourShoukakuOptions,
    	nodeResolver: (nodes, connection) => getYourIdealNode(nodes, connection),
    };
  4. How to create a custom Connector

    master

    If your library is not supported, you can create a custom connector by extending the Connector class. A custom connector must implement the following methods:

    • sendPacket(shardId: number, payload: any, important: boolean): void: Used to send packets from the library to the Discord Gateway.
    • getId(): string: A getter that returns the ID of the client user (the bot's ID).
    • listen(nodes: NodeOption[]): void: Attaches event listeners to your library. Typically, you should attach to the library's ready event once to call this.ready(nodes), and attach to the raw websocket event to call this.raw(packet).
    import { Connector } from "../Connector";
    import { NodeOption } from "../../Shoukaku";
    
    export class MyCustomConnector extends Connector {
    	// sendPacket is where your library send packets to Discord Gateway
    	public sendPacket(shardId: number, payload: any, important: boolean): void {
    		// Implementation for sending packets
    	}
    
    	// getId is a getter where the lib stores the client user (the one logged in as a bot) id
    	public getId(): string {
    		return "BOT_ID";
    	}
    
    	// Listen attaches the event listener to the library you are using
    	public listen(nodes: NodeOption[]): void {
    		// Attach to ready event once
    		this.client.once("ready", () => this.ready(nodes));
    		// Attach to the raw websocket event
    		this.client.on("raw", (packet: any) => this.raw(packet));
    	}
    }
  5. Join a voice channel, search for a track, and play it

    master

    To play music, follow these steps using the Shoukaku instance and the returned player:

    1. Join a voice channel: Use shoukaku.joinVoiceChannel providing the guildId, channelId, and shardId (use 0 if unsharded).
    2. Select a node: Use the nodeResolver from shoukaku.options to pick a node from shoukaku.nodes.
    3. Search for a track: Use node.rest.resolve with a provider prefix (e.g., scsearch: for SoundCloud) followed by the query.
    4. Play the track: Pass the track's encoded data to player.playTrack.
    5. Disconnect: Use shoukaku.leaveVoiceChannel(guildId) to leave the channel.
    // 1. Join
    const player = await shoukaku.joinVoiceChannel({
    	guildId: "your_guild_id",
    	channelId: "your_channel_id",
    	shardId: 0,
    });
    
    // 2. Resolve Node
    const node = shoukaku.options.nodeResolver(shoukaku.nodes);
    
    // 3. Search (e.g. SoundCloud)
    const result = await node.rest.resolve("scsearch:snowhalation");
    if (!result?.tracks.length) return;
    const metadata = result.tracks.shift();
    
    // 4. Play
    await player.playTrack({ track: { encoded: metadata.encoded } });
    
    // 5. Leave after 30s
    setTimeout(() => shoukaku.leaveVoiceChannel(player.guildId), 30000).unref();
  6. Use Connectors with Discord.JS

    master

    To use Shoukaku with Discord.JS, instantiate a Connectors.DiscordJS object passing your Discord.JS client as the argument. This connector supports Discord.JS versions v14.x.x and v13.x.x.

    import { Shoukaku, Connectors } from "shoukaku";
    new Shoukaku(new Connectors.DiscordJS(client), servers, options);
  7. Migrate from Shoukaku v3 to v4

    master
    Shoukaku v4 introduces several breaking changes regarding how nodes are resolved, how voice channels are joined/left, and how player methods behave. Key changes include moving voice channel management from the Node class to the main Shoukaku class and transitioning player methods to return Promises.
  8. How to implement a custom Shoukaku connector

    master
    If your Discord library is not supported, you can implement your own connector. For detailed implementation requirements and logic, refer to the existing connector implementations in the libs folder, specifically DiscordJS.ts or Eris.ts. These files serve as the reference for how to map your library's methods to the interface expected by Shoukaku.
  9. Use Connectors with Eris

    master

    To use Shoukaku with Eris, instantiate a Connectors.Eris object passing your Eris client as the argument. This connector supports Eris versions 0.17.x, 0.16.x, and 0.15.x.

    import { Shoukaku, Connectors } from "shoukaku";
    new Shoukaku(new Connectors.Eris(client), servers, options);
  10. Initialize Shoukaku

    master

    To use Shoukaku, you must instantiate the main Shoukaku class by providing a connector instance (specific to your library, e.g., Discord.js), an array of Lavalink nodes, and an optional configuration object.

    new Shoukaku(new Connectors.DiscordJS(client), Nodes, Options);