Skip to content

execaman/discolink

ℹ️ Introduction

This project follows SemVer and an Agile SDLC.

The goal of this library is to abstract away obvious steps involved in the process of acting as an intermediary between a Lavalink server and a Discord bot to provide a simple and intuitive interface to work with.

⚙️ Requirements

  • Runtime - one of the following:
  • Library - any gateway client that supports:
    • sending raw payloads over the connection
    • receiving raw payloads from the connection

📝 Implementation

Examples

Basic Setup - JavaScript (ESM)
import { Client } from "main-lib";
import { Player } from "discolink";

const client = new Client(...);

const player = new Player({
  nodes: [ // add your nodes
    {
      name: "local",
      origin: "http://localhost:2333",
      password: "youshallnotpass"
    }
  ],
  async forwardVoiceUpdate(guildId, payload) {
    // send the given payload to your gateway connection
    client.guilds.cache.get(guildId).shard.send(payload);
  }
});

client.on("raw", (payload) => {
  // call the handler on gateway dispatch
  player.voices.handleDispatch(payload);
});

client.login();
Module Augmentation - TypeScript
/**
 * fields defined here appear wherever they're concerned
 */
declare module "discolink" {
  // appears on queue, related options, etc
  interface QueueContext {
    textId: string;
  }

  // appears on track, related options, etc
  interface CommonUserData {
    id: string;
    username: string;
    displayName: string;
  }

  // appears on track, playlist, etc
  interface CommonPluginInfo {
    save_uri?: string;
  }

  // appears throughout filter management
  interface CommonPluginFilters {
    custom: string;
  }
}
Custom Plugin (with events) - TypeScript
import { PlayerPlugin, type Player } from "discolink";

export class CustomPlugin extends PlayerPlugin<{
  // define events you want to emit on player
  eventName: [s: number, d: object];
}> {
  readonly name = "custom"; // 'readonly' is mandatory
  #player!: Player; // optional, just for convenience

  init(player: Player) {
    this.#player = player;
    player.on("nodeDispatch", this.#onDispatch);
  }

  transform(...args: unknown[]): [s: number, d: object] {}

  #onDispatch(this: Player, ...args: unknown[]) {
    // work with data
    // e.g. transform -> rename event -> dispatch
    const transformed = this.transform(...args);
    this.emit("eventName", ...transformed);
  }
}

Additional Notes

Note

replaced is an edge case where we cannot reliably determine the exact track object in queue that ended. The queue implements a workaround for this and provides a inQueue (think cache hit/miss) boolean in track events

Session Resumption

Resuming a node's session after your bot restarts requires careful planning, depending on scale. As such, the lib has no plans to provide built-in support for it. Disable either or both of autoSync and relocateQueues options for predictable behavior if you're implementing this feature.

About

A Lavalink client with load-aware queue distribution, regional voice latency routing, and automatic node failover for Discord bots in TypeScript

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Sponsor this project

 

Contributors