SkillAgentSearch skills...

Discolink

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

Install / Use

/learn @execaman/Discolink
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<div align="center"> <img alt="Discolink" src="assets/music-album.png" width="120" />

Icon by juicy_fish <br/> API Reference | Coverage

NPM Version Codecov Coverage

</div>

🎯 Purpose

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

🙌 Motivation

It's the JS ecosystem, how can we not have 30 libs for the same thing. My friends were monkey-patching, applying hotfixes, despite their clients being open-source; and I wanted to do a project professionally while exploring more of GitHub. This project follows SemVer and an Agile SDLC.

⚙️ 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

<details> <summary>Basic Setup - JavaScript (ESM)</summary>
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();
</details> <details> <summary>Module Augmentation - TypeScript</summary>
/**
 * 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;
  }
}
</details> <details> <summary>Custom Plugin (with events) - TypeScript</summary>
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);
  }
}
</details>

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.

🤖 Bots in Production

| Name | Since | Owner | | ----------------------------------------------------------------------------- | ------------- | ---------------------------------------------------------------- | | Mesuic | 18th Feb 2026 | @knifecodez | | Fuego | 19th Feb 2026 | @painfuego | | Flame | 28th Feb 2026 | @aiosqlite.db | | Bumblebee | 2nd Apr 2026 | @freycikkk |

🤝 Acknowledgements

Key aspects of this lib were inspired from the following projects:

View on GitHub
GitHub Stars11
CategoryDevelopment
Updated1d ago
Forks3

Languages

TypeScript

Security Score

95/100

Audited on Apr 7, 2026

No findings