lavacord 2.2.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +24 -201
- package/README.md +473 -69
- package/dist/cjs/index.cjs +44 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/index.d.cts +1211 -0
- package/dist/cjs/lib/LavalinkNode.cjs +423 -0
- package/dist/cjs/lib/LavalinkNode.cjs.map +1 -0
- package/dist/cjs/lib/Manager.cjs +405 -0
- package/dist/cjs/lib/Manager.cjs.map +1 -0
- package/dist/cjs/lib/Player.cjs +220 -0
- package/dist/cjs/lib/Player.cjs.map +1 -0
- package/dist/cjs/lib/Rest.cjs +192 -0
- package/dist/cjs/lib/Rest.cjs.map +1 -0
- package/dist/cjs/lib/Types.cjs +4 -0
- package/dist/cjs/lib/Types.cjs.map +1 -0
- package/dist/cjs/wrappers/cloudstorm.cjs +54 -0
- package/dist/cjs/wrappers/cloudstorm.cjs.map +1 -0
- package/dist/cjs/wrappers/detritus.cjs +57 -0
- package/dist/cjs/wrappers/detritus.cjs.map +1 -0
- package/dist/cjs/wrappers/discord.js.cjs +37 -0
- package/dist/cjs/wrappers/discord.js.cjs.map +1 -0
- package/dist/cjs/wrappers/eris.cjs +51 -0
- package/dist/cjs/wrappers/eris.cjs.map +1 -0
- package/dist/cjs/wrappers/oceanic.cjs +52 -0
- package/dist/cjs/wrappers/oceanic.cjs.map +1 -0
- package/dist/esm/chunk-PAWJFY3S.mjs +6 -0
- package/dist/esm/chunk-PAWJFY3S.mjs.map +1 -0
- package/dist/esm/index.d.mts +1211 -0
- package/dist/esm/index.mjs +12 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/lib/LavalinkNode.mjs +420 -0
- package/dist/esm/lib/LavalinkNode.mjs.map +1 -0
- package/dist/esm/lib/Manager.mjs +402 -0
- package/dist/esm/lib/Manager.mjs.map +1 -0
- package/dist/esm/lib/Player.mjs +217 -0
- package/dist/esm/lib/Player.mjs.map +1 -0
- package/dist/esm/lib/Rest.mjs +188 -0
- package/dist/esm/lib/Rest.mjs.map +1 -0
- package/dist/esm/lib/Types.mjs +3 -0
- package/dist/esm/lib/Types.mjs.map +1 -0
- package/dist/esm/wrappers/cloudstorm.mjs +45 -0
- package/dist/esm/wrappers/cloudstorm.mjs.map +1 -0
- package/dist/esm/wrappers/detritus.mjs +48 -0
- package/dist/esm/wrappers/detritus.mjs.map +1 -0
- package/dist/esm/wrappers/discord.js.mjs +28 -0
- package/dist/esm/wrappers/discord.js.mjs.map +1 -0
- package/dist/esm/wrappers/eris.mjs +42 -0
- package/dist/esm/wrappers/eris.mjs.map +1 -0
- package/dist/esm/wrappers/oceanic.mjs +43 -0
- package/dist/esm/wrappers/oceanic.mjs.map +1 -0
- package/dist/lib/LavalinkNode.d.ts +3 -3
- package/dist/lib/LavalinkNode.js +16 -26
- package/dist/lib/LavalinkNode.js.map +1 -1
- package/dist/lib/Manager.d.ts +2 -2
- package/dist/lib/Manager.js.map +1 -1
- package/dist/lib/Rest.js +5 -7
- package/dist/lib/Rest.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +109 -64
package/README.md
CHANGED
|
@@ -1,116 +1,520 @@
|
|
|
1
|
-
|
|
2
|
-
[](https://www.npmjs.com/package/lavacord)
|
|
3
|
-
[](https://www.npmjs.com/package/lavacord)
|
|
4
|
-
[](https://github.com/lavacord/lavacord/)
|
|
5
|
-
[](https://depfu.com/github/lavacord/Lavacord?project_id=11810)
|
|
6
|
-
[](https://www.codacy.com/app/lavacord/lavacord)
|
|
1
|
+
<div align="center" style="padding-bottom: 1rem">
|
|
7
2
|
|
|
8
|
-
|
|
9
|
-
A simple and easy to use lavalink wrapper.
|
|
3
|
+
<img src="https://github.com/lavacord/Lavacord/blob/gh-pages/assets/Lavacordlogotransparent.png?raw=true" alt="Lavacord Logo" height="200">
|
|
10
4
|
|
|
11
|
-
|
|
12
|
-
[**lavacord.github.io/lavacord**](https://lavacord.github.io/Lavacord/)
|
|
5
|
+
<p>Lightweight and efficient Lavalink client for Node.js built with TypeScript</p>
|
|
13
6
|
|
|
14
|
-
|
|
7
|
+
[](https://npmjs.com/package/lavacord)
|
|
8
|
+
[](https://npmjs.com/package/lavacord)
|
|
9
|
+
[](https://www.typescriptlang.org/)
|
|
10
|
+
[](LICENSE)
|
|
11
|
+
|
|
12
|
+
[](https://discord.gg/wXrjZmV)
|
|
13
|
+
|
|
14
|
+
[**Click here for the documentation**](https://lavacord.js.org/)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<details>
|
|
19
|
+
<summary>Table of Contents</summary>
|
|
20
|
+
|
|
21
|
+
- [Features](#features)
|
|
22
|
+
- [Installation](#installation)
|
|
23
|
+
- [Quick Start](#quick-start)
|
|
24
|
+
- [Lavalink Node Configuration](#lavalink-node-configuration)
|
|
25
|
+
- [Supported Discord Libraries](#supported-discord-libraries)
|
|
26
|
+
- [Wrapper Example](#wrapper-example)
|
|
27
|
+
- [Basic Usage](#basic-usage)
|
|
28
|
+
- [Search Examples](#search-examples)
|
|
29
|
+
- [Advanced Usage](#advanced-usage)
|
|
30
|
+
- [Player Controls](#player-controls)
|
|
31
|
+
- [Audio Filters](#audio-filters)
|
|
32
|
+
- [Error Handling](#error-handling)
|
|
33
|
+
- [Multiple Nodes & Load Balancing](#multiple-nodes--load-balancing)
|
|
34
|
+
- [Events](#events)
|
|
35
|
+
- [Donate](#donate)
|
|
36
|
+
- [Contributors](#contributors)
|
|
37
|
+
|
|
38
|
+
</details>
|
|
39
|
+
|
|
40
|
+
<br>
|
|
41
|
+
|
|
42
|
+
# Features
|
|
43
|
+
|
|
44
|
+
- Supports **Lavalink v4**
|
|
45
|
+
- Built with **TypeScript** with **ES Modules** and **CommonJS** support
|
|
46
|
+
- Multiple Discord library wrappers available
|
|
47
|
+
- Follows the **Lavalink API** closely and provides a consistent way to interact with Lavalink
|
|
48
|
+
|
|
49
|
+
# Installation
|
|
50
|
+
|
|
51
|
+
Install Lavacord using either `yarn`, `npm`, `pnpm` or the package manager of your choice:
|
|
15
52
|
|
|
16
|
-
**For stable**
|
|
17
53
|
```bash
|
|
18
54
|
# Using yarn
|
|
19
55
|
yarn add lavacord
|
|
20
|
-
|
|
21
56
|
# Using npm
|
|
22
57
|
npm install lavacord
|
|
58
|
+
# Using pnpm
|
|
59
|
+
pnpm add lavacord
|
|
23
60
|
```
|
|
24
61
|
|
|
25
|
-
**
|
|
26
|
-
```bash
|
|
27
|
-
# Using yarn
|
|
28
|
-
yarn add lavacord/lavacord
|
|
62
|
+
**Requirements:**
|
|
29
63
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
```
|
|
64
|
+
- **Node.js** v20 or newer is **required**.
|
|
65
|
+
- A running **Lavalink** server (Java 17+ required).
|
|
33
66
|
|
|
34
|
-
|
|
35
|
-
Download Lavalink from [their GitHub releases](https://github.com/lavalink-devs/Lavalink/releases)
|
|
67
|
+
# Quick Start
|
|
36
68
|
|
|
37
|
-
|
|
69
|
+
To get started with using Lavacord, first ensure you have a Lavalink server running. You can find instructions on how to set up a Lavalink server on the [Lavalink Getting Started page](https://lavalink.dev/getting-started/).
|
|
38
70
|
|
|
39
|
-
|
|
71
|
+
Once you have Lavacord installed, you will want to import the `Manager` class from Lavacord or one of the library wrappers, depending on which Discord library you are using, then initialise it with your Lavalink nodes and bot user ID and send function if not using a wrapper.
|
|
40
72
|
|
|
41
|
-
|
|
42
|
-
If you're having a problem with the module contact us in the [**Discord Server**](https://discord.gg/wXrjZmV)
|
|
73
|
+
**Also keep in mind that while all the examples below use CommonJS syntax, Lavacord supports TypeScript, ESM, and CJS. You can import the `Manager` class using either `require` or `import` syntax, depending on your project setup.**
|
|
43
74
|
|
|
44
|
-
|
|
45
|
-
Start by creating a new `Manager` passing an array of nodes and an object with `user` the client's user id.
|
|
75
|
+
## Lavalink Node Configuration
|
|
46
76
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
77
|
+
To connect to a Lavalink server, you need to configure the Lavalink nodes. Each node should have a unique identifier, host, port, password, and an optional secure flag if using SSL/TLS.
|
|
78
|
+
|
|
79
|
+
We are going to use this node's array throughout all the examples in this readme, so make sure to define it before using the examples.
|
|
80
|
+
|
|
81
|
+
See [LavalinkNodeOptions](https://lavacord.js.org/interfaces/LavalinkNodeOptions.html) for more details on the available options.
|
|
82
|
+
|
|
83
|
+
You can define your Lavalink nodes in an array like this:
|
|
50
84
|
|
|
51
|
-
|
|
85
|
+
```javascript
|
|
52
86
|
const nodes = [
|
|
53
|
-
|
|
87
|
+
{
|
|
88
|
+
id: "node1", // Unique identifier for the node
|
|
89
|
+
host: "localhost", // Lavalink server host
|
|
90
|
+
port: 2333, // Lavalink server port
|
|
91
|
+
password: "youshallnotpass", // Lavalink server password
|
|
92
|
+
secure: false, // Set to true if using SSL/TLS, false by default,
|
|
93
|
+
reconnectInterval: 10000, // How long the interval should be to reconnect, default is 10000 ms
|
|
94
|
+
state: {
|
|
95
|
+
// State is a arbitrary object that can be used to store any data you want, it is not used by Lavacord nor do you have to use it
|
|
96
|
+
customData: "example" // Example custom data
|
|
97
|
+
}
|
|
98
|
+
}
|
|
54
99
|
];
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Supported Discord Libraries
|
|
103
|
+
|
|
104
|
+
Lavacord provides wrappers for popular Discord libraries:
|
|
105
|
+
|
|
106
|
+
Each wrapper automatically wires up voice events and exports a `Manager` class tailored for that library.
|
|
107
|
+
|
|
108
|
+
| Library | Import Path |
|
|
109
|
+
| ---------- | --------------------- |
|
|
110
|
+
| discord.js | `lavacord/discord.js` |
|
|
111
|
+
| eris | `lavacord/eris` |
|
|
112
|
+
| oceanic.js | `lavacord/oceanic` |
|
|
113
|
+
| cloudstorm | `lavacord/cloudstorm` |
|
|
114
|
+
| detritus | `lavacord/detritus` |
|
|
115
|
+
|
|
116
|
+
> Want support for another Discord API library?
|
|
117
|
+
> [Open an issue or discussion](https://github.com/lavacord/lavacord/issues) to suggest it!
|
|
118
|
+
|
|
119
|
+
## Wrapper Example
|
|
120
|
+
|
|
121
|
+
Here's how to use Lavacord with the `discord.js` library wrapper:
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
const { Manager } = require("lavacord/discord.js");
|
|
125
|
+
const { Client, GatewayIntentBits } = require("discord.js");
|
|
126
|
+
|
|
127
|
+
const client = new Client({
|
|
128
|
+
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates]
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// When using library wrappers, pass the client instance as the first parameter
|
|
132
|
+
const manager = new Manager(client, nodes);
|
|
133
|
+
|
|
134
|
+
client.once("ready", async () => {
|
|
135
|
+
console.log(`${client.user.tag} is ready!`);
|
|
136
|
+
// Connect to all Lavalink nodes
|
|
137
|
+
await manager.connect();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
client.login("your-bot-token");
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Library wrappers automatically handle:
|
|
55
144
|
|
|
56
|
-
|
|
145
|
+
- **Voice events**: Listens for `VOICE_SERVER_UPDATE` and `VOICE_STATE_UPDATE` events
|
|
146
|
+
- **Send function**: Implements the Discord gateway packet sending for you
|
|
147
|
+
|
|
148
|
+
This eliminates the need to manually wire up voice events or implement the send function, making integration much simpler compared to using the core library directly.
|
|
149
|
+
|
|
150
|
+
# Basic Usage
|
|
151
|
+
|
|
152
|
+
Here's a complete example using the core Lavacord library without wrappers:
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
const { Manager, Rest } = require("lavacord");
|
|
156
|
+
|
|
157
|
+
// Create a new Manager instance with Lavalink nodes
|
|
57
158
|
const manager = new Manager(nodes, {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
159
|
+
userId: "123456789012345678", // Your bot's user ID
|
|
160
|
+
send: (packet) => {
|
|
161
|
+
// Send voice packets to Discord's gateway
|
|
162
|
+
// Implementation depends on your Discord library
|
|
163
|
+
// Use library wrappers to avoid implementing this manually
|
|
164
|
+
discordClient.gateway.send(packet);
|
|
165
|
+
}
|
|
63
166
|
});
|
|
64
167
|
|
|
65
|
-
//
|
|
168
|
+
// Connect to all Lavalink nodes
|
|
66
169
|
await manager.connect();
|
|
67
170
|
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
171
|
+
// Join a voice channel and create a player
|
|
172
|
+
const player = await manager.join({
|
|
173
|
+
guild: "987654321098765432", // Guild ID where you want to play music
|
|
174
|
+
channel: "123456789012345678", // Voice channel ID to join
|
|
175
|
+
node: "node1" // Lavalink node ID to use (optional, auto-selects if not provided)
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Load a track from various sources
|
|
179
|
+
// see https://lavalink.dev/api/rest.html#track-loading
|
|
180
|
+
const loadResult = await Rest.load(player.node, "https://www.youtube.com/watch?v=dQw4w9WgXcQ");
|
|
181
|
+
|
|
182
|
+
if (loadResult.loadType === "track") {
|
|
183
|
+
// Play the loaded track
|
|
184
|
+
await player.play(loadResult.data.encoded);
|
|
185
|
+
console.log(`Now playing: ${loadResult.data.info.title}`);
|
|
186
|
+
} else if (loadResult.loadType === "playlist") {
|
|
187
|
+
// Play first track from playlist
|
|
188
|
+
const firstTrack = loadResult.data.tracks[0];
|
|
189
|
+
await player.play(firstTrack.encoded);
|
|
190
|
+
console.log(`Playing playlist: ${loadResult.data.info.name}`);
|
|
191
|
+
} else if (loadResult.loadType === "search") {
|
|
192
|
+
// Play first search result
|
|
193
|
+
if (loadResult.data.length > 0) {
|
|
194
|
+
await player.play(loadResult.data[0].encoded);
|
|
195
|
+
console.log(`Now playing: ${loadResult.data[0].info.title}`);
|
|
196
|
+
} else {
|
|
197
|
+
console.log("No search results found");
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
console.log("No tracks found");
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Listen for when tracks start playing
|
|
204
|
+
player.on("trackStart", (track) => {
|
|
205
|
+
console.log(`Started playing: ${track.info.title}`);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Listen for when tracks end
|
|
209
|
+
player.on("trackEnd", (track, reason) => {
|
|
210
|
+
console.log(`Track ended: ${track.info.title} (${reason})`);
|
|
72
211
|
});
|
|
73
212
|
```
|
|
74
213
|
|
|
75
|
-
|
|
214
|
+
## Search Examples
|
|
215
|
+
|
|
216
|
+
You can also search for tracks instead of using direct URLs:
|
|
217
|
+
See [Track Loading](https://lavalink.dev/api/rest.html#track-loading) for more information on the loadtracks endpoint.
|
|
76
218
|
|
|
77
219
|
```javascript
|
|
78
|
-
|
|
220
|
+
// Search YouTube
|
|
221
|
+
const searchResult = await Rest.load(player.node, "ytsearch:Never Gonna Give You Up");
|
|
222
|
+
|
|
223
|
+
// Search SoundCloud
|
|
224
|
+
const scResult = await Rest.load(player.node, "scsearch:lofi hip hop");
|
|
79
225
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const node = manager.idealNodes[0];
|
|
226
|
+
// Search Spotify (if enabled on Lavalink server)
|
|
227
|
+
const spotifyResult = await Rest.load(player.node, "spsearch:bohemian rhapsody");
|
|
83
228
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
});
|
|
229
|
+
if (searchResult.loadType === "search") {
|
|
230
|
+
if (searchResult.data.length > 0) {
|
|
231
|
+
await player.play(searchResult.data[0].encoded); // Play first result
|
|
232
|
+
}
|
|
89
233
|
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
# Advanced Usage
|
|
90
237
|
|
|
91
|
-
|
|
92
|
-
|
|
238
|
+
## Player Controls
|
|
239
|
+
|
|
240
|
+
```javascript
|
|
241
|
+
// Basic playback controls
|
|
242
|
+
await player.pause(true); // Pause
|
|
243
|
+
await player.pause(false); // Resume
|
|
244
|
+
await player.stop(); // Stop current track
|
|
245
|
+
await player.seek(30000); // Seek to 30 seconds
|
|
246
|
+
await player.setVolume(50); // Set volume to 50% (0-1000 range)
|
|
247
|
+
|
|
248
|
+
// All of these helpers call player.update(UpdatePlayerData), each of which returns a Promise<UpdatePlayerResult>
|
|
249
|
+
// You can see more here https://lavalink.dev/api/rest.html#update-player
|
|
250
|
+
// For example to set the volume using player.update:
|
|
251
|
+
await player.update({
|
|
252
|
+
volume: 50 // Set volume to 50%
|
|
93
253
|
});
|
|
94
254
|
```
|
|
95
255
|
|
|
96
|
-
|
|
256
|
+
## Audio Filters
|
|
257
|
+
|
|
258
|
+
Lavacord supports Lavalink's audio filters for sound enhancement:
|
|
97
259
|
|
|
98
260
|
```javascript
|
|
99
|
-
//
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
261
|
+
// Apply equalizer (15-band, -0.25 to 1.0 gain per band)
|
|
262
|
+
await player.setEqualizer([
|
|
263
|
+
{ band: 0, gain: 0.2 }, // 25 Hz
|
|
264
|
+
{ band: 1, gain: 0.15 }, // 40 Hz
|
|
265
|
+
{ band: 2, gain: 0.1 } // 63 Hz
|
|
266
|
+
// ... up to band 14 (16 kHz)
|
|
267
|
+
]);
|
|
268
|
+
|
|
269
|
+
// Apply multiple filters at once
|
|
270
|
+
await player.setFilters({
|
|
271
|
+
timescale: {
|
|
272
|
+
speed: 1.2, // 20% faster
|
|
273
|
+
pitch: 1.0, // Same pitch
|
|
274
|
+
rate: 1.0 // Same rate
|
|
275
|
+
},
|
|
276
|
+
karaoke: {
|
|
277
|
+
level: 1.0,
|
|
278
|
+
monoLevel: 1.0,
|
|
279
|
+
filterBand: 220.0,
|
|
280
|
+
filterWidth: 100.0
|
|
281
|
+
},
|
|
282
|
+
tremolo: {
|
|
283
|
+
frequency: 2.0,
|
|
284
|
+
depth: 0.5
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// Clear all filters
|
|
289
|
+
await player.setFilters({});
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Error Handling
|
|
293
|
+
|
|
294
|
+
```javascript
|
|
295
|
+
// Handle player errors
|
|
296
|
+
player.on("trackException", (track, exception) => {
|
|
297
|
+
console.error(`Track failed: ${track.info.title}`, exception);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
player.on("trackStuck", (track, thresholdMs) => {
|
|
301
|
+
console.error(`Track stuck: ${track.info.title} (${thresholdMs}ms)`);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
// Handle node errors
|
|
305
|
+
manager.on("error", (error, node) => {
|
|
306
|
+
console.error(`Node ${node.id} error:`, error);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
manager.on("disconnect", (code, reason, node) => {
|
|
310
|
+
console.warn(`Node ${node.id} disconnected: ${reason} (${code})`);
|
|
311
|
+
// Players will automatically switch to other available nodes
|
|
312
|
+
});
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Multiple Nodes & Load Balancing
|
|
316
|
+
|
|
317
|
+
```javascript
|
|
318
|
+
const nodes = [
|
|
319
|
+
{
|
|
320
|
+
id: "node1",
|
|
321
|
+
host: "lavalink1.example.com",
|
|
322
|
+
port: 2333,
|
|
323
|
+
password: "youshallnotpass"
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
id: "node2",
|
|
327
|
+
host: "lavalink2.example.com",
|
|
328
|
+
port: 2333,
|
|
329
|
+
password: "youshallnotpass"
|
|
330
|
+
}
|
|
331
|
+
];
|
|
332
|
+
|
|
333
|
+
const manager = new Manager(nodes, options);
|
|
334
|
+
|
|
335
|
+
// Lavacord automatically selects the best node based on CPU load
|
|
336
|
+
const player = await manager.join({ guild: "...", channel: "...", node: "node1" });
|
|
337
|
+
console.log(`Using node: ${player.node.id}`);
|
|
338
|
+
|
|
339
|
+
// Manually switch a player to a different node
|
|
340
|
+
const targetNode = manager.nodes.get("node2");
|
|
341
|
+
await manager.switch(player, targetNode);
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
# Events
|
|
345
|
+
|
|
346
|
+
Lavacord emits events at both the `Manager` and `Player` levels, allowing you to handle events globally or per-player. Player events emitted on the `Manager` are prefixed with `player` to avoid conflicts.
|
|
347
|
+
|
|
348
|
+
## Manager Events
|
|
349
|
+
|
|
350
|
+
```javascript
|
|
351
|
+
// Fired when a node successfully connects
|
|
352
|
+
manager.on("ready", (node) => {
|
|
353
|
+
console.log(`Node ${node.id} is ready`);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
// Fired when a node encounters an error
|
|
357
|
+
manager.on("error", (error, node) => {
|
|
358
|
+
console.error(`Node ${node.id} error:`, error);
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
// Fired when a node disconnects
|
|
362
|
+
manager.on("disconnect", (code, reason, node) => {
|
|
363
|
+
console.log(`Node ${node.id} disconnected: ${reason} (Code: ${code})`);
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
// Fired when a node is attempting to reconnect
|
|
367
|
+
manager.on("reconnecting", (node) => {
|
|
368
|
+
console.log(`Reconnecting to node ${node.id}`);
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
// Fired for raw WebSocket messages (useful for debugging)
|
|
372
|
+
manager.on("raw", (message, node) => {
|
|
373
|
+
console.log(`Raw data from ${node.id}:`, message);
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
// Fired for warning messages
|
|
377
|
+
manager.on("warn", (message, node) => {
|
|
378
|
+
console.warn(`Warning from ${node.id}: ${message}`);
|
|
379
|
+
});
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Player Events on Manager
|
|
383
|
+
|
|
384
|
+
```javascript
|
|
385
|
+
// Track events
|
|
386
|
+
|
|
387
|
+
// https://lavalink.dev/api/websocket.html#trackstartevent
|
|
388
|
+
manager.on("playerTrackStart", (player, event) => {
|
|
389
|
+
console.log(`Player ${player.guildId} started: ${event.track.info.title}`);
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
// https://lavalink.dev/api/websocket.html#trackendevent
|
|
393
|
+
manager.on("playerTrackEnd", (player, event) => {
|
|
394
|
+
console.log(`Player ${player.guildId} ended: ${event.track.info.title} (${event.reason})`);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
// https://lavalink.dev/api/websocket.html#trackexceptionevent
|
|
398
|
+
manager.on("playerTrackException", (player, event) => {
|
|
399
|
+
console.error(`Player ${player.guildId} exception:`, event.exception);
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
// https://lavalink.dev/api/websocket.html#trackstuckevent
|
|
403
|
+
// Fired when a track is stuck (e.g., no audio received for a long time)
|
|
404
|
+
manager.on("playerTrackStuck", (player, event) => {
|
|
405
|
+
console.error(`Player ${player.guildId} stuck: ${event.thresholdMs}ms`);
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
// playerState will emit every x time specified in the Lavalink config
|
|
409
|
+
// See https://lavalink.dev/api/websocket.html#player-update-op
|
|
410
|
+
manager.on("playerState", (player, state) => {
|
|
411
|
+
console.log(`Player ${player.guildId} state update:`, state);
|
|
104
412
|
});
|
|
105
413
|
|
|
106
|
-
|
|
414
|
+
// https://lavalink.dev/api/websocket.html#websocketclosedevent
|
|
415
|
+
manager.on("playerWebSocketClosed", (player, event) => {
|
|
416
|
+
console.log(`Player ${player.guildId} WebSocket closed: ${event.reason} (${event.code}) by ${event.byRemote ? "discord" : "local"}`);
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
// These events aren’t part of the Lavalink API; they are emitted by Lavacord when you invoke specific methods
|
|
420
|
+
|
|
421
|
+
// for example pause is emitted when calling player.pause(true) or player.pause(false);
|
|
422
|
+
manager.on("playerPause", (player, state) => {
|
|
423
|
+
console.log(`Player ${player.guildId} pause: ${state}`);
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
manager.on("playerVolume", (player, volume) => {
|
|
427
|
+
console.log(`Player ${player.guildId} volume: ${volume}`);
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
manager.on("playerSeek", (player, position) => {
|
|
431
|
+
console.log(`Player ${player.guildId} seek: ${position}ms`);
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
manager.on("playerFilters", (player, filters) => {
|
|
435
|
+
console.log(`Player ${player.guildId} filters:`, filters);
|
|
436
|
+
});
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
## Player Events
|
|
440
|
+
|
|
441
|
+
Handle events on individual player instances:
|
|
442
|
+
|
|
443
|
+
```javascript
|
|
444
|
+
// Track events - fired when tracks start, end, or encounter issues
|
|
445
|
+
|
|
446
|
+
// https://lavalink.dev/api/websocket.html#trackstartevent
|
|
447
|
+
player.on("trackStart", (event) => {
|
|
448
|
+
console.log(`Now playing: ${event.track.info.title} by ${event.track.info.author}`);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
// https://lavalink.dev/api/websocket.html#trackendevent
|
|
452
|
+
player.on("trackEnd", (event) => {
|
|
453
|
+
console.log(`Track ended: ${event.track.info.title} (${event.reason})`);
|
|
454
|
+
// Reasons: "finished", "loadFailed", "stopped", "replaced", "cleanup"
|
|
455
|
+
});
|
|
456
|
+
// https://lavalink.dev/api/websocket.html#trackexceptionevent
|
|
457
|
+
player.on("trackException", (event) => {
|
|
458
|
+
console.error(`Track exception: ${event.track.info.title}`, event.exception);
|
|
459
|
+
});
|
|
107
460
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
461
|
+
// https://lavalink.dev/api/websocket.html#trackstuckevent
|
|
462
|
+
// Fired when a track is stuck (e.g., no audio received for a long time)
|
|
463
|
+
player.on("trackStuck", (event) => {
|
|
464
|
+
console.error(`Track stuck: ${event.track.info.title} (${event.thresholdMs}ms)`);
|
|
112
465
|
});
|
|
113
466
|
|
|
114
|
-
//
|
|
115
|
-
|
|
467
|
+
// state will emit every x time specified in the Lavalink config
|
|
468
|
+
// See https://lavalink.dev/api/websocket.html#player-update-op
|
|
469
|
+
player.on("state", (state) => {
|
|
470
|
+
console.log(`Player state:`, {
|
|
471
|
+
position: state.position,
|
|
472
|
+
time: state.time,
|
|
473
|
+
connected: state.connected,
|
|
474
|
+
ping: state.ping
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
// https://lavalink.dev/api/websocket.html#websocketclosedevent
|
|
479
|
+
player.on("webSocketClosed", (event) => {
|
|
480
|
+
console.log(`WebSocket closed: ${event.reason} (${event.code}) by ${event.byRemote ? "discord" : "local"}`);
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
// These events aren’t part of the Lavalink API; they are emitted by Lavacord when you invoke specific methods
|
|
484
|
+
|
|
485
|
+
// for example pause is emitted when calling player.pause(true) or player.pause(false);
|
|
486
|
+
player.on("pause", (state) => {
|
|
487
|
+
console.log(`Player ${state ? "paused" : "resumed"}`);
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
player.on("volume", (volume) => {
|
|
491
|
+
console.log(`Volume changed to: ${volume}`);
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
player.on("seek", (position) => {
|
|
495
|
+
console.log(`Seeked to: ${position}ms`);
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
player.on("filters", (filters) => {
|
|
499
|
+
console.log(`Filters applied:`, filters);
|
|
500
|
+
});
|
|
116
501
|
```
|
|
502
|
+
|
|
503
|
+
# Donate
|
|
504
|
+
|
|
505
|
+
If you find Lavacord useful and want to support its development, you can sponsor the main maintainers directly:
|
|
506
|
+
|
|
507
|
+
- [MrJacz](https://github.com/sponsors/MrJacz)
|
|
508
|
+
- [AmandaDiscord](https://github.com/sponsors/AmandaDiscord)
|
|
509
|
+
|
|
510
|
+
Thank you for your support!
|
|
511
|
+
|
|
512
|
+
# Contributors
|
|
513
|
+
|
|
514
|
+
Please make sure to read the [Contributing Guide](CONTRIBUTING.md) before making a pull request.
|
|
515
|
+
|
|
516
|
+
Thank you to everyone who has contributed to Lavacord!
|
|
517
|
+
|
|
518
|
+
<a href="https://github.com/lavacord/Lavacord/graphs/contributors">
|
|
519
|
+
<img src="https://contrib.rocks/image?repo=lavacord/Lavacord" alt="Contributors to Lavacord" />
|
|
520
|
+
</a>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var LavalinkNode_cjs = require('./lib/LavalinkNode.cjs');
|
|
4
|
+
var Player_cjs = require('./lib/Player.cjs');
|
|
5
|
+
var Manager_cjs = require('./lib/Manager.cjs');
|
|
6
|
+
var Rest_cjs = require('./lib/Rest.cjs');
|
|
7
|
+
var Types_cjs = require('./lib/Types.cjs');
|
|
8
|
+
|
|
9
|
+
// src/index.ts
|
|
10
|
+
var VERSION = "3.0.0";
|
|
11
|
+
|
|
12
|
+
exports.VERSION = VERSION;
|
|
13
|
+
Object.keys(LavalinkNode_cjs).forEach(function (k) {
|
|
14
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function () { return LavalinkNode_cjs[k]; }
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
Object.keys(Player_cjs).forEach(function (k) {
|
|
20
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function () { return Player_cjs[k]; }
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
Object.keys(Manager_cjs).forEach(function (k) {
|
|
26
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
get: function () { return Manager_cjs[k]; }
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
Object.keys(Rest_cjs).forEach(function (k) {
|
|
32
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get: function () { return Rest_cjs[k]; }
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
Object.keys(Types_cjs).forEach(function (k) {
|
|
38
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
39
|
+
enumerable: true,
|
|
40
|
+
get: function () { return Types_cjs[k]; }
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=index.cjs.map
|
|
44
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;AAYO,IAAM,OAAA,GAAkB","file":"index.cjs","sourcesContent":["/**\n * @module Lavacord\n */\nexport * from \"./lib/LavalinkNode\";\nexport * from \"./lib/Player\";\nexport * from \"./lib/Manager\";\nexport * from \"./lib/Rest\";\nexport * from \"./lib/Types\";\n\n// This is a placeholder for the version of the library, which should be injected during build time\n// this need to be explicitly typed as string.\n// eslint-disable-next-line @typescript-eslint/no-inferrable-types\nexport const VERSION: string = \"3.0.0\";\n"]}
|