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 +8 -1
- package/dist/index.d.mts +137 -160
- package/dist/index.d.ts +137 -160
- package/dist/index.js +56 -30
- package/dist/index.mjs +56 -30
- package/package.json +5 -5
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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\?.+(?:&|&);v=))([a-zA-Z0-9\-_]{11})?(?:(?:\?|&|&)index=((?:\d){1,3}))?(?:(?:\?|&|&)?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\?.+(?:&|&);v=))([a-zA-Z0-9\-_]{11})?(?:(?:\?|&|&)index=((?:\d){1,3}))?(?:(?:\?|&|&)?list=([a-zA-Z\-_0-9]{34}))?(?:\S+)?/,
|
|
484
|
-
SoundCloudRegex: /https
|
|
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 (
|
|
1005
|
-
|
|
1006
|
-
|
|
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
|
|
1444
|
-
this.socket
|
|
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
|
|
1459
|
-
this.socket
|
|
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
|
|
1489
|
-
this.socket
|
|
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("/")
|
|
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.
|
|
2900
|
-
this.filters.
|
|
2901
|
-
this.filters.
|
|
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
|
-
|
|
3808
|
+
const sortedIndexes = removeQueryTrack.sort((a, b) => b - a);
|
|
3809
|
+
for (const i of sortedIndexes) {
|
|
3786
3810
|
if (this.tracks[i]) {
|
|
3787
|
-
removed3.
|
|
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.
|
|
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,
|
|
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,
|
|
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" &&
|
|
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" &&
|
|
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
|
|
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
|
|
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\?.+(?:&|&);v=))([a-zA-Z0-9\-_]{11})?(?:(?:\?|&|&)index=((?:\d){1,3}))?(?:(?:\?|&|&)?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\?.+(?:&|&);v=))([a-zA-Z0-9\-_]{11})?(?:(?:\?|&|&)index=((?:\d){1,3}))?(?:(?:\?|&|&)?list=([a-zA-Z\-_0-9]{34}))?(?:\S+)?/,
|
|
424
|
-
SoundCloudRegex: /https
|
|
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 (
|
|
945
|
-
|
|
946
|
-
|
|
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
|
|
1384
|
-
this.socket
|
|
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
|
|
1399
|
-
this.socket
|
|
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
|
|
1429
|
-
this.socket
|
|
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("/")
|
|
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.
|
|
2840
|
-
this.filters.
|
|
2841
|
-
this.filters.
|
|
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
|
-
|
|
3748
|
+
const sortedIndexes = removeQueryTrack.sort((a, b) => b - a);
|
|
3749
|
+
for (const i of sortedIndexes) {
|
|
3726
3750
|
if (this.tracks[i]) {
|
|
3727
|
-
removed3.
|
|
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.
|
|
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,
|
|
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,
|
|
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" &&
|
|
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" &&
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
60
|
+
"@types/node": "^24.10.1",
|
|
61
61
|
"@types/ws": "^8.18.1",
|
|
62
|
-
"@typescript-eslint/eslint-plugin": "^8.46.
|
|
63
|
-
"@typescript-eslint/parser": "^8.46.
|
|
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.
|
|
65
|
+
"tsup": "^8.5.1",
|
|
66
66
|
"typescript": "^5.9.3"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|