lavalink-client 2.6.6 → 2.7.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/README.md CHANGED
@@ -108,15 +108,19 @@ pnpm add tomato6966/lavalink-client
108
108
  ## 💖 Used In
109
109
  This client powers various Discord bots:
110
110
  - **[Mivator](https://discord.gg/5dUb7M2qCj)** (Public Bot by @Tomato6966)
111
- - **[Betty](https://betty.cx/)** (Public Bot by fb_sean)
111
+ - **[Betty](https://betty.bot/?utm_source=lavalink-client)** (Public Bot by @fb_sean)
112
+ - **[Nero](https://betty.bot/?utm_source=lavalink-client)** (Public Bot by @fb_sean)
112
113
  - **Bots by Contributors:**
113
114
  - [Mintone](https://mintone.tech/) (@appujet)
114
115
  - [Stelle](https://github.com/Ganyu-Studios/stelle-music) (@EvilG-MC)
115
116
  - [Panais](https://panais.xyz/) (@LucasB25)
116
117
  - [Akyn](https://akynbot.vercel.app/) (@notdeltaxd)
118
+ - [ARINO](https://site.arinoapp.qzz.io/) (@ryanwtf88)
119
+ - [iHorizon](https://github.com/ihrz/ihrz) (@iHorizon)
117
120
  - **Bots Community (Users):**
118
121
  - [Soundy](https://github.com/idMJA/Soundy) (@idMJA)
119
122
  - [BeatBot ](https://getbeatbot.vercel.app/) (@zenitsujs)
123
+ - [Atom Music](https://top.gg/bot/1320469557411971165) (@sakshamyep)
120
124
 
121
125
  ***
122
126
 
@@ -457,3 +461,6 @@ if (response.tracks.length > 0) {
457
461
  </details>
458
462
 
459
463
  </div>
464
+
465
+
466
+
package/dist/index.d.mts CHANGED
@@ -210,6 +210,7 @@ declare enum DebugEvents {
210
210
  PlayerUpdateSuccess = "PlayerUpdateSuccess",
211
211
  HeartBeatTriggered = "HeartBeatTriggered",
212
212
  NoSocketOnDestroy = "NoSocketOnDestroy",
213
+ SocketCleanupError = "SocketCleanupError",
213
214
  SocketTerminateHeartBeatTimeout = "SocketTerminateHeartBeatTimeout",
214
215
  TryingConnectWhileConnected = "TryingConnectWhileConnected",
215
216
  LavaSearchNothingFound = "LavaSearchNothingFound",
@@ -332,6 +333,7 @@ declare class FilterManager {
332
333
  * ```
333
334
  */
334
335
  applyPlayerFilters(): Promise<void>;
336
+ privateNot0(value: number | undefined): boolean;
335
337
  /**
336
338
  * Checks if the filters are correctly stated (active / not-active) - mostly used internally.
337
339
  * @param oldFilterTimescale
@@ -703,138 +705,6 @@ declare class FilterManager {
703
705
  clearEQ(): Promise<this>;
704
706
  }
705
707
 
706
- /** Sourcenames provided by lavalink server */
707
- type LavalinkSourceNames = "youtube" | "youtubemusic" | "soundcloud" | "bandcamp" | "twitch";
708
- /** Source Names provided by lava src plugin */
709
- type LavalinkPlugin_LavaSrc_SourceNames = "deezer" | "spotify" | "applemusic" | "yandexmusic" | "flowery-tts" | "vkmusic" | "tidal" | "qobuz" | "pandora";
710
- /** Source Names provided by jiosaavan plugin */
711
- type LavalinkPlugin_JioSaavn_SourceNames = "jiosaavn";
712
- /** The SourceNames provided by lavalink */
713
- type SourceNames = LavalinkSourceNames | LavalinkPlugin_LavaSrc_SourceNames | LavalinkPlugin_JioSaavn_SourceNames;
714
- interface LavalinkTrackInfo {
715
- /** The Identifier of the Track */
716
- identifier: string;
717
- /** The Track Title / Name */
718
- title: string;
719
- /** The Name of the Author */
720
- author: string;
721
- /** The duration of the Track */
722
- length: number;
723
- /** The URL of the artwork if available */
724
- artworkUrl: string | null;
725
- /** The URL (aka Link) of the Track called URI */
726
- uri: string;
727
- /** The Source name of the Track, e.g. soundcloud, youtube, spotify */
728
- sourceName: SourceNames;
729
- /** Wether the audio is seekable */
730
- isSeekable: boolean;
731
- /** Wether the audio is of a live stream */
732
- isStream: boolean;
733
- /** If isrc code is available, it's provided */
734
- isrc: string | null;
735
- }
736
- interface TrackInfo {
737
- /** The Identifier of the Track */
738
- identifier: string;
739
- /** The Track Title / Name */
740
- title: string;
741
- /** The Name of the Author */
742
- author: string;
743
- /** The duration of the Track */
744
- duration: number;
745
- /** The URL of the artwork if available */
746
- artworkUrl: string | null;
747
- /** The URL (aka Link) of the Track called URI */
748
- uri: string;
749
- /** The Source name of the Track, e.g. soundcloud, youtube, spotify */
750
- sourceName: SourceNames;
751
- /** Wether the audio is seekable */
752
- isSeekable: boolean;
753
- /** Wether the audio is of a live stream */
754
- isStream: boolean;
755
- /** If isrc code is available, it's provided */
756
- isrc: string | null;
757
- }
758
- interface PluginInfo {
759
- /** The Type provided by a plugin */
760
- type?: "album" | "playlist" | "artist" | "recommendations" | string;
761
- /** The Identifier provided by a plugin */
762
- albumName?: string;
763
- /** The url of the album */
764
- albumUrl?: string;
765
- /** The url of the album art */
766
- albumArtUrl?: string;
767
- /** The url of the artist */
768
- artistUrl?: string;
769
- /** The url of the artist artwork */
770
- artistArtworkUrl?: string;
771
- /** The url of the preview */
772
- previewUrl?: string;
773
- /** Whether the track is a preview */
774
- isPreview?: boolean;
775
- /** The total number of tracks in the playlist */
776
- totalTracks?: number;
777
- /** The Identifier provided by a plugin */
778
- identifier?: string;
779
- /** The ArtworkUrl provided by a plugin */
780
- artworkUrl?: string;
781
- /** The Author Information provided by a plugin */
782
- author?: string;
783
- /** The Url provided by a Plugin */
784
- url?: string;
785
- /** The Url provided by a Plugin */
786
- uri?: string;
787
- /** You can put specific track information here, to transform the tracks... */
788
- clientData?: {
789
- previousTrack?: boolean;
790
- [key: string]: any;
791
- };
792
- }
793
- interface LavalinkTrack {
794
- /** The Base 64 encoded String */
795
- encoded?: Base64;
796
- /** Track Information */
797
- info: LavalinkTrackInfo;
798
- /** Plugin Information from Lavalink */
799
- pluginInfo: Partial<PluginInfo>;
800
- /** The userData Object from when you provide to the lavalink request */
801
- userData?: anyObject;
802
- }
803
- interface Track {
804
- /** The Base 64 encoded String */
805
- encoded?: Base64;
806
- /** Track Information */
807
- info: TrackInfo;
808
- /** Plugin Information from Lavalink */
809
- pluginInfo: Partial<PluginInfo>;
810
- /** The Track's Requester */
811
- requester?: unknown;
812
- /** The userData Object from when you provide to the lavalink request */
813
- userData?: anyObject;
814
- }
815
- interface UnresolvedTrackInfo extends Partial<TrackInfo> {
816
- /** Required */
817
- title: string;
818
- }
819
- interface UnresolvedQuery extends UnresolvedTrackInfo {
820
- /** The base64 of the unresolved track to "encode" */
821
- encoded?: Base64;
822
- }
823
- interface UnresolvedTrack {
824
- /** Required */
825
- resolve: (player: Player) => Promise<void>;
826
- /** The Base 64 encoded String */
827
- encoded?: Base64;
828
- /** Track Information */
829
- info: UnresolvedTrackInfo;
830
- /** Plugin Information from Lavalink */
831
- pluginInfo: Partial<PluginInfo>;
832
- /** The userData Object from when you provide to the lavalink request */
833
- userData?: anyObject;
834
- /** The Track's Requester */
835
- requester?: unknown;
836
- }
837
-
838
708
  declare class QueueSaver {
839
709
  /**
840
710
  * The queue store manager
@@ -976,6 +846,7 @@ declare class Queue {
976
846
  * - single Track | UnresolvedTrack
977
847
  * - multiple Track | UnresovedTrack
978
848
  * - at the index or multiple indexes
849
+ * - Since v2.7 the removed tracks get unshifted into the previous queue state instead of pushed (indexed at the start instead of end - as it should)
979
850
  * @param removeQueryTrack
980
851
  * @returns null (if nothing was removed) / { removed } where removed is an array with all removed elements
981
852
  *
@@ -1248,6 +1119,138 @@ declare class Player {
1248
1119
  toJSON(): PlayerJson;
1249
1120
  }
1250
1121
 
1122
+ /** Sourcenames provided by lavalink server */
1123
+ type LavalinkSourceNames = "youtube" | "youtubemusic" | "soundcloud" | "bandcamp" | "twitch";
1124
+ /** Source Names provided by lava src plugin */
1125
+ type LavalinkPlugin_LavaSrc_SourceNames = "deezer" | "spotify" | "applemusic" | "yandexmusic" | "flowery-tts" | "vkmusic" | "tidal" | "qobuz" | "pandora";
1126
+ /** Source Names provided by jiosaavan plugin */
1127
+ type LavalinkPlugin_JioSaavn_SourceNames = "jiosaavn";
1128
+ /** The SourceNames provided by lavalink */
1129
+ type SourceNames = LavalinkSourceNames | LavalinkPlugin_LavaSrc_SourceNames | LavalinkPlugin_JioSaavn_SourceNames;
1130
+ interface LavalinkTrackInfo {
1131
+ /** The Identifier of the Track */
1132
+ identifier: string;
1133
+ /** The Track Title / Name */
1134
+ title: string;
1135
+ /** The Name of the Author */
1136
+ author: string;
1137
+ /** The duration of the Track */
1138
+ length: number;
1139
+ /** The URL of the artwork if available */
1140
+ artworkUrl: string | null;
1141
+ /** The URL (aka Link) of the Track called URI */
1142
+ uri: string;
1143
+ /** The Source name of the Track, e.g. soundcloud, youtube, spotify */
1144
+ sourceName: SourceNames;
1145
+ /** Wether the audio is seekable */
1146
+ isSeekable: boolean;
1147
+ /** Wether the audio is of a live stream */
1148
+ isStream: boolean;
1149
+ /** If isrc code is available, it's provided */
1150
+ isrc: string | null;
1151
+ }
1152
+ interface TrackInfo {
1153
+ /** The Identifier of the Track */
1154
+ identifier: string;
1155
+ /** The Track Title / Name */
1156
+ title: string;
1157
+ /** The Name of the Author */
1158
+ author: string;
1159
+ /** The duration of the Track */
1160
+ duration: number;
1161
+ /** The URL of the artwork if available */
1162
+ artworkUrl: string | null;
1163
+ /** The URL (aka Link) of the Track called URI */
1164
+ uri: string;
1165
+ /** The Source name of the Track, e.g. soundcloud, youtube, spotify */
1166
+ sourceName: SourceNames;
1167
+ /** Wether the audio is seekable */
1168
+ isSeekable: boolean;
1169
+ /** Wether the audio is of a live stream */
1170
+ isStream: boolean;
1171
+ /** If isrc code is available, it's provided */
1172
+ isrc: string | null;
1173
+ }
1174
+ interface PluginInfo {
1175
+ /** The Type provided by a plugin */
1176
+ type?: "album" | "playlist" | "artist" | "recommendations" | string;
1177
+ /** The Identifier provided by a plugin */
1178
+ albumName?: string;
1179
+ /** The url of the album */
1180
+ albumUrl?: string;
1181
+ /** The url of the album art */
1182
+ albumArtUrl?: string;
1183
+ /** The url of the artist */
1184
+ artistUrl?: string;
1185
+ /** The url of the artist artwork */
1186
+ artistArtworkUrl?: string;
1187
+ /** The url of the preview */
1188
+ previewUrl?: string;
1189
+ /** Whether the track is a preview */
1190
+ isPreview?: boolean;
1191
+ /** The total number of tracks in the playlist */
1192
+ totalTracks?: number;
1193
+ /** The Identifier provided by a plugin */
1194
+ identifier?: string;
1195
+ /** The ArtworkUrl provided by a plugin */
1196
+ artworkUrl?: string;
1197
+ /** The Author Information provided by a plugin */
1198
+ author?: string;
1199
+ /** The Url provided by a Plugin */
1200
+ url?: string;
1201
+ /** The Url provided by a Plugin */
1202
+ uri?: string;
1203
+ /** You can put specific track information here, to transform the tracks... */
1204
+ clientData?: {
1205
+ previousTrack?: boolean;
1206
+ [key: string]: any;
1207
+ };
1208
+ }
1209
+ interface LavalinkTrack {
1210
+ /** The Base 64 encoded String */
1211
+ encoded?: Base64;
1212
+ /** Track Information */
1213
+ info: LavalinkTrackInfo;
1214
+ /** Plugin Information from Lavalink */
1215
+ pluginInfo: Partial<PluginInfo>;
1216
+ /** The userData Object from when you provide to the lavalink request */
1217
+ userData?: anyObject;
1218
+ }
1219
+ interface Track {
1220
+ /** The Base 64 encoded String */
1221
+ encoded?: Base64;
1222
+ /** Track Information */
1223
+ info: TrackInfo;
1224
+ /** Plugin Information from Lavalink */
1225
+ pluginInfo: Partial<PluginInfo>;
1226
+ /** The Track's Requester */
1227
+ requester?: unknown;
1228
+ /** The userData Object from when you provide to the lavalink request */
1229
+ userData?: anyObject;
1230
+ }
1231
+ interface UnresolvedTrackInfo extends Partial<TrackInfo> {
1232
+ /** Required */
1233
+ title: string;
1234
+ }
1235
+ interface UnresolvedQuery extends UnresolvedTrackInfo {
1236
+ /** The base64 of the unresolved track to "encode" */
1237
+ encoded?: Base64;
1238
+ }
1239
+ interface UnresolvedTrack {
1240
+ /** Required */
1241
+ resolve: (player: Player) => Promise<void>;
1242
+ /** The Base 64 encoded String */
1243
+ encoded?: Base64;
1244
+ /** Track Information */
1245
+ info: UnresolvedTrackInfo;
1246
+ /** Plugin Information from Lavalink */
1247
+ pluginInfo: Partial<PluginInfo>;
1248
+ /** The userData Object from when you provide to the lavalink request */
1249
+ userData?: anyObject;
1250
+ /** The Track's Requester */
1251
+ requester?: unknown;
1252
+ }
1253
+
1251
1254
  interface StoredQueue {
1252
1255
  current: Track | null;
1253
1256
  previous: Track[];
@@ -1265,7 +1268,7 @@ interface QueueStoreManager {
1265
1268
  /** @async Parse the saved value back to the Queue (IF YOU DON'T NEED PARSING/STRINGIFY, then just return the value) */
1266
1269
  parse: (value: StoredQueue | string) => Awaitable<Partial<StoredQueue>>;
1267
1270
  }
1268
- interface ManagerQueueOptions<CustomPlayerT extends Player = Player> {
1271
+ interface ManagerQueueOptions {
1269
1272
  /** Maximum Amount of tracks for the queue.previous array. Set to 0 to not save previous songs. Defaults to 25 Tracks */
1270
1273
  maxPreviousTracks?: number;
1271
1274
  /** Custom Queue Store option */
@@ -1915,38 +1918,12 @@ interface LyricsFoundEvent extends PlayerEvent {
1915
1918
  /** The lyrics */
1916
1919
  lyrics: LyricsResult;
1917
1920
  }
1918
- interface LyricsFoundEvent extends PlayerEvent {
1919
- /** The lyricsfound event */
1920
- type: "LyricsFoundEvent";
1921
- /** The guildId */
1922
- guildId: string;
1923
- /** The lyrics */
1924
- lyrics: LyricsResult;
1925
- }
1926
1921
  interface LyricsNotFoundEvent extends PlayerEvent {
1927
1922
  /**The lyricsnotfound event*/
1928
1923
  type: "LyricsNotFoundEvent";
1929
1924
  /**The guildId*/
1930
1925
  guildId: string;
1931
1926
  }
1932
- interface LyricsNotFoundEvent extends PlayerEvent {
1933
- /**The lyricsnotfound event*/
1934
- type: "LyricsNotFoundEvent";
1935
- /**The guildId*/
1936
- guildId: string;
1937
- }
1938
- interface LyricsLineEvent extends PlayerEvent {
1939
- /**The lyricsline event*/
1940
- type: "LyricsLineEvent";
1941
- /** The guildId */
1942
- guildId: string;
1943
- /** The line number */
1944
- lineIndex: number;
1945
- /** The line */
1946
- line: LyricsLine;
1947
- /**skipped is true if the line was skipped */
1948
- skipped: boolean;
1949
- }
1950
1927
  interface LyricsLineEvent extends PlayerEvent {
1951
1928
  /**The lyricsline event*/
1952
1929
  type: "LyricsLineEvent";
@@ -3039,7 +3016,7 @@ interface ManagerOptions<CustomPlayerT extends Player = Player> {
3039
3016
  /** The Bot Client's Data for Authorization */
3040
3017
  client?: BotClientOptions;
3041
3018
  /** QueueOptions for all Queues */
3042
- queueOptions?: ManagerQueueOptions<CustomPlayerT>;
3019
+ queueOptions?: ManagerQueueOptions;
3043
3020
  /** PlayerOptions for all Players */
3044
3021
  playerOptions?: ManagerPlayerOptions<CustomPlayerT>;
3045
3022
  /** The player class you want to use when creating a player. (can be extendable) */
package/dist/index.d.ts CHANGED
@@ -210,6 +210,7 @@ declare enum DebugEvents {
210
210
  PlayerUpdateSuccess = "PlayerUpdateSuccess",
211
211
  HeartBeatTriggered = "HeartBeatTriggered",
212
212
  NoSocketOnDestroy = "NoSocketOnDestroy",
213
+ SocketCleanupError = "SocketCleanupError",
213
214
  SocketTerminateHeartBeatTimeout = "SocketTerminateHeartBeatTimeout",
214
215
  TryingConnectWhileConnected = "TryingConnectWhileConnected",
215
216
  LavaSearchNothingFound = "LavaSearchNothingFound",
@@ -332,6 +333,7 @@ declare class FilterManager {
332
333
  * ```
333
334
  */
334
335
  applyPlayerFilters(): Promise<void>;
336
+ privateNot0(value: number | undefined): boolean;
335
337
  /**
336
338
  * Checks if the filters are correctly stated (active / not-active) - mostly used internally.
337
339
  * @param oldFilterTimescale
@@ -703,138 +705,6 @@ declare class FilterManager {
703
705
  clearEQ(): Promise<this>;
704
706
  }
705
707
 
706
- /** Sourcenames provided by lavalink server */
707
- type LavalinkSourceNames = "youtube" | "youtubemusic" | "soundcloud" | "bandcamp" | "twitch";
708
- /** Source Names provided by lava src plugin */
709
- type LavalinkPlugin_LavaSrc_SourceNames = "deezer" | "spotify" | "applemusic" | "yandexmusic" | "flowery-tts" | "vkmusic" | "tidal" | "qobuz" | "pandora";
710
- /** Source Names provided by jiosaavan plugin */
711
- type LavalinkPlugin_JioSaavn_SourceNames = "jiosaavn";
712
- /** The SourceNames provided by lavalink */
713
- type SourceNames = LavalinkSourceNames | LavalinkPlugin_LavaSrc_SourceNames | LavalinkPlugin_JioSaavn_SourceNames;
714
- interface LavalinkTrackInfo {
715
- /** The Identifier of the Track */
716
- identifier: string;
717
- /** The Track Title / Name */
718
- title: string;
719
- /** The Name of the Author */
720
- author: string;
721
- /** The duration of the Track */
722
- length: number;
723
- /** The URL of the artwork if available */
724
- artworkUrl: string | null;
725
- /** The URL (aka Link) of the Track called URI */
726
- uri: string;
727
- /** The Source name of the Track, e.g. soundcloud, youtube, spotify */
728
- sourceName: SourceNames;
729
- /** Wether the audio is seekable */
730
- isSeekable: boolean;
731
- /** Wether the audio is of a live stream */
732
- isStream: boolean;
733
- /** If isrc code is available, it's provided */
734
- isrc: string | null;
735
- }
736
- interface TrackInfo {
737
- /** The Identifier of the Track */
738
- identifier: string;
739
- /** The Track Title / Name */
740
- title: string;
741
- /** The Name of the Author */
742
- author: string;
743
- /** The duration of the Track */
744
- duration: number;
745
- /** The URL of the artwork if available */
746
- artworkUrl: string | null;
747
- /** The URL (aka Link) of the Track called URI */
748
- uri: string;
749
- /** The Source name of the Track, e.g. soundcloud, youtube, spotify */
750
- sourceName: SourceNames;
751
- /** Wether the audio is seekable */
752
- isSeekable: boolean;
753
- /** Wether the audio is of a live stream */
754
- isStream: boolean;
755
- /** If isrc code is available, it's provided */
756
- isrc: string | null;
757
- }
758
- interface PluginInfo {
759
- /** The Type provided by a plugin */
760
- type?: "album" | "playlist" | "artist" | "recommendations" | string;
761
- /** The Identifier provided by a plugin */
762
- albumName?: string;
763
- /** The url of the album */
764
- albumUrl?: string;
765
- /** The url of the album art */
766
- albumArtUrl?: string;
767
- /** The url of the artist */
768
- artistUrl?: string;
769
- /** The url of the artist artwork */
770
- artistArtworkUrl?: string;
771
- /** The url of the preview */
772
- previewUrl?: string;
773
- /** Whether the track is a preview */
774
- isPreview?: boolean;
775
- /** The total number of tracks in the playlist */
776
- totalTracks?: number;
777
- /** The Identifier provided by a plugin */
778
- identifier?: string;
779
- /** The ArtworkUrl provided by a plugin */
780
- artworkUrl?: string;
781
- /** The Author Information provided by a plugin */
782
- author?: string;
783
- /** The Url provided by a Plugin */
784
- url?: string;
785
- /** The Url provided by a Plugin */
786
- uri?: string;
787
- /** You can put specific track information here, to transform the tracks... */
788
- clientData?: {
789
- previousTrack?: boolean;
790
- [key: string]: any;
791
- };
792
- }
793
- interface LavalinkTrack {
794
- /** The Base 64 encoded String */
795
- encoded?: Base64;
796
- /** Track Information */
797
- info: LavalinkTrackInfo;
798
- /** Plugin Information from Lavalink */
799
- pluginInfo: Partial<PluginInfo>;
800
- /** The userData Object from when you provide to the lavalink request */
801
- userData?: anyObject;
802
- }
803
- interface Track {
804
- /** The Base 64 encoded String */
805
- encoded?: Base64;
806
- /** Track Information */
807
- info: TrackInfo;
808
- /** Plugin Information from Lavalink */
809
- pluginInfo: Partial<PluginInfo>;
810
- /** The Track's Requester */
811
- requester?: unknown;
812
- /** The userData Object from when you provide to the lavalink request */
813
- userData?: anyObject;
814
- }
815
- interface UnresolvedTrackInfo extends Partial<TrackInfo> {
816
- /** Required */
817
- title: string;
818
- }
819
- interface UnresolvedQuery extends UnresolvedTrackInfo {
820
- /** The base64 of the unresolved track to "encode" */
821
- encoded?: Base64;
822
- }
823
- interface UnresolvedTrack {
824
- /** Required */
825
- resolve: (player: Player) => Promise<void>;
826
- /** The Base 64 encoded String */
827
- encoded?: Base64;
828
- /** Track Information */
829
- info: UnresolvedTrackInfo;
830
- /** Plugin Information from Lavalink */
831
- pluginInfo: Partial<PluginInfo>;
832
- /** The userData Object from when you provide to the lavalink request */
833
- userData?: anyObject;
834
- /** The Track's Requester */
835
- requester?: unknown;
836
- }
837
-
838
708
  declare class QueueSaver {
839
709
  /**
840
710
  * The queue store manager
@@ -976,6 +846,7 @@ declare class Queue {
976
846
  * - single Track | UnresolvedTrack
977
847
  * - multiple Track | UnresovedTrack
978
848
  * - at the index or multiple indexes
849
+ * - Since v2.7 the removed tracks get unshifted into the previous queue state instead of pushed (indexed at the start instead of end - as it should)
979
850
  * @param removeQueryTrack
980
851
  * @returns null (if nothing was removed) / { removed } where removed is an array with all removed elements
981
852
  *
@@ -1248,6 +1119,138 @@ declare class Player {
1248
1119
  toJSON(): PlayerJson;
1249
1120
  }
1250
1121
 
1122
+ /** Sourcenames provided by lavalink server */
1123
+ type LavalinkSourceNames = "youtube" | "youtubemusic" | "soundcloud" | "bandcamp" | "twitch";
1124
+ /** Source Names provided by lava src plugin */
1125
+ type LavalinkPlugin_LavaSrc_SourceNames = "deezer" | "spotify" | "applemusic" | "yandexmusic" | "flowery-tts" | "vkmusic" | "tidal" | "qobuz" | "pandora";
1126
+ /** Source Names provided by jiosaavan plugin */
1127
+ type LavalinkPlugin_JioSaavn_SourceNames = "jiosaavn";
1128
+ /** The SourceNames provided by lavalink */
1129
+ type SourceNames = LavalinkSourceNames | LavalinkPlugin_LavaSrc_SourceNames | LavalinkPlugin_JioSaavn_SourceNames;
1130
+ interface LavalinkTrackInfo {
1131
+ /** The Identifier of the Track */
1132
+ identifier: string;
1133
+ /** The Track Title / Name */
1134
+ title: string;
1135
+ /** The Name of the Author */
1136
+ author: string;
1137
+ /** The duration of the Track */
1138
+ length: number;
1139
+ /** The URL of the artwork if available */
1140
+ artworkUrl: string | null;
1141
+ /** The URL (aka Link) of the Track called URI */
1142
+ uri: string;
1143
+ /** The Source name of the Track, e.g. soundcloud, youtube, spotify */
1144
+ sourceName: SourceNames;
1145
+ /** Wether the audio is seekable */
1146
+ isSeekable: boolean;
1147
+ /** Wether the audio is of a live stream */
1148
+ isStream: boolean;
1149
+ /** If isrc code is available, it's provided */
1150
+ isrc: string | null;
1151
+ }
1152
+ interface TrackInfo {
1153
+ /** The Identifier of the Track */
1154
+ identifier: string;
1155
+ /** The Track Title / Name */
1156
+ title: string;
1157
+ /** The Name of the Author */
1158
+ author: string;
1159
+ /** The duration of the Track */
1160
+ duration: number;
1161
+ /** The URL of the artwork if available */
1162
+ artworkUrl: string | null;
1163
+ /** The URL (aka Link) of the Track called URI */
1164
+ uri: string;
1165
+ /** The Source name of the Track, e.g. soundcloud, youtube, spotify */
1166
+ sourceName: SourceNames;
1167
+ /** Wether the audio is seekable */
1168
+ isSeekable: boolean;
1169
+ /** Wether the audio is of a live stream */
1170
+ isStream: boolean;
1171
+ /** If isrc code is available, it's provided */
1172
+ isrc: string | null;
1173
+ }
1174
+ interface PluginInfo {
1175
+ /** The Type provided by a plugin */
1176
+ type?: "album" | "playlist" | "artist" | "recommendations" | string;
1177
+ /** The Identifier provided by a plugin */
1178
+ albumName?: string;
1179
+ /** The url of the album */
1180
+ albumUrl?: string;
1181
+ /** The url of the album art */
1182
+ albumArtUrl?: string;
1183
+ /** The url of the artist */
1184
+ artistUrl?: string;
1185
+ /** The url of the artist artwork */
1186
+ artistArtworkUrl?: string;
1187
+ /** The url of the preview */
1188
+ previewUrl?: string;
1189
+ /** Whether the track is a preview */
1190
+ isPreview?: boolean;
1191
+ /** The total number of tracks in the playlist */
1192
+ totalTracks?: number;
1193
+ /** The Identifier provided by a plugin */
1194
+ identifier?: string;
1195
+ /** The ArtworkUrl provided by a plugin */
1196
+ artworkUrl?: string;
1197
+ /** The Author Information provided by a plugin */
1198
+ author?: string;
1199
+ /** The Url provided by a Plugin */
1200
+ url?: string;
1201
+ /** The Url provided by a Plugin */
1202
+ uri?: string;
1203
+ /** You can put specific track information here, to transform the tracks... */
1204
+ clientData?: {
1205
+ previousTrack?: boolean;
1206
+ [key: string]: any;
1207
+ };
1208
+ }
1209
+ interface LavalinkTrack {
1210
+ /** The Base 64 encoded String */
1211
+ encoded?: Base64;
1212
+ /** Track Information */
1213
+ info: LavalinkTrackInfo;
1214
+ /** Plugin Information from Lavalink */
1215
+ pluginInfo: Partial<PluginInfo>;
1216
+ /** The userData Object from when you provide to the lavalink request */
1217
+ userData?: anyObject;
1218
+ }
1219
+ interface Track {
1220
+ /** The Base 64 encoded String */
1221
+ encoded?: Base64;
1222
+ /** Track Information */
1223
+ info: TrackInfo;
1224
+ /** Plugin Information from Lavalink */
1225
+ pluginInfo: Partial<PluginInfo>;
1226
+ /** The Track's Requester */
1227
+ requester?: unknown;
1228
+ /** The userData Object from when you provide to the lavalink request */
1229
+ userData?: anyObject;
1230
+ }
1231
+ interface UnresolvedTrackInfo extends Partial<TrackInfo> {
1232
+ /** Required */
1233
+ title: string;
1234
+ }
1235
+ interface UnresolvedQuery extends UnresolvedTrackInfo {
1236
+ /** The base64 of the unresolved track to "encode" */
1237
+ encoded?: Base64;
1238
+ }
1239
+ interface UnresolvedTrack {
1240
+ /** Required */
1241
+ resolve: (player: Player) => Promise<void>;
1242
+ /** The Base 64 encoded String */
1243
+ encoded?: Base64;
1244
+ /** Track Information */
1245
+ info: UnresolvedTrackInfo;
1246
+ /** Plugin Information from Lavalink */
1247
+ pluginInfo: Partial<PluginInfo>;
1248
+ /** The userData Object from when you provide to the lavalink request */
1249
+ userData?: anyObject;
1250
+ /** The Track's Requester */
1251
+ requester?: unknown;
1252
+ }
1253
+
1251
1254
  interface StoredQueue {
1252
1255
  current: Track | null;
1253
1256
  previous: Track[];
@@ -1265,7 +1268,7 @@ interface QueueStoreManager {
1265
1268
  /** @async Parse the saved value back to the Queue (IF YOU DON'T NEED PARSING/STRINGIFY, then just return the value) */
1266
1269
  parse: (value: StoredQueue | string) => Awaitable<Partial<StoredQueue>>;
1267
1270
  }
1268
- interface ManagerQueueOptions<CustomPlayerT extends Player = Player> {
1271
+ interface ManagerQueueOptions {
1269
1272
  /** Maximum Amount of tracks for the queue.previous array. Set to 0 to not save previous songs. Defaults to 25 Tracks */
1270
1273
  maxPreviousTracks?: number;
1271
1274
  /** Custom Queue Store option */
@@ -1915,38 +1918,12 @@ interface LyricsFoundEvent extends PlayerEvent {
1915
1918
  /** The lyrics */
1916
1919
  lyrics: LyricsResult;
1917
1920
  }
1918
- interface LyricsFoundEvent extends PlayerEvent {
1919
- /** The lyricsfound event */
1920
- type: "LyricsFoundEvent";
1921
- /** The guildId */
1922
- guildId: string;
1923
- /** The lyrics */
1924
- lyrics: LyricsResult;
1925
- }
1926
1921
  interface LyricsNotFoundEvent extends PlayerEvent {
1927
1922
  /**The lyricsnotfound event*/
1928
1923
  type: "LyricsNotFoundEvent";
1929
1924
  /**The guildId*/
1930
1925
  guildId: string;
1931
1926
  }
1932
- interface LyricsNotFoundEvent extends PlayerEvent {
1933
- /**The lyricsnotfound event*/
1934
- type: "LyricsNotFoundEvent";
1935
- /**The guildId*/
1936
- guildId: string;
1937
- }
1938
- interface LyricsLineEvent extends PlayerEvent {
1939
- /**The lyricsline event*/
1940
- type: "LyricsLineEvent";
1941
- /** The guildId */
1942
- guildId: string;
1943
- /** The line number */
1944
- lineIndex: number;
1945
- /** The line */
1946
- line: LyricsLine;
1947
- /**skipped is true if the line was skipped */
1948
- skipped: boolean;
1949
- }
1950
1927
  interface LyricsLineEvent extends PlayerEvent {
1951
1928
  /**The lyricsline event*/
1952
1929
  type: "LyricsLineEvent";
@@ -3039,7 +3016,7 @@ interface ManagerOptions<CustomPlayerT extends Player = Player> {
3039
3016
  /** The Bot Client's Data for Authorization */
3040
3017
  client?: BotClientOptions;
3041
3018
  /** QueueOptions for all Queues */
3042
- queueOptions?: ManagerQueueOptions<CustomPlayerT>;
3019
+ queueOptions?: ManagerQueueOptions;
3043
3020
  /** PlayerOptions for all Players */
3044
3021
  playerOptions?: ManagerPlayerOptions<CustomPlayerT>;
3045
3022
  /** The player class you want to use when creating a player. (can be extendable) */
package/dist/index.js CHANGED
@@ -79,6 +79,7 @@ var DebugEvents = /* @__PURE__ */ ((DebugEvents2) => {
79
79
  DebugEvents2["PlayerUpdateSuccess"] = "PlayerUpdateSuccess";
80
80
  DebugEvents2["HeartBeatTriggered"] = "HeartBeatTriggered";
81
81
  DebugEvents2["NoSocketOnDestroy"] = "NoSocketOnDestroy";
82
+ DebugEvents2["SocketCleanupError"] = "SocketCleanupError";
82
83
  DebugEvents2["SocketTerminateHeartBeatTimeout"] = "SocketTerminateHeartBeatTimeout";
83
84
  DebugEvents2["TryingConnectWhileConnected"] = "TryingConnectWhileConnected";
84
85
  DebugEvents2["LavaSearchNothingFound"] = "LavaSearchNothingFound";
@@ -481,7 +482,7 @@ var SourceLinksRegexes = {
481
482
  /** DEFAULT SUPPORTED BY LAVALINK */
482
483
  YoutubeRegex: /https?:\/\/?(?:www\.)?(?:(m|www)\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|shorts|playlist\?|watch\?v=|watch\?.+(?:&|&#38;);v=))([a-zA-Z0-9\-_]{11})?(?:(?:\?|&|&#38;)index=((?:\d){1,3}))?(?:(?:\?|&|&#38;)?list=([a-zA-Z\-_0-9]{34}))?(?:\S+)?/,
483
484
  YoutubeMusicRegex: /https?:\/\/?(?:www\.)?(?:(music|m|www)\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|shorts|playlist\?|watch\?v=|watch\?.+(?:&|&#38;);v=))([a-zA-Z0-9\-_]{11})?(?:(?:\?|&|&#38;)index=((?:\d){1,3}))?(?:(?:\?|&|&#38;)?list=([a-zA-Z\-_0-9]{34}))?(?:\S+)?/,
484
- SoundCloudRegex: /https:\/\/(?:on\.)?soundcloud\.com\//,
485
+ SoundCloudRegex: /https?:\/\/(?:on\.)?soundcloud\.com\//,
485
486
  SoundCloudMobileRegex: /https?:\/\/(soundcloud\.app\.goo\.gl)\/(\S+)/,
486
487
  bandcamp: /https?:\/\/?(?:www\.)?([\d|\w]+)\.bandcamp\.com\/(\S+)/,
487
488
  TwitchTv: /https?:\/\/?(?:www\.)?twitch\.tv\/\w+/,
@@ -1001,9 +1002,15 @@ async function getClosestTrack(data, player) {
1001
1002
  source: sourceName !== "twitch" && sourceName !== "flowery-tts" ? sourceName : player.LavalinkManager.options?.playerOptions?.defaultSearchPlatform
1002
1003
  }, data.requester).then((res) => {
1003
1004
  let trackToUse = null;
1004
- if (data.info.author && !trackToUse) trackToUse = res.tracks.find((track) => [data.info?.author || "", `${data.info?.author} - Topic`].some((name) => new RegExp(`^${escapeRegExp(name)}$`, "i").test(track.info?.author)) || new RegExp(`^${escapeRegExp(data.info?.title)}$`, "i").test(track.info?.title));
1005
- if (data.info.duration && !trackToUse) trackToUse = res.tracks.find((track) => track.info?.duration >= data.info?.duration - 1500 && track?.info.duration <= data.info?.duration + 1500);
1006
- if (data.info.isrc && !trackToUse) trackToUse = res.tracks.find((track) => track.info?.isrc === data.info?.isrc);
1005
+ if ((data.info?.title || data.info?.author) && !trackToUse) trackToUse = res.tracks.find(
1006
+ (track) => (
1007
+ // find via author name (i ... case insensitve)
1008
+ [data.info?.author || "", `${data.info?.author} - Topic`].some((name) => new RegExp(`^${escapeRegExp(name)}$`, "i").test(track.info?.author)) || // find via title (i ... case insensitve)
1009
+ new RegExp(`^${escapeRegExp(data.info?.title)}$`, "i").test(track.info?.title)
1010
+ )
1011
+ );
1012
+ if (data.info?.isrc && !trackToUse) trackToUse = res.tracks.find((track) => track.info?.isrc === data.info?.isrc);
1013
+ if (data.info?.duration && !trackToUse) trackToUse = res.tracks.find((track) => track.info?.duration >= data.info?.duration - 1500 && track?.info.duration <= data.info?.duration + 1500);
1007
1014
  return applyUnresolvedData(trackToUse || res.tracks[0], data, player.LavalinkManager.utils);
1008
1015
  });
1009
1016
  }
@@ -1440,8 +1447,8 @@ var LavalinkNode = class {
1440
1447
  }
1441
1448
  };
1442
1449
  handlePlayerOperations().finally(() => {
1443
- this.socket.close(1e3, "Node-Destroy");
1444
- this.socket.removeAllListeners();
1450
+ this.socket?.close(1e3, "Node-Destroy");
1451
+ this.socket?.removeAllListeners();
1445
1452
  this.socket = null;
1446
1453
  this.reconnectAttempts = 1;
1447
1454
  clearTimeout(this.reconnectTimeout);
@@ -1455,8 +1462,8 @@ var LavalinkNode = class {
1455
1462
  }
1456
1463
  });
1457
1464
  } else {
1458
- this.socket.close(1e3, "Node-Destroy");
1459
- this.socket.removeAllListeners();
1465
+ this.socket?.close(1e3, "Node-Destroy");
1466
+ this.socket?.removeAllListeners();
1460
1467
  this.socket = null;
1461
1468
  this.reconnectAttempts = 1;
1462
1469
  clearTimeout(this.reconnectTimeout);
@@ -1485,8 +1492,8 @@ var LavalinkNode = class {
1485
1492
  */
1486
1493
  disconnect(disconnectReason) {
1487
1494
  if (!this.connected) return;
1488
- this.socket.close(1e3, "Node-Disconnect");
1489
- this.socket.removeAllListeners();
1495
+ this.socket?.close(1e3, "Node-Disconnect");
1496
+ this.socket?.removeAllListeners();
1490
1497
  this.socket = null;
1491
1498
  this.reconnectAttempts = 1;
1492
1499
  clearTimeout(this.reconnectTimeout);
@@ -1877,8 +1884,6 @@ var LavalinkNode = class {
1877
1884
  this.NodeManager.emit("error", this, error);
1878
1885
  return this.destroy("NodeReconnectFail" /* NodeReconnectFail */);
1879
1886
  }
1880
- this.socket.removeAllListeners();
1881
- this.socket = null;
1882
1887
  this.NodeManager.emit("reconnecting", this);
1883
1888
  this.connect();
1884
1889
  this.reconnectAttempts++;
@@ -1891,8 +1896,6 @@ var LavalinkNode = class {
1891
1896
  this.NodeManager.emit("error", this, error);
1892
1897
  return this.destroy("NodeReconnectFail" /* NodeReconnectFail */);
1893
1898
  }
1894
- this.socket.removeAllListeners();
1895
- this.socket = null;
1896
1899
  this.NodeManager.emit("reconnecting", this);
1897
1900
  this.connect();
1898
1901
  this.reconnectAttempts++;
@@ -1901,6 +1904,8 @@ var LavalinkNode = class {
1901
1904
  /** @private util function for handling opening events from websocket */
1902
1905
  async open() {
1903
1906
  this.isAlive = true;
1907
+ this.reconnectAttempts = 1;
1908
+ if (this.reconnectTimeout) clearTimeout(this.reconnectTimeout);
1904
1909
  if (this.options.enablePingOnStatsCheck) this.heartBeat();
1905
1910
  if (this.heartBeatInterval) clearInterval(this.heartBeatInterval);
1906
1911
  if (this.options.heartBeatInterval > 0) {
@@ -1916,8 +1921,6 @@ var LavalinkNode = class {
1916
1921
  this.socket.ping();
1917
1922
  }, this.options.heartBeatInterval || 3e4);
1918
1923
  }
1919
- if (this.reconnectTimeout) clearTimeout(this.reconnectTimeout);
1920
- this.reconnectAttempts = 1;
1921
1924
  this.info = await this.fetchInfo().catch((e) => (console.error(e, "ON-OPEN-FETCH"), null));
1922
1925
  if (!this.info && ["v3", "v4"].includes(this.version)) {
1923
1926
  const errorString = `Lavalink Node (${this.restAddress}) does not provide any /${this.version}/info`;
@@ -1928,6 +1931,21 @@ var LavalinkNode = class {
1928
1931
  /** @private util function for handling closing events from websocket */
1929
1932
  close(code, reason) {
1930
1933
  if (this.pingTimeout) clearTimeout(this.pingTimeout);
1934
+ try {
1935
+ if (this.socket) {
1936
+ this.socket.removeAllListeners();
1937
+ this.socket = null;
1938
+ }
1939
+ } catch (e) {
1940
+ if (this.NodeManager?.LavalinkManager?.options?.advancedOptions?.enableDebugEvents) {
1941
+ this.NodeManager.LavalinkManager.emit("debug", "SocketCleanupError" /* SocketCleanupError */, {
1942
+ state: "warn",
1943
+ message: `An error occurred during socket cleanup in close() (likely a race condition): ${e.message}`,
1944
+ functionLayer: "LavalinkNode > close()"
1945
+ });
1946
+ }
1947
+ }
1948
+ this.isAlive = false;
1931
1949
  if (this.heartBeatInterval) clearInterval(this.heartBeatInterval);
1932
1950
  if (code === 1006 && !reason) reason = "Socket got terminated due to no ping connection";
1933
1951
  if (code === 1e3 && reason === "Node-Disconnect") return;
@@ -2697,7 +2715,7 @@ var bandCampSearch = async (player, query, requestUser) => {
2697
2715
  artworkUrl: item.img,
2698
2716
  author: item.band_name,
2699
2717
  title: item.name,
2700
- identifier: item.id ? `${item.id}` : item.url?.split("/").reverse()[0]
2718
+ identifier: item.id ? `${item.id}` : item.url?.split("/")?.reverse()[0]
2701
2719
  }, requestUser));
2702
2720
  } catch (e) {
2703
2721
  error = e;
@@ -2882,6 +2900,9 @@ var FilterManager = class {
2882
2900
  this.player.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
2883
2901
  return;
2884
2902
  }
2903
+ privateNot0(value) {
2904
+ return typeof value === "number" && value !== 0;
2905
+ }
2885
2906
  /**
2886
2907
  * Checks if the filters are correctly stated (active / not-active) - mostly used internally.
2887
2908
  * @param oldFilterTimescale
@@ -2896,9 +2917,10 @@ var FilterManager = class {
2896
2917
  * ```
2897
2918
  */
2898
2919
  checkFiltersState(oldFilterTimescale) {
2899
- this.filters.rotation = this.data.rotation.rotationHz !== 0;
2900
- this.filters.vibrato = this.data.vibrato.frequency !== 0 || this.data.vibrato.depth !== 0;
2901
- this.filters.tremolo = this.data.tremolo.frequency !== 0 || this.data.tremolo.depth !== 0;
2920
+ this.data = this.data ?? {};
2921
+ this.filters.rotation = this.privateNot0(this.data.rotation?.rotationHz);
2922
+ this.filters.vibrato = this.privateNot0(this.data.vibrato?.frequency) || this.privateNot0(this.data.vibrato?.depth);
2923
+ this.filters.tremolo = this.privateNot0(this.data.tremolo?.frequency) || this.privateNot0(this.data.tremolo?.depth);
2902
2924
  const lavalinkFilterData = this.data.pluginFilters?.["lavalink-filter-plugin"] || { echo: { decay: this.data.pluginFilters?.echo?.decay && !this.data.pluginFilters?.echo?.echoLength ? this.data.pluginFilters.echo.decay : 0, delay: this.data.pluginFilters?.echo?.delay || 0 }, reverb: { gains: [], delays: [], ...this.data.pluginFilters.reverb } };
2903
2925
  this.filters.lavalinkFilterPlugin.echo = lavalinkFilterData.echo.decay !== 0 || lavalinkFilterData.echo.delay !== 0;
2904
2926
  this.filters.lavalinkFilterPlugin.reverb = lavalinkFilterData.reverb?.delays?.length !== 0 || lavalinkFilterData.reverb?.gains?.length !== 0;
@@ -3737,6 +3759,7 @@ var Queue = class {
3737
3759
  * - single Track | UnresolvedTrack
3738
3760
  * - multiple Track | UnresovedTrack
3739
3761
  * - at the index or multiple indexes
3762
+ * - Since v2.7 the removed tracks get unshifted into the previous queue state instead of pushed (indexed at the start instead of end - as it should)
3740
3763
  * @param removeQueryTrack
3741
3764
  * @returns null (if nothing was removed) / { removed } where removed is an array with all removed elements
3742
3765
  *
@@ -3782,9 +3805,10 @@ var Queue = class {
3782
3805
  if (Array.isArray(removeQueryTrack)) {
3783
3806
  if (removeQueryTrack.every((v) => typeof v === "number")) {
3784
3807
  const removed3 = [];
3785
- for (const i of removeQueryTrack) {
3808
+ const sortedIndexes = removeQueryTrack.sort((a, b) => b - a);
3809
+ for (const i of sortedIndexes) {
3786
3810
  if (this.tracks[i]) {
3787
- removed3.push(...this.tracks.splice(i, 1));
3811
+ removed3.unshift(...this.tracks.splice(i, 1));
3788
3812
  }
3789
3813
  }
3790
3814
  if (!removed3.length) return null;
@@ -3800,9 +3824,10 @@ var Queue = class {
3800
3824
  ));
3801
3825
  if (!tracksToRemove.length) return null;
3802
3826
  const removed2 = [];
3827
+ tracksToRemove.sort((a, b) => b.i - a.i);
3803
3828
  for (const { i } of tracksToRemove) {
3804
3829
  if (this.tracks[i]) {
3805
- removed2.push(...this.tracks.splice(i, 1));
3830
+ removed2.unshift(...this.tracks.splice(i, 1));
3806
3831
  }
3807
3832
  }
3808
3833
  if (typeof this.queueChanges?.tracksRemoved === "function") try {
@@ -4025,7 +4050,7 @@ var Player = class {
4025
4050
  this.queue.current = options.clientTrack || null;
4026
4051
  this.queue.utils.save();
4027
4052
  if (typeof options?.volume === "number" && !isNaN(options?.volume)) {
4028
- this.volume = Math.max(Math.min(options?.volume, 500), 0);
4053
+ this.volume = Math.max(Math.min(options?.volume, 1e3), 0);
4029
4054
  let vol = Number(this.volume);
4030
4055
  if (this.LavalinkManager.options.playerOptions.volumeDecrementer) vol *= this.LavalinkManager.options.playerOptions.volumeDecrementer;
4031
4056
  this.lavalinkVolume = Math.round(vol);
@@ -4095,7 +4120,7 @@ var Player = class {
4095
4120
  }
4096
4121
  if (!this.queue.current) throw new Error(`There is no Track in the Queue, nor provided in the PlayOptions`);
4097
4122
  if (typeof options?.volume === "number" && !isNaN(options?.volume)) {
4098
- this.volume = Math.max(Math.min(options?.volume, 500), 0);
4123
+ this.volume = Math.max(Math.min(options?.volume, 1e3), 0);
4099
4124
  let vol = Number(this.volume);
4100
4125
  if (this.LavalinkManager.options.playerOptions.volumeDecrementer) vol *= this.LavalinkManager.options.playerOptions.volumeDecrementer;
4101
4126
  this.lavalinkVolume = Math.round(vol);
@@ -4118,9 +4143,9 @@ var Player = class {
4118
4143
  paused: options?.paused ?? void 0,
4119
4144
  voice: options?.voice ?? void 0
4120
4145
  }).filter((v) => typeof v[1] !== "undefined"));
4121
- if (typeof finalOptions.position !== "undefined" && isNaN(finalOptions.position) || typeof finalOptions.position === "number" && (finalOptions.position < 0 || finalOptions.position >= this.queue.current.info.duration)) throw new Error("PlayerOption#position must be a positive number, less than track's duration");
4146
+ if (typeof finalOptions.position !== "undefined" && isNaN(finalOptions.position) || typeof finalOptions.position === "number" && finalOptions.position < 0 || typeof finalOptions.position === "number" && this.queue.current.info.duration > 0 && finalOptions.position >= this.queue.current.info.duration) throw new Error("PlayerOption#position must be a positive number, less than track's duration");
4122
4147
  if (typeof finalOptions.volume !== "undefined" && isNaN(finalOptions.volume) || typeof finalOptions.volume === "number" && finalOptions.volume < 0) throw new Error("PlayerOption#volume must be a positive number");
4123
- if (typeof finalOptions.endTime !== "undefined" && isNaN(finalOptions.endTime) || typeof finalOptions.endTime === "number" && (finalOptions.endTime < 0 || finalOptions.endTime >= this.queue.current.info.duration)) throw new Error("PlayerOption#endTime must be a positive number, less than track's duration");
4148
+ if (typeof finalOptions.endTime !== "undefined" && isNaN(finalOptions.endTime) || typeof finalOptions.endTime === "number" && finalOptions.endTime < 0 || typeof finalOptions.endTime === "number" && this.queue.current.info.duration > 0 && finalOptions.endTime >= this.queue.current.info.duration) throw new Error("PlayerOption#endTime must be a positive number, less than track's duration");
4124
4149
  if (typeof finalOptions.position === "number" && typeof finalOptions.endTime === "number" && finalOptions.endTime < finalOptions.position) throw new Error("PlayerOption#endTime must be bigger than PlayerOption#position");
4125
4150
  const now = performance.now();
4126
4151
  await this.node.updatePlayer({
@@ -4195,7 +4220,7 @@ var Player = class {
4195
4220
  */
4196
4221
  async search(query, requestUser, throwOnEmpty = false) {
4197
4222
  const Query = this.LavalinkManager.utils.transformQuery(query);
4198
- if (["bcsearch", "bandcamp"].includes(Query.source) && !this.node.info.sourceManagers.includes("bandcamp")) {
4223
+ if (["bcsearch", "bandcamp"].includes(Query.source) && !this.node.info?.sourceManagers.includes("bandcamp")) {
4199
4224
  if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
4200
4225
  this.LavalinkManager.emit("debug", "BandcampSearchLokalEngine" /* BandcampSearchLokalEngine */, {
4201
4226
  state: "log",
@@ -4450,7 +4475,7 @@ var Player = class {
4450
4475
  if (this.queue.current || this.queue.tracks.length) {
4451
4476
  const trackSources = new Set([this.queue.current, ...this.queue.tracks].map((track) => track.info.sourceName));
4452
4477
  const missingSources = [...trackSources].filter(
4453
- (source) => !updateNode.info.sourceManagers.includes(source)
4478
+ (source) => !updateNode.info?.sourceManagers.includes(source)
4454
4479
  );
4455
4480
  if (missingSources.length)
4456
4481
  throw new RangeError(`Sources missing for Node ${updateNode.id}: ${missingSources.join(", ")}`);
@@ -4872,7 +4897,7 @@ var LavalinkManager = class extends import_events2.EventEmitter {
4872
4897
  deletePlayer(guildId) {
4873
4898
  const oldPlayer = this.getPlayer(guildId);
4874
4899
  if (!oldPlayer) return;
4875
- if (oldPlayer.voiceChannelId === "string" && oldPlayer.connected && !oldPlayer.get("internal_destroywithoutdisconnect")) {
4900
+ if (typeof oldPlayer.voiceChannelId === "string" && oldPlayer.connected && !oldPlayer.get("internal_destroywithoutdisconnect")) {
4876
4901
  if (!this.options?.advancedOptions?.debugOptions?.playerDestroy?.dontThrowError) throw new Error(`Use Player#destroy() not LavalinkManager#deletePlayer() to stop the Player ${safeStringify(oldPlayer.toJSON?.())}`);
4877
4902
  else if (this.options?.advancedOptions?.enableDebugEvents) {
4878
4903
  this.emit("debug", "PlayerDeleteInsteadOfDestroy" /* PlayerDeleteInsteadOfDestroy */, {
@@ -5135,6 +5160,7 @@ var LavalinkManager = class extends import_events2.EventEmitter {
5135
5160
  message: `Auto reconnected, but nothing to play`,
5136
5161
  functionLayer: "LavalinkManager > sendRawData()"
5137
5162
  });
5163
+ return;
5138
5164
  } catch (e) {
5139
5165
  console.error(e);
5140
5166
  return void await player.destroy("PlayerReconnectFail" /* PlayerReconnectFail */);
package/dist/index.mjs CHANGED
@@ -19,6 +19,7 @@ var DebugEvents = /* @__PURE__ */ ((DebugEvents2) => {
19
19
  DebugEvents2["PlayerUpdateSuccess"] = "PlayerUpdateSuccess";
20
20
  DebugEvents2["HeartBeatTriggered"] = "HeartBeatTriggered";
21
21
  DebugEvents2["NoSocketOnDestroy"] = "NoSocketOnDestroy";
22
+ DebugEvents2["SocketCleanupError"] = "SocketCleanupError";
22
23
  DebugEvents2["SocketTerminateHeartBeatTimeout"] = "SocketTerminateHeartBeatTimeout";
23
24
  DebugEvents2["TryingConnectWhileConnected"] = "TryingConnectWhileConnected";
24
25
  DebugEvents2["LavaSearchNothingFound"] = "LavaSearchNothingFound";
@@ -421,7 +422,7 @@ var SourceLinksRegexes = {
421
422
  /** DEFAULT SUPPORTED BY LAVALINK */
422
423
  YoutubeRegex: /https?:\/\/?(?:www\.)?(?:(m|www)\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|shorts|playlist\?|watch\?v=|watch\?.+(?:&|&#38;);v=))([a-zA-Z0-9\-_]{11})?(?:(?:\?|&|&#38;)index=((?:\d){1,3}))?(?:(?:\?|&|&#38;)?list=([a-zA-Z\-_0-9]{34}))?(?:\S+)?/,
423
424
  YoutubeMusicRegex: /https?:\/\/?(?:www\.)?(?:(music|m|www)\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|shorts|playlist\?|watch\?v=|watch\?.+(?:&|&#38;);v=))([a-zA-Z0-9\-_]{11})?(?:(?:\?|&|&#38;)index=((?:\d){1,3}))?(?:(?:\?|&|&#38;)?list=([a-zA-Z\-_0-9]{34}))?(?:\S+)?/,
424
- SoundCloudRegex: /https:\/\/(?:on\.)?soundcloud\.com\//,
425
+ SoundCloudRegex: /https?:\/\/(?:on\.)?soundcloud\.com\//,
425
426
  SoundCloudMobileRegex: /https?:\/\/(soundcloud\.app\.goo\.gl)\/(\S+)/,
426
427
  bandcamp: /https?:\/\/?(?:www\.)?([\d|\w]+)\.bandcamp\.com\/(\S+)/,
427
428
  TwitchTv: /https?:\/\/?(?:www\.)?twitch\.tv\/\w+/,
@@ -941,9 +942,15 @@ async function getClosestTrack(data, player) {
941
942
  source: sourceName !== "twitch" && sourceName !== "flowery-tts" ? sourceName : player.LavalinkManager.options?.playerOptions?.defaultSearchPlatform
942
943
  }, data.requester).then((res) => {
943
944
  let trackToUse = null;
944
- if (data.info.author && !trackToUse) trackToUse = res.tracks.find((track) => [data.info?.author || "", `${data.info?.author} - Topic`].some((name) => new RegExp(`^${escapeRegExp(name)}$`, "i").test(track.info?.author)) || new RegExp(`^${escapeRegExp(data.info?.title)}$`, "i").test(track.info?.title));
945
- if (data.info.duration && !trackToUse) trackToUse = res.tracks.find((track) => track.info?.duration >= data.info?.duration - 1500 && track?.info.duration <= data.info?.duration + 1500);
946
- if (data.info.isrc && !trackToUse) trackToUse = res.tracks.find((track) => track.info?.isrc === data.info?.isrc);
945
+ if ((data.info?.title || data.info?.author) && !trackToUse) trackToUse = res.tracks.find(
946
+ (track) => (
947
+ // find via author name (i ... case insensitve)
948
+ [data.info?.author || "", `${data.info?.author} - Topic`].some((name) => new RegExp(`^${escapeRegExp(name)}$`, "i").test(track.info?.author)) || // find via title (i ... case insensitve)
949
+ new RegExp(`^${escapeRegExp(data.info?.title)}$`, "i").test(track.info?.title)
950
+ )
951
+ );
952
+ if (data.info?.isrc && !trackToUse) trackToUse = res.tracks.find((track) => track.info?.isrc === data.info?.isrc);
953
+ if (data.info?.duration && !trackToUse) trackToUse = res.tracks.find((track) => track.info?.duration >= data.info?.duration - 1500 && track?.info.duration <= data.info?.duration + 1500);
947
954
  return applyUnresolvedData(trackToUse || res.tracks[0], data, player.LavalinkManager.utils);
948
955
  });
949
956
  }
@@ -1380,8 +1387,8 @@ var LavalinkNode = class {
1380
1387
  }
1381
1388
  };
1382
1389
  handlePlayerOperations().finally(() => {
1383
- this.socket.close(1e3, "Node-Destroy");
1384
- this.socket.removeAllListeners();
1390
+ this.socket?.close(1e3, "Node-Destroy");
1391
+ this.socket?.removeAllListeners();
1385
1392
  this.socket = null;
1386
1393
  this.reconnectAttempts = 1;
1387
1394
  clearTimeout(this.reconnectTimeout);
@@ -1395,8 +1402,8 @@ var LavalinkNode = class {
1395
1402
  }
1396
1403
  });
1397
1404
  } else {
1398
- this.socket.close(1e3, "Node-Destroy");
1399
- this.socket.removeAllListeners();
1405
+ this.socket?.close(1e3, "Node-Destroy");
1406
+ this.socket?.removeAllListeners();
1400
1407
  this.socket = null;
1401
1408
  this.reconnectAttempts = 1;
1402
1409
  clearTimeout(this.reconnectTimeout);
@@ -1425,8 +1432,8 @@ var LavalinkNode = class {
1425
1432
  */
1426
1433
  disconnect(disconnectReason) {
1427
1434
  if (!this.connected) return;
1428
- this.socket.close(1e3, "Node-Disconnect");
1429
- this.socket.removeAllListeners();
1435
+ this.socket?.close(1e3, "Node-Disconnect");
1436
+ this.socket?.removeAllListeners();
1430
1437
  this.socket = null;
1431
1438
  this.reconnectAttempts = 1;
1432
1439
  clearTimeout(this.reconnectTimeout);
@@ -1817,8 +1824,6 @@ var LavalinkNode = class {
1817
1824
  this.NodeManager.emit("error", this, error);
1818
1825
  return this.destroy("NodeReconnectFail" /* NodeReconnectFail */);
1819
1826
  }
1820
- this.socket.removeAllListeners();
1821
- this.socket = null;
1822
1827
  this.NodeManager.emit("reconnecting", this);
1823
1828
  this.connect();
1824
1829
  this.reconnectAttempts++;
@@ -1831,8 +1836,6 @@ var LavalinkNode = class {
1831
1836
  this.NodeManager.emit("error", this, error);
1832
1837
  return this.destroy("NodeReconnectFail" /* NodeReconnectFail */);
1833
1838
  }
1834
- this.socket.removeAllListeners();
1835
- this.socket = null;
1836
1839
  this.NodeManager.emit("reconnecting", this);
1837
1840
  this.connect();
1838
1841
  this.reconnectAttempts++;
@@ -1841,6 +1844,8 @@ var LavalinkNode = class {
1841
1844
  /** @private util function for handling opening events from websocket */
1842
1845
  async open() {
1843
1846
  this.isAlive = true;
1847
+ this.reconnectAttempts = 1;
1848
+ if (this.reconnectTimeout) clearTimeout(this.reconnectTimeout);
1844
1849
  if (this.options.enablePingOnStatsCheck) this.heartBeat();
1845
1850
  if (this.heartBeatInterval) clearInterval(this.heartBeatInterval);
1846
1851
  if (this.options.heartBeatInterval > 0) {
@@ -1856,8 +1861,6 @@ var LavalinkNode = class {
1856
1861
  this.socket.ping();
1857
1862
  }, this.options.heartBeatInterval || 3e4);
1858
1863
  }
1859
- if (this.reconnectTimeout) clearTimeout(this.reconnectTimeout);
1860
- this.reconnectAttempts = 1;
1861
1864
  this.info = await this.fetchInfo().catch((e) => (console.error(e, "ON-OPEN-FETCH"), null));
1862
1865
  if (!this.info && ["v3", "v4"].includes(this.version)) {
1863
1866
  const errorString = `Lavalink Node (${this.restAddress}) does not provide any /${this.version}/info`;
@@ -1868,6 +1871,21 @@ var LavalinkNode = class {
1868
1871
  /** @private util function for handling closing events from websocket */
1869
1872
  close(code, reason) {
1870
1873
  if (this.pingTimeout) clearTimeout(this.pingTimeout);
1874
+ try {
1875
+ if (this.socket) {
1876
+ this.socket.removeAllListeners();
1877
+ this.socket = null;
1878
+ }
1879
+ } catch (e) {
1880
+ if (this.NodeManager?.LavalinkManager?.options?.advancedOptions?.enableDebugEvents) {
1881
+ this.NodeManager.LavalinkManager.emit("debug", "SocketCleanupError" /* SocketCleanupError */, {
1882
+ state: "warn",
1883
+ message: `An error occurred during socket cleanup in close() (likely a race condition): ${e.message}`,
1884
+ functionLayer: "LavalinkNode > close()"
1885
+ });
1886
+ }
1887
+ }
1888
+ this.isAlive = false;
1871
1889
  if (this.heartBeatInterval) clearInterval(this.heartBeatInterval);
1872
1890
  if (code === 1006 && !reason) reason = "Socket got terminated due to no ping connection";
1873
1891
  if (code === 1e3 && reason === "Node-Disconnect") return;
@@ -2637,7 +2655,7 @@ var bandCampSearch = async (player, query, requestUser) => {
2637
2655
  artworkUrl: item.img,
2638
2656
  author: item.band_name,
2639
2657
  title: item.name,
2640
- identifier: item.id ? `${item.id}` : item.url?.split("/").reverse()[0]
2658
+ identifier: item.id ? `${item.id}` : item.url?.split("/")?.reverse()[0]
2641
2659
  }, requestUser));
2642
2660
  } catch (e) {
2643
2661
  error = e;
@@ -2822,6 +2840,9 @@ var FilterManager = class {
2822
2840
  this.player.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
2823
2841
  return;
2824
2842
  }
2843
+ privateNot0(value) {
2844
+ return typeof value === "number" && value !== 0;
2845
+ }
2825
2846
  /**
2826
2847
  * Checks if the filters are correctly stated (active / not-active) - mostly used internally.
2827
2848
  * @param oldFilterTimescale
@@ -2836,9 +2857,10 @@ var FilterManager = class {
2836
2857
  * ```
2837
2858
  */
2838
2859
  checkFiltersState(oldFilterTimescale) {
2839
- this.filters.rotation = this.data.rotation.rotationHz !== 0;
2840
- this.filters.vibrato = this.data.vibrato.frequency !== 0 || this.data.vibrato.depth !== 0;
2841
- this.filters.tremolo = this.data.tremolo.frequency !== 0 || this.data.tremolo.depth !== 0;
2860
+ this.data = this.data ?? {};
2861
+ this.filters.rotation = this.privateNot0(this.data.rotation?.rotationHz);
2862
+ this.filters.vibrato = this.privateNot0(this.data.vibrato?.frequency) || this.privateNot0(this.data.vibrato?.depth);
2863
+ this.filters.tremolo = this.privateNot0(this.data.tremolo?.frequency) || this.privateNot0(this.data.tremolo?.depth);
2842
2864
  const lavalinkFilterData = this.data.pluginFilters?.["lavalink-filter-plugin"] || { echo: { decay: this.data.pluginFilters?.echo?.decay && !this.data.pluginFilters?.echo?.echoLength ? this.data.pluginFilters.echo.decay : 0, delay: this.data.pluginFilters?.echo?.delay || 0 }, reverb: { gains: [], delays: [], ...this.data.pluginFilters.reverb } };
2843
2865
  this.filters.lavalinkFilterPlugin.echo = lavalinkFilterData.echo.decay !== 0 || lavalinkFilterData.echo.delay !== 0;
2844
2866
  this.filters.lavalinkFilterPlugin.reverb = lavalinkFilterData.reverb?.delays?.length !== 0 || lavalinkFilterData.reverb?.gains?.length !== 0;
@@ -3677,6 +3699,7 @@ var Queue = class {
3677
3699
  * - single Track | UnresolvedTrack
3678
3700
  * - multiple Track | UnresovedTrack
3679
3701
  * - at the index or multiple indexes
3702
+ * - Since v2.7 the removed tracks get unshifted into the previous queue state instead of pushed (indexed at the start instead of end - as it should)
3680
3703
  * @param removeQueryTrack
3681
3704
  * @returns null (if nothing was removed) / { removed } where removed is an array with all removed elements
3682
3705
  *
@@ -3722,9 +3745,10 @@ var Queue = class {
3722
3745
  if (Array.isArray(removeQueryTrack)) {
3723
3746
  if (removeQueryTrack.every((v) => typeof v === "number")) {
3724
3747
  const removed3 = [];
3725
- for (const i of removeQueryTrack) {
3748
+ const sortedIndexes = removeQueryTrack.sort((a, b) => b - a);
3749
+ for (const i of sortedIndexes) {
3726
3750
  if (this.tracks[i]) {
3727
- removed3.push(...this.tracks.splice(i, 1));
3751
+ removed3.unshift(...this.tracks.splice(i, 1));
3728
3752
  }
3729
3753
  }
3730
3754
  if (!removed3.length) return null;
@@ -3740,9 +3764,10 @@ var Queue = class {
3740
3764
  ));
3741
3765
  if (!tracksToRemove.length) return null;
3742
3766
  const removed2 = [];
3767
+ tracksToRemove.sort((a, b) => b.i - a.i);
3743
3768
  for (const { i } of tracksToRemove) {
3744
3769
  if (this.tracks[i]) {
3745
- removed2.push(...this.tracks.splice(i, 1));
3770
+ removed2.unshift(...this.tracks.splice(i, 1));
3746
3771
  }
3747
3772
  }
3748
3773
  if (typeof this.queueChanges?.tracksRemoved === "function") try {
@@ -3965,7 +3990,7 @@ var Player = class {
3965
3990
  this.queue.current = options.clientTrack || null;
3966
3991
  this.queue.utils.save();
3967
3992
  if (typeof options?.volume === "number" && !isNaN(options?.volume)) {
3968
- this.volume = Math.max(Math.min(options?.volume, 500), 0);
3993
+ this.volume = Math.max(Math.min(options?.volume, 1e3), 0);
3969
3994
  let vol = Number(this.volume);
3970
3995
  if (this.LavalinkManager.options.playerOptions.volumeDecrementer) vol *= this.LavalinkManager.options.playerOptions.volumeDecrementer;
3971
3996
  this.lavalinkVolume = Math.round(vol);
@@ -4035,7 +4060,7 @@ var Player = class {
4035
4060
  }
4036
4061
  if (!this.queue.current) throw new Error(`There is no Track in the Queue, nor provided in the PlayOptions`);
4037
4062
  if (typeof options?.volume === "number" && !isNaN(options?.volume)) {
4038
- this.volume = Math.max(Math.min(options?.volume, 500), 0);
4063
+ this.volume = Math.max(Math.min(options?.volume, 1e3), 0);
4039
4064
  let vol = Number(this.volume);
4040
4065
  if (this.LavalinkManager.options.playerOptions.volumeDecrementer) vol *= this.LavalinkManager.options.playerOptions.volumeDecrementer;
4041
4066
  this.lavalinkVolume = Math.round(vol);
@@ -4058,9 +4083,9 @@ var Player = class {
4058
4083
  paused: options?.paused ?? void 0,
4059
4084
  voice: options?.voice ?? void 0
4060
4085
  }).filter((v) => typeof v[1] !== "undefined"));
4061
- if (typeof finalOptions.position !== "undefined" && isNaN(finalOptions.position) || typeof finalOptions.position === "number" && (finalOptions.position < 0 || finalOptions.position >= this.queue.current.info.duration)) throw new Error("PlayerOption#position must be a positive number, less than track's duration");
4086
+ if (typeof finalOptions.position !== "undefined" && isNaN(finalOptions.position) || typeof finalOptions.position === "number" && finalOptions.position < 0 || typeof finalOptions.position === "number" && this.queue.current.info.duration > 0 && finalOptions.position >= this.queue.current.info.duration) throw new Error("PlayerOption#position must be a positive number, less than track's duration");
4062
4087
  if (typeof finalOptions.volume !== "undefined" && isNaN(finalOptions.volume) || typeof finalOptions.volume === "number" && finalOptions.volume < 0) throw new Error("PlayerOption#volume must be a positive number");
4063
- if (typeof finalOptions.endTime !== "undefined" && isNaN(finalOptions.endTime) || typeof finalOptions.endTime === "number" && (finalOptions.endTime < 0 || finalOptions.endTime >= this.queue.current.info.duration)) throw new Error("PlayerOption#endTime must be a positive number, less than track's duration");
4088
+ if (typeof finalOptions.endTime !== "undefined" && isNaN(finalOptions.endTime) || typeof finalOptions.endTime === "number" && finalOptions.endTime < 0 || typeof finalOptions.endTime === "number" && this.queue.current.info.duration > 0 && finalOptions.endTime >= this.queue.current.info.duration) throw new Error("PlayerOption#endTime must be a positive number, less than track's duration");
4064
4089
  if (typeof finalOptions.position === "number" && typeof finalOptions.endTime === "number" && finalOptions.endTime < finalOptions.position) throw new Error("PlayerOption#endTime must be bigger than PlayerOption#position");
4065
4090
  const now = performance.now();
4066
4091
  await this.node.updatePlayer({
@@ -4135,7 +4160,7 @@ var Player = class {
4135
4160
  */
4136
4161
  async search(query, requestUser, throwOnEmpty = false) {
4137
4162
  const Query = this.LavalinkManager.utils.transformQuery(query);
4138
- if (["bcsearch", "bandcamp"].includes(Query.source) && !this.node.info.sourceManagers.includes("bandcamp")) {
4163
+ if (["bcsearch", "bandcamp"].includes(Query.source) && !this.node.info?.sourceManagers.includes("bandcamp")) {
4139
4164
  if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
4140
4165
  this.LavalinkManager.emit("debug", "BandcampSearchLokalEngine" /* BandcampSearchLokalEngine */, {
4141
4166
  state: "log",
@@ -4390,7 +4415,7 @@ var Player = class {
4390
4415
  if (this.queue.current || this.queue.tracks.length) {
4391
4416
  const trackSources = new Set([this.queue.current, ...this.queue.tracks].map((track) => track.info.sourceName));
4392
4417
  const missingSources = [...trackSources].filter(
4393
- (source) => !updateNode.info.sourceManagers.includes(source)
4418
+ (source) => !updateNode.info?.sourceManagers.includes(source)
4394
4419
  );
4395
4420
  if (missingSources.length)
4396
4421
  throw new RangeError(`Sources missing for Node ${updateNode.id}: ${missingSources.join(", ")}`);
@@ -4812,7 +4837,7 @@ var LavalinkManager = class extends EventEmitter2 {
4812
4837
  deletePlayer(guildId) {
4813
4838
  const oldPlayer = this.getPlayer(guildId);
4814
4839
  if (!oldPlayer) return;
4815
- if (oldPlayer.voiceChannelId === "string" && oldPlayer.connected && !oldPlayer.get("internal_destroywithoutdisconnect")) {
4840
+ if (typeof oldPlayer.voiceChannelId === "string" && oldPlayer.connected && !oldPlayer.get("internal_destroywithoutdisconnect")) {
4816
4841
  if (!this.options?.advancedOptions?.debugOptions?.playerDestroy?.dontThrowError) throw new Error(`Use Player#destroy() not LavalinkManager#deletePlayer() to stop the Player ${safeStringify(oldPlayer.toJSON?.())}`);
4817
4842
  else if (this.options?.advancedOptions?.enableDebugEvents) {
4818
4843
  this.emit("debug", "PlayerDeleteInsteadOfDestroy" /* PlayerDeleteInsteadOfDestroy */, {
@@ -5075,6 +5100,7 @@ var LavalinkManager = class extends EventEmitter2 {
5075
5100
  message: `Auto reconnected, but nothing to play`,
5076
5101
  functionLayer: "LavalinkManager > sendRawData()"
5077
5102
  });
5103
+ return;
5078
5104
  } catch (e) {
5079
5105
  console.error(e);
5080
5106
  return void await player.destroy("PlayerReconnectFail" /* PlayerReconnectFail */);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lavalink-client",
3
- "version": "2.6.6",
3
+ "version": "2.7.0",
4
4
  "description": "Easy, flexible and feature-rich lavalink@v4 Client. Both for Beginners and Proficients.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -57,12 +57,12 @@
57
57
  "devDependencies": {
58
58
  "@eslint/eslintrc": "^3.3.1",
59
59
  "@eslint/js": "^9.39.1",
60
- "@types/node": "^24.10.0",
60
+ "@types/node": "^24.10.1",
61
61
  "@types/ws": "^8.18.1",
62
- "@typescript-eslint/eslint-plugin": "^8.46.3",
63
- "@typescript-eslint/parser": "^8.46.3",
62
+ "@typescript-eslint/eslint-plugin": "^8.46.4",
63
+ "@typescript-eslint/parser": "^8.46.4",
64
64
  "eslint": "^9.39.1",
65
- "tsup": "^8.5.0",
65
+ "tsup": "^8.5.1",
66
66
  "typescript": "^5.9.3"
67
67
  },
68
68
  "dependencies": {