harmonylink
v2.0.0
Published
Seamlessly connect to Lavalink, NodeLink, and FrequenC nodes for high-quality audio streaming in your Discord bots. Supports Discord.js, Eris, Oceanic.js, and a powerful plugin system.
Maintainers
Readme
[!NOTE] HarmonyLink v2.0+ introduces advanced type safety with Result types, generic filter builders and a better plugin system cause the old one was not good enough ig. See Migration Guide for upgrading from older versions.
[!WARNING]
Support for Lavalink Version 3 is planned, but not confirmed to be done.
Features
- Multi-library support: Discord.js v14, Eris, Oceanic.js
- Plugin system: Extensible with lifecycle management
- Type safety: Full TypeScript support, neverthrow Result types
- Advanced filters: Type-safe audio filter builder
- Robust node/player management
- Modern, well-documented API
Demo
| URL | Features | Additional Information | |-----|----------|------------------------| | RhythmCore | Advanced Music bot With AI | Invite | | Example Bot | Verry basic example bot | coming soon |
Installation
npm install harmonylinkQuick Start (Discord.js v14)
import { DJSLibrary, HarmonyLink } from "harmonylink";
import { Client, GatewayIntentBits } from "discord.js";
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates]
});
const music = new HarmonyLink({
nodes: [{
name: "Example Node",
host: "localhost",
port: 2333,
password: "youshallnotpass",
secure: false
}],
library: new DJSLibrary(client),
});
client.on("ready", async () => {
// Create a player - using unwrapOr for cleaner code
const player = (await music.createPlayer({
guildId: "YOUR_GUILD_ID",
voiceId: "VOICE_CHANNEL_ID",
textId: "TEXT_CHANNEL_ID"
})).unwrapOr(null);
if (player) {
// Search and play a track
const response = (await music.resolve({
query: "Rick Astley - Never Gonna Give You Up",
requester: client.user
})).unwrapOr(null);
if (response && response.tracks.length > 0) {
player.queue.add(response.tracks[0]);
await player.play();
console.log("Now playing!");
}
}
});
client.login("YOUR_BOT_TOKEN");Result Types: HarmonyLink uses neverthrow Result types instead of throwing errors. You can handle them in three ways:
// Option 1: Check with .isOk() (explicit)
if (result.isOk()) {
console.log(result.value); // Safe access
} else {
console.error(result.error); // Handle error
}
// Option 2: Use .unwrapOr() (cleaner)
const value = result.unwrapOr(null); // Returns null if error
if (value) {
console.log(value); // Use the value
}
// Option 3: Use .match() (pattern matching)
result.match(
(value) => console.log(value),
(error) => console.error(error)
);
// So it would look something like this:
const tracks = await <Player>.resolve({ query: "Rick Astley - Never Gonna Give You Up", requester: client.user })
tracks.match(
(tracks) => <Player>.queue.add(tracks[0]),
(error) => console.error("Failed to resolve track:", error.message)
);
For more examples, please refer to the Documentation
Documentation
Plugins
HarmonyLink supports plugins for custom features and integrations. See the Plugin Guide and loadPlugins for details.
Migration Guide
From v1.x to v2.x
Breaking Changes:
Result Types: All async methods now return
Result<T, E>instead of throwing errors// v1.x (old) try { const player = await music.createPlayer(options); } catch (error) { console.error(error); } // v2.x (new) const playerResult = await music.createPlayer(options); if (playerResult.isOk()) { const player = playerResult.value; } else { console.error(playerResult.error); } // Or use unwrapOr for cleaner code const player = (await music.createPlayer(options)).unwrapOr(null);Plugin System: New lifecycle-based plugin architecture
// v1.x (old) class MyPlugin extends Plugin { load() { /* ... */ } } // v2.x (new) class MyPlugin extends AbstractPlugin { async initialize(manager: HarmonyLink): Promise<Result<void, Error>> { // Plugin initialization logic return ok(); } }Import Changes: Package exports have been reorganized
// v1.x (old) import { HarmonyLink } from "harmonylink/dist/HarmonyLink"; // v2.x (new) import { HarmonyLink } from "harmonylink";
New Features in v2.x:
- Type-safe filters: Enhanced audio filter system with better TypeScript support
- Improved error handling: Comprehensive Result types throughout the API
- Better plugin lifecycle: More robust plugin loading and management
For detailed migration assistance, see the full documentation.
Contributing
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Commit your Changes (
git commit -m 'Add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request
License
Distributed under the MIT License. See LICENSE for more information.
