lavalink-client 1.1.21 → 1.1.23

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.
@@ -296,11 +296,11 @@ export interface FilterData {
296
296
  }
297
297
  export type PluginFiltersKey = "lavalink-filter-plugin" | string;
298
298
  export interface PluginFiltersValues extends LavalinkFiltersPlugin {
299
- [key: string]: any;
299
+ [key: string]: string | number | string[] | number[] | EchoFilter | ReverbFilter;
300
300
  }
301
301
  export interface LavalinkFiltersPlugin {
302
- echo: EchoFilter;
303
- reverb: ReverbFilter;
302
+ "echo": EchoFilter;
303
+ "reverb": ReverbFilter;
304
304
  }
305
305
  /**
306
306
  * Actual Filter Data sent to Lavalink
@@ -1,11 +1,11 @@
1
1
  /// <reference types="node" />
2
2
  import { EventEmitter } from "events";
3
- import { NodeManager } from "./NodeManager";
4
- import { ManagerQueueOptions } from "./Queue";
5
- import { GuildShardPayload, ManagerUtils, MiniMap, SearchPlatform, TrackEndEvent, TrackExceptionEvent, TrackStartEvent, TrackStuckEvent, VoicePacket, VoiceServer, VoiceState, WebSocketClosedEvent } from "./Utils";
6
3
  import { LavalinkNodeOptions } from "./Node";
4
+ import { NodeManager } from "./NodeManager";
7
5
  import { DestroyReasonsType, Player, PlayerJson, PlayerOptions } from "./Player";
6
+ import { ManagerQueueOptions } from "./Queue";
8
7
  import { Track, UnresolvedTrack } from "./Track";
8
+ import { ChannelDeletePacket, GuildShardPayload, ManagerUtils, MiniMap, SearchPlatform, TrackEndEvent, TrackExceptionEvent, TrackStartEvent, TrackStuckEvent, VoicePacket, VoiceServer, VoiceState, WebSocketClosedEvent } from "./Utils";
9
9
  export interface LavalinkManager {
10
10
  nodeManager: NodeManager;
11
11
  utils: ManagerUtils;
@@ -59,7 +59,14 @@ export interface ManagerOptions {
59
59
  /** optional */
60
60
  debugOptions?: {
61
61
  /** logs for debugging the "no-Audio" playing error */
62
- noAudio: boolean;
62
+ noAudio?: boolean;
63
+ /** For Logging the Destroy function */
64
+ playerDestroy?: {
65
+ /** To show the debug reason at all times. */
66
+ debugLog?: boolean;
67
+ /** If you get 'Error: Use Player#destroy(true) not PlayerManager#deletePlayer() to stop the Player' put it on true */
68
+ dontThrowError?: boolean;
69
+ };
63
70
  };
64
71
  }
65
72
  interface LavalinkManagerEvents {
@@ -134,7 +141,7 @@ export declare class LavalinkManager extends EventEmitter {
134
141
  constructor(options: ManagerOptions);
135
142
  createPlayer(options: PlayerOptions): Player;
136
143
  getPlayer(guildId: string): Player;
137
- deletePlayer(guildId: string): boolean;
144
+ deletePlayer(guildId: string, throwError?: boolean): boolean;
138
145
  get useable(): boolean;
139
146
  /**
140
147
  * Initiates the Manager.
@@ -145,6 +152,6 @@ export declare class LavalinkManager extends EventEmitter {
145
152
  * Sends voice data to the Lavalink server.
146
153
  * @param data
147
154
  */
148
- sendRawData(data: VoicePacket | VoiceServer | VoiceState | any): Promise<void>;
155
+ sendRawData(data: VoicePacket | VoiceServer | VoiceState | ChannelDeletePacket): Promise<void>;
149
156
  }
150
157
  export {};
@@ -2,11 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LavalinkManager = void 0;
4
4
  const events_1 = require("events");
5
+ const LavalinkManagerStatics_1 = require("./LavalinkManagerStatics");
5
6
  const NodeManager_1 = require("./NodeManager");
7
+ const Player_1 = require("./Player");
6
8
  const Queue_1 = require("./Queue");
7
9
  const Utils_1 = require("./Utils");
8
- const LavalinkManagerStatics_1 = require("./LavalinkManagerStatics");
9
- const Player_1 = require("./Player");
10
10
  class LavalinkManager extends events_1.EventEmitter {
11
11
  static DefaultSources = LavalinkManagerStatics_1.DefaultSources;
12
12
  static SourceLinksRegexes = LavalinkManagerStatics_1.SourceLinksRegexes;
@@ -44,7 +44,11 @@ class LavalinkManager extends events_1.EventEmitter {
44
44
  queueStore: options?.queueOptions?.queueStore ?? new Queue_1.DefaultQueueStore(),
45
45
  },
46
46
  debugOptions: {
47
- noAudio: options?.debugOptions?.noAudio ?? false
47
+ noAudio: options?.debugOptions?.noAudio ?? false,
48
+ playerDestroy: {
49
+ dontThrowError: options?.debugOptions?.playerDestroy?.dontThrowError ?? false,
50
+ debugLog: options?.debugOptions?.playerDestroy?.debugLog ?? false,
51
+ }
48
52
  }
49
53
  };
50
54
  return;
@@ -87,8 +91,9 @@ class LavalinkManager extends events_1.EventEmitter {
87
91
  this.nodeManager = new NodeManager_1.NodeManager(this);
88
92
  }
89
93
  createPlayer(options) {
90
- if (this.players.has(options?.guildId))
91
- return this.players.get(options?.guildId);
94
+ const oldPlayer = this.getPlayer(options?.guildId);
95
+ if (oldPlayer)
96
+ return oldPlayer;
92
97
  const newPlayer = new Player_1.Player(options, this);
93
98
  this.players.set(newPlayer.guildId, newPlayer);
94
99
  return newPlayer;
@@ -96,9 +101,16 @@ class LavalinkManager extends events_1.EventEmitter {
96
101
  getPlayer(guildId) {
97
102
  return this.players.get(guildId);
98
103
  }
99
- deletePlayer(guildId) {
100
- if (typeof this.players.get(guildId)?.voiceChannelId === "string")
101
- throw new Error("Use Player#destroy(true) not PlayerManager#deletePlayer() to stop the Player");
104
+ deletePlayer(guildId, throwError = true) {
105
+ const oldPlayer = this.getPlayer(guildId);
106
+ if (!oldPlayer)
107
+ return;
108
+ if (oldPlayer.voiceChannelId === "string" && oldPlayer.connected) {
109
+ if (throwError)
110
+ throw new Error(`Use Player#destroy(true) not PlayerManager#deletePlayer() to stop the Player ${JSON.stringify(oldPlayer.toJSON?.())}`);
111
+ else
112
+ console.error("Use Player#destroy(true) not PlayerManager#deletePlayer() to stop the Player", oldPlayer.toJSON?.());
113
+ }
102
114
  return this.players.delete(guildId);
103
115
  }
104
116
  get useable() {
@@ -156,11 +168,11 @@ class LavalinkManager extends events_1.EventEmitter {
156
168
  return;
157
169
  const player = this.getPlayer(update.guild_id);
158
170
  if (player && player.voiceChannelId === update.id)
159
- return player.destroy(Player_1.DestroyReasons.ChannelDeleted);
171
+ return void player.destroy(Player_1.DestroyReasons.ChannelDeleted);
160
172
  }
161
173
  // for voice updates
162
174
  if (["VOICE_STATE_UPDATE", "VOICE_SERVER_UPDATE"].includes(data.t)) {
163
- const update = "d" in data ? data.d : data;
175
+ const update = ("d" in data ? data.d : data);
164
176
  if (!update) {
165
177
  if (this.options?.debugOptions?.noAudio === true)
166
178
  console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, no update data found in payload:", data);
@@ -177,6 +189,11 @@ class LavalinkManager extends events_1.EventEmitter {
177
189
  console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, No Lavalink Player found via key: 'guild_id' of update-data:", update);
178
190
  return;
179
191
  }
192
+ if (player.get("internal_destroystatus") === true) {
193
+ if (this.options?.debugOptions?.noAudio === true)
194
+ console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, Player is in a destroying state. can't signal the voice states");
195
+ return;
196
+ }
180
197
  if ("token" in update) {
181
198
  if (!player.node?.sessionId)
182
199
  throw new Error("Lavalink Node is either not ready or not up to date");
@@ -208,7 +225,7 @@ class LavalinkManager extends events_1.EventEmitter {
208
225
  }
209
226
  else {
210
227
  if (this.options?.playerOptions?.onDisconnect?.destroyPlayer === true) {
211
- return await player.destroy(Player_1.DestroyReasons.Disconnected);
228
+ return void await player.destroy(Player_1.DestroyReasons.Disconnected);
212
229
  }
213
230
  this.emit("playerDisconnect", player, player.voiceChannelId);
214
231
  if (!player.paused)
@@ -218,9 +235,9 @@ class LavalinkManager extends events_1.EventEmitter {
218
235
  await player.connect();
219
236
  }
220
237
  catch {
221
- return await player.destroy(Player_1.DestroyReasons.PlayerReconnectFail);
238
+ return void await player.destroy(Player_1.DestroyReasons.PlayerReconnectFail);
222
239
  }
223
- return player.paused && await player.resume();
240
+ return void player.paused && await player.resume();
224
241
  }
225
242
  player.voiceChannelId = null;
226
243
  player.voice = Object.assign({});
@@ -7,6 +7,8 @@ exports.DefaultSources = {
7
7
  "youtubemusic": "ytmsearch",
8
8
  "ytmsearch": "ytmsearch",
9
9
  "ytm": "ytmsearch",
10
+ "musicyoutube": "ytmsearch",
11
+ "music youtube": "ytmsearch",
10
12
  // youtube
11
13
  "youtube": "ytsearch",
12
14
  "yt": "ytsearch",
@@ -21,10 +23,14 @@ exports.DefaultSources = {
21
23
  "applemusic": "amsearch",
22
24
  "amsearch": "amsearch",
23
25
  "am": "amsearch",
26
+ "musicapple": "amsearch",
27
+ "music apple": "amsearch",
24
28
  // spotify
25
29
  "spotify": "spsearch",
26
30
  "spsearch": "spsearch",
27
31
  "sp": "spsearch",
32
+ "spotify.com": "spsearch",
33
+ "spotifycom": "spsearch",
28
34
  "sprec": "sprec",
29
35
  "spsuggestion": "sprec",
30
36
  // deezer
@@ -43,6 +49,7 @@ exports.DefaultSources = {
43
49
  "ftts": "ftts",
44
50
  // Client sided search platforms
45
51
  "bandcamp": "bcsearch",
52
+ "bc": "bcsearch",
46
53
  "bcsearch": "bcsearch",
47
54
  };
48
55
  exports.LavalinkPlugins = {
@@ -30,15 +30,25 @@ export interface PlayerJson {
30
30
  }
31
31
  export type RepeatMode = "queue" | "track" | "off";
32
32
  export interface PlayerOptions {
33
+ /** Guild id of the player */
33
34
  guildId: string;
35
+ /** The Voice Channel Id */
34
36
  voiceChannelId: string;
37
+ /** The Text Channel Id of the Player */
38
+ textChannelId?: string;
39
+ /** instantly change volume with the one play request */
35
40
  volume?: number;
41
+ /** VC Region for node selections */
36
42
  vcRegion?: string;
43
+ /** if it should join deafened */
37
44
  selfDeaf?: boolean;
45
+ /** If it should join muted */
38
46
  selfMute?: boolean;
39
- textChannelId?: string;
47
+ /** If it should use a specific lavalink node */
40
48
  node?: LavalinkNode | string;
49
+ /** If when applying filters, it should use the insta apply filters fix */
41
50
  instaUpdateFiltersFix?: boolean;
51
+ /** If a volume should be applied via filters instead of lavalink-volume */
42
52
  applyVolumeAsFilter?: boolean;
43
53
  }
44
54
  export interface PlayOptions {
@@ -113,7 +123,7 @@ export declare class Player {
113
123
  * @param key
114
124
  * @param value
115
125
  */
116
- set(key: string, value: unknown): void;
126
+ set(key: string, value: unknown): this;
117
127
  /**
118
128
  * Get custom data.
119
129
  * @param key
@@ -122,7 +132,7 @@ export declare class Player {
122
132
  /**
123
133
  * CLears all the custom data.
124
134
  */
125
- clearData(): void;
135
+ clearData(): this;
126
136
  /**
127
137
  * Get all custom Data
128
138
  */
@@ -137,32 +147,32 @@ export declare class Player {
137
147
  * @param volume The Volume in percent
138
148
  * @param ignoreVolumeDecrementer If it should ignore the volumedecrementer option
139
149
  */
140
- setVolume(volume: number, ignoreVolumeDecrementer?: boolean): Promise<void>;
150
+ setVolume(volume: number, ignoreVolumeDecrementer?: boolean): Promise<this>;
141
151
  lavaSearch(query: LavaSearchQuery, requestUser: unknown): Promise<import("./Utils").SearchResult | import("./Utils").LavaSearchResponse>;
142
152
  /**
143
153
  *
144
154
  * @param query Query for your data
145
155
  * @param requestUser
146
156
  */
147
- search(query: SearchQuery, requestUser: unknown): Promise<import("./Utils").SearchResult | import("./Utils").UnresolvedSearchResult>;
157
+ search(query: SearchQuery, requestUser: unknown): Promise<import("./Utils").UnresolvedSearchResult | import("./Utils").SearchResult>;
148
158
  /**
149
159
  * Pause the player
150
160
  */
151
- pause(): Promise<void>;
161
+ pause(): Promise<this>;
152
162
  /**
153
163
  * Resume the Player
154
164
  */
155
- resume(): Promise<void>;
165
+ resume(): Promise<this>;
156
166
  /**
157
167
  * Seek to a specific Position
158
168
  * @param position
159
169
  */
160
- seek(position: number): Promise<any>;
170
+ seek(position: number): Promise<this>;
161
171
  /**
162
172
  * Set the Repeatmode of the Player
163
173
  * @param repeatMode
164
174
  */
165
- setRepeatMode(repeatMode: RepeatMode): Promise<RepeatMode>;
175
+ setRepeatMode(repeatMode: RepeatMode): Promise<this>;
166
176
  /**
167
177
  * Skip the current song, or a specific amount of songs
168
178
  * @param amount provide the index of the next track to skip to
@@ -172,17 +182,17 @@ export declare class Player {
172
182
  * Connects the Player to the Voice Channel
173
183
  * @returns
174
184
  */
175
- connect(): Promise<void>;
185
+ connect(): Promise<this>;
176
186
  /**
177
187
  * Disconnects the Player from the Voice Channel, but keeps the player in the cache
178
188
  * @param force If false it throws an error, if player thinks it's already disconnected
179
189
  * @returns
180
190
  */
181
- disconnect(force?: boolean): Promise<void>;
191
+ disconnect(force?: boolean): Promise<this>;
182
192
  /**
183
193
  * Destroy the player and disconnect from the voice channel
184
194
  */
185
- destroy(reason?: string): Promise<void>;
195
+ destroy(reason?: string): Promise<this>;
186
196
  /**
187
197
  * Move the player on a different Audio-Node
188
198
  * @param newNode New Node / New Node Id
@@ -91,7 +91,7 @@ class Player {
91
91
  */
92
92
  set(key, value) {
93
93
  this.data[key] = value;
94
- return;
94
+ return this;
95
95
  }
96
96
  /**
97
97
  * Get custom data.
@@ -110,7 +110,7 @@ class Player {
110
110
  continue;
111
111
  delete this.data[key];
112
112
  }
113
- return;
113
+ return this;
114
114
  }
115
115
  /**
116
116
  * Get all custom Data
@@ -148,7 +148,7 @@ class Player {
148
148
  delete options.encodedTrack;
149
149
  if (this.queue.tracks[0])
150
150
  return this.play(options);
151
- return;
151
+ return this;
152
152
  }
153
153
  }
154
154
  const track = this.queue.current;
@@ -187,6 +187,7 @@ class Player {
187
187
  playerOptions: finalOptions,
188
188
  });
189
189
  this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
190
+ return this;
190
191
  }
191
192
  /**
192
193
  * Set the Volume for the Player
@@ -209,7 +210,7 @@ class Player {
209
210
  await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { volume: this.lavalinkVolume } });
210
211
  }
211
212
  this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
212
- return;
213
+ return this;
213
214
  }
214
215
  async lavaSearch(query, requestUser) {
215
216
  return this.node.lavaSearch(query, requestUser);
@@ -239,7 +240,7 @@ class Player {
239
240
  const now = performance.now();
240
241
  await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { paused: true } });
241
242
  this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
242
- return;
243
+ return this;
243
244
  }
244
245
  /**
245
246
  * Resume the Player
@@ -251,7 +252,7 @@ class Player {
251
252
  const now = performance.now();
252
253
  await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { paused: false } });
253
254
  this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
254
- return;
255
+ return this;
255
256
  }
256
257
  /**
257
258
  * Seek to a specific Position
@@ -272,7 +273,7 @@ class Player {
272
273
  const now = performance.now();
273
274
  await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { position } });
274
275
  this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
275
- return;
276
+ return this;
276
277
  }
277
278
  /**
278
279
  * Set the Repeatmode of the Player
@@ -281,7 +282,8 @@ class Player {
281
282
  async setRepeatMode(repeatMode) {
282
283
  if (!["off", "track", "queue"].includes(repeatMode))
283
284
  throw new RangeError("Repeatmode must be either 'off', 'track', or 'queue'");
284
- return this.repeatMode = repeatMode;
285
+ this.repeatMode = repeatMode;
286
+ return this;
285
287
  }
286
288
  /**
287
289
  * Skip the current song, or a specific amount of songs
@@ -300,7 +302,7 @@ class Player {
300
302
  const now = performance.now();
301
303
  await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { encodedTrack: null } });
302
304
  this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
303
- return true;
305
+ return this;
304
306
  }
305
307
  /**
306
308
  * Connects the Player to the Voice Channel
@@ -318,7 +320,7 @@ class Player {
318
320
  self_deaf: this.options.selfDeaf ?? true,
319
321
  }
320
322
  });
321
- return;
323
+ return this;
322
324
  }
323
325
  /**
324
326
  * Disconnects the Player from the Voice Channel, but keeps the player in the cache
@@ -338,18 +340,34 @@ class Player {
338
340
  }
339
341
  });
340
342
  this.voiceChannelId = null;
341
- return;
343
+ return this;
342
344
  }
343
345
  /**
344
346
  * Destroy the player and disconnect from the voice channel
345
347
  */
346
348
  async destroy(reason) {
349
+ if (this.LavalinkManager.options.debugOptions.playerDestroy.debugLog)
350
+ console.log(`Lavalink-Client-Debug | PlayerDestroy [::] destroy Function, [guildId ${this.guildId}] - Destroy-Reason: ${String(reason)}`);
351
+ if (this.get("internal_destroystatus") === true) {
352
+ if (this.LavalinkManager.options.debugOptions.playerDestroy.debugLog)
353
+ console.log(`Lavalink-Client-Debug | PlayerDestroy [::] destroy Function, [guildId ${this.guildId}] - Already destroying somewhere else..`);
354
+ return;
355
+ }
356
+ this.set("internal_destroystatus", true);
357
+ // disconnect player and set VoiceChannel to Null
347
358
  await this.disconnect(true);
359
+ // Destroy the queue
348
360
  await this.queue.utils.destroy();
349
- this.LavalinkManager.deletePlayer(this.guildId);
361
+ // delete the player from cache
362
+ this.LavalinkManager.deletePlayer(this.guildId, !this.LavalinkManager.options.debugOptions.playerDestroy.dontThrowError);
363
+ // destroy the player on lavalink side
350
364
  await this.node.destroyPlayer(this.guildId);
365
+ if (this.LavalinkManager.options.debugOptions.playerDestroy.debugLog)
366
+ console.log(`Lavalink-Client-Debug | PlayerDestroy [::] destroy Function, [guildId ${this.guildId}] - Player got destroyed successfully`);
367
+ // emit the event
351
368
  this.LavalinkManager.emit("playerDestroy", this, reason);
352
- return;
369
+ // return smt
370
+ return this;
353
371
  }
354
372
  /**
355
373
  * Move the player on a different Audio-Node
@@ -16,9 +16,9 @@ export type LavaSrcSearchPlatformBase = "spsearch" | "sprec" | "amsearch" | "dzs
16
16
  export type LavaSrcSearchPlatform = LavaSrcSearchPlatformBase | "ftts";
17
17
  export type DuncteSearchPlatform = "speak" | "tts";
18
18
  export type LavalinkClientSearchPlatform = "bcsearch";
19
- export type LavalinkClientSearchPlatformResolve = "bandcamp";
19
+ export type LavalinkClientSearchPlatformResolve = "bandcamp" | "bc";
20
20
  export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | LavaSrcSearchPlatform | DuncteSearchPlatform | LavalinkClientSearchPlatform;
21
- export type ClientSearchPlatform = "youtube" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "sp" | "spsuggestion" | "spotify" | "dz" | "deezer" | "yandex" | "yandex music" | "yandexmusic" | LavalinkClientSearchPlatformResolve | LavalinkClientSearchPlatform;
21
+ export type ClientSearchPlatform = "youtube" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "musicyoutube" | "music youtube" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "musicapple" | "music apple" | "sp" | "spsuggestion" | "spotify" | "spotify.com" | "spotifycom" | "dz" | "deezer" | "yandex" | "yandex music" | "yandexmusic" | LavalinkClientSearchPlatformResolve | LavalinkClientSearchPlatform;
22
22
  export type SearchPlatform = LavalinkSearchPlatform | ClientSearchPlatform;
23
23
  export type SourcesRegex = "YoutubeRegex" | "YoutubeMusicRegex" | "SoundCloudRegex" | "SoundCloudMobileRegex" | "DeezerTrackRegex" | "DeezerArtistRegex" | "DeezerEpisodeRegex" | "DeezerMixesRegex" | "DeezerPageLinkRegex" | "DeezerPlaylistRegex" | "DeezerAlbumRegex" | "AllDeezerRegex" | "AllDeezerRegexWithoutPageLink" | "SpotifySongRegex" | "SpotifyPlaylistRegex" | "SpotifyArtistRegex" | "SpotifyEpisodeRegex" | "SpotifyShowRegex" | "SpotifyAlbumRegex" | "AllSpotifyRegex" | "mp3Url" | "m3uUrl" | "m3u8Url" | "mp4Url" | "m4aUrl" | "wavUrl" | "aacpUrl" | "tiktok" | "mixcloud" | "musicYandex" | "radiohost" | "bandcamp" | "appleMusic" | "TwitchTv" | "vimeo";
24
24
  export interface PlaylistInfo {
@@ -283,6 +283,13 @@ export interface LavalinkPlayer {
283
283
  voice: LavalinkPlayerVoice;
284
284
  filters: Partial<LavalinkFilterData>;
285
285
  }
286
+ export interface ChannelDeletePacket {
287
+ t: "CHANNEL_DELETE";
288
+ d: {
289
+ guild_id: string;
290
+ id: string;
291
+ };
292
+ }
286
293
  export interface VoiceState {
287
294
  op: "voiceUpdate";
288
295
  guildId: string;
@@ -66,9 +66,13 @@ class ManagerUtils {
66
66
  const closest = await getClosestTrack(this, player);
67
67
  if (!closest)
68
68
  throw new SyntaxError("No closest Track found");
69
- Object.getOwnPropertyNames(this).forEach(prop => delete this[prop]);
70
- Object.assign(this, closest);
71
- return;
69
+ for (const prop of Object.getOwnPropertyNames(this))
70
+ delete this[prop];
71
+ // delete symbol
72
+ delete this[exports.UnresolvedTrackSymbol];
73
+ // assign new symbol
74
+ Object.defineProperty(this, exports.TrackSymbol, { configurable: true, value: true });
75
+ return Object.assign(this, closest);
72
76
  }
73
77
  };
74
78
  if (!this.isUnresolvedTrack(unresolvedTrack))
@@ -296,11 +296,11 @@ export interface FilterData {
296
296
  }
297
297
  export type PluginFiltersKey = "lavalink-filter-plugin" | string;
298
298
  export interface PluginFiltersValues extends LavalinkFiltersPlugin {
299
- [key: string]: any;
299
+ [key: string]: string | number | string[] | number[] | EchoFilter | ReverbFilter;
300
300
  }
301
301
  export interface LavalinkFiltersPlugin {
302
- echo: EchoFilter;
303
- reverb: ReverbFilter;
302
+ "echo": EchoFilter;
303
+ "reverb": ReverbFilter;
304
304
  }
305
305
  /**
306
306
  * Actual Filter Data sent to Lavalink
@@ -1,11 +1,11 @@
1
1
  /// <reference types="node" />
2
2
  import { EventEmitter } from "events";
3
- import { NodeManager } from "./NodeManager";
4
- import { ManagerQueueOptions } from "./Queue";
5
- import { GuildShardPayload, ManagerUtils, MiniMap, SearchPlatform, TrackEndEvent, TrackExceptionEvent, TrackStartEvent, TrackStuckEvent, VoicePacket, VoiceServer, VoiceState, WebSocketClosedEvent } from "./Utils";
6
3
  import { LavalinkNodeOptions } from "./Node";
4
+ import { NodeManager } from "./NodeManager";
7
5
  import { DestroyReasonsType, Player, PlayerJson, PlayerOptions } from "./Player";
6
+ import { ManagerQueueOptions } from "./Queue";
8
7
  import { Track, UnresolvedTrack } from "./Track";
8
+ import { ChannelDeletePacket, GuildShardPayload, ManagerUtils, MiniMap, SearchPlatform, TrackEndEvent, TrackExceptionEvent, TrackStartEvent, TrackStuckEvent, VoicePacket, VoiceServer, VoiceState, WebSocketClosedEvent } from "./Utils";
9
9
  export interface LavalinkManager {
10
10
  nodeManager: NodeManager;
11
11
  utils: ManagerUtils;
@@ -59,7 +59,14 @@ export interface ManagerOptions {
59
59
  /** optional */
60
60
  debugOptions?: {
61
61
  /** logs for debugging the "no-Audio" playing error */
62
- noAudio: boolean;
62
+ noAudio?: boolean;
63
+ /** For Logging the Destroy function */
64
+ playerDestroy?: {
65
+ /** To show the debug reason at all times. */
66
+ debugLog?: boolean;
67
+ /** If you get 'Error: Use Player#destroy(true) not PlayerManager#deletePlayer() to stop the Player' put it on true */
68
+ dontThrowError?: boolean;
69
+ };
63
70
  };
64
71
  }
65
72
  interface LavalinkManagerEvents {
@@ -134,7 +141,7 @@ export declare class LavalinkManager extends EventEmitter {
134
141
  constructor(options: ManagerOptions);
135
142
  createPlayer(options: PlayerOptions): Player;
136
143
  getPlayer(guildId: string): Player;
137
- deletePlayer(guildId: string): boolean;
144
+ deletePlayer(guildId: string, throwError?: boolean): boolean;
138
145
  get useable(): boolean;
139
146
  /**
140
147
  * Initiates the Manager.
@@ -145,6 +152,6 @@ export declare class LavalinkManager extends EventEmitter {
145
152
  * Sends voice data to the Lavalink server.
146
153
  * @param data
147
154
  */
148
- sendRawData(data: VoicePacket | VoiceServer | VoiceState | any): Promise<void>;
155
+ sendRawData(data: VoicePacket | VoiceServer | VoiceState | ChannelDeletePacket): Promise<void>;
149
156
  }
150
157
  export {};
@@ -1,9 +1,9 @@
1
1
  import { EventEmitter } from "events";
2
+ import { DefaultSources, SourceLinksRegexes } from "./LavalinkManagerStatics";
2
3
  import { NodeManager } from "./NodeManager";
4
+ import { DestroyReasons, Player } from "./Player";
3
5
  import { DefaultQueueStore } from "./Queue";
4
6
  import { ManagerUtils, MiniMap } from "./Utils";
5
- import { DefaultSources, SourceLinksRegexes } from "./LavalinkManagerStatics";
6
- import { DestroyReasons, Player } from "./Player";
7
7
  export class LavalinkManager extends EventEmitter {
8
8
  static DefaultSources = DefaultSources;
9
9
  static SourceLinksRegexes = SourceLinksRegexes;
@@ -41,7 +41,11 @@ export class LavalinkManager extends EventEmitter {
41
41
  queueStore: options?.queueOptions?.queueStore ?? new DefaultQueueStore(),
42
42
  },
43
43
  debugOptions: {
44
- noAudio: options?.debugOptions?.noAudio ?? false
44
+ noAudio: options?.debugOptions?.noAudio ?? false,
45
+ playerDestroy: {
46
+ dontThrowError: options?.debugOptions?.playerDestroy?.dontThrowError ?? false,
47
+ debugLog: options?.debugOptions?.playerDestroy?.debugLog ?? false,
48
+ }
45
49
  }
46
50
  };
47
51
  return;
@@ -84,8 +88,9 @@ export class LavalinkManager extends EventEmitter {
84
88
  this.nodeManager = new NodeManager(this);
85
89
  }
86
90
  createPlayer(options) {
87
- if (this.players.has(options?.guildId))
88
- return this.players.get(options?.guildId);
91
+ const oldPlayer = this.getPlayer(options?.guildId);
92
+ if (oldPlayer)
93
+ return oldPlayer;
89
94
  const newPlayer = new Player(options, this);
90
95
  this.players.set(newPlayer.guildId, newPlayer);
91
96
  return newPlayer;
@@ -93,9 +98,16 @@ export class LavalinkManager extends EventEmitter {
93
98
  getPlayer(guildId) {
94
99
  return this.players.get(guildId);
95
100
  }
96
- deletePlayer(guildId) {
97
- if (typeof this.players.get(guildId)?.voiceChannelId === "string")
98
- throw new Error("Use Player#destroy(true) not PlayerManager#deletePlayer() to stop the Player");
101
+ deletePlayer(guildId, throwError = true) {
102
+ const oldPlayer = this.getPlayer(guildId);
103
+ if (!oldPlayer)
104
+ return;
105
+ if (oldPlayer.voiceChannelId === "string" && oldPlayer.connected) {
106
+ if (throwError)
107
+ throw new Error(`Use Player#destroy(true) not PlayerManager#deletePlayer() to stop the Player ${JSON.stringify(oldPlayer.toJSON?.())}`);
108
+ else
109
+ console.error("Use Player#destroy(true) not PlayerManager#deletePlayer() to stop the Player", oldPlayer.toJSON?.());
110
+ }
99
111
  return this.players.delete(guildId);
100
112
  }
101
113
  get useable() {
@@ -153,11 +165,11 @@ export class LavalinkManager extends EventEmitter {
153
165
  return;
154
166
  const player = this.getPlayer(update.guild_id);
155
167
  if (player && player.voiceChannelId === update.id)
156
- return player.destroy(DestroyReasons.ChannelDeleted);
168
+ return void player.destroy(DestroyReasons.ChannelDeleted);
157
169
  }
158
170
  // for voice updates
159
171
  if (["VOICE_STATE_UPDATE", "VOICE_SERVER_UPDATE"].includes(data.t)) {
160
- const update = "d" in data ? data.d : data;
172
+ const update = ("d" in data ? data.d : data);
161
173
  if (!update) {
162
174
  if (this.options?.debugOptions?.noAudio === true)
163
175
  console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, no update data found in payload:", data);
@@ -174,6 +186,11 @@ export class LavalinkManager extends EventEmitter {
174
186
  console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, No Lavalink Player found via key: 'guild_id' of update-data:", update);
175
187
  return;
176
188
  }
189
+ if (player.get("internal_destroystatus") === true) {
190
+ if (this.options?.debugOptions?.noAudio === true)
191
+ console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, Player is in a destroying state. can't signal the voice states");
192
+ return;
193
+ }
177
194
  if ("token" in update) {
178
195
  if (!player.node?.sessionId)
179
196
  throw new Error("Lavalink Node is either not ready or not up to date");
@@ -205,7 +222,7 @@ export class LavalinkManager extends EventEmitter {
205
222
  }
206
223
  else {
207
224
  if (this.options?.playerOptions?.onDisconnect?.destroyPlayer === true) {
208
- return await player.destroy(DestroyReasons.Disconnected);
225
+ return void await player.destroy(DestroyReasons.Disconnected);
209
226
  }
210
227
  this.emit("playerDisconnect", player, player.voiceChannelId);
211
228
  if (!player.paused)
@@ -215,9 +232,9 @@ export class LavalinkManager extends EventEmitter {
215
232
  await player.connect();
216
233
  }
217
234
  catch {
218
- return await player.destroy(DestroyReasons.PlayerReconnectFail);
235
+ return void await player.destroy(DestroyReasons.PlayerReconnectFail);
219
236
  }
220
- return player.paused && await player.resume();
237
+ return void player.paused && await player.resume();
221
238
  }
222
239
  player.voiceChannelId = null;
223
240
  player.voice = Object.assign({});
@@ -4,6 +4,8 @@ export const DefaultSources = {
4
4
  "youtubemusic": "ytmsearch",
5
5
  "ytmsearch": "ytmsearch",
6
6
  "ytm": "ytmsearch",
7
+ "musicyoutube": "ytmsearch",
8
+ "music youtube": "ytmsearch",
7
9
  // youtube
8
10
  "youtube": "ytsearch",
9
11
  "yt": "ytsearch",
@@ -18,10 +20,14 @@ export const DefaultSources = {
18
20
  "applemusic": "amsearch",
19
21
  "amsearch": "amsearch",
20
22
  "am": "amsearch",
23
+ "musicapple": "amsearch",
24
+ "music apple": "amsearch",
21
25
  // spotify
22
26
  "spotify": "spsearch",
23
27
  "spsearch": "spsearch",
24
28
  "sp": "spsearch",
29
+ "spotify.com": "spsearch",
30
+ "spotifycom": "spsearch",
25
31
  "sprec": "sprec",
26
32
  "spsuggestion": "sprec",
27
33
  // deezer
@@ -40,6 +46,7 @@ export const DefaultSources = {
40
46
  "ftts": "ftts",
41
47
  // Client sided search platforms
42
48
  "bandcamp": "bcsearch",
49
+ "bc": "bcsearch",
43
50
  "bcsearch": "bcsearch",
44
51
  };
45
52
  export const LavalinkPlugins = {
@@ -30,15 +30,25 @@ export interface PlayerJson {
30
30
  }
31
31
  export type RepeatMode = "queue" | "track" | "off";
32
32
  export interface PlayerOptions {
33
+ /** Guild id of the player */
33
34
  guildId: string;
35
+ /** The Voice Channel Id */
34
36
  voiceChannelId: string;
37
+ /** The Text Channel Id of the Player */
38
+ textChannelId?: string;
39
+ /** instantly change volume with the one play request */
35
40
  volume?: number;
41
+ /** VC Region for node selections */
36
42
  vcRegion?: string;
43
+ /** if it should join deafened */
37
44
  selfDeaf?: boolean;
45
+ /** If it should join muted */
38
46
  selfMute?: boolean;
39
- textChannelId?: string;
47
+ /** If it should use a specific lavalink node */
40
48
  node?: LavalinkNode | string;
49
+ /** If when applying filters, it should use the insta apply filters fix */
41
50
  instaUpdateFiltersFix?: boolean;
51
+ /** If a volume should be applied via filters instead of lavalink-volume */
42
52
  applyVolumeAsFilter?: boolean;
43
53
  }
44
54
  export interface PlayOptions {
@@ -113,7 +123,7 @@ export declare class Player {
113
123
  * @param key
114
124
  * @param value
115
125
  */
116
- set(key: string, value: unknown): void;
126
+ set(key: string, value: unknown): this;
117
127
  /**
118
128
  * Get custom data.
119
129
  * @param key
@@ -122,7 +132,7 @@ export declare class Player {
122
132
  /**
123
133
  * CLears all the custom data.
124
134
  */
125
- clearData(): void;
135
+ clearData(): this;
126
136
  /**
127
137
  * Get all custom Data
128
138
  */
@@ -137,32 +147,32 @@ export declare class Player {
137
147
  * @param volume The Volume in percent
138
148
  * @param ignoreVolumeDecrementer If it should ignore the volumedecrementer option
139
149
  */
140
- setVolume(volume: number, ignoreVolumeDecrementer?: boolean): Promise<void>;
150
+ setVolume(volume: number, ignoreVolumeDecrementer?: boolean): Promise<this>;
141
151
  lavaSearch(query: LavaSearchQuery, requestUser: unknown): Promise<import("./Utils").SearchResult | import("./Utils").LavaSearchResponse>;
142
152
  /**
143
153
  *
144
154
  * @param query Query for your data
145
155
  * @param requestUser
146
156
  */
147
- search(query: SearchQuery, requestUser: unknown): Promise<import("./Utils").SearchResult | import("./Utils").UnresolvedSearchResult>;
157
+ search(query: SearchQuery, requestUser: unknown): Promise<import("./Utils").UnresolvedSearchResult | import("./Utils").SearchResult>;
148
158
  /**
149
159
  * Pause the player
150
160
  */
151
- pause(): Promise<void>;
161
+ pause(): Promise<this>;
152
162
  /**
153
163
  * Resume the Player
154
164
  */
155
- resume(): Promise<void>;
165
+ resume(): Promise<this>;
156
166
  /**
157
167
  * Seek to a specific Position
158
168
  * @param position
159
169
  */
160
- seek(position: number): Promise<any>;
170
+ seek(position: number): Promise<this>;
161
171
  /**
162
172
  * Set the Repeatmode of the Player
163
173
  * @param repeatMode
164
174
  */
165
- setRepeatMode(repeatMode: RepeatMode): Promise<RepeatMode>;
175
+ setRepeatMode(repeatMode: RepeatMode): Promise<this>;
166
176
  /**
167
177
  * Skip the current song, or a specific amount of songs
168
178
  * @param amount provide the index of the next track to skip to
@@ -172,17 +182,17 @@ export declare class Player {
172
182
  * Connects the Player to the Voice Channel
173
183
  * @returns
174
184
  */
175
- connect(): Promise<void>;
185
+ connect(): Promise<this>;
176
186
  /**
177
187
  * Disconnects the Player from the Voice Channel, but keeps the player in the cache
178
188
  * @param force If false it throws an error, if player thinks it's already disconnected
179
189
  * @returns
180
190
  */
181
- disconnect(force?: boolean): Promise<void>;
191
+ disconnect(force?: boolean): Promise<this>;
182
192
  /**
183
193
  * Destroy the player and disconnect from the voice channel
184
194
  */
185
- destroy(reason?: string): Promise<void>;
195
+ destroy(reason?: string): Promise<this>;
186
196
  /**
187
197
  * Move the player on a different Audio-Node
188
198
  * @param newNode New Node / New Node Id
@@ -88,7 +88,7 @@ export class Player {
88
88
  */
89
89
  set(key, value) {
90
90
  this.data[key] = value;
91
- return;
91
+ return this;
92
92
  }
93
93
  /**
94
94
  * Get custom data.
@@ -107,7 +107,7 @@ export class Player {
107
107
  continue;
108
108
  delete this.data[key];
109
109
  }
110
- return;
110
+ return this;
111
111
  }
112
112
  /**
113
113
  * Get all custom Data
@@ -145,7 +145,7 @@ export class Player {
145
145
  delete options.encodedTrack;
146
146
  if (this.queue.tracks[0])
147
147
  return this.play(options);
148
- return;
148
+ return this;
149
149
  }
150
150
  }
151
151
  const track = this.queue.current;
@@ -184,6 +184,7 @@ export class Player {
184
184
  playerOptions: finalOptions,
185
185
  });
186
186
  this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
187
+ return this;
187
188
  }
188
189
  /**
189
190
  * Set the Volume for the Player
@@ -206,7 +207,7 @@ export class Player {
206
207
  await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { volume: this.lavalinkVolume } });
207
208
  }
208
209
  this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
209
- return;
210
+ return this;
210
211
  }
211
212
  async lavaSearch(query, requestUser) {
212
213
  return this.node.lavaSearch(query, requestUser);
@@ -236,7 +237,7 @@ export class Player {
236
237
  const now = performance.now();
237
238
  await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { paused: true } });
238
239
  this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
239
- return;
240
+ return this;
240
241
  }
241
242
  /**
242
243
  * Resume the Player
@@ -248,7 +249,7 @@ export class Player {
248
249
  const now = performance.now();
249
250
  await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { paused: false } });
250
251
  this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
251
- return;
252
+ return this;
252
253
  }
253
254
  /**
254
255
  * Seek to a specific Position
@@ -269,7 +270,7 @@ export class Player {
269
270
  const now = performance.now();
270
271
  await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { position } });
271
272
  this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
272
- return;
273
+ return this;
273
274
  }
274
275
  /**
275
276
  * Set the Repeatmode of the Player
@@ -278,7 +279,8 @@ export class Player {
278
279
  async setRepeatMode(repeatMode) {
279
280
  if (!["off", "track", "queue"].includes(repeatMode))
280
281
  throw new RangeError("Repeatmode must be either 'off', 'track', or 'queue'");
281
- return this.repeatMode = repeatMode;
282
+ this.repeatMode = repeatMode;
283
+ return this;
282
284
  }
283
285
  /**
284
286
  * Skip the current song, or a specific amount of songs
@@ -297,7 +299,7 @@ export class Player {
297
299
  const now = performance.now();
298
300
  await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { encodedTrack: null } });
299
301
  this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
300
- return true;
302
+ return this;
301
303
  }
302
304
  /**
303
305
  * Connects the Player to the Voice Channel
@@ -315,7 +317,7 @@ export class Player {
315
317
  self_deaf: this.options.selfDeaf ?? true,
316
318
  }
317
319
  });
318
- return;
320
+ return this;
319
321
  }
320
322
  /**
321
323
  * Disconnects the Player from the Voice Channel, but keeps the player in the cache
@@ -335,18 +337,34 @@ export class Player {
335
337
  }
336
338
  });
337
339
  this.voiceChannelId = null;
338
- return;
340
+ return this;
339
341
  }
340
342
  /**
341
343
  * Destroy the player and disconnect from the voice channel
342
344
  */
343
345
  async destroy(reason) {
346
+ if (this.LavalinkManager.options.debugOptions.playerDestroy.debugLog)
347
+ console.log(`Lavalink-Client-Debug | PlayerDestroy [::] destroy Function, [guildId ${this.guildId}] - Destroy-Reason: ${String(reason)}`);
348
+ if (this.get("internal_destroystatus") === true) {
349
+ if (this.LavalinkManager.options.debugOptions.playerDestroy.debugLog)
350
+ console.log(`Lavalink-Client-Debug | PlayerDestroy [::] destroy Function, [guildId ${this.guildId}] - Already destroying somewhere else..`);
351
+ return;
352
+ }
353
+ this.set("internal_destroystatus", true);
354
+ // disconnect player and set VoiceChannel to Null
344
355
  await this.disconnect(true);
356
+ // Destroy the queue
345
357
  await this.queue.utils.destroy();
346
- this.LavalinkManager.deletePlayer(this.guildId);
358
+ // delete the player from cache
359
+ this.LavalinkManager.deletePlayer(this.guildId, !this.LavalinkManager.options.debugOptions.playerDestroy.dontThrowError);
360
+ // destroy the player on lavalink side
347
361
  await this.node.destroyPlayer(this.guildId);
362
+ if (this.LavalinkManager.options.debugOptions.playerDestroy.debugLog)
363
+ console.log(`Lavalink-Client-Debug | PlayerDestroy [::] destroy Function, [guildId ${this.guildId}] - Player got destroyed successfully`);
364
+ // emit the event
348
365
  this.LavalinkManager.emit("playerDestroy", this, reason);
349
- return;
366
+ // return smt
367
+ return this;
350
368
  }
351
369
  /**
352
370
  * Move the player on a different Audio-Node
@@ -16,9 +16,9 @@ export type LavaSrcSearchPlatformBase = "spsearch" | "sprec" | "amsearch" | "dzs
16
16
  export type LavaSrcSearchPlatform = LavaSrcSearchPlatformBase | "ftts";
17
17
  export type DuncteSearchPlatform = "speak" | "tts";
18
18
  export type LavalinkClientSearchPlatform = "bcsearch";
19
- export type LavalinkClientSearchPlatformResolve = "bandcamp";
19
+ export type LavalinkClientSearchPlatformResolve = "bandcamp" | "bc";
20
20
  export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | LavaSrcSearchPlatform | DuncteSearchPlatform | LavalinkClientSearchPlatform;
21
- export type ClientSearchPlatform = "youtube" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "sp" | "spsuggestion" | "spotify" | "dz" | "deezer" | "yandex" | "yandex music" | "yandexmusic" | LavalinkClientSearchPlatformResolve | LavalinkClientSearchPlatform;
21
+ export type ClientSearchPlatform = "youtube" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "musicyoutube" | "music youtube" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "musicapple" | "music apple" | "sp" | "spsuggestion" | "spotify" | "spotify.com" | "spotifycom" | "dz" | "deezer" | "yandex" | "yandex music" | "yandexmusic" | LavalinkClientSearchPlatformResolve | LavalinkClientSearchPlatform;
22
22
  export type SearchPlatform = LavalinkSearchPlatform | ClientSearchPlatform;
23
23
  export type SourcesRegex = "YoutubeRegex" | "YoutubeMusicRegex" | "SoundCloudRegex" | "SoundCloudMobileRegex" | "DeezerTrackRegex" | "DeezerArtistRegex" | "DeezerEpisodeRegex" | "DeezerMixesRegex" | "DeezerPageLinkRegex" | "DeezerPlaylistRegex" | "DeezerAlbumRegex" | "AllDeezerRegex" | "AllDeezerRegexWithoutPageLink" | "SpotifySongRegex" | "SpotifyPlaylistRegex" | "SpotifyArtistRegex" | "SpotifyEpisodeRegex" | "SpotifyShowRegex" | "SpotifyAlbumRegex" | "AllSpotifyRegex" | "mp3Url" | "m3uUrl" | "m3u8Url" | "mp4Url" | "m4aUrl" | "wavUrl" | "aacpUrl" | "tiktok" | "mixcloud" | "musicYandex" | "radiohost" | "bandcamp" | "appleMusic" | "TwitchTv" | "vimeo";
24
24
  export interface PlaylistInfo {
@@ -283,6 +283,13 @@ export interface LavalinkPlayer {
283
283
  voice: LavalinkPlayerVoice;
284
284
  filters: Partial<LavalinkFilterData>;
285
285
  }
286
+ export interface ChannelDeletePacket {
287
+ t: "CHANNEL_DELETE";
288
+ d: {
289
+ guild_id: string;
290
+ id: string;
291
+ };
292
+ }
286
293
  export interface VoiceState {
287
294
  op: "voiceUpdate";
288
295
  guildId: string;
@@ -63,9 +63,13 @@ export class ManagerUtils {
63
63
  const closest = await getClosestTrack(this, player);
64
64
  if (!closest)
65
65
  throw new SyntaxError("No closest Track found");
66
- Object.getOwnPropertyNames(this).forEach(prop => delete this[prop]);
67
- Object.assign(this, closest);
68
- return;
66
+ for (const prop of Object.getOwnPropertyNames(this))
67
+ delete this[prop];
68
+ // delete symbol
69
+ delete this[UnresolvedTrackSymbol];
70
+ // assign new symbol
71
+ Object.defineProperty(this, TrackSymbol, { configurable: true, value: true });
72
+ return Object.assign(this, closest);
69
73
  }
70
74
  };
71
75
  if (!this.isUnresolvedTrack(unresolvedTrack))
@@ -296,11 +296,11 @@ export interface FilterData {
296
296
  }
297
297
  export type PluginFiltersKey = "lavalink-filter-plugin" | string;
298
298
  export interface PluginFiltersValues extends LavalinkFiltersPlugin {
299
- [key: string]: any;
299
+ [key: string]: string | number | string[] | number[] | EchoFilter | ReverbFilter;
300
300
  }
301
301
  export interface LavalinkFiltersPlugin {
302
- echo: EchoFilter;
303
- reverb: ReverbFilter;
302
+ "echo": EchoFilter;
303
+ "reverb": ReverbFilter;
304
304
  }
305
305
  /**
306
306
  * Actual Filter Data sent to Lavalink
@@ -1,11 +1,11 @@
1
1
  /// <reference types="node" />
2
2
  import { EventEmitter } from "events";
3
- import { NodeManager } from "./NodeManager";
4
- import { ManagerQueueOptions } from "./Queue";
5
- import { GuildShardPayload, ManagerUtils, MiniMap, SearchPlatform, TrackEndEvent, TrackExceptionEvent, TrackStartEvent, TrackStuckEvent, VoicePacket, VoiceServer, VoiceState, WebSocketClosedEvent } from "./Utils";
6
3
  import { LavalinkNodeOptions } from "./Node";
4
+ import { NodeManager } from "./NodeManager";
7
5
  import { DestroyReasonsType, Player, PlayerJson, PlayerOptions } from "./Player";
6
+ import { ManagerQueueOptions } from "./Queue";
8
7
  import { Track, UnresolvedTrack } from "./Track";
8
+ import { ChannelDeletePacket, GuildShardPayload, ManagerUtils, MiniMap, SearchPlatform, TrackEndEvent, TrackExceptionEvent, TrackStartEvent, TrackStuckEvent, VoicePacket, VoiceServer, VoiceState, WebSocketClosedEvent } from "./Utils";
9
9
  export interface LavalinkManager {
10
10
  nodeManager: NodeManager;
11
11
  utils: ManagerUtils;
@@ -59,7 +59,14 @@ export interface ManagerOptions {
59
59
  /** optional */
60
60
  debugOptions?: {
61
61
  /** logs for debugging the "no-Audio" playing error */
62
- noAudio: boolean;
62
+ noAudio?: boolean;
63
+ /** For Logging the Destroy function */
64
+ playerDestroy?: {
65
+ /** To show the debug reason at all times. */
66
+ debugLog?: boolean;
67
+ /** If you get 'Error: Use Player#destroy(true) not PlayerManager#deletePlayer() to stop the Player' put it on true */
68
+ dontThrowError?: boolean;
69
+ };
63
70
  };
64
71
  }
65
72
  interface LavalinkManagerEvents {
@@ -134,7 +141,7 @@ export declare class LavalinkManager extends EventEmitter {
134
141
  constructor(options: ManagerOptions);
135
142
  createPlayer(options: PlayerOptions): Player;
136
143
  getPlayer(guildId: string): Player;
137
- deletePlayer(guildId: string): boolean;
144
+ deletePlayer(guildId: string, throwError?: boolean): boolean;
138
145
  get useable(): boolean;
139
146
  /**
140
147
  * Initiates the Manager.
@@ -145,6 +152,6 @@ export declare class LavalinkManager extends EventEmitter {
145
152
  * Sends voice data to the Lavalink server.
146
153
  * @param data
147
154
  */
148
- sendRawData(data: VoicePacket | VoiceServer | VoiceState | any): Promise<void>;
155
+ sendRawData(data: VoicePacket | VoiceServer | VoiceState | ChannelDeletePacket): Promise<void>;
149
156
  }
150
157
  export {};
@@ -30,15 +30,25 @@ export interface PlayerJson {
30
30
  }
31
31
  export type RepeatMode = "queue" | "track" | "off";
32
32
  export interface PlayerOptions {
33
+ /** Guild id of the player */
33
34
  guildId: string;
35
+ /** The Voice Channel Id */
34
36
  voiceChannelId: string;
37
+ /** The Text Channel Id of the Player */
38
+ textChannelId?: string;
39
+ /** instantly change volume with the one play request */
35
40
  volume?: number;
41
+ /** VC Region for node selections */
36
42
  vcRegion?: string;
43
+ /** if it should join deafened */
37
44
  selfDeaf?: boolean;
45
+ /** If it should join muted */
38
46
  selfMute?: boolean;
39
- textChannelId?: string;
47
+ /** If it should use a specific lavalink node */
40
48
  node?: LavalinkNode | string;
49
+ /** If when applying filters, it should use the insta apply filters fix */
41
50
  instaUpdateFiltersFix?: boolean;
51
+ /** If a volume should be applied via filters instead of lavalink-volume */
42
52
  applyVolumeAsFilter?: boolean;
43
53
  }
44
54
  export interface PlayOptions {
@@ -113,7 +123,7 @@ export declare class Player {
113
123
  * @param key
114
124
  * @param value
115
125
  */
116
- set(key: string, value: unknown): void;
126
+ set(key: string, value: unknown): this;
117
127
  /**
118
128
  * Get custom data.
119
129
  * @param key
@@ -122,7 +132,7 @@ export declare class Player {
122
132
  /**
123
133
  * CLears all the custom data.
124
134
  */
125
- clearData(): void;
135
+ clearData(): this;
126
136
  /**
127
137
  * Get all custom Data
128
138
  */
@@ -137,32 +147,32 @@ export declare class Player {
137
147
  * @param volume The Volume in percent
138
148
  * @param ignoreVolumeDecrementer If it should ignore the volumedecrementer option
139
149
  */
140
- setVolume(volume: number, ignoreVolumeDecrementer?: boolean): Promise<void>;
150
+ setVolume(volume: number, ignoreVolumeDecrementer?: boolean): Promise<this>;
141
151
  lavaSearch(query: LavaSearchQuery, requestUser: unknown): Promise<import("./Utils").SearchResult | import("./Utils").LavaSearchResponse>;
142
152
  /**
143
153
  *
144
154
  * @param query Query for your data
145
155
  * @param requestUser
146
156
  */
147
- search(query: SearchQuery, requestUser: unknown): Promise<import("./Utils").SearchResult | import("./Utils").UnresolvedSearchResult>;
157
+ search(query: SearchQuery, requestUser: unknown): Promise<import("./Utils").UnresolvedSearchResult | import("./Utils").SearchResult>;
148
158
  /**
149
159
  * Pause the player
150
160
  */
151
- pause(): Promise<void>;
161
+ pause(): Promise<this>;
152
162
  /**
153
163
  * Resume the Player
154
164
  */
155
- resume(): Promise<void>;
165
+ resume(): Promise<this>;
156
166
  /**
157
167
  * Seek to a specific Position
158
168
  * @param position
159
169
  */
160
- seek(position: number): Promise<any>;
170
+ seek(position: number): Promise<this>;
161
171
  /**
162
172
  * Set the Repeatmode of the Player
163
173
  * @param repeatMode
164
174
  */
165
- setRepeatMode(repeatMode: RepeatMode): Promise<RepeatMode>;
175
+ setRepeatMode(repeatMode: RepeatMode): Promise<this>;
166
176
  /**
167
177
  * Skip the current song, or a specific amount of songs
168
178
  * @param amount provide the index of the next track to skip to
@@ -172,17 +182,17 @@ export declare class Player {
172
182
  * Connects the Player to the Voice Channel
173
183
  * @returns
174
184
  */
175
- connect(): Promise<void>;
185
+ connect(): Promise<this>;
176
186
  /**
177
187
  * Disconnects the Player from the Voice Channel, but keeps the player in the cache
178
188
  * @param force If false it throws an error, if player thinks it's already disconnected
179
189
  * @returns
180
190
  */
181
- disconnect(force?: boolean): Promise<void>;
191
+ disconnect(force?: boolean): Promise<this>;
182
192
  /**
183
193
  * Destroy the player and disconnect from the voice channel
184
194
  */
185
- destroy(reason?: string): Promise<void>;
195
+ destroy(reason?: string): Promise<this>;
186
196
  /**
187
197
  * Move the player on a different Audio-Node
188
198
  * @param newNode New Node / New Node Id
@@ -16,9 +16,9 @@ export type LavaSrcSearchPlatformBase = "spsearch" | "sprec" | "amsearch" | "dzs
16
16
  export type LavaSrcSearchPlatform = LavaSrcSearchPlatformBase | "ftts";
17
17
  export type DuncteSearchPlatform = "speak" | "tts";
18
18
  export type LavalinkClientSearchPlatform = "bcsearch";
19
- export type LavalinkClientSearchPlatformResolve = "bandcamp";
19
+ export type LavalinkClientSearchPlatformResolve = "bandcamp" | "bc";
20
20
  export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | LavaSrcSearchPlatform | DuncteSearchPlatform | LavalinkClientSearchPlatform;
21
- export type ClientSearchPlatform = "youtube" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "sp" | "spsuggestion" | "spotify" | "dz" | "deezer" | "yandex" | "yandex music" | "yandexmusic" | LavalinkClientSearchPlatformResolve | LavalinkClientSearchPlatform;
21
+ export type ClientSearchPlatform = "youtube" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "musicyoutube" | "music youtube" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "musicapple" | "music apple" | "sp" | "spsuggestion" | "spotify" | "spotify.com" | "spotifycom" | "dz" | "deezer" | "yandex" | "yandex music" | "yandexmusic" | LavalinkClientSearchPlatformResolve | LavalinkClientSearchPlatform;
22
22
  export type SearchPlatform = LavalinkSearchPlatform | ClientSearchPlatform;
23
23
  export type SourcesRegex = "YoutubeRegex" | "YoutubeMusicRegex" | "SoundCloudRegex" | "SoundCloudMobileRegex" | "DeezerTrackRegex" | "DeezerArtistRegex" | "DeezerEpisodeRegex" | "DeezerMixesRegex" | "DeezerPageLinkRegex" | "DeezerPlaylistRegex" | "DeezerAlbumRegex" | "AllDeezerRegex" | "AllDeezerRegexWithoutPageLink" | "SpotifySongRegex" | "SpotifyPlaylistRegex" | "SpotifyArtistRegex" | "SpotifyEpisodeRegex" | "SpotifyShowRegex" | "SpotifyAlbumRegex" | "AllSpotifyRegex" | "mp3Url" | "m3uUrl" | "m3u8Url" | "mp4Url" | "m4aUrl" | "wavUrl" | "aacpUrl" | "tiktok" | "mixcloud" | "musicYandex" | "radiohost" | "bandcamp" | "appleMusic" | "TwitchTv" | "vimeo";
24
24
  export interface PlaylistInfo {
@@ -283,6 +283,13 @@ export interface LavalinkPlayer {
283
283
  voice: LavalinkPlayerVoice;
284
284
  filters: Partial<LavalinkFilterData>;
285
285
  }
286
+ export interface ChannelDeletePacket {
287
+ t: "CHANNEL_DELETE";
288
+ d: {
289
+ guild_id: string;
290
+ id: string;
291
+ };
292
+ }
286
293
  export interface VoiceState {
287
294
  op: "voiceUpdate";
288
295
  guildId: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lavalink-client",
3
- "version": "1.1.21",
3
+ "version": "1.1.23",
4
4
  "description": "Easy, flexible and feature-rich lavalink@v4 Client. Both for Beginners and Proficients.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",