lavalink-client 2.7.7 → 2.7.8
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 +1 -0
- package/dist/index.d.mts +198 -0
- package/dist/index.d.ts +198 -0
- package/dist/index.js +228 -2
- package/dist/index.mjs +228 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
- ✨ **Flexible Queue Stores:** Use the default in-memory store or bring your own (Redis, databases, etc.) to sync queues across multiple processes.
|
|
33
33
|
- 🎶 **Unresolved Tracks:** Supports unresolved track objects, fetching full data only when a track is about to play, saving API requests and resources.
|
|
34
34
|
- 🎚️ **Built-in Filters & EQ:** Easy-to-use management for audio filters and equalizers.
|
|
35
|
+
- 🔍 **Advanced Queue Filtering:** Search and filter tracks in the queue by title, author, duration, and more with powerful query options.
|
|
35
36
|
- ⚙️ **Advanced Player Options:** Fine-tune player behavior for disconnects, empty queues, volume handling, and more.
|
|
36
37
|
- 🛡️ **Lavalink-Side Validation:** Ensures you only use filters, plugins, and sources that your Lavalink node actually supports.
|
|
37
38
|
- 🔒 **Client-Side Validation:** Whitelist and blacklist URLs or domains to prevent unwanted requests and protect your bot.
|
package/dist/index.d.mts
CHANGED
|
@@ -704,6 +704,77 @@ declare class Queue {
|
|
|
704
704
|
* @returns {number}
|
|
705
705
|
*/
|
|
706
706
|
totalDuration: () => number;
|
|
707
|
+
/**
|
|
708
|
+
* Find tracks in the queue matching specific criteria.
|
|
709
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new array without modifying the original queue.
|
|
710
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
711
|
+
* @returns Array of matching tracks with their indexes
|
|
712
|
+
*
|
|
713
|
+
* @example
|
|
714
|
+
* ```ts
|
|
715
|
+
* // Find by author
|
|
716
|
+
* const artistTracks = player.queue.utils.filterTracks({ author: "Artist Name" });
|
|
717
|
+
*
|
|
718
|
+
* // Find by duration range (5-10 minutes)
|
|
719
|
+
* const longTracks = player.queue.utils.filterTracks({ duration: { min: 300000, max: 600000 } });
|
|
720
|
+
*
|
|
721
|
+
* // Find by title (partial match)
|
|
722
|
+
* const titleMatches = player.queue.utils.filterTracks({ title: "Never Gonna" });
|
|
723
|
+
*
|
|
724
|
+
* // Custom predicate
|
|
725
|
+
* const customFilter = player.queue.utils.filterTracks(track => track.info.isStream);
|
|
726
|
+
* ```
|
|
727
|
+
*/
|
|
728
|
+
filterTracks: (predicate: ((track: Track | UnresolvedTrack, index: number) => boolean) | {
|
|
729
|
+
title?: string;
|
|
730
|
+
author?: string;
|
|
731
|
+
duration?: number | {
|
|
732
|
+
min?: number;
|
|
733
|
+
max?: number;
|
|
734
|
+
};
|
|
735
|
+
uri?: string;
|
|
736
|
+
identifier?: string;
|
|
737
|
+
sourceName?: string;
|
|
738
|
+
isStream?: boolean;
|
|
739
|
+
isSeekable?: boolean;
|
|
740
|
+
}) => Array<{
|
|
741
|
+
track: Track | UnresolvedTrack;
|
|
742
|
+
index: number;
|
|
743
|
+
}>;
|
|
744
|
+
/**
|
|
745
|
+
* Find a single track in the queue matching specific criteria.
|
|
746
|
+
* **This method DOES NOT MUTATE the queue** - it searches without modifying the original queue.
|
|
747
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
748
|
+
* @returns First matching track with its index, or null if not found
|
|
749
|
+
*
|
|
750
|
+
* @example
|
|
751
|
+
* ```ts
|
|
752
|
+
* // Find first track by author
|
|
753
|
+
* const track = player.queue.utils.findTrack({ author: "Artist Name" });
|
|
754
|
+
* if (track) {
|
|
755
|
+
* console.log(`Found at index ${track.index}: ${track.track.info.title}`);
|
|
756
|
+
* }
|
|
757
|
+
*
|
|
758
|
+
* // Find with custom predicate
|
|
759
|
+
* const liveStream = player.queue.utils.findTrack(track => track.info.isStream);
|
|
760
|
+
* ```
|
|
761
|
+
*/
|
|
762
|
+
findTrack: (predicate: ((track: Track | UnresolvedTrack, index: number) => boolean) | {
|
|
763
|
+
title?: string;
|
|
764
|
+
author?: string;
|
|
765
|
+
duration?: number | {
|
|
766
|
+
min?: number;
|
|
767
|
+
max?: number;
|
|
768
|
+
};
|
|
769
|
+
uri?: string;
|
|
770
|
+
identifier?: string;
|
|
771
|
+
sourceName?: string;
|
|
772
|
+
isStream?: boolean;
|
|
773
|
+
isSeekable?: boolean;
|
|
774
|
+
}) => {
|
|
775
|
+
track: Track | UnresolvedTrack;
|
|
776
|
+
index: number;
|
|
777
|
+
} | null;
|
|
707
778
|
};
|
|
708
779
|
/**
|
|
709
780
|
* Shuffles the current Queue, then saves it
|
|
@@ -773,6 +844,126 @@ declare class Queue {
|
|
|
773
844
|
* ```
|
|
774
845
|
*/
|
|
775
846
|
shiftPrevious(): Promise<Track>;
|
|
847
|
+
/**
|
|
848
|
+
* Find tracks in the queue matching specific criteria.
|
|
849
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new array without modifying the original queue.
|
|
850
|
+
* @deprecated Use `player.queue.utils.filterTracks()` instead.
|
|
851
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
852
|
+
* @returns Array of matching tracks with their indexes
|
|
853
|
+
*
|
|
854
|
+
* @example
|
|
855
|
+
* ```ts
|
|
856
|
+
* // Use the new method instead:
|
|
857
|
+
* const artistTracks = player.queue.utils.filterTracks({ author: "Artist Name" });
|
|
858
|
+
* ```
|
|
859
|
+
*/
|
|
860
|
+
filter(predicate: ((track: Track | UnresolvedTrack, index: number) => boolean) | {
|
|
861
|
+
title?: string;
|
|
862
|
+
author?: string;
|
|
863
|
+
duration?: number | {
|
|
864
|
+
min?: number;
|
|
865
|
+
max?: number;
|
|
866
|
+
};
|
|
867
|
+
uri?: string;
|
|
868
|
+
identifier?: string;
|
|
869
|
+
sourceName?: string;
|
|
870
|
+
isStream?: boolean;
|
|
871
|
+
isSeekable?: boolean;
|
|
872
|
+
}): Array<{
|
|
873
|
+
track: Track | UnresolvedTrack;
|
|
874
|
+
index: number;
|
|
875
|
+
}>;
|
|
876
|
+
/**
|
|
877
|
+
* Find a single track in the queue matching specific criteria.
|
|
878
|
+
* **This method DOES NOT MUTATE the queue** - it searches without modifying the original queue.
|
|
879
|
+
* @deprecated Use `player.queue.utils.findTrack()` instead.
|
|
880
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
881
|
+
* @returns First matching track with its index, or null if not found
|
|
882
|
+
*
|
|
883
|
+
* @example
|
|
884
|
+
* ```ts
|
|
885
|
+
* // Use the new method instead:
|
|
886
|
+
* const track = player.queue.utils.findTrack({ author: "Artist Name" });
|
|
887
|
+
* ```
|
|
888
|
+
*/
|
|
889
|
+
find(predicate: ((track: Track | UnresolvedTrack, index: number) => boolean) | {
|
|
890
|
+
title?: string;
|
|
891
|
+
author?: string;
|
|
892
|
+
duration?: number | {
|
|
893
|
+
min?: number;
|
|
894
|
+
max?: number;
|
|
895
|
+
};
|
|
896
|
+
uri?: string;
|
|
897
|
+
identifier?: string;
|
|
898
|
+
sourceName?: string;
|
|
899
|
+
isStream?: boolean;
|
|
900
|
+
isSeekable?: boolean;
|
|
901
|
+
}): {
|
|
902
|
+
track: Track | UnresolvedTrack;
|
|
903
|
+
index: number;
|
|
904
|
+
} | null;
|
|
905
|
+
/**
|
|
906
|
+
* Sort the queue tracks by a specific property.
|
|
907
|
+
* **⚠️ This method MUTATES the queue** - it modifies the original queue in place.
|
|
908
|
+
* @param sortBy Property to sort by or custom comparator function
|
|
909
|
+
* @param order Sort order: 'asc' or 'desc' (default: 'asc')
|
|
910
|
+
* @returns The queue instance for chaining
|
|
911
|
+
*
|
|
912
|
+
* @example
|
|
913
|
+
* ```ts
|
|
914
|
+
* // Sort by duration (shortest first)
|
|
915
|
+
* await player.queue.sortBy("duration", "asc");
|
|
916
|
+
*
|
|
917
|
+
* // Sort by title alphabetically (Z-A)
|
|
918
|
+
* await player.queue.sortBy("title", "desc");
|
|
919
|
+
*
|
|
920
|
+
* // Custom sorting
|
|
921
|
+
* await player.queue.sortBy((a, b) => {
|
|
922
|
+
* return a.info.title.localeCompare(b.info.title);
|
|
923
|
+
* });
|
|
924
|
+
* ```
|
|
925
|
+
*/
|
|
926
|
+
sortBy(sortBy: "duration" | "title" | "author" | ((a: Track | UnresolvedTrack, b: Track | UnresolvedTrack) => number), order?: "asc" | "desc"): Promise<this>;
|
|
927
|
+
/**
|
|
928
|
+
* Get a sorted copy of the queue tracks without modifying the original queue.
|
|
929
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new sorted array, similar to `Array.toSorted()`.
|
|
930
|
+
* @param sortBy Property to sort by or custom comparator function
|
|
931
|
+
* @param order Sort order: 'asc' or 'desc' (default: 'asc')
|
|
932
|
+
* @returns A new sorted array of tracks (does not modify the queue)
|
|
933
|
+
*
|
|
934
|
+
* @example
|
|
935
|
+
* ```ts
|
|
936
|
+
* // Get sorted copy by duration (shortest first)
|
|
937
|
+
* const sortedTracks = player.queue.toSortedBy("duration", "asc");
|
|
938
|
+
* // Original queue remains unchanged
|
|
939
|
+
*
|
|
940
|
+
* // Get sorted copy by title alphabetically (Z-A)
|
|
941
|
+
* const sortedByTitle = player.queue.toSortedBy("title", "desc");
|
|
942
|
+
*
|
|
943
|
+
* // Custom sorting
|
|
944
|
+
* const customSorted = player.queue.toSortedBy((a, b) => {
|
|
945
|
+
* return a.info.title.localeCompare(b.info.title);
|
|
946
|
+
* });
|
|
947
|
+
* ```
|
|
948
|
+
*/
|
|
949
|
+
toSortedBy(sortBy: "duration" | "title" | "author" | ((a: Track | UnresolvedTrack, b: Track | UnresolvedTrack) => number), order?: "asc" | "desc"): (Track | UnresolvedTrack)[];
|
|
950
|
+
/**
|
|
951
|
+
* Get a range of tracks from the queue.
|
|
952
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new array slice, similar to `Array.slice()`.
|
|
953
|
+
* @param start Start index (inclusive)
|
|
954
|
+
* @param end End index (exclusive)
|
|
955
|
+
* @returns Array of tracks in the specified range
|
|
956
|
+
*
|
|
957
|
+
* @example
|
|
958
|
+
* ```ts
|
|
959
|
+
* // Get tracks 5-15
|
|
960
|
+
* const tracks = player.queue.getTracks(5, 15);
|
|
961
|
+
*
|
|
962
|
+
* // Get first 10 tracks
|
|
963
|
+
* const firstTen = player.queue.getTracks(0, 10);
|
|
964
|
+
* ```
|
|
965
|
+
*/
|
|
966
|
+
getTracks(start: number, end?: number): (Track | UnresolvedTrack)[];
|
|
776
967
|
}
|
|
777
968
|
|
|
778
969
|
declare class Player {
|
|
@@ -3031,6 +3222,13 @@ interface LavalinkManagerEvents<CustomPlayerT extends Player = Player> {
|
|
|
3031
3222
|
* @event Manager#playerDisconnect
|
|
3032
3223
|
*/
|
|
3033
3224
|
"playerDisconnect": (player: CustomPlayerT, voiceChannelId: string) => void;
|
|
3225
|
+
/**
|
|
3226
|
+
* Emitted when a Player automatically reconnects after a disconnect.
|
|
3227
|
+
* This event is triggered when the player successfully reconnects to the voice channel
|
|
3228
|
+
* and resumes playback after being disconnected (requires onDisconnect.autoReconnect to be enabled).
|
|
3229
|
+
* @event Manager#playerReconnect
|
|
3230
|
+
*/
|
|
3231
|
+
"playerReconnect": (player: CustomPlayerT, voiceChannelId: string) => void;
|
|
3034
3232
|
/**
|
|
3035
3233
|
* Emitted when a Node-Socket got closed for a specific Player.
|
|
3036
3234
|
* Usually emits when the audio websocket to discord is closed, This can happen for various reasons (normal and abnormal), e.g. when using an expired voice server update. 4xxx codes are usually bad.
|
package/dist/index.d.ts
CHANGED
|
@@ -704,6 +704,77 @@ declare class Queue {
|
|
|
704
704
|
* @returns {number}
|
|
705
705
|
*/
|
|
706
706
|
totalDuration: () => number;
|
|
707
|
+
/**
|
|
708
|
+
* Find tracks in the queue matching specific criteria.
|
|
709
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new array without modifying the original queue.
|
|
710
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
711
|
+
* @returns Array of matching tracks with their indexes
|
|
712
|
+
*
|
|
713
|
+
* @example
|
|
714
|
+
* ```ts
|
|
715
|
+
* // Find by author
|
|
716
|
+
* const artistTracks = player.queue.utils.filterTracks({ author: "Artist Name" });
|
|
717
|
+
*
|
|
718
|
+
* // Find by duration range (5-10 minutes)
|
|
719
|
+
* const longTracks = player.queue.utils.filterTracks({ duration: { min: 300000, max: 600000 } });
|
|
720
|
+
*
|
|
721
|
+
* // Find by title (partial match)
|
|
722
|
+
* const titleMatches = player.queue.utils.filterTracks({ title: "Never Gonna" });
|
|
723
|
+
*
|
|
724
|
+
* // Custom predicate
|
|
725
|
+
* const customFilter = player.queue.utils.filterTracks(track => track.info.isStream);
|
|
726
|
+
* ```
|
|
727
|
+
*/
|
|
728
|
+
filterTracks: (predicate: ((track: Track | UnresolvedTrack, index: number) => boolean) | {
|
|
729
|
+
title?: string;
|
|
730
|
+
author?: string;
|
|
731
|
+
duration?: number | {
|
|
732
|
+
min?: number;
|
|
733
|
+
max?: number;
|
|
734
|
+
};
|
|
735
|
+
uri?: string;
|
|
736
|
+
identifier?: string;
|
|
737
|
+
sourceName?: string;
|
|
738
|
+
isStream?: boolean;
|
|
739
|
+
isSeekable?: boolean;
|
|
740
|
+
}) => Array<{
|
|
741
|
+
track: Track | UnresolvedTrack;
|
|
742
|
+
index: number;
|
|
743
|
+
}>;
|
|
744
|
+
/**
|
|
745
|
+
* Find a single track in the queue matching specific criteria.
|
|
746
|
+
* **This method DOES NOT MUTATE the queue** - it searches without modifying the original queue.
|
|
747
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
748
|
+
* @returns First matching track with its index, or null if not found
|
|
749
|
+
*
|
|
750
|
+
* @example
|
|
751
|
+
* ```ts
|
|
752
|
+
* // Find first track by author
|
|
753
|
+
* const track = player.queue.utils.findTrack({ author: "Artist Name" });
|
|
754
|
+
* if (track) {
|
|
755
|
+
* console.log(`Found at index ${track.index}: ${track.track.info.title}`);
|
|
756
|
+
* }
|
|
757
|
+
*
|
|
758
|
+
* // Find with custom predicate
|
|
759
|
+
* const liveStream = player.queue.utils.findTrack(track => track.info.isStream);
|
|
760
|
+
* ```
|
|
761
|
+
*/
|
|
762
|
+
findTrack: (predicate: ((track: Track | UnresolvedTrack, index: number) => boolean) | {
|
|
763
|
+
title?: string;
|
|
764
|
+
author?: string;
|
|
765
|
+
duration?: number | {
|
|
766
|
+
min?: number;
|
|
767
|
+
max?: number;
|
|
768
|
+
};
|
|
769
|
+
uri?: string;
|
|
770
|
+
identifier?: string;
|
|
771
|
+
sourceName?: string;
|
|
772
|
+
isStream?: boolean;
|
|
773
|
+
isSeekable?: boolean;
|
|
774
|
+
}) => {
|
|
775
|
+
track: Track | UnresolvedTrack;
|
|
776
|
+
index: number;
|
|
777
|
+
} | null;
|
|
707
778
|
};
|
|
708
779
|
/**
|
|
709
780
|
* Shuffles the current Queue, then saves it
|
|
@@ -773,6 +844,126 @@ declare class Queue {
|
|
|
773
844
|
* ```
|
|
774
845
|
*/
|
|
775
846
|
shiftPrevious(): Promise<Track>;
|
|
847
|
+
/**
|
|
848
|
+
* Find tracks in the queue matching specific criteria.
|
|
849
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new array without modifying the original queue.
|
|
850
|
+
* @deprecated Use `player.queue.utils.filterTracks()` instead.
|
|
851
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
852
|
+
* @returns Array of matching tracks with their indexes
|
|
853
|
+
*
|
|
854
|
+
* @example
|
|
855
|
+
* ```ts
|
|
856
|
+
* // Use the new method instead:
|
|
857
|
+
* const artistTracks = player.queue.utils.filterTracks({ author: "Artist Name" });
|
|
858
|
+
* ```
|
|
859
|
+
*/
|
|
860
|
+
filter(predicate: ((track: Track | UnresolvedTrack, index: number) => boolean) | {
|
|
861
|
+
title?: string;
|
|
862
|
+
author?: string;
|
|
863
|
+
duration?: number | {
|
|
864
|
+
min?: number;
|
|
865
|
+
max?: number;
|
|
866
|
+
};
|
|
867
|
+
uri?: string;
|
|
868
|
+
identifier?: string;
|
|
869
|
+
sourceName?: string;
|
|
870
|
+
isStream?: boolean;
|
|
871
|
+
isSeekable?: boolean;
|
|
872
|
+
}): Array<{
|
|
873
|
+
track: Track | UnresolvedTrack;
|
|
874
|
+
index: number;
|
|
875
|
+
}>;
|
|
876
|
+
/**
|
|
877
|
+
* Find a single track in the queue matching specific criteria.
|
|
878
|
+
* **This method DOES NOT MUTATE the queue** - it searches without modifying the original queue.
|
|
879
|
+
* @deprecated Use `player.queue.utils.findTrack()` instead.
|
|
880
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
881
|
+
* @returns First matching track with its index, or null if not found
|
|
882
|
+
*
|
|
883
|
+
* @example
|
|
884
|
+
* ```ts
|
|
885
|
+
* // Use the new method instead:
|
|
886
|
+
* const track = player.queue.utils.findTrack({ author: "Artist Name" });
|
|
887
|
+
* ```
|
|
888
|
+
*/
|
|
889
|
+
find(predicate: ((track: Track | UnresolvedTrack, index: number) => boolean) | {
|
|
890
|
+
title?: string;
|
|
891
|
+
author?: string;
|
|
892
|
+
duration?: number | {
|
|
893
|
+
min?: number;
|
|
894
|
+
max?: number;
|
|
895
|
+
};
|
|
896
|
+
uri?: string;
|
|
897
|
+
identifier?: string;
|
|
898
|
+
sourceName?: string;
|
|
899
|
+
isStream?: boolean;
|
|
900
|
+
isSeekable?: boolean;
|
|
901
|
+
}): {
|
|
902
|
+
track: Track | UnresolvedTrack;
|
|
903
|
+
index: number;
|
|
904
|
+
} | null;
|
|
905
|
+
/**
|
|
906
|
+
* Sort the queue tracks by a specific property.
|
|
907
|
+
* **⚠️ This method MUTATES the queue** - it modifies the original queue in place.
|
|
908
|
+
* @param sortBy Property to sort by or custom comparator function
|
|
909
|
+
* @param order Sort order: 'asc' or 'desc' (default: 'asc')
|
|
910
|
+
* @returns The queue instance for chaining
|
|
911
|
+
*
|
|
912
|
+
* @example
|
|
913
|
+
* ```ts
|
|
914
|
+
* // Sort by duration (shortest first)
|
|
915
|
+
* await player.queue.sortBy("duration", "asc");
|
|
916
|
+
*
|
|
917
|
+
* // Sort by title alphabetically (Z-A)
|
|
918
|
+
* await player.queue.sortBy("title", "desc");
|
|
919
|
+
*
|
|
920
|
+
* // Custom sorting
|
|
921
|
+
* await player.queue.sortBy((a, b) => {
|
|
922
|
+
* return a.info.title.localeCompare(b.info.title);
|
|
923
|
+
* });
|
|
924
|
+
* ```
|
|
925
|
+
*/
|
|
926
|
+
sortBy(sortBy: "duration" | "title" | "author" | ((a: Track | UnresolvedTrack, b: Track | UnresolvedTrack) => number), order?: "asc" | "desc"): Promise<this>;
|
|
927
|
+
/**
|
|
928
|
+
* Get a sorted copy of the queue tracks without modifying the original queue.
|
|
929
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new sorted array, similar to `Array.toSorted()`.
|
|
930
|
+
* @param sortBy Property to sort by or custom comparator function
|
|
931
|
+
* @param order Sort order: 'asc' or 'desc' (default: 'asc')
|
|
932
|
+
* @returns A new sorted array of tracks (does not modify the queue)
|
|
933
|
+
*
|
|
934
|
+
* @example
|
|
935
|
+
* ```ts
|
|
936
|
+
* // Get sorted copy by duration (shortest first)
|
|
937
|
+
* const sortedTracks = player.queue.toSortedBy("duration", "asc");
|
|
938
|
+
* // Original queue remains unchanged
|
|
939
|
+
*
|
|
940
|
+
* // Get sorted copy by title alphabetically (Z-A)
|
|
941
|
+
* const sortedByTitle = player.queue.toSortedBy("title", "desc");
|
|
942
|
+
*
|
|
943
|
+
* // Custom sorting
|
|
944
|
+
* const customSorted = player.queue.toSortedBy((a, b) => {
|
|
945
|
+
* return a.info.title.localeCompare(b.info.title);
|
|
946
|
+
* });
|
|
947
|
+
* ```
|
|
948
|
+
*/
|
|
949
|
+
toSortedBy(sortBy: "duration" | "title" | "author" | ((a: Track | UnresolvedTrack, b: Track | UnresolvedTrack) => number), order?: "asc" | "desc"): (Track | UnresolvedTrack)[];
|
|
950
|
+
/**
|
|
951
|
+
* Get a range of tracks from the queue.
|
|
952
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new array slice, similar to `Array.slice()`.
|
|
953
|
+
* @param start Start index (inclusive)
|
|
954
|
+
* @param end End index (exclusive)
|
|
955
|
+
* @returns Array of tracks in the specified range
|
|
956
|
+
*
|
|
957
|
+
* @example
|
|
958
|
+
* ```ts
|
|
959
|
+
* // Get tracks 5-15
|
|
960
|
+
* const tracks = player.queue.getTracks(5, 15);
|
|
961
|
+
*
|
|
962
|
+
* // Get first 10 tracks
|
|
963
|
+
* const firstTen = player.queue.getTracks(0, 10);
|
|
964
|
+
* ```
|
|
965
|
+
*/
|
|
966
|
+
getTracks(start: number, end?: number): (Track | UnresolvedTrack)[];
|
|
776
967
|
}
|
|
777
968
|
|
|
778
969
|
declare class Player {
|
|
@@ -3031,6 +3222,13 @@ interface LavalinkManagerEvents<CustomPlayerT extends Player = Player> {
|
|
|
3031
3222
|
* @event Manager#playerDisconnect
|
|
3032
3223
|
*/
|
|
3033
3224
|
"playerDisconnect": (player: CustomPlayerT, voiceChannelId: string) => void;
|
|
3225
|
+
/**
|
|
3226
|
+
* Emitted when a Player automatically reconnects after a disconnect.
|
|
3227
|
+
* This event is triggered when the player successfully reconnects to the voice channel
|
|
3228
|
+
* and resumes playback after being disconnected (requires onDisconnect.autoReconnect to be enabled).
|
|
3229
|
+
* @event Manager#playerReconnect
|
|
3230
|
+
*/
|
|
3231
|
+
"playerReconnect": (player: CustomPlayerT, voiceChannelId: string) => void;
|
|
3034
3232
|
/**
|
|
3035
3233
|
* Emitted when a Node-Socket got closed for a specific Player.
|
|
3036
3234
|
* Usually emits when the audio websocket to discord is closed, This can happen for various reasons (normal and abnormal), e.g. when using an expired voice server update. 4xxx codes are usually bad.
|
package/dist/index.js
CHANGED
|
@@ -1433,7 +1433,6 @@ var LavalinkNode = class {
|
|
|
1433
1433
|
functionLayer: "LavalinkNode > nodeEvent > stats > heartBeat()"
|
|
1434
1434
|
});
|
|
1435
1435
|
this.resetAckTimeouts(false, true);
|
|
1436
|
-
if (this.pingTimeout) clearTimeout(this.pingTimeout);
|
|
1437
1436
|
this.pingTimeout = setTimeout(() => {
|
|
1438
1437
|
this.pingTimeout = null;
|
|
1439
1438
|
if (!this.socket) {
|
|
@@ -1958,9 +1957,10 @@ var LavalinkNode = class {
|
|
|
1958
1957
|
}, this.options.retryDelay || 1e3);
|
|
1959
1958
|
}
|
|
1960
1959
|
get reconnectionAttemptCount() {
|
|
1960
|
+
if (!Array.isArray(this.reconnectAttempts)) this.reconnectAttempts = [];
|
|
1961
1961
|
const maxAllowedTimestan = this.options.retryTimespan || -1;
|
|
1962
1962
|
if (maxAllowedTimestan <= 0) return this.reconnectAttempts.length;
|
|
1963
|
-
return this.reconnectAttempts
|
|
1963
|
+
return this.reconnectAttempts?.filter((timestamp) => Date.now() - timestamp <= maxAllowedTimestan).length || 0;
|
|
1964
1964
|
}
|
|
1965
1965
|
/**
|
|
1966
1966
|
* Private Utility function to execute the reconnection
|
|
@@ -1973,6 +1973,7 @@ var LavalinkNode = class {
|
|
|
1973
1973
|
this.destroy("NodeReconnectFail" /* NodeReconnectFail */);
|
|
1974
1974
|
return;
|
|
1975
1975
|
}
|
|
1976
|
+
if (!Array.isArray(this.reconnectAttempts)) this.reconnectAttempts = [];
|
|
1976
1977
|
this.reconnectAttempts.push(Date.now());
|
|
1977
1978
|
this.reconnectionState = "RECONNECTING" /* RECONNECTING */;
|
|
1978
1979
|
this.NodeManager.emit("reconnecting", this);
|
|
@@ -3817,6 +3818,87 @@ var Queue = class {
|
|
|
3817
3818
|
*/
|
|
3818
3819
|
totalDuration: () => {
|
|
3819
3820
|
return this.tracks.reduce((acc, cur) => acc + (cur.info.duration || 0), this.current?.info.duration || 0);
|
|
3821
|
+
},
|
|
3822
|
+
/**
|
|
3823
|
+
* Find tracks in the queue matching specific criteria.
|
|
3824
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new array without modifying the original queue.
|
|
3825
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
3826
|
+
* @returns Array of matching tracks with their indexes
|
|
3827
|
+
*
|
|
3828
|
+
* @example
|
|
3829
|
+
* ```ts
|
|
3830
|
+
* // Find by author
|
|
3831
|
+
* const artistTracks = player.queue.utils.filterTracks({ author: "Artist Name" });
|
|
3832
|
+
*
|
|
3833
|
+
* // Find by duration range (5-10 minutes)
|
|
3834
|
+
* const longTracks = player.queue.utils.filterTracks({ duration: { min: 300000, max: 600000 } });
|
|
3835
|
+
*
|
|
3836
|
+
* // Find by title (partial match)
|
|
3837
|
+
* const titleMatches = player.queue.utils.filterTracks({ title: "Never Gonna" });
|
|
3838
|
+
*
|
|
3839
|
+
* // Custom predicate
|
|
3840
|
+
* const customFilter = player.queue.utils.filterTracks(track => track.info.isStream);
|
|
3841
|
+
* ```
|
|
3842
|
+
*/
|
|
3843
|
+
filterTracks: (predicate) => {
|
|
3844
|
+
if (typeof predicate === "function") {
|
|
3845
|
+
return this.tracks.map((track, index) => ({ track, index })).filter(({ track, index }) => predicate(track, index));
|
|
3846
|
+
}
|
|
3847
|
+
return this.tracks.map((track, index) => ({ track, index })).filter(({ track }) => {
|
|
3848
|
+
if (predicate.title && !track.info?.title?.toLowerCase().includes(predicate.title.toLowerCase())) {
|
|
3849
|
+
return false;
|
|
3850
|
+
}
|
|
3851
|
+
if (predicate.author && !track.info?.author?.toLowerCase().includes(predicate.author.toLowerCase())) {
|
|
3852
|
+
return false;
|
|
3853
|
+
}
|
|
3854
|
+
if (predicate.duration !== void 0) {
|
|
3855
|
+
const duration = track.info?.duration || 0;
|
|
3856
|
+
if (typeof predicate.duration === "number") {
|
|
3857
|
+
if (duration !== predicate.duration) return false;
|
|
3858
|
+
} else {
|
|
3859
|
+
if (predicate.duration.min !== void 0 && duration < predicate.duration.min) return false;
|
|
3860
|
+
if (predicate.duration.max !== void 0 && duration > predicate.duration.max) return false;
|
|
3861
|
+
}
|
|
3862
|
+
}
|
|
3863
|
+
if (predicate.uri && track.info?.uri !== predicate.uri) {
|
|
3864
|
+
return false;
|
|
3865
|
+
}
|
|
3866
|
+
if (predicate.identifier && track.info?.identifier !== predicate.identifier) {
|
|
3867
|
+
return false;
|
|
3868
|
+
}
|
|
3869
|
+
if (predicate.sourceName && track.info?.sourceName?.toLowerCase() !== predicate.sourceName.toLowerCase()) {
|
|
3870
|
+
return false;
|
|
3871
|
+
}
|
|
3872
|
+
if (predicate.isStream !== void 0 && track.info?.isStream !== predicate.isStream) {
|
|
3873
|
+
return false;
|
|
3874
|
+
}
|
|
3875
|
+
if (predicate.isSeekable !== void 0 && track.info?.isSeekable !== predicate.isSeekable) {
|
|
3876
|
+
return false;
|
|
3877
|
+
}
|
|
3878
|
+
return true;
|
|
3879
|
+
});
|
|
3880
|
+
},
|
|
3881
|
+
/**
|
|
3882
|
+
* Find a single track in the queue matching specific criteria.
|
|
3883
|
+
* **This method DOES NOT MUTATE the queue** - it searches without modifying the original queue.
|
|
3884
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
3885
|
+
* @returns First matching track with its index, or null if not found
|
|
3886
|
+
*
|
|
3887
|
+
* @example
|
|
3888
|
+
* ```ts
|
|
3889
|
+
* // Find first track by author
|
|
3890
|
+
* const track = player.queue.utils.findTrack({ author: "Artist Name" });
|
|
3891
|
+
* if (track) {
|
|
3892
|
+
* console.log(`Found at index ${track.index}: ${track.track.info.title}`);
|
|
3893
|
+
* }
|
|
3894
|
+
*
|
|
3895
|
+
* // Find with custom predicate
|
|
3896
|
+
* const liveStream = player.queue.utils.findTrack(track => track.info.isStream);
|
|
3897
|
+
* ```
|
|
3898
|
+
*/
|
|
3899
|
+
findTrack: (predicate) => {
|
|
3900
|
+
const results = this.utils.filterTracks(predicate);
|
|
3901
|
+
return results.length > 0 ? results[0] : null;
|
|
3820
3902
|
}
|
|
3821
3903
|
};
|
|
3822
3904
|
/**
|
|
@@ -3998,6 +4080,149 @@ var Queue = class {
|
|
|
3998
4080
|
if (removed) await this.utils.save();
|
|
3999
4081
|
return removed ?? null;
|
|
4000
4082
|
}
|
|
4083
|
+
/**
|
|
4084
|
+
* Find tracks in the queue matching specific criteria.
|
|
4085
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new array without modifying the original queue.
|
|
4086
|
+
* @deprecated Use `player.queue.utils.filterTracks()` instead.
|
|
4087
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
4088
|
+
* @returns Array of matching tracks with their indexes
|
|
4089
|
+
*
|
|
4090
|
+
* @example
|
|
4091
|
+
* ```ts
|
|
4092
|
+
* // Use the new method instead:
|
|
4093
|
+
* const artistTracks = player.queue.utils.filterTracks({ author: "Artist Name" });
|
|
4094
|
+
* ```
|
|
4095
|
+
*/
|
|
4096
|
+
filter(predicate) {
|
|
4097
|
+
return this.utils.filterTracks(predicate);
|
|
4098
|
+
}
|
|
4099
|
+
/**
|
|
4100
|
+
* Find a single track in the queue matching specific criteria.
|
|
4101
|
+
* **This method DOES NOT MUTATE the queue** - it searches without modifying the original queue.
|
|
4102
|
+
* @deprecated Use `player.queue.utils.findTrack()` instead.
|
|
4103
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
4104
|
+
* @returns First matching track with its index, or null if not found
|
|
4105
|
+
*
|
|
4106
|
+
* @example
|
|
4107
|
+
* ```ts
|
|
4108
|
+
* // Use the new method instead:
|
|
4109
|
+
* const track = player.queue.utils.findTrack({ author: "Artist Name" });
|
|
4110
|
+
* ```
|
|
4111
|
+
*/
|
|
4112
|
+
find(predicate) {
|
|
4113
|
+
return this.utils.findTrack(predicate);
|
|
4114
|
+
}
|
|
4115
|
+
/**
|
|
4116
|
+
* Sort the queue tracks by a specific property.
|
|
4117
|
+
* **⚠️ This method MUTATES the queue** - it modifies the original queue in place.
|
|
4118
|
+
* @param sortBy Property to sort by or custom comparator function
|
|
4119
|
+
* @param order Sort order: 'asc' or 'desc' (default: 'asc')
|
|
4120
|
+
* @returns The queue instance for chaining
|
|
4121
|
+
*
|
|
4122
|
+
* @example
|
|
4123
|
+
* ```ts
|
|
4124
|
+
* // Sort by duration (shortest first)
|
|
4125
|
+
* await player.queue.sortBy("duration", "asc");
|
|
4126
|
+
*
|
|
4127
|
+
* // Sort by title alphabetically (Z-A)
|
|
4128
|
+
* await player.queue.sortBy("title", "desc");
|
|
4129
|
+
*
|
|
4130
|
+
* // Custom sorting
|
|
4131
|
+
* await player.queue.sortBy((a, b) => {
|
|
4132
|
+
* return a.info.title.localeCompare(b.info.title);
|
|
4133
|
+
* });
|
|
4134
|
+
* ```
|
|
4135
|
+
*/
|
|
4136
|
+
async sortBy(sortBy, order = "asc") {
|
|
4137
|
+
const oldStored = typeof this.queueChanges?.tracksAdd === "function" ? this.utils.toJSON() : null;
|
|
4138
|
+
if (typeof sortBy === "function") {
|
|
4139
|
+
this.tracks.sort(sortBy);
|
|
4140
|
+
} else {
|
|
4141
|
+
this.tracks.sort((a, b) => {
|
|
4142
|
+
let comparison = 0;
|
|
4143
|
+
switch (sortBy) {
|
|
4144
|
+
case "duration":
|
|
4145
|
+
comparison = (a.info?.duration || 0) - (b.info?.duration || 0);
|
|
4146
|
+
break;
|
|
4147
|
+
case "title":
|
|
4148
|
+
comparison = (a.info?.title || "").localeCompare(b.info?.title || "");
|
|
4149
|
+
break;
|
|
4150
|
+
case "author":
|
|
4151
|
+
comparison = (a.info?.author || "").localeCompare(b.info?.author || "");
|
|
4152
|
+
break;
|
|
4153
|
+
default:
|
|
4154
|
+
return 0;
|
|
4155
|
+
}
|
|
4156
|
+
return order === "desc" ? -comparison : comparison;
|
|
4157
|
+
});
|
|
4158
|
+
}
|
|
4159
|
+
await this.utils.save();
|
|
4160
|
+
return this;
|
|
4161
|
+
}
|
|
4162
|
+
/**
|
|
4163
|
+
* Get a sorted copy of the queue tracks without modifying the original queue.
|
|
4164
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new sorted array, similar to `Array.toSorted()`.
|
|
4165
|
+
* @param sortBy Property to sort by or custom comparator function
|
|
4166
|
+
* @param order Sort order: 'asc' or 'desc' (default: 'asc')
|
|
4167
|
+
* @returns A new sorted array of tracks (does not modify the queue)
|
|
4168
|
+
*
|
|
4169
|
+
* @example
|
|
4170
|
+
* ```ts
|
|
4171
|
+
* // Get sorted copy by duration (shortest first)
|
|
4172
|
+
* const sortedTracks = player.queue.toSortedBy("duration", "asc");
|
|
4173
|
+
* // Original queue remains unchanged
|
|
4174
|
+
*
|
|
4175
|
+
* // Get sorted copy by title alphabetically (Z-A)
|
|
4176
|
+
* const sortedByTitle = player.queue.toSortedBy("title", "desc");
|
|
4177
|
+
*
|
|
4178
|
+
* // Custom sorting
|
|
4179
|
+
* const customSorted = player.queue.toSortedBy((a, b) => {
|
|
4180
|
+
* return a.info.title.localeCompare(b.info.title);
|
|
4181
|
+
* });
|
|
4182
|
+
* ```
|
|
4183
|
+
*/
|
|
4184
|
+
toSortedBy(sortBy, order = "asc") {
|
|
4185
|
+
const tracksCopy = [...this.tracks];
|
|
4186
|
+
if (typeof sortBy === "function") {
|
|
4187
|
+
return tracksCopy.sort(sortBy);
|
|
4188
|
+
}
|
|
4189
|
+
return tracksCopy.sort((a, b) => {
|
|
4190
|
+
let comparison = 0;
|
|
4191
|
+
switch (sortBy) {
|
|
4192
|
+
case "duration":
|
|
4193
|
+
comparison = (a.info?.duration || 0) - (b.info?.duration || 0);
|
|
4194
|
+
break;
|
|
4195
|
+
case "title":
|
|
4196
|
+
comparison = (a.info?.title || "").localeCompare(b.info?.title || "");
|
|
4197
|
+
break;
|
|
4198
|
+
case "author":
|
|
4199
|
+
comparison = (a.info?.author || "").localeCompare(b.info?.author || "");
|
|
4200
|
+
break;
|
|
4201
|
+
default:
|
|
4202
|
+
return 0;
|
|
4203
|
+
}
|
|
4204
|
+
return order === "desc" ? -comparison : comparison;
|
|
4205
|
+
});
|
|
4206
|
+
}
|
|
4207
|
+
/**
|
|
4208
|
+
* Get a range of tracks from the queue.
|
|
4209
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new array slice, similar to `Array.slice()`.
|
|
4210
|
+
* @param start Start index (inclusive)
|
|
4211
|
+
* @param end End index (exclusive)
|
|
4212
|
+
* @returns Array of tracks in the specified range
|
|
4213
|
+
*
|
|
4214
|
+
* @example
|
|
4215
|
+
* ```ts
|
|
4216
|
+
* // Get tracks 5-15
|
|
4217
|
+
* const tracks = player.queue.getTracks(5, 15);
|
|
4218
|
+
*
|
|
4219
|
+
* // Get first 10 tracks
|
|
4220
|
+
* const firstTen = player.queue.getTracks(0, 10);
|
|
4221
|
+
* ```
|
|
4222
|
+
*/
|
|
4223
|
+
getTracks(start, end) {
|
|
4224
|
+
return this.tracks.slice(start, end);
|
|
4225
|
+
}
|
|
4001
4226
|
};
|
|
4002
4227
|
|
|
4003
4228
|
// src/structures/Player.ts
|
|
@@ -5262,6 +5487,7 @@ var LavalinkManager = class extends import_events2.EventEmitter {
|
|
|
5262
5487
|
});
|
|
5263
5488
|
if (!autoReconnectOnlyWithTracks || autoReconnectOnlyWithTracks && (player.queue.current || player.queue.tracks.length)) {
|
|
5264
5489
|
await player.connect();
|
|
5490
|
+
this.emit("playerReconnect", player, player.voiceChannelId);
|
|
5265
5491
|
}
|
|
5266
5492
|
if (player.queue.current) {
|
|
5267
5493
|
return void await player.play({ position: previousPosition, paused: previousPaused, clientTrack: player.queue.current });
|
package/dist/index.mjs
CHANGED
|
@@ -1372,7 +1372,6 @@ var LavalinkNode = class {
|
|
|
1372
1372
|
functionLayer: "LavalinkNode > nodeEvent > stats > heartBeat()"
|
|
1373
1373
|
});
|
|
1374
1374
|
this.resetAckTimeouts(false, true);
|
|
1375
|
-
if (this.pingTimeout) clearTimeout(this.pingTimeout);
|
|
1376
1375
|
this.pingTimeout = setTimeout(() => {
|
|
1377
1376
|
this.pingTimeout = null;
|
|
1378
1377
|
if (!this.socket) {
|
|
@@ -1897,9 +1896,10 @@ var LavalinkNode = class {
|
|
|
1897
1896
|
}, this.options.retryDelay || 1e3);
|
|
1898
1897
|
}
|
|
1899
1898
|
get reconnectionAttemptCount() {
|
|
1899
|
+
if (!Array.isArray(this.reconnectAttempts)) this.reconnectAttempts = [];
|
|
1900
1900
|
const maxAllowedTimestan = this.options.retryTimespan || -1;
|
|
1901
1901
|
if (maxAllowedTimestan <= 0) return this.reconnectAttempts.length;
|
|
1902
|
-
return this.reconnectAttempts
|
|
1902
|
+
return this.reconnectAttempts?.filter((timestamp) => Date.now() - timestamp <= maxAllowedTimestan).length || 0;
|
|
1903
1903
|
}
|
|
1904
1904
|
/**
|
|
1905
1905
|
* Private Utility function to execute the reconnection
|
|
@@ -1912,6 +1912,7 @@ var LavalinkNode = class {
|
|
|
1912
1912
|
this.destroy("NodeReconnectFail" /* NodeReconnectFail */);
|
|
1913
1913
|
return;
|
|
1914
1914
|
}
|
|
1915
|
+
if (!Array.isArray(this.reconnectAttempts)) this.reconnectAttempts = [];
|
|
1915
1916
|
this.reconnectAttempts.push(Date.now());
|
|
1916
1917
|
this.reconnectionState = "RECONNECTING" /* RECONNECTING */;
|
|
1917
1918
|
this.NodeManager.emit("reconnecting", this);
|
|
@@ -3756,6 +3757,87 @@ var Queue = class {
|
|
|
3756
3757
|
*/
|
|
3757
3758
|
totalDuration: () => {
|
|
3758
3759
|
return this.tracks.reduce((acc, cur) => acc + (cur.info.duration || 0), this.current?.info.duration || 0);
|
|
3760
|
+
},
|
|
3761
|
+
/**
|
|
3762
|
+
* Find tracks in the queue matching specific criteria.
|
|
3763
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new array without modifying the original queue.
|
|
3764
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
3765
|
+
* @returns Array of matching tracks with their indexes
|
|
3766
|
+
*
|
|
3767
|
+
* @example
|
|
3768
|
+
* ```ts
|
|
3769
|
+
* // Find by author
|
|
3770
|
+
* const artistTracks = player.queue.utils.filterTracks({ author: "Artist Name" });
|
|
3771
|
+
*
|
|
3772
|
+
* // Find by duration range (5-10 minutes)
|
|
3773
|
+
* const longTracks = player.queue.utils.filterTracks({ duration: { min: 300000, max: 600000 } });
|
|
3774
|
+
*
|
|
3775
|
+
* // Find by title (partial match)
|
|
3776
|
+
* const titleMatches = player.queue.utils.filterTracks({ title: "Never Gonna" });
|
|
3777
|
+
*
|
|
3778
|
+
* // Custom predicate
|
|
3779
|
+
* const customFilter = player.queue.utils.filterTracks(track => track.info.isStream);
|
|
3780
|
+
* ```
|
|
3781
|
+
*/
|
|
3782
|
+
filterTracks: (predicate) => {
|
|
3783
|
+
if (typeof predicate === "function") {
|
|
3784
|
+
return this.tracks.map((track, index) => ({ track, index })).filter(({ track, index }) => predicate(track, index));
|
|
3785
|
+
}
|
|
3786
|
+
return this.tracks.map((track, index) => ({ track, index })).filter(({ track }) => {
|
|
3787
|
+
if (predicate.title && !track.info?.title?.toLowerCase().includes(predicate.title.toLowerCase())) {
|
|
3788
|
+
return false;
|
|
3789
|
+
}
|
|
3790
|
+
if (predicate.author && !track.info?.author?.toLowerCase().includes(predicate.author.toLowerCase())) {
|
|
3791
|
+
return false;
|
|
3792
|
+
}
|
|
3793
|
+
if (predicate.duration !== void 0) {
|
|
3794
|
+
const duration = track.info?.duration || 0;
|
|
3795
|
+
if (typeof predicate.duration === "number") {
|
|
3796
|
+
if (duration !== predicate.duration) return false;
|
|
3797
|
+
} else {
|
|
3798
|
+
if (predicate.duration.min !== void 0 && duration < predicate.duration.min) return false;
|
|
3799
|
+
if (predicate.duration.max !== void 0 && duration > predicate.duration.max) return false;
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
if (predicate.uri && track.info?.uri !== predicate.uri) {
|
|
3803
|
+
return false;
|
|
3804
|
+
}
|
|
3805
|
+
if (predicate.identifier && track.info?.identifier !== predicate.identifier) {
|
|
3806
|
+
return false;
|
|
3807
|
+
}
|
|
3808
|
+
if (predicate.sourceName && track.info?.sourceName?.toLowerCase() !== predicate.sourceName.toLowerCase()) {
|
|
3809
|
+
return false;
|
|
3810
|
+
}
|
|
3811
|
+
if (predicate.isStream !== void 0 && track.info?.isStream !== predicate.isStream) {
|
|
3812
|
+
return false;
|
|
3813
|
+
}
|
|
3814
|
+
if (predicate.isSeekable !== void 0 && track.info?.isSeekable !== predicate.isSeekable) {
|
|
3815
|
+
return false;
|
|
3816
|
+
}
|
|
3817
|
+
return true;
|
|
3818
|
+
});
|
|
3819
|
+
},
|
|
3820
|
+
/**
|
|
3821
|
+
* Find a single track in the queue matching specific criteria.
|
|
3822
|
+
* **This method DOES NOT MUTATE the queue** - it searches without modifying the original queue.
|
|
3823
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
3824
|
+
* @returns First matching track with its index, or null if not found
|
|
3825
|
+
*
|
|
3826
|
+
* @example
|
|
3827
|
+
* ```ts
|
|
3828
|
+
* // Find first track by author
|
|
3829
|
+
* const track = player.queue.utils.findTrack({ author: "Artist Name" });
|
|
3830
|
+
* if (track) {
|
|
3831
|
+
* console.log(`Found at index ${track.index}: ${track.track.info.title}`);
|
|
3832
|
+
* }
|
|
3833
|
+
*
|
|
3834
|
+
* // Find with custom predicate
|
|
3835
|
+
* const liveStream = player.queue.utils.findTrack(track => track.info.isStream);
|
|
3836
|
+
* ```
|
|
3837
|
+
*/
|
|
3838
|
+
findTrack: (predicate) => {
|
|
3839
|
+
const results = this.utils.filterTracks(predicate);
|
|
3840
|
+
return results.length > 0 ? results[0] : null;
|
|
3759
3841
|
}
|
|
3760
3842
|
};
|
|
3761
3843
|
/**
|
|
@@ -3937,6 +4019,149 @@ var Queue = class {
|
|
|
3937
4019
|
if (removed) await this.utils.save();
|
|
3938
4020
|
return removed ?? null;
|
|
3939
4021
|
}
|
|
4022
|
+
/**
|
|
4023
|
+
* Find tracks in the queue matching specific criteria.
|
|
4024
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new array without modifying the original queue.
|
|
4025
|
+
* @deprecated Use `player.queue.utils.filterTracks()` instead.
|
|
4026
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
4027
|
+
* @returns Array of matching tracks with their indexes
|
|
4028
|
+
*
|
|
4029
|
+
* @example
|
|
4030
|
+
* ```ts
|
|
4031
|
+
* // Use the new method instead:
|
|
4032
|
+
* const artistTracks = player.queue.utils.filterTracks({ author: "Artist Name" });
|
|
4033
|
+
* ```
|
|
4034
|
+
*/
|
|
4035
|
+
filter(predicate) {
|
|
4036
|
+
return this.utils.filterTracks(predicate);
|
|
4037
|
+
}
|
|
4038
|
+
/**
|
|
4039
|
+
* Find a single track in the queue matching specific criteria.
|
|
4040
|
+
* **This method DOES NOT MUTATE the queue** - it searches without modifying the original queue.
|
|
4041
|
+
* @deprecated Use `player.queue.utils.findTrack()` instead.
|
|
4042
|
+
* @param predicate Function to test each track, or an object with criteria to match
|
|
4043
|
+
* @returns First matching track with its index, or null if not found
|
|
4044
|
+
*
|
|
4045
|
+
* @example
|
|
4046
|
+
* ```ts
|
|
4047
|
+
* // Use the new method instead:
|
|
4048
|
+
* const track = player.queue.utils.findTrack({ author: "Artist Name" });
|
|
4049
|
+
* ```
|
|
4050
|
+
*/
|
|
4051
|
+
find(predicate) {
|
|
4052
|
+
return this.utils.findTrack(predicate);
|
|
4053
|
+
}
|
|
4054
|
+
/**
|
|
4055
|
+
* Sort the queue tracks by a specific property.
|
|
4056
|
+
* **⚠️ This method MUTATES the queue** - it modifies the original queue in place.
|
|
4057
|
+
* @param sortBy Property to sort by or custom comparator function
|
|
4058
|
+
* @param order Sort order: 'asc' or 'desc' (default: 'asc')
|
|
4059
|
+
* @returns The queue instance for chaining
|
|
4060
|
+
*
|
|
4061
|
+
* @example
|
|
4062
|
+
* ```ts
|
|
4063
|
+
* // Sort by duration (shortest first)
|
|
4064
|
+
* await player.queue.sortBy("duration", "asc");
|
|
4065
|
+
*
|
|
4066
|
+
* // Sort by title alphabetically (Z-A)
|
|
4067
|
+
* await player.queue.sortBy("title", "desc");
|
|
4068
|
+
*
|
|
4069
|
+
* // Custom sorting
|
|
4070
|
+
* await player.queue.sortBy((a, b) => {
|
|
4071
|
+
* return a.info.title.localeCompare(b.info.title);
|
|
4072
|
+
* });
|
|
4073
|
+
* ```
|
|
4074
|
+
*/
|
|
4075
|
+
async sortBy(sortBy, order = "asc") {
|
|
4076
|
+
const oldStored = typeof this.queueChanges?.tracksAdd === "function" ? this.utils.toJSON() : null;
|
|
4077
|
+
if (typeof sortBy === "function") {
|
|
4078
|
+
this.tracks.sort(sortBy);
|
|
4079
|
+
} else {
|
|
4080
|
+
this.tracks.sort((a, b) => {
|
|
4081
|
+
let comparison = 0;
|
|
4082
|
+
switch (sortBy) {
|
|
4083
|
+
case "duration":
|
|
4084
|
+
comparison = (a.info?.duration || 0) - (b.info?.duration || 0);
|
|
4085
|
+
break;
|
|
4086
|
+
case "title":
|
|
4087
|
+
comparison = (a.info?.title || "").localeCompare(b.info?.title || "");
|
|
4088
|
+
break;
|
|
4089
|
+
case "author":
|
|
4090
|
+
comparison = (a.info?.author || "").localeCompare(b.info?.author || "");
|
|
4091
|
+
break;
|
|
4092
|
+
default:
|
|
4093
|
+
return 0;
|
|
4094
|
+
}
|
|
4095
|
+
return order === "desc" ? -comparison : comparison;
|
|
4096
|
+
});
|
|
4097
|
+
}
|
|
4098
|
+
await this.utils.save();
|
|
4099
|
+
return this;
|
|
4100
|
+
}
|
|
4101
|
+
/**
|
|
4102
|
+
* Get a sorted copy of the queue tracks without modifying the original queue.
|
|
4103
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new sorted array, similar to `Array.toSorted()`.
|
|
4104
|
+
* @param sortBy Property to sort by or custom comparator function
|
|
4105
|
+
* @param order Sort order: 'asc' or 'desc' (default: 'asc')
|
|
4106
|
+
* @returns A new sorted array of tracks (does not modify the queue)
|
|
4107
|
+
*
|
|
4108
|
+
* @example
|
|
4109
|
+
* ```ts
|
|
4110
|
+
* // Get sorted copy by duration (shortest first)
|
|
4111
|
+
* const sortedTracks = player.queue.toSortedBy("duration", "asc");
|
|
4112
|
+
* // Original queue remains unchanged
|
|
4113
|
+
*
|
|
4114
|
+
* // Get sorted copy by title alphabetically (Z-A)
|
|
4115
|
+
* const sortedByTitle = player.queue.toSortedBy("title", "desc");
|
|
4116
|
+
*
|
|
4117
|
+
* // Custom sorting
|
|
4118
|
+
* const customSorted = player.queue.toSortedBy((a, b) => {
|
|
4119
|
+
* return a.info.title.localeCompare(b.info.title);
|
|
4120
|
+
* });
|
|
4121
|
+
* ```
|
|
4122
|
+
*/
|
|
4123
|
+
toSortedBy(sortBy, order = "asc") {
|
|
4124
|
+
const tracksCopy = [...this.tracks];
|
|
4125
|
+
if (typeof sortBy === "function") {
|
|
4126
|
+
return tracksCopy.sort(sortBy);
|
|
4127
|
+
}
|
|
4128
|
+
return tracksCopy.sort((a, b) => {
|
|
4129
|
+
let comparison = 0;
|
|
4130
|
+
switch (sortBy) {
|
|
4131
|
+
case "duration":
|
|
4132
|
+
comparison = (a.info?.duration || 0) - (b.info?.duration || 0);
|
|
4133
|
+
break;
|
|
4134
|
+
case "title":
|
|
4135
|
+
comparison = (a.info?.title || "").localeCompare(b.info?.title || "");
|
|
4136
|
+
break;
|
|
4137
|
+
case "author":
|
|
4138
|
+
comparison = (a.info?.author || "").localeCompare(b.info?.author || "");
|
|
4139
|
+
break;
|
|
4140
|
+
default:
|
|
4141
|
+
return 0;
|
|
4142
|
+
}
|
|
4143
|
+
return order === "desc" ? -comparison : comparison;
|
|
4144
|
+
});
|
|
4145
|
+
}
|
|
4146
|
+
/**
|
|
4147
|
+
* Get a range of tracks from the queue.
|
|
4148
|
+
* **This method DOES NOT MUTATE the queue** - it returns a new array slice, similar to `Array.slice()`.
|
|
4149
|
+
* @param start Start index (inclusive)
|
|
4150
|
+
* @param end End index (exclusive)
|
|
4151
|
+
* @returns Array of tracks in the specified range
|
|
4152
|
+
*
|
|
4153
|
+
* @example
|
|
4154
|
+
* ```ts
|
|
4155
|
+
* // Get tracks 5-15
|
|
4156
|
+
* const tracks = player.queue.getTracks(5, 15);
|
|
4157
|
+
*
|
|
4158
|
+
* // Get first 10 tracks
|
|
4159
|
+
* const firstTen = player.queue.getTracks(0, 10);
|
|
4160
|
+
* ```
|
|
4161
|
+
*/
|
|
4162
|
+
getTracks(start, end) {
|
|
4163
|
+
return this.tracks.slice(start, end);
|
|
4164
|
+
}
|
|
3940
4165
|
};
|
|
3941
4166
|
|
|
3942
4167
|
// src/structures/Player.ts
|
|
@@ -5201,6 +5426,7 @@ var LavalinkManager = class extends EventEmitter2 {
|
|
|
5201
5426
|
});
|
|
5202
5427
|
if (!autoReconnectOnlyWithTracks || autoReconnectOnlyWithTracks && (player.queue.current || player.queue.tracks.length)) {
|
|
5203
5428
|
await player.connect();
|
|
5429
|
+
this.emit("playerReconnect", player, player.voiceChannelId);
|
|
5204
5430
|
}
|
|
5205
5431
|
if (player.queue.current) {
|
|
5206
5432
|
return void await player.play({ position: previousPosition, paused: previousPaused, clientTrack: player.queue.current });
|
package/package.json
CHANGED