lavalink-client 2.9.0 → 2.9.2
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 +2 -1
- package/dist/index.d.mts +109 -4
- package/dist/index.d.ts +109 -4
- package/dist/index.js +151 -35
- package/dist/index.mjs +151 -35
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
|
|
45
45
|
## 📦 Installation
|
|
46
46
|
|
|
47
|
-
**Latest Stable Version: `v2.
|
|
47
|
+
**Latest Stable Version: `v2.9.x`**
|
|
48
48
|
|
|
49
49
|
<details>
|
|
50
50
|
<summary><strong>👉 via NPM</strong></summary>
|
|
@@ -359,6 +359,7 @@ This client powers various Discord bots:
|
|
|
359
359
|
- [All Time Bot](https://top.gg/bot/1163027457671180418) (@PeterGamez)
|
|
360
360
|
- [BeatDock](https://github.com/lazaroagomez/BeatDock) (@lazaroagomez)
|
|
361
361
|
- [Nazha](https://top.gg/bot/1124681788070055967) (@Nazha-Team)
|
|
362
|
+
- [Arii Music](https://arimusic.me/) (@friston_ae)
|
|
362
363
|
|
|
363
364
|
---
|
|
364
365
|
|
package/dist/index.d.mts
CHANGED
|
@@ -417,7 +417,19 @@ declare function parseLavalinkConnUrl(connectionUrl: string): {
|
|
|
417
417
|
declare class ManagerUtils {
|
|
418
418
|
LavalinkManager: LavalinkManager | undefined;
|
|
419
419
|
constructor(LavalinkManager?: LavalinkManager);
|
|
420
|
+
/**
|
|
421
|
+
* Builds a pluginInfo object based on the provided data, extracting relevant information from the data and clientData parameters. This function is used to construct the pluginInfo property for tracks, allowing for consistent handling of plugin-related information across different track sources and formats.
|
|
422
|
+
* @param data
|
|
423
|
+
* @param clientData
|
|
424
|
+
* @returns
|
|
425
|
+
*/
|
|
420
426
|
buildPluginInfo(data: any, clientData?: any): any;
|
|
427
|
+
/**
|
|
428
|
+
* Builds a Track object from the provided data and requester information. It validates the presence of required properties in the data, transforms the requester using a custom transformer function if provided, and constructs a Track object with the appropriate properties and plugin information. The function also includes error handling to ensure that the input data is valid and provides debug information if track building fails.
|
|
429
|
+
* @param data
|
|
430
|
+
* @param requester
|
|
431
|
+
* @returns
|
|
432
|
+
*/
|
|
421
433
|
buildTrack(data: LavalinkTrack | Track, requester: unknown): Track;
|
|
422
434
|
/**
|
|
423
435
|
* Builds a UnresolvedTrack to be resolved before being played .
|
|
@@ -430,6 +442,11 @@ declare class ManagerUtils {
|
|
|
430
442
|
* @param data
|
|
431
443
|
*/
|
|
432
444
|
isNode(data: LavalinkNode): boolean;
|
|
445
|
+
/**
|
|
446
|
+
* Gets the transformed requester based on the LavalinkManager options. If a custom requester transformer function is provided in the player options, it applies that function to the requester; otherwise, it returns the requester as is. The function also includes error handling to catch any exceptions that may occur during the transformation process and emits a debug event if the transformation fails.
|
|
447
|
+
* @param requester
|
|
448
|
+
* @returns
|
|
449
|
+
*/
|
|
433
450
|
getTransformedRequester(requester: unknown): unknown;
|
|
434
451
|
/**
|
|
435
452
|
* Validate if a data is equal to node options
|
|
@@ -470,18 +487,73 @@ declare class ManagerUtils {
|
|
|
470
487
|
* @param track
|
|
471
488
|
*/
|
|
472
489
|
isUnresolvedTrackQuery(data: UnresolvedQuery): boolean;
|
|
490
|
+
/**
|
|
491
|
+
* Gets the closest track by resolving the provided UnresolvedTrack using the getClosestTrack function. It includes error handling to catch any exceptions that may occur during the resolution process and emits a debug event if the resolution fails. The function returns a Promise that resolves to a Track object if successful, or undefined if no closest track is found.
|
|
492
|
+
* @param data
|
|
493
|
+
* @param player
|
|
494
|
+
* @returns
|
|
495
|
+
*/
|
|
473
496
|
getClosestTrack(data: UnresolvedTrack, player: Player): Promise<Track | undefined>;
|
|
474
|
-
|
|
497
|
+
/**
|
|
498
|
+
* Validates the query string against various criteria, including checking for empty strings, length limits for specific sources, blacklisted links or words, and ensuring that the Lavalink node has the necessary source managers enabled for the provided query. The function also includes debug event emissions to assist with troubleshooting and understanding the validation process.
|
|
499
|
+
* @param node
|
|
500
|
+
* @param queryString
|
|
501
|
+
* @param sourceString
|
|
502
|
+
* @returns
|
|
503
|
+
*/
|
|
504
|
+
validateQueryString(node: LavalinkNode, queryString: string, sourceString?: SearchPlatform): void;
|
|
505
|
+
/**
|
|
506
|
+
* Finds the source of a query string by checking if it starts with a valid source prefix defined in the DefaultSources object. If a valid source prefix is found, it returns the corresponding SearchPlatform; otherwise, it returns null. This function is useful for determining the intended search platform for a given query string, allowing for more accurate search results when the user specifies a source (e.g., "ytsearch:Never Gonna Give You Up" would indicate that the search should be performed on YouTube).
|
|
507
|
+
* @param queryString
|
|
508
|
+
* @returns
|
|
509
|
+
*/
|
|
510
|
+
findSourceOfQuery(queryString: string): SearchPlatform;
|
|
511
|
+
/**
|
|
512
|
+
* Extracts the source from the query if it starts with a valid source prefix (e.g., "ytsearch:") and updates the searchQuery object accordingly.
|
|
513
|
+
* @param searchQuery
|
|
514
|
+
* @returns The updated searchQuery object with the extracted source and modified query string.
|
|
515
|
+
*/
|
|
516
|
+
extractSourceOfQuery<T extends {
|
|
517
|
+
query: string;
|
|
518
|
+
source?: string;
|
|
519
|
+
}>(searchQuery: T): T;
|
|
520
|
+
/**
|
|
521
|
+
* Converts a string to lowercase if the input is a string, otherwise returns the input as is. This is useful for ensuring that search platform identifiers are case-insensitive while allowing other types of input to pass through unchanged.
|
|
522
|
+
* @param input
|
|
523
|
+
* @returns
|
|
524
|
+
*/
|
|
525
|
+
typedLowerCase<T extends unknown>(input: T): T;
|
|
526
|
+
/**
|
|
527
|
+
* Transforms a search query by determining the appropriate search platform based on the query string and the default search platform specified in the LavalinkManager options. It checks if the query string starts with a valid source prefix and extracts it if present. The function returns an object containing the modified query string, any extra URL parameters, and the determined search platform to be used for the search operation.
|
|
528
|
+
* @param query
|
|
529
|
+
* @returns
|
|
530
|
+
*/
|
|
475
531
|
transformQuery(query: SearchQuery): {
|
|
476
532
|
query: string;
|
|
477
|
-
extraQueryUrlParams:
|
|
478
|
-
source:
|
|
533
|
+
extraQueryUrlParams: any;
|
|
534
|
+
source: SearchPlatform;
|
|
479
535
|
};
|
|
536
|
+
/**
|
|
537
|
+
* Transforms a LavaSearchQuery by determining the appropriate search platform based on the query string and the default search platform specified in the LavalinkManager options. It checks if the query string starts with a valid source prefix and extracts it if present. The function returns an object containing the modified query string, any extra URL parameters, the determined search platform to be used for the search operation, and the types of search (track, playlist, artist, album, text) to be performed.
|
|
538
|
+
* @param query
|
|
539
|
+
* @returns
|
|
540
|
+
*/
|
|
480
541
|
transformLavaSearchQuery(query: LavaSearchQuery): {
|
|
542
|
+
query: never;
|
|
543
|
+
types: any[];
|
|
544
|
+
extraQueryUrlParams: any;
|
|
545
|
+
source: SearchPlatform;
|
|
546
|
+
} | {
|
|
481
547
|
query: string;
|
|
482
548
|
types: string[];
|
|
483
|
-
source:
|
|
549
|
+
source: "ytsearch" | "ytmsearch" | "scsearch" | "bcsearch" | "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "dzrec" | "ymsearch" | "ymrec" | "vksearch" | "vkrec" | "tdsearch" | "tdrec" | "qbsearch" | "qbisrc" | "qbrec" | "pdsearch" | "pdisrc" | "pdrec" | "ftts" | "speak" | "phsearch" | "pornhub" | "porn" | "tts" | "jssearch" | "jsrec" | "local" | "http" | "https" | "link" | "uri" | "youtube" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "musicyoutube" | "music youtube" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "musicapple" | "music apple" | "sp" | "spsuggestion" | "spotify" | "spotify.com" | "spotifycom" | "dz" | "deezer" | "yandex" | "yandex music" | "yandexmusic" | "vk" | "vk music" | "vkmusic" | "tidal" | "tidal music" | "qobuz" | "pandora" | "pd" | "pandora music" | "pandoramusic" | "flowerytts" | "flowery" | "flowery.tts" | "bandcamp" | "bc" | "js" | "jiosaavn" | "td";
|
|
484
550
|
};
|
|
551
|
+
/**
|
|
552
|
+
* Validates the provided source string against the capabilities of the Lavalink node. It checks if the source string is supported by the node's enabled source managers and plugins, throwing errors if any required sources or plugins are missing for the specified search platform. This ensures that search queries are only executed with compatible sources based on the node's configuration.
|
|
553
|
+
* @param node
|
|
554
|
+
* @param sourceString
|
|
555
|
+
* @returns
|
|
556
|
+
*/
|
|
485
557
|
validateSourceString(node: LavalinkNode, sourceString: SearchPlatform): void;
|
|
486
558
|
}
|
|
487
559
|
/**
|
|
@@ -2627,6 +2699,14 @@ declare class Player {
|
|
|
2627
2699
|
* @param options
|
|
2628
2700
|
*/
|
|
2629
2701
|
play(options?: Partial<PlayOptions>): any;
|
|
2702
|
+
/**
|
|
2703
|
+
* The old JSON of the player, used for the "playerClientUpdate" event, which is emitted on every update of the player via a function call, so that you can compare the old data with the new data and do something with it if you want to.
|
|
2704
|
+
*/
|
|
2705
|
+
oldJSON: PlayerJson;
|
|
2706
|
+
/**
|
|
2707
|
+
* Emits the "playerClientUpdate" event, which is emitted on every update of the player via a function call, so that you can compare the old data with the new data and do something with it if you want to.
|
|
2708
|
+
*/
|
|
2709
|
+
triggerPlayerClientUpdate(): void;
|
|
2630
2710
|
/**
|
|
2631
2711
|
* Set the Volume for the Player
|
|
2632
2712
|
* @param volume The Volume in percent
|
|
@@ -3721,6 +3801,20 @@ interface LavalinkManagerEvents<CustomPlayerT extends Player = Player> {
|
|
|
3721
3801
|
* @event Manager#playerUpdate
|
|
3722
3802
|
*/
|
|
3723
3803
|
playerUpdate: (oldPlayerJson: PlayerJson, newPlayer: CustomPlayerT) => void;
|
|
3804
|
+
/**
|
|
3805
|
+
* Always emits when the player (on client side) got updated via a function-call.
|
|
3806
|
+
* This is useful for example, if you want to save the player data on every update, or similar.
|
|
3807
|
+
* @event Manager#playerClientUpdate
|
|
3808
|
+
*
|
|
3809
|
+
* Emits only when you call one of those functions:
|
|
3810
|
+
* player.pause()
|
|
3811
|
+
* player.resume()
|
|
3812
|
+
* player.seek()
|
|
3813
|
+
* player.setRepeatMode()
|
|
3814
|
+
* player.setVolume()
|
|
3815
|
+
* and on every call of the filterManager.
|
|
3816
|
+
*/
|
|
3817
|
+
playerClientUpdate: (oldPlayerJson: PlayerJson, newPlayer: CustomPlayerT) => void;
|
|
3724
3818
|
/**
|
|
3725
3819
|
* Emitted when the player's selfMuted or serverMuted state changed (true -> false | false -> true)
|
|
3726
3820
|
* @event Manager#playerMuteChange
|
|
@@ -3842,6 +3936,8 @@ interface ManagerPlayerOptions<CustomPlayerT extends Player = Player> {
|
|
|
3842
3936
|
clientBasedPositionUpdateInterval?: number;
|
|
3843
3937
|
/** What should be used as a searchPlatform, if no source was provided during the query */
|
|
3844
3938
|
defaultSearchPlatform?: SearchPlatform;
|
|
3939
|
+
/** Allow custom sources which lavalink-client does not support (yet) */
|
|
3940
|
+
allowCustomSources?: boolean;
|
|
3845
3941
|
/** Applies the volume via a filter, not via the lavalink volume transformer */
|
|
3846
3942
|
applyVolumeAsFilter?: boolean;
|
|
3847
3943
|
/** Transforms the saved data of a requested user */
|
|
@@ -3870,6 +3966,14 @@ interface ManagerPlayerOptions<CustomPlayerT extends Player = Player> {
|
|
|
3870
3966
|
destroyAfterMs?: number;
|
|
3871
3967
|
};
|
|
3872
3968
|
useUnresolvedData?: boolean;
|
|
3969
|
+
/**
|
|
3970
|
+
* If true (default), when changing nodes, `setSponsorBlock()` with default categories is called
|
|
3971
|
+
* even if the user never explicitly set categories. This is needed so the SponsorBlock plugin
|
|
3972
|
+
* registers its event listeners (ChapterStarted/ChapterLoaded) on the new node.
|
|
3973
|
+
* Set to false to disable this behavior if you don't use SponsorBlock events.
|
|
3974
|
+
* @default true
|
|
3975
|
+
*/
|
|
3976
|
+
enforceSponsorBlockRequestForEventEnablement?: boolean;
|
|
3873
3977
|
}
|
|
3874
3978
|
type DeepRequired<T> = {
|
|
3875
3979
|
[K in keyof T]-?: NonNullable<T[K]> extends object ? DeepRequired<NonNullable<T[K]>> : NonNullable<T[K]>;
|
|
@@ -4016,6 +4120,7 @@ declare class LavalinkManager<CustomPlayerT extends Player = Player> extends Eve
|
|
|
4016
4120
|
* applyVolumeAsFilter: false,
|
|
4017
4121
|
* clientBasedPositionUpdateInterval: 150,
|
|
4018
4122
|
* defaultSearchPlatform: "ytmsearch",
|
|
4123
|
+
* allowCustomSources: false,
|
|
4019
4124
|
* volumeDecrementer: 0.75,
|
|
4020
4125
|
* //requesterTransformer: YourRequesterTransformerFunction,
|
|
4021
4126
|
* onDisconnect: {
|
package/dist/index.d.ts
CHANGED
|
@@ -417,7 +417,19 @@ declare function parseLavalinkConnUrl(connectionUrl: string): {
|
|
|
417
417
|
declare class ManagerUtils {
|
|
418
418
|
LavalinkManager: LavalinkManager | undefined;
|
|
419
419
|
constructor(LavalinkManager?: LavalinkManager);
|
|
420
|
+
/**
|
|
421
|
+
* Builds a pluginInfo object based on the provided data, extracting relevant information from the data and clientData parameters. This function is used to construct the pluginInfo property for tracks, allowing for consistent handling of plugin-related information across different track sources and formats.
|
|
422
|
+
* @param data
|
|
423
|
+
* @param clientData
|
|
424
|
+
* @returns
|
|
425
|
+
*/
|
|
420
426
|
buildPluginInfo(data: any, clientData?: any): any;
|
|
427
|
+
/**
|
|
428
|
+
* Builds a Track object from the provided data and requester information. It validates the presence of required properties in the data, transforms the requester using a custom transformer function if provided, and constructs a Track object with the appropriate properties and plugin information. The function also includes error handling to ensure that the input data is valid and provides debug information if track building fails.
|
|
429
|
+
* @param data
|
|
430
|
+
* @param requester
|
|
431
|
+
* @returns
|
|
432
|
+
*/
|
|
421
433
|
buildTrack(data: LavalinkTrack | Track, requester: unknown): Track;
|
|
422
434
|
/**
|
|
423
435
|
* Builds a UnresolvedTrack to be resolved before being played .
|
|
@@ -430,6 +442,11 @@ declare class ManagerUtils {
|
|
|
430
442
|
* @param data
|
|
431
443
|
*/
|
|
432
444
|
isNode(data: LavalinkNode): boolean;
|
|
445
|
+
/**
|
|
446
|
+
* Gets the transformed requester based on the LavalinkManager options. If a custom requester transformer function is provided in the player options, it applies that function to the requester; otherwise, it returns the requester as is. The function also includes error handling to catch any exceptions that may occur during the transformation process and emits a debug event if the transformation fails.
|
|
447
|
+
* @param requester
|
|
448
|
+
* @returns
|
|
449
|
+
*/
|
|
433
450
|
getTransformedRequester(requester: unknown): unknown;
|
|
434
451
|
/**
|
|
435
452
|
* Validate if a data is equal to node options
|
|
@@ -470,18 +487,73 @@ declare class ManagerUtils {
|
|
|
470
487
|
* @param track
|
|
471
488
|
*/
|
|
472
489
|
isUnresolvedTrackQuery(data: UnresolvedQuery): boolean;
|
|
490
|
+
/**
|
|
491
|
+
* Gets the closest track by resolving the provided UnresolvedTrack using the getClosestTrack function. It includes error handling to catch any exceptions that may occur during the resolution process and emits a debug event if the resolution fails. The function returns a Promise that resolves to a Track object if successful, or undefined if no closest track is found.
|
|
492
|
+
* @param data
|
|
493
|
+
* @param player
|
|
494
|
+
* @returns
|
|
495
|
+
*/
|
|
473
496
|
getClosestTrack(data: UnresolvedTrack, player: Player): Promise<Track | undefined>;
|
|
474
|
-
|
|
497
|
+
/**
|
|
498
|
+
* Validates the query string against various criteria, including checking for empty strings, length limits for specific sources, blacklisted links or words, and ensuring that the Lavalink node has the necessary source managers enabled for the provided query. The function also includes debug event emissions to assist with troubleshooting and understanding the validation process.
|
|
499
|
+
* @param node
|
|
500
|
+
* @param queryString
|
|
501
|
+
* @param sourceString
|
|
502
|
+
* @returns
|
|
503
|
+
*/
|
|
504
|
+
validateQueryString(node: LavalinkNode, queryString: string, sourceString?: SearchPlatform): void;
|
|
505
|
+
/**
|
|
506
|
+
* Finds the source of a query string by checking if it starts with a valid source prefix defined in the DefaultSources object. If a valid source prefix is found, it returns the corresponding SearchPlatform; otherwise, it returns null. This function is useful for determining the intended search platform for a given query string, allowing for more accurate search results when the user specifies a source (e.g., "ytsearch:Never Gonna Give You Up" would indicate that the search should be performed on YouTube).
|
|
507
|
+
* @param queryString
|
|
508
|
+
* @returns
|
|
509
|
+
*/
|
|
510
|
+
findSourceOfQuery(queryString: string): SearchPlatform;
|
|
511
|
+
/**
|
|
512
|
+
* Extracts the source from the query if it starts with a valid source prefix (e.g., "ytsearch:") and updates the searchQuery object accordingly.
|
|
513
|
+
* @param searchQuery
|
|
514
|
+
* @returns The updated searchQuery object with the extracted source and modified query string.
|
|
515
|
+
*/
|
|
516
|
+
extractSourceOfQuery<T extends {
|
|
517
|
+
query: string;
|
|
518
|
+
source?: string;
|
|
519
|
+
}>(searchQuery: T): T;
|
|
520
|
+
/**
|
|
521
|
+
* Converts a string to lowercase if the input is a string, otherwise returns the input as is. This is useful for ensuring that search platform identifiers are case-insensitive while allowing other types of input to pass through unchanged.
|
|
522
|
+
* @param input
|
|
523
|
+
* @returns
|
|
524
|
+
*/
|
|
525
|
+
typedLowerCase<T extends unknown>(input: T): T;
|
|
526
|
+
/**
|
|
527
|
+
* Transforms a search query by determining the appropriate search platform based on the query string and the default search platform specified in the LavalinkManager options. It checks if the query string starts with a valid source prefix and extracts it if present. The function returns an object containing the modified query string, any extra URL parameters, and the determined search platform to be used for the search operation.
|
|
528
|
+
* @param query
|
|
529
|
+
* @returns
|
|
530
|
+
*/
|
|
475
531
|
transformQuery(query: SearchQuery): {
|
|
476
532
|
query: string;
|
|
477
|
-
extraQueryUrlParams:
|
|
478
|
-
source:
|
|
533
|
+
extraQueryUrlParams: any;
|
|
534
|
+
source: SearchPlatform;
|
|
479
535
|
};
|
|
536
|
+
/**
|
|
537
|
+
* Transforms a LavaSearchQuery by determining the appropriate search platform based on the query string and the default search platform specified in the LavalinkManager options. It checks if the query string starts with a valid source prefix and extracts it if present. The function returns an object containing the modified query string, any extra URL parameters, the determined search platform to be used for the search operation, and the types of search (track, playlist, artist, album, text) to be performed.
|
|
538
|
+
* @param query
|
|
539
|
+
* @returns
|
|
540
|
+
*/
|
|
480
541
|
transformLavaSearchQuery(query: LavaSearchQuery): {
|
|
542
|
+
query: never;
|
|
543
|
+
types: any[];
|
|
544
|
+
extraQueryUrlParams: any;
|
|
545
|
+
source: SearchPlatform;
|
|
546
|
+
} | {
|
|
481
547
|
query: string;
|
|
482
548
|
types: string[];
|
|
483
|
-
source:
|
|
549
|
+
source: "ytsearch" | "ytmsearch" | "scsearch" | "bcsearch" | "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "dzrec" | "ymsearch" | "ymrec" | "vksearch" | "vkrec" | "tdsearch" | "tdrec" | "qbsearch" | "qbisrc" | "qbrec" | "pdsearch" | "pdisrc" | "pdrec" | "ftts" | "speak" | "phsearch" | "pornhub" | "porn" | "tts" | "jssearch" | "jsrec" | "local" | "http" | "https" | "link" | "uri" | "youtube" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "musicyoutube" | "music youtube" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "musicapple" | "music apple" | "sp" | "spsuggestion" | "spotify" | "spotify.com" | "spotifycom" | "dz" | "deezer" | "yandex" | "yandex music" | "yandexmusic" | "vk" | "vk music" | "vkmusic" | "tidal" | "tidal music" | "qobuz" | "pandora" | "pd" | "pandora music" | "pandoramusic" | "flowerytts" | "flowery" | "flowery.tts" | "bandcamp" | "bc" | "js" | "jiosaavn" | "td";
|
|
484
550
|
};
|
|
551
|
+
/**
|
|
552
|
+
* Validates the provided source string against the capabilities of the Lavalink node. It checks if the source string is supported by the node's enabled source managers and plugins, throwing errors if any required sources or plugins are missing for the specified search platform. This ensures that search queries are only executed with compatible sources based on the node's configuration.
|
|
553
|
+
* @param node
|
|
554
|
+
* @param sourceString
|
|
555
|
+
* @returns
|
|
556
|
+
*/
|
|
485
557
|
validateSourceString(node: LavalinkNode, sourceString: SearchPlatform): void;
|
|
486
558
|
}
|
|
487
559
|
/**
|
|
@@ -2627,6 +2699,14 @@ declare class Player {
|
|
|
2627
2699
|
* @param options
|
|
2628
2700
|
*/
|
|
2629
2701
|
play(options?: Partial<PlayOptions>): any;
|
|
2702
|
+
/**
|
|
2703
|
+
* The old JSON of the player, used for the "playerClientUpdate" event, which is emitted on every update of the player via a function call, so that you can compare the old data with the new data and do something with it if you want to.
|
|
2704
|
+
*/
|
|
2705
|
+
oldJSON: PlayerJson;
|
|
2706
|
+
/**
|
|
2707
|
+
* Emits the "playerClientUpdate" event, which is emitted on every update of the player via a function call, so that you can compare the old data with the new data and do something with it if you want to.
|
|
2708
|
+
*/
|
|
2709
|
+
triggerPlayerClientUpdate(): void;
|
|
2630
2710
|
/**
|
|
2631
2711
|
* Set the Volume for the Player
|
|
2632
2712
|
* @param volume The Volume in percent
|
|
@@ -3721,6 +3801,20 @@ interface LavalinkManagerEvents<CustomPlayerT extends Player = Player> {
|
|
|
3721
3801
|
* @event Manager#playerUpdate
|
|
3722
3802
|
*/
|
|
3723
3803
|
playerUpdate: (oldPlayerJson: PlayerJson, newPlayer: CustomPlayerT) => void;
|
|
3804
|
+
/**
|
|
3805
|
+
* Always emits when the player (on client side) got updated via a function-call.
|
|
3806
|
+
* This is useful for example, if you want to save the player data on every update, or similar.
|
|
3807
|
+
* @event Manager#playerClientUpdate
|
|
3808
|
+
*
|
|
3809
|
+
* Emits only when you call one of those functions:
|
|
3810
|
+
* player.pause()
|
|
3811
|
+
* player.resume()
|
|
3812
|
+
* player.seek()
|
|
3813
|
+
* player.setRepeatMode()
|
|
3814
|
+
* player.setVolume()
|
|
3815
|
+
* and on every call of the filterManager.
|
|
3816
|
+
*/
|
|
3817
|
+
playerClientUpdate: (oldPlayerJson: PlayerJson, newPlayer: CustomPlayerT) => void;
|
|
3724
3818
|
/**
|
|
3725
3819
|
* Emitted when the player's selfMuted or serverMuted state changed (true -> false | false -> true)
|
|
3726
3820
|
* @event Manager#playerMuteChange
|
|
@@ -3842,6 +3936,8 @@ interface ManagerPlayerOptions<CustomPlayerT extends Player = Player> {
|
|
|
3842
3936
|
clientBasedPositionUpdateInterval?: number;
|
|
3843
3937
|
/** What should be used as a searchPlatform, if no source was provided during the query */
|
|
3844
3938
|
defaultSearchPlatform?: SearchPlatform;
|
|
3939
|
+
/** Allow custom sources which lavalink-client does not support (yet) */
|
|
3940
|
+
allowCustomSources?: boolean;
|
|
3845
3941
|
/** Applies the volume via a filter, not via the lavalink volume transformer */
|
|
3846
3942
|
applyVolumeAsFilter?: boolean;
|
|
3847
3943
|
/** Transforms the saved data of a requested user */
|
|
@@ -3870,6 +3966,14 @@ interface ManagerPlayerOptions<CustomPlayerT extends Player = Player> {
|
|
|
3870
3966
|
destroyAfterMs?: number;
|
|
3871
3967
|
};
|
|
3872
3968
|
useUnresolvedData?: boolean;
|
|
3969
|
+
/**
|
|
3970
|
+
* If true (default), when changing nodes, `setSponsorBlock()` with default categories is called
|
|
3971
|
+
* even if the user never explicitly set categories. This is needed so the SponsorBlock plugin
|
|
3972
|
+
* registers its event listeners (ChapterStarted/ChapterLoaded) on the new node.
|
|
3973
|
+
* Set to false to disable this behavior if you don't use SponsorBlock events.
|
|
3974
|
+
* @default true
|
|
3975
|
+
*/
|
|
3976
|
+
enforceSponsorBlockRequestForEventEnablement?: boolean;
|
|
3873
3977
|
}
|
|
3874
3978
|
type DeepRequired<T> = {
|
|
3875
3979
|
[K in keyof T]-?: NonNullable<T[K]> extends object ? DeepRequired<NonNullable<T[K]>> : NonNullable<T[K]>;
|
|
@@ -4016,6 +4120,7 @@ declare class LavalinkManager<CustomPlayerT extends Player = Player> extends Eve
|
|
|
4016
4120
|
* applyVolumeAsFilter: false,
|
|
4017
4121
|
* clientBasedPositionUpdateInterval: 150,
|
|
4018
4122
|
* defaultSearchPlatform: "ytmsearch",
|
|
4123
|
+
* allowCustomSources: false,
|
|
4019
4124
|
* volumeDecrementer: 0.75,
|
|
4020
4125
|
* //requesterTransformer: YourRequesterTransformerFunction,
|
|
4021
4126
|
* onDisconnect: {
|
package/dist/index.js
CHANGED
|
@@ -604,12 +604,24 @@ var ManagerUtils = class {
|
|
|
604
604
|
constructor(LavalinkManager2) {
|
|
605
605
|
this.LavalinkManager = LavalinkManager2;
|
|
606
606
|
}
|
|
607
|
+
/**
|
|
608
|
+
* Builds a pluginInfo object based on the provided data, extracting relevant information from the data and clientData parameters. This function is used to construct the pluginInfo property for tracks, allowing for consistent handling of plugin-related information across different track sources and formats.
|
|
609
|
+
* @param data
|
|
610
|
+
* @param clientData
|
|
611
|
+
* @returns
|
|
612
|
+
*/
|
|
607
613
|
buildPluginInfo(data, clientData = {}) {
|
|
608
614
|
return {
|
|
609
615
|
clientData,
|
|
610
616
|
...data.pluginInfo || data.plugin
|
|
611
617
|
};
|
|
612
618
|
}
|
|
619
|
+
/**
|
|
620
|
+
* Builds a Track object from the provided data and requester information. It validates the presence of required properties in the data, transforms the requester using a custom transformer function if provided, and constructs a Track object with the appropriate properties and plugin information. The function also includes error handling to ensure that the input data is valid and provides debug information if track building fails.
|
|
621
|
+
* @param data
|
|
622
|
+
* @param requester
|
|
623
|
+
* @returns
|
|
624
|
+
*/
|
|
613
625
|
buildTrack(data, requester) {
|
|
614
626
|
if (!data?.encoded || typeof data.encoded !== "string")
|
|
615
627
|
throw new RangeError("Argument 'data.encoded' must be present.");
|
|
@@ -707,6 +719,11 @@ var ManagerUtils = class {
|
|
|
707
719
|
return false;
|
|
708
720
|
return true;
|
|
709
721
|
}
|
|
722
|
+
/**
|
|
723
|
+
* Gets the transformed requester based on the LavalinkManager options. If a custom requester transformer function is provided in the player options, it applies that function to the requester; otherwise, it returns the requester as is. The function also includes error handling to catch any exceptions that may occur during the transformation process and emits a debug event if the transformation fails.
|
|
724
|
+
* @param requester
|
|
725
|
+
* @returns
|
|
726
|
+
*/
|
|
710
727
|
getTransformedRequester(requester) {
|
|
711
728
|
try {
|
|
712
729
|
return typeof this.LavalinkManager?.options?.playerOptions?.requesterTransformer === "function" ? this.LavalinkManager?.options?.playerOptions?.requesterTransformer(requester) : requester;
|
|
@@ -795,6 +812,12 @@ var ManagerUtils = class {
|
|
|
795
812
|
isUnresolvedTrackQuery(data) {
|
|
796
813
|
return typeof data === "object" && !("info" in data) && typeof data.title === "string";
|
|
797
814
|
}
|
|
815
|
+
/**
|
|
816
|
+
* Gets the closest track by resolving the provided UnresolvedTrack using the getClosestTrack function. It includes error handling to catch any exceptions that may occur during the resolution process and emits a debug event if the resolution fails. The function returns a Promise that resolves to a Track object if successful, or undefined if no closest track is found.
|
|
817
|
+
* @param data
|
|
818
|
+
* @param player
|
|
819
|
+
* @returns
|
|
820
|
+
*/
|
|
798
821
|
async getClosestTrack(data, player) {
|
|
799
822
|
try {
|
|
800
823
|
return getClosestTrack(data, player);
|
|
@@ -810,6 +833,13 @@ var ManagerUtils = class {
|
|
|
810
833
|
throw e;
|
|
811
834
|
}
|
|
812
835
|
}
|
|
836
|
+
/**
|
|
837
|
+
* Validates the query string against various criteria, including checking for empty strings, length limits for specific sources, blacklisted links or words, and ensuring that the Lavalink node has the necessary source managers enabled for the provided query. The function also includes debug event emissions to assist with troubleshooting and understanding the validation process.
|
|
838
|
+
* @param node
|
|
839
|
+
* @param queryString
|
|
840
|
+
* @param sourceString
|
|
841
|
+
* @returns
|
|
842
|
+
*/
|
|
813
843
|
validateQueryString(node, queryString, sourceString) {
|
|
814
844
|
if (!node.info) throw new Error("No Lavalink Node was provided");
|
|
815
845
|
if (node._checkForSources && !node.info.sourceManagers?.length)
|
|
@@ -897,24 +927,84 @@ var ManagerUtils = class {
|
|
|
897
927
|
}
|
|
898
928
|
return;
|
|
899
929
|
}
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
};
|
|
907
|
-
const foundSource = Object.keys(DefaultSources).find((source) => Query.query?.toLowerCase?.()?.startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
930
|
+
/**
|
|
931
|
+
* Finds the source of a query string by checking if it starts with a valid source prefix defined in the DefaultSources object. If a valid source prefix is found, it returns the corresponding SearchPlatform; otherwise, it returns null. This function is useful for determining the intended search platform for a given query string, allowing for more accurate search results when the user specifies a source (e.g., "ytsearch:Never Gonna Give You Up" would indicate that the search should be performed on YouTube).
|
|
932
|
+
* @param queryString
|
|
933
|
+
* @returns
|
|
934
|
+
*/
|
|
935
|
+
findSourceOfQuery(queryString) {
|
|
936
|
+
const foundSource = Object.keys(DefaultSources).find((source) => queryString?.toLowerCase?.()?.startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
908
937
|
if (foundSource && !["https", "http"].includes(foundSource) && DefaultSources[foundSource]) {
|
|
909
|
-
|
|
910
|
-
|
|
938
|
+
return foundSource;
|
|
939
|
+
}
|
|
940
|
+
return null;
|
|
941
|
+
}
|
|
942
|
+
/**
|
|
943
|
+
* Extracts the source from the query if it starts with a valid source prefix (e.g., "ytsearch:") and updates the searchQuery object accordingly.
|
|
944
|
+
* @param searchQuery
|
|
945
|
+
* @returns The updated searchQuery object with the extracted source and modified query string.
|
|
946
|
+
*/
|
|
947
|
+
extractSourceOfQuery(searchQuery) {
|
|
948
|
+
const foundSource = this.findSourceOfQuery(searchQuery.query);
|
|
949
|
+
if (foundSource) {
|
|
950
|
+
searchQuery.source = DefaultSources[foundSource];
|
|
951
|
+
searchQuery.query = searchQuery.query.slice(`${foundSource}:`.length, searchQuery.query.length);
|
|
911
952
|
}
|
|
912
|
-
return
|
|
953
|
+
return searchQuery;
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* Converts a string to lowercase if the input is a string, otherwise returns the input as is. This is useful for ensuring that search platform identifiers are case-insensitive while allowing other types of input to pass through unchanged.
|
|
957
|
+
* @param input
|
|
958
|
+
* @returns
|
|
959
|
+
*/
|
|
960
|
+
typedLowerCase(input) {
|
|
961
|
+
if (!input) return input;
|
|
962
|
+
if (typeof input === "string") return input.toLowerCase();
|
|
963
|
+
return input;
|
|
913
964
|
}
|
|
965
|
+
/**
|
|
966
|
+
* Transforms a search query by determining the appropriate search platform based on the query string and the default search platform specified in the LavalinkManager options. It checks if the query string starts with a valid source prefix and extracts it if present. The function returns an object containing the modified query string, any extra URL parameters, and the determined search platform to be used for the search operation.
|
|
967
|
+
* @param query
|
|
968
|
+
* @returns
|
|
969
|
+
*/
|
|
970
|
+
transformQuery(query) {
|
|
971
|
+
const typedDefault = this.typedLowerCase(this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform);
|
|
972
|
+
if (typeof query === "string") {
|
|
973
|
+
const Query = {
|
|
974
|
+
query,
|
|
975
|
+
extraQueryUrlParams: void 0,
|
|
976
|
+
source: typedDefault
|
|
977
|
+
};
|
|
978
|
+
return this.extractSourceOfQuery(Query);
|
|
979
|
+
}
|
|
980
|
+
const providedSource = query?.source?.trim?.()?.toLowerCase?.();
|
|
981
|
+
const validSourceExtracted = DefaultSources[providedSource ?? typedDefault];
|
|
982
|
+
return this.extractSourceOfQuery({
|
|
983
|
+
query: query.query,
|
|
984
|
+
extraQueryUrlParams: query.extraQueryUrlParams,
|
|
985
|
+
source: validSourceExtracted ?? providedSource ?? typedDefault
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
/**
|
|
989
|
+
* Transforms a LavaSearchQuery by determining the appropriate search platform based on the query string and the default search platform specified in the LavalinkManager options. It checks if the query string starts with a valid source prefix and extracts it if present. The function returns an object containing the modified query string, any extra URL parameters, the determined search platform to be used for the search operation, and the types of search (track, playlist, artist, album, text) to be performed.
|
|
990
|
+
* @param query
|
|
991
|
+
* @returns
|
|
992
|
+
*/
|
|
914
993
|
transformLavaSearchQuery(query) {
|
|
915
|
-
const
|
|
994
|
+
const typedDefault = this.typedLowerCase(this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform);
|
|
995
|
+
if (typeof query === "string") {
|
|
996
|
+
const Query2 = {
|
|
997
|
+
query,
|
|
998
|
+
types: [],
|
|
999
|
+
extraQueryUrlParams: void 0,
|
|
1000
|
+
source: typedDefault
|
|
1001
|
+
};
|
|
1002
|
+
return this.extractSourceOfQuery(Query2);
|
|
1003
|
+
}
|
|
1004
|
+
const providedSource = query?.source?.trim?.()?.toLowerCase?.();
|
|
1005
|
+
const validSourceExtracted = DefaultSources[providedSource ?? typedDefault];
|
|
916
1006
|
const Query = {
|
|
917
|
-
query:
|
|
1007
|
+
query: query.query,
|
|
918
1008
|
types: query.types ? ["track", "playlist", "artist", "album", "text"].filter(
|
|
919
1009
|
(v) => query.types?.find((x) => x.toLowerCase().startsWith(v))
|
|
920
1010
|
) : [
|
|
@@ -924,19 +1014,23 @@ var ManagerUtils = class {
|
|
|
924
1014
|
"album"
|
|
925
1015
|
/*"text"*/
|
|
926
1016
|
],
|
|
927
|
-
source:
|
|
1017
|
+
source: validSourceExtracted ?? providedSource ?? typedDefault
|
|
928
1018
|
};
|
|
929
|
-
|
|
930
|
-
if (foundSource && DefaultSources[foundSource]) {
|
|
931
|
-
Query.source = DefaultSources[foundSource];
|
|
932
|
-
Query.query = Query.query.slice(`${foundSource}:`.length, Query.query.length);
|
|
933
|
-
}
|
|
934
|
-
return Query;
|
|
1019
|
+
return this.extractSourceOfQuery(Query);
|
|
935
1020
|
}
|
|
1021
|
+
/**
|
|
1022
|
+
* Validates the provided source string against the capabilities of the Lavalink node. It checks if the source string is supported by the node's enabled source managers and plugins, throwing errors if any required sources or plugins are missing for the specified search platform. This ensures that search queries are only executed with compatible sources based on the node's configuration.
|
|
1023
|
+
* @param node
|
|
1024
|
+
* @param sourceString
|
|
1025
|
+
* @returns
|
|
1026
|
+
*/
|
|
936
1027
|
validateSourceString(node, sourceString) {
|
|
937
1028
|
if (!sourceString) throw new Error(`No SourceString was provided`);
|
|
938
1029
|
const source = DefaultSources[sourceString.toLowerCase().trim()];
|
|
939
|
-
if (!source
|
|
1030
|
+
if (!source && !!this.LavalinkManager.options.playerOptions.allowCustomSources)
|
|
1031
|
+
throw new Error(
|
|
1032
|
+
`Lavalink-Client does not support SearchQuerySource: '${sourceString}'. You can disable this check by setting 'ManagerOptions.PlayerOptions.allowCustomSources' to true`
|
|
1033
|
+
);
|
|
940
1034
|
if (!node.info) throw new Error("Lavalink Node does not have any info cached yet, not ready yet!");
|
|
941
1035
|
if (!node._checkForSources) return;
|
|
942
1036
|
if (source === "amsearch" && !node.info?.sourceManagers?.includes("applemusic")) {
|
|
@@ -2487,12 +2581,13 @@ var LavalinkNode = class _LavalinkNode {
|
|
|
2487
2581
|
if (!error) return;
|
|
2488
2582
|
this.NodeManager.emit("error", this, error);
|
|
2489
2583
|
this.reconnectionState = "IDLE" /* IDLE */;
|
|
2490
|
-
this.reconnect();
|
|
2491
2584
|
if (this.options.closeOnError) {
|
|
2492
2585
|
if (this.heartBeatInterval) clearInterval(this.heartBeatInterval);
|
|
2493
2586
|
if (this.pingTimeout) clearTimeout(this.pingTimeout);
|
|
2494
2587
|
this.socket?.close(500, "Node-Error - Force Reconnect");
|
|
2588
|
+
return;
|
|
2495
2589
|
}
|
|
2590
|
+
this.reconnect();
|
|
2496
2591
|
}
|
|
2497
2592
|
/** @private util function for handling message events from websocket */
|
|
2498
2593
|
async message(d) {
|
|
@@ -2716,7 +2811,7 @@ var LavalinkNode = class _LavalinkNode {
|
|
|
2716
2811
|
(v) => Date.now() - v < this._LManager.options.playerOptions.maxErrorsPerTime?.threshold
|
|
2717
2812
|
);
|
|
2718
2813
|
player.set("internal_erroredTracksTimestamps", [...oldTimestamps, Date.now()]);
|
|
2719
|
-
if (oldTimestamps.length
|
|
2814
|
+
if (oldTimestamps.length >= this._LManager.options.playerOptions.maxErrorsPerTime?.maxAmount) {
|
|
2720
2815
|
this._emitDebugEvent("TrackStuckMaxTracksErroredPerTime" /* TrackStuckMaxTracksErroredPerTime */, {
|
|
2721
2816
|
state: "log",
|
|
2722
2817
|
message: `trackStuck Event was triggered too often within a given threshold (LavalinkManager.options.playerOptions.maxErrorsPerTime). Threshold: "${this._LManager.options.playerOptions.maxErrorsPerTime?.threshold}ms", maxAmount: "${this._LManager.options.playerOptions.maxErrorsPerTime?.maxAmount}"`,
|
|
@@ -2754,7 +2849,7 @@ var LavalinkNode = class _LavalinkNode {
|
|
|
2754
2849
|
(v) => Date.now() - v < this._LManager.options.playerOptions.maxErrorsPerTime?.threshold
|
|
2755
2850
|
);
|
|
2756
2851
|
player.set("internal_erroredTracksTimestamps", [...oldTimestamps, Date.now()]);
|
|
2757
|
-
if (oldTimestamps.length
|
|
2852
|
+
if (oldTimestamps.length >= this._LManager.options.playerOptions.maxErrorsPerTime?.maxAmount) {
|
|
2758
2853
|
this._emitDebugEvent("TrackErrorMaxTracksErroredPerTime" /* TrackErrorMaxTracksErroredPerTime */, {
|
|
2759
2854
|
state: "log",
|
|
2760
2855
|
message: `TrackError Event was triggered too often within a given threshold (LavalinkManager.options.playerOptions.maxErrorsPerTime). Threshold: "${this._LManager.options.playerOptions.maxErrorsPerTime?.threshold}ms", maxAmount: "${this._LManager.options.playerOptions.maxErrorsPerTime?.maxAmount}"`,
|
|
@@ -3814,6 +3909,7 @@ var FilterManager = class {
|
|
|
3814
3909
|
}
|
|
3815
3910
|
const now = performance.now();
|
|
3816
3911
|
if (this.player.options.instaUpdateFiltersFix === true) this.filterUpdatedState = true;
|
|
3912
|
+
this.player.triggerPlayerClientUpdate();
|
|
3817
3913
|
await this.player.node.updatePlayer({
|
|
3818
3914
|
guildId: this.player.guildId,
|
|
3819
3915
|
playerOptions: {
|
|
@@ -3908,7 +4004,7 @@ var FilterManager = class {
|
|
|
3908
4004
|
this.filters.tremolo = false;
|
|
3909
4005
|
this.filters.vibrato = false;
|
|
3910
4006
|
this.filters.karaoke = false;
|
|
3911
|
-
this.filters.
|
|
4007
|
+
this.filters.vaporwave = false;
|
|
3912
4008
|
this.filters.volume = false;
|
|
3913
4009
|
this.filters.nodeLinkEcho = false;
|
|
3914
4010
|
this.filters.nodeLinkChorus = false;
|
|
@@ -3989,7 +4085,7 @@ var FilterManager = class {
|
|
|
3989
4085
|
this.data = this.data ?? {};
|
|
3990
4086
|
this.filters.nightcore = false;
|
|
3991
4087
|
this.filters.vaporwave = false;
|
|
3992
|
-
this.data.timescale = { ...DEFAULT_FILTER_DATAS.timescale, speed };
|
|
4088
|
+
this.data.timescale = { ...DEFAULT_FILTER_DATAS.timescale, ...this.data.timescale, speed };
|
|
3993
4089
|
this.isCustomFilterActive();
|
|
3994
4090
|
await this.applyPlayerFilters();
|
|
3995
4091
|
return this;
|
|
@@ -4011,7 +4107,7 @@ var FilterManager = class {
|
|
|
4011
4107
|
this.data = this.data ?? {};
|
|
4012
4108
|
this.filters.nightcore = false;
|
|
4013
4109
|
this.filters.vaporwave = false;
|
|
4014
|
-
this.data.timescale = { ...DEFAULT_FILTER_DATAS.timescale, pitch };
|
|
4110
|
+
this.data.timescale = { ...DEFAULT_FILTER_DATAS.timescale, ...this.data.timescale, pitch };
|
|
4015
4111
|
this.isCustomFilterActive();
|
|
4016
4112
|
await this.applyPlayerFilters();
|
|
4017
4113
|
return this;
|
|
@@ -4033,7 +4129,7 @@ var FilterManager = class {
|
|
|
4033
4129
|
this.data = this.data ?? {};
|
|
4034
4130
|
this.filters.nightcore = false;
|
|
4035
4131
|
this.filters.vaporwave = false;
|
|
4036
|
-
this.data.timescale = { ...DEFAULT_FILTER_DATAS.timescale, rate };
|
|
4132
|
+
this.data.timescale = { ...DEFAULT_FILTER_DATAS.timescale, ...this.data.timescale, rate };
|
|
4037
4133
|
this.isCustomFilterActive();
|
|
4038
4134
|
await this.applyPlayerFilters();
|
|
4039
4135
|
return this;
|
|
@@ -4462,6 +4558,7 @@ var FilterManager = class {
|
|
|
4462
4558
|
if (!this.player.node.sessionId) throw new Error("The Lavalink-Node is either not ready or not up to date");
|
|
4463
4559
|
const now = performance.now();
|
|
4464
4560
|
if (this.player.options.instaUpdateFiltersFix === true) this.filterUpdatedState = true;
|
|
4561
|
+
this.player.triggerPlayerClientUpdate();
|
|
4465
4562
|
await this.player.node.updatePlayer({
|
|
4466
4563
|
guildId: this.player.guildId,
|
|
4467
4564
|
playerOptions: {
|
|
@@ -4618,7 +4715,7 @@ var Queue = class {
|
|
|
4618
4715
|
* @param queueOptions
|
|
4619
4716
|
*/
|
|
4620
4717
|
constructor(guildId, data = {}, QueueSaver2, queueOptions) {
|
|
4621
|
-
this.queueChanges = queueOptions
|
|
4718
|
+
this.queueChanges = queueOptions?.queueChangesWatcher || null;
|
|
4622
4719
|
this.guildId = guildId;
|
|
4623
4720
|
this.QueueSaver = QueueSaver2;
|
|
4624
4721
|
this.options.maxPreviousTracks = this.QueueSaver?.options?.maxPreviousTracks ?? this.options.maxPreviousTracks;
|
|
@@ -4669,7 +4766,7 @@ var Queue = class {
|
|
|
4669
4766
|
))
|
|
4670
4767
|
this.previous.splice(
|
|
4671
4768
|
0,
|
|
4672
|
-
override ? this.
|
|
4769
|
+
override ? this.previous.length : 0,
|
|
4673
4770
|
...data.previous.filter(
|
|
4674
4771
|
(track) => this.managerUtils.isTrack(track) || this.managerUtils.isUnresolvedTrack(track)
|
|
4675
4772
|
)
|
|
@@ -4684,8 +4781,8 @@ var Queue = class {
|
|
|
4684
4781
|
* @returns {{current:Track|null, previous:Track[], tracks:Track[]}}The Queue, but in a raw State, which allows easier handling for the QueueStoreManager
|
|
4685
4782
|
*/
|
|
4686
4783
|
toJSON: () => {
|
|
4687
|
-
if (this.previous
|
|
4688
|
-
this.previous
|
|
4784
|
+
if (this.previous?.length > this.options?.maxPreviousTracks)
|
|
4785
|
+
this.previous?.splice(this.options?.maxPreviousTracks, this.previous.length);
|
|
4689
4786
|
return {
|
|
4690
4787
|
current: this.current ? { ...this.current } : null,
|
|
4691
4788
|
previous: this.previous ? [...this.previous] : [],
|
|
@@ -5501,6 +5598,17 @@ var Player = class {
|
|
|
5501
5598
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
5502
5599
|
return this;
|
|
5503
5600
|
}
|
|
5601
|
+
/**
|
|
5602
|
+
* The old JSON of the player, used for the "playerClientUpdate" event, which is emitted on every update of the player via a function call, so that you can compare the old data with the new data and do something with it if you want to.
|
|
5603
|
+
*/
|
|
5604
|
+
oldJSON = this.toJSON();
|
|
5605
|
+
/**
|
|
5606
|
+
* Emits the "playerClientUpdate" event, which is emitted on every update of the player via a function call, so that you can compare the old data with the new data and do something with it if you want to.
|
|
5607
|
+
*/
|
|
5608
|
+
triggerPlayerClientUpdate() {
|
|
5609
|
+
this.LavalinkManager.emit("playerClientUpdate", this.oldJSON, this);
|
|
5610
|
+
this.oldJSON = this.toJSON();
|
|
5611
|
+
}
|
|
5504
5612
|
/**
|
|
5505
5613
|
* Set the Volume for the Player
|
|
5506
5614
|
* @param volume The Volume in percent
|
|
@@ -5521,6 +5629,7 @@ var Player = class {
|
|
|
5521
5629
|
0
|
|
5522
5630
|
)
|
|
5523
5631
|
);
|
|
5632
|
+
this.triggerPlayerClientUpdate();
|
|
5524
5633
|
const now = performance.now();
|
|
5525
5634
|
if (this.LavalinkManager.options.playerOptions.applyVolumeAsFilter) {
|
|
5526
5635
|
this._emitDebugEvent("PlayerVolumeAsFilter" /* PlayerVolumeAsFilter */, {
|
|
@@ -5595,6 +5704,7 @@ var Player = class {
|
|
|
5595
5704
|
this.paused = true;
|
|
5596
5705
|
this.lastPositionChange = null;
|
|
5597
5706
|
const now = performance.now();
|
|
5707
|
+
this.triggerPlayerClientUpdate();
|
|
5598
5708
|
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { paused: true } });
|
|
5599
5709
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
5600
5710
|
this.LavalinkManager.emit("playerPaused", this, this.queue.current);
|
|
@@ -5607,6 +5717,7 @@ var Player = class {
|
|
|
5607
5717
|
if (!this.paused) throw new Error("Player isn't paused - not able to resume.");
|
|
5608
5718
|
this.paused = false;
|
|
5609
5719
|
const now = performance.now();
|
|
5720
|
+
this.triggerPlayerClientUpdate();
|
|
5610
5721
|
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { paused: false } });
|
|
5611
5722
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
5612
5723
|
this.LavalinkManager.emit("playerResumed", this, this.queue.current);
|
|
@@ -5627,6 +5738,7 @@ var Player = class {
|
|
|
5627
5738
|
this.lastPositionChange = Date.now();
|
|
5628
5739
|
this.lastPosition = position;
|
|
5629
5740
|
const now = performance.now();
|
|
5741
|
+
this.triggerPlayerClientUpdate();
|
|
5630
5742
|
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { position } });
|
|
5631
5743
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
5632
5744
|
return this;
|
|
@@ -5639,6 +5751,7 @@ var Player = class {
|
|
|
5639
5751
|
if (!["off", "track", "queue"].includes(repeatMode))
|
|
5640
5752
|
throw new RangeError("Repeatmode must be either 'off', 'track', or 'queue'");
|
|
5641
5753
|
this.repeatMode = repeatMode;
|
|
5754
|
+
this.triggerPlayerClientUpdate();
|
|
5642
5755
|
return this;
|
|
5643
5756
|
}
|
|
5644
5757
|
/**
|
|
@@ -5893,7 +6006,7 @@ var Player = class {
|
|
|
5893
6006
|
functionLayer: "Player > changeNode()"
|
|
5894
6007
|
});
|
|
5895
6008
|
});
|
|
5896
|
-
} else {
|
|
6009
|
+
} else if (this.LavalinkManager.options?.playerOptions?.enforceSponsorBlockRequestForEventEnablement !== false) {
|
|
5897
6010
|
await this.setSponsorBlock().catch((error) => {
|
|
5898
6011
|
this._emitDebugEvent("PlayerChangeNode" /* PlayerChangeNode */, {
|
|
5899
6012
|
state: "error",
|
|
@@ -5989,7 +6102,7 @@ var Player = class {
|
|
|
5989
6102
|
nodeId: this.node?.id,
|
|
5990
6103
|
nodeSessionId: this.node?.sessionId,
|
|
5991
6104
|
ping: this.ping,
|
|
5992
|
-
queue: this.queue
|
|
6105
|
+
queue: this.queue?.utils?.toJSON?.()
|
|
5993
6106
|
};
|
|
5994
6107
|
}
|
|
5995
6108
|
};
|
|
@@ -6072,6 +6185,7 @@ var LavalinkManager = class extends import_events2.EventEmitter {
|
|
|
6072
6185
|
applyVolumeAsFilter: options?.playerOptions?.applyVolumeAsFilter ?? false,
|
|
6073
6186
|
clientBasedPositionUpdateInterval: options?.playerOptions?.clientBasedPositionUpdateInterval ?? 100,
|
|
6074
6187
|
defaultSearchPlatform: options?.playerOptions?.defaultSearchPlatform ?? "ytsearch",
|
|
6188
|
+
allowCustomSources: options?.playerOptions?.allowCustomSources ?? false,
|
|
6075
6189
|
onDisconnect: {
|
|
6076
6190
|
destroyPlayer: options?.playerOptions?.onDisconnect?.destroyPlayer ?? true,
|
|
6077
6191
|
autoReconnect: options?.playerOptions?.onDisconnect?.autoReconnect ?? false,
|
|
@@ -6088,7 +6202,8 @@ var LavalinkManager = class extends import_events2.EventEmitter {
|
|
|
6088
6202
|
maxErrorsPerTime: {
|
|
6089
6203
|
threshold: options?.playerOptions?.maxErrorsPerTime?.threshold ?? 35e3,
|
|
6090
6204
|
maxAmount: options?.playerOptions?.maxErrorsPerTime?.maxAmount ?? 3
|
|
6091
|
-
}
|
|
6205
|
+
},
|
|
6206
|
+
enforceSponsorBlockRequestForEventEnablement: options?.playerOptions?.enforceSponsorBlockRequestForEventEnablement ?? true
|
|
6092
6207
|
},
|
|
6093
6208
|
linksWhitelist: options?.linksWhitelist ?? [],
|
|
6094
6209
|
linksBlacklist: options?.linksBlacklist ?? [],
|
|
@@ -6188,6 +6303,7 @@ var LavalinkManager = class extends import_events2.EventEmitter {
|
|
|
6188
6303
|
* applyVolumeAsFilter: false,
|
|
6189
6304
|
* clientBasedPositionUpdateInterval: 150,
|
|
6190
6305
|
* defaultSearchPlatform: "ytmsearch",
|
|
6306
|
+
* allowCustomSources: false,
|
|
6191
6307
|
* volumeDecrementer: 0.75,
|
|
6192
6308
|
* //requesterTransformer: YourRequesterTransformerFunction,
|
|
6193
6309
|
* onDisconnect: {
|
package/dist/index.mjs
CHANGED
|
@@ -540,12 +540,24 @@ var ManagerUtils = class {
|
|
|
540
540
|
constructor(LavalinkManager2) {
|
|
541
541
|
this.LavalinkManager = LavalinkManager2;
|
|
542
542
|
}
|
|
543
|
+
/**
|
|
544
|
+
* Builds a pluginInfo object based on the provided data, extracting relevant information from the data and clientData parameters. This function is used to construct the pluginInfo property for tracks, allowing for consistent handling of plugin-related information across different track sources and formats.
|
|
545
|
+
* @param data
|
|
546
|
+
* @param clientData
|
|
547
|
+
* @returns
|
|
548
|
+
*/
|
|
543
549
|
buildPluginInfo(data, clientData = {}) {
|
|
544
550
|
return {
|
|
545
551
|
clientData,
|
|
546
552
|
...data.pluginInfo || data.plugin
|
|
547
553
|
};
|
|
548
554
|
}
|
|
555
|
+
/**
|
|
556
|
+
* Builds a Track object from the provided data and requester information. It validates the presence of required properties in the data, transforms the requester using a custom transformer function if provided, and constructs a Track object with the appropriate properties and plugin information. The function also includes error handling to ensure that the input data is valid and provides debug information if track building fails.
|
|
557
|
+
* @param data
|
|
558
|
+
* @param requester
|
|
559
|
+
* @returns
|
|
560
|
+
*/
|
|
549
561
|
buildTrack(data, requester) {
|
|
550
562
|
if (!data?.encoded || typeof data.encoded !== "string")
|
|
551
563
|
throw new RangeError("Argument 'data.encoded' must be present.");
|
|
@@ -643,6 +655,11 @@ var ManagerUtils = class {
|
|
|
643
655
|
return false;
|
|
644
656
|
return true;
|
|
645
657
|
}
|
|
658
|
+
/**
|
|
659
|
+
* Gets the transformed requester based on the LavalinkManager options. If a custom requester transformer function is provided in the player options, it applies that function to the requester; otherwise, it returns the requester as is. The function also includes error handling to catch any exceptions that may occur during the transformation process and emits a debug event if the transformation fails.
|
|
660
|
+
* @param requester
|
|
661
|
+
* @returns
|
|
662
|
+
*/
|
|
646
663
|
getTransformedRequester(requester) {
|
|
647
664
|
try {
|
|
648
665
|
return typeof this.LavalinkManager?.options?.playerOptions?.requesterTransformer === "function" ? this.LavalinkManager?.options?.playerOptions?.requesterTransformer(requester) : requester;
|
|
@@ -731,6 +748,12 @@ var ManagerUtils = class {
|
|
|
731
748
|
isUnresolvedTrackQuery(data) {
|
|
732
749
|
return typeof data === "object" && !("info" in data) && typeof data.title === "string";
|
|
733
750
|
}
|
|
751
|
+
/**
|
|
752
|
+
* Gets the closest track by resolving the provided UnresolvedTrack using the getClosestTrack function. It includes error handling to catch any exceptions that may occur during the resolution process and emits a debug event if the resolution fails. The function returns a Promise that resolves to a Track object if successful, or undefined if no closest track is found.
|
|
753
|
+
* @param data
|
|
754
|
+
* @param player
|
|
755
|
+
* @returns
|
|
756
|
+
*/
|
|
734
757
|
async getClosestTrack(data, player) {
|
|
735
758
|
try {
|
|
736
759
|
return getClosestTrack(data, player);
|
|
@@ -746,6 +769,13 @@ var ManagerUtils = class {
|
|
|
746
769
|
throw e;
|
|
747
770
|
}
|
|
748
771
|
}
|
|
772
|
+
/**
|
|
773
|
+
* Validates the query string against various criteria, including checking for empty strings, length limits for specific sources, blacklisted links or words, and ensuring that the Lavalink node has the necessary source managers enabled for the provided query. The function also includes debug event emissions to assist with troubleshooting and understanding the validation process.
|
|
774
|
+
* @param node
|
|
775
|
+
* @param queryString
|
|
776
|
+
* @param sourceString
|
|
777
|
+
* @returns
|
|
778
|
+
*/
|
|
749
779
|
validateQueryString(node, queryString, sourceString) {
|
|
750
780
|
if (!node.info) throw new Error("No Lavalink Node was provided");
|
|
751
781
|
if (node._checkForSources && !node.info.sourceManagers?.length)
|
|
@@ -833,24 +863,84 @@ var ManagerUtils = class {
|
|
|
833
863
|
}
|
|
834
864
|
return;
|
|
835
865
|
}
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
};
|
|
843
|
-
const foundSource = Object.keys(DefaultSources).find((source) => Query.query?.toLowerCase?.()?.startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
866
|
+
/**
|
|
867
|
+
* Finds the source of a query string by checking if it starts with a valid source prefix defined in the DefaultSources object. If a valid source prefix is found, it returns the corresponding SearchPlatform; otherwise, it returns null. This function is useful for determining the intended search platform for a given query string, allowing for more accurate search results when the user specifies a source (e.g., "ytsearch:Never Gonna Give You Up" would indicate that the search should be performed on YouTube).
|
|
868
|
+
* @param queryString
|
|
869
|
+
* @returns
|
|
870
|
+
*/
|
|
871
|
+
findSourceOfQuery(queryString) {
|
|
872
|
+
const foundSource = Object.keys(DefaultSources).find((source) => queryString?.toLowerCase?.()?.startsWith(`${source}:`.toLowerCase()))?.trim?.()?.toLowerCase?.();
|
|
844
873
|
if (foundSource && !["https", "http"].includes(foundSource) && DefaultSources[foundSource]) {
|
|
845
|
-
|
|
846
|
-
|
|
874
|
+
return foundSource;
|
|
875
|
+
}
|
|
876
|
+
return null;
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Extracts the source from the query if it starts with a valid source prefix (e.g., "ytsearch:") and updates the searchQuery object accordingly.
|
|
880
|
+
* @param searchQuery
|
|
881
|
+
* @returns The updated searchQuery object with the extracted source and modified query string.
|
|
882
|
+
*/
|
|
883
|
+
extractSourceOfQuery(searchQuery) {
|
|
884
|
+
const foundSource = this.findSourceOfQuery(searchQuery.query);
|
|
885
|
+
if (foundSource) {
|
|
886
|
+
searchQuery.source = DefaultSources[foundSource];
|
|
887
|
+
searchQuery.query = searchQuery.query.slice(`${foundSource}:`.length, searchQuery.query.length);
|
|
847
888
|
}
|
|
848
|
-
return
|
|
889
|
+
return searchQuery;
|
|
890
|
+
}
|
|
891
|
+
/**
|
|
892
|
+
* Converts a string to lowercase if the input is a string, otherwise returns the input as is. This is useful for ensuring that search platform identifiers are case-insensitive while allowing other types of input to pass through unchanged.
|
|
893
|
+
* @param input
|
|
894
|
+
* @returns
|
|
895
|
+
*/
|
|
896
|
+
typedLowerCase(input) {
|
|
897
|
+
if (!input) return input;
|
|
898
|
+
if (typeof input === "string") return input.toLowerCase();
|
|
899
|
+
return input;
|
|
849
900
|
}
|
|
901
|
+
/**
|
|
902
|
+
* Transforms a search query by determining the appropriate search platform based on the query string and the default search platform specified in the LavalinkManager options. It checks if the query string starts with a valid source prefix and extracts it if present. The function returns an object containing the modified query string, any extra URL parameters, and the determined search platform to be used for the search operation.
|
|
903
|
+
* @param query
|
|
904
|
+
* @returns
|
|
905
|
+
*/
|
|
906
|
+
transformQuery(query) {
|
|
907
|
+
const typedDefault = this.typedLowerCase(this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform);
|
|
908
|
+
if (typeof query === "string") {
|
|
909
|
+
const Query = {
|
|
910
|
+
query,
|
|
911
|
+
extraQueryUrlParams: void 0,
|
|
912
|
+
source: typedDefault
|
|
913
|
+
};
|
|
914
|
+
return this.extractSourceOfQuery(Query);
|
|
915
|
+
}
|
|
916
|
+
const providedSource = query?.source?.trim?.()?.toLowerCase?.();
|
|
917
|
+
const validSourceExtracted = DefaultSources[providedSource ?? typedDefault];
|
|
918
|
+
return this.extractSourceOfQuery({
|
|
919
|
+
query: query.query,
|
|
920
|
+
extraQueryUrlParams: query.extraQueryUrlParams,
|
|
921
|
+
source: validSourceExtracted ?? providedSource ?? typedDefault
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
/**
|
|
925
|
+
* Transforms a LavaSearchQuery by determining the appropriate search platform based on the query string and the default search platform specified in the LavalinkManager options. It checks if the query string starts with a valid source prefix and extracts it if present. The function returns an object containing the modified query string, any extra URL parameters, the determined search platform to be used for the search operation, and the types of search (track, playlist, artist, album, text) to be performed.
|
|
926
|
+
* @param query
|
|
927
|
+
* @returns
|
|
928
|
+
*/
|
|
850
929
|
transformLavaSearchQuery(query) {
|
|
851
|
-
const
|
|
930
|
+
const typedDefault = this.typedLowerCase(this.LavalinkManager?.options?.playerOptions?.defaultSearchPlatform);
|
|
931
|
+
if (typeof query === "string") {
|
|
932
|
+
const Query2 = {
|
|
933
|
+
query,
|
|
934
|
+
types: [],
|
|
935
|
+
extraQueryUrlParams: void 0,
|
|
936
|
+
source: typedDefault
|
|
937
|
+
};
|
|
938
|
+
return this.extractSourceOfQuery(Query2);
|
|
939
|
+
}
|
|
940
|
+
const providedSource = query?.source?.trim?.()?.toLowerCase?.();
|
|
941
|
+
const validSourceExtracted = DefaultSources[providedSource ?? typedDefault];
|
|
852
942
|
const Query = {
|
|
853
|
-
query:
|
|
943
|
+
query: query.query,
|
|
854
944
|
types: query.types ? ["track", "playlist", "artist", "album", "text"].filter(
|
|
855
945
|
(v) => query.types?.find((x) => x.toLowerCase().startsWith(v))
|
|
856
946
|
) : [
|
|
@@ -860,19 +950,23 @@ var ManagerUtils = class {
|
|
|
860
950
|
"album"
|
|
861
951
|
/*"text"*/
|
|
862
952
|
],
|
|
863
|
-
source:
|
|
953
|
+
source: validSourceExtracted ?? providedSource ?? typedDefault
|
|
864
954
|
};
|
|
865
|
-
|
|
866
|
-
if (foundSource && DefaultSources[foundSource]) {
|
|
867
|
-
Query.source = DefaultSources[foundSource];
|
|
868
|
-
Query.query = Query.query.slice(`${foundSource}:`.length, Query.query.length);
|
|
869
|
-
}
|
|
870
|
-
return Query;
|
|
955
|
+
return this.extractSourceOfQuery(Query);
|
|
871
956
|
}
|
|
957
|
+
/**
|
|
958
|
+
* Validates the provided source string against the capabilities of the Lavalink node. It checks if the source string is supported by the node's enabled source managers and plugins, throwing errors if any required sources or plugins are missing for the specified search platform. This ensures that search queries are only executed with compatible sources based on the node's configuration.
|
|
959
|
+
* @param node
|
|
960
|
+
* @param sourceString
|
|
961
|
+
* @returns
|
|
962
|
+
*/
|
|
872
963
|
validateSourceString(node, sourceString) {
|
|
873
964
|
if (!sourceString) throw new Error(`No SourceString was provided`);
|
|
874
965
|
const source = DefaultSources[sourceString.toLowerCase().trim()];
|
|
875
|
-
if (!source
|
|
966
|
+
if (!source && !!this.LavalinkManager.options.playerOptions.allowCustomSources)
|
|
967
|
+
throw new Error(
|
|
968
|
+
`Lavalink-Client does not support SearchQuerySource: '${sourceString}'. You can disable this check by setting 'ManagerOptions.PlayerOptions.allowCustomSources' to true`
|
|
969
|
+
);
|
|
876
970
|
if (!node.info) throw new Error("Lavalink Node does not have any info cached yet, not ready yet!");
|
|
877
971
|
if (!node._checkForSources) return;
|
|
878
972
|
if (source === "amsearch" && !node.info?.sourceManagers?.includes("applemusic")) {
|
|
@@ -2423,12 +2517,13 @@ var LavalinkNode = class _LavalinkNode {
|
|
|
2423
2517
|
if (!error) return;
|
|
2424
2518
|
this.NodeManager.emit("error", this, error);
|
|
2425
2519
|
this.reconnectionState = "IDLE" /* IDLE */;
|
|
2426
|
-
this.reconnect();
|
|
2427
2520
|
if (this.options.closeOnError) {
|
|
2428
2521
|
if (this.heartBeatInterval) clearInterval(this.heartBeatInterval);
|
|
2429
2522
|
if (this.pingTimeout) clearTimeout(this.pingTimeout);
|
|
2430
2523
|
this.socket?.close(500, "Node-Error - Force Reconnect");
|
|
2524
|
+
return;
|
|
2431
2525
|
}
|
|
2526
|
+
this.reconnect();
|
|
2432
2527
|
}
|
|
2433
2528
|
/** @private util function for handling message events from websocket */
|
|
2434
2529
|
async message(d) {
|
|
@@ -2652,7 +2747,7 @@ var LavalinkNode = class _LavalinkNode {
|
|
|
2652
2747
|
(v) => Date.now() - v < this._LManager.options.playerOptions.maxErrorsPerTime?.threshold
|
|
2653
2748
|
);
|
|
2654
2749
|
player.set("internal_erroredTracksTimestamps", [...oldTimestamps, Date.now()]);
|
|
2655
|
-
if (oldTimestamps.length
|
|
2750
|
+
if (oldTimestamps.length >= this._LManager.options.playerOptions.maxErrorsPerTime?.maxAmount) {
|
|
2656
2751
|
this._emitDebugEvent("TrackStuckMaxTracksErroredPerTime" /* TrackStuckMaxTracksErroredPerTime */, {
|
|
2657
2752
|
state: "log",
|
|
2658
2753
|
message: `trackStuck Event was triggered too often within a given threshold (LavalinkManager.options.playerOptions.maxErrorsPerTime). Threshold: "${this._LManager.options.playerOptions.maxErrorsPerTime?.threshold}ms", maxAmount: "${this._LManager.options.playerOptions.maxErrorsPerTime?.maxAmount}"`,
|
|
@@ -2690,7 +2785,7 @@ var LavalinkNode = class _LavalinkNode {
|
|
|
2690
2785
|
(v) => Date.now() - v < this._LManager.options.playerOptions.maxErrorsPerTime?.threshold
|
|
2691
2786
|
);
|
|
2692
2787
|
player.set("internal_erroredTracksTimestamps", [...oldTimestamps, Date.now()]);
|
|
2693
|
-
if (oldTimestamps.length
|
|
2788
|
+
if (oldTimestamps.length >= this._LManager.options.playerOptions.maxErrorsPerTime?.maxAmount) {
|
|
2694
2789
|
this._emitDebugEvent("TrackErrorMaxTracksErroredPerTime" /* TrackErrorMaxTracksErroredPerTime */, {
|
|
2695
2790
|
state: "log",
|
|
2696
2791
|
message: `TrackError Event was triggered too often within a given threshold (LavalinkManager.options.playerOptions.maxErrorsPerTime). Threshold: "${this._LManager.options.playerOptions.maxErrorsPerTime?.threshold}ms", maxAmount: "${this._LManager.options.playerOptions.maxErrorsPerTime?.maxAmount}"`,
|
|
@@ -3750,6 +3845,7 @@ var FilterManager = class {
|
|
|
3750
3845
|
}
|
|
3751
3846
|
const now = performance.now();
|
|
3752
3847
|
if (this.player.options.instaUpdateFiltersFix === true) this.filterUpdatedState = true;
|
|
3848
|
+
this.player.triggerPlayerClientUpdate();
|
|
3753
3849
|
await this.player.node.updatePlayer({
|
|
3754
3850
|
guildId: this.player.guildId,
|
|
3755
3851
|
playerOptions: {
|
|
@@ -3844,7 +3940,7 @@ var FilterManager = class {
|
|
|
3844
3940
|
this.filters.tremolo = false;
|
|
3845
3941
|
this.filters.vibrato = false;
|
|
3846
3942
|
this.filters.karaoke = false;
|
|
3847
|
-
this.filters.
|
|
3943
|
+
this.filters.vaporwave = false;
|
|
3848
3944
|
this.filters.volume = false;
|
|
3849
3945
|
this.filters.nodeLinkEcho = false;
|
|
3850
3946
|
this.filters.nodeLinkChorus = false;
|
|
@@ -3925,7 +4021,7 @@ var FilterManager = class {
|
|
|
3925
4021
|
this.data = this.data ?? {};
|
|
3926
4022
|
this.filters.nightcore = false;
|
|
3927
4023
|
this.filters.vaporwave = false;
|
|
3928
|
-
this.data.timescale = { ...DEFAULT_FILTER_DATAS.timescale, speed };
|
|
4024
|
+
this.data.timescale = { ...DEFAULT_FILTER_DATAS.timescale, ...this.data.timescale, speed };
|
|
3929
4025
|
this.isCustomFilterActive();
|
|
3930
4026
|
await this.applyPlayerFilters();
|
|
3931
4027
|
return this;
|
|
@@ -3947,7 +4043,7 @@ var FilterManager = class {
|
|
|
3947
4043
|
this.data = this.data ?? {};
|
|
3948
4044
|
this.filters.nightcore = false;
|
|
3949
4045
|
this.filters.vaporwave = false;
|
|
3950
|
-
this.data.timescale = { ...DEFAULT_FILTER_DATAS.timescale, pitch };
|
|
4046
|
+
this.data.timescale = { ...DEFAULT_FILTER_DATAS.timescale, ...this.data.timescale, pitch };
|
|
3951
4047
|
this.isCustomFilterActive();
|
|
3952
4048
|
await this.applyPlayerFilters();
|
|
3953
4049
|
return this;
|
|
@@ -3969,7 +4065,7 @@ var FilterManager = class {
|
|
|
3969
4065
|
this.data = this.data ?? {};
|
|
3970
4066
|
this.filters.nightcore = false;
|
|
3971
4067
|
this.filters.vaporwave = false;
|
|
3972
|
-
this.data.timescale = { ...DEFAULT_FILTER_DATAS.timescale, rate };
|
|
4068
|
+
this.data.timescale = { ...DEFAULT_FILTER_DATAS.timescale, ...this.data.timescale, rate };
|
|
3973
4069
|
this.isCustomFilterActive();
|
|
3974
4070
|
await this.applyPlayerFilters();
|
|
3975
4071
|
return this;
|
|
@@ -4398,6 +4494,7 @@ var FilterManager = class {
|
|
|
4398
4494
|
if (!this.player.node.sessionId) throw new Error("The Lavalink-Node is either not ready or not up to date");
|
|
4399
4495
|
const now = performance.now();
|
|
4400
4496
|
if (this.player.options.instaUpdateFiltersFix === true) this.filterUpdatedState = true;
|
|
4497
|
+
this.player.triggerPlayerClientUpdate();
|
|
4401
4498
|
await this.player.node.updatePlayer({
|
|
4402
4499
|
guildId: this.player.guildId,
|
|
4403
4500
|
playerOptions: {
|
|
@@ -4554,7 +4651,7 @@ var Queue = class {
|
|
|
4554
4651
|
* @param queueOptions
|
|
4555
4652
|
*/
|
|
4556
4653
|
constructor(guildId, data = {}, QueueSaver2, queueOptions) {
|
|
4557
|
-
this.queueChanges = queueOptions
|
|
4654
|
+
this.queueChanges = queueOptions?.queueChangesWatcher || null;
|
|
4558
4655
|
this.guildId = guildId;
|
|
4559
4656
|
this.QueueSaver = QueueSaver2;
|
|
4560
4657
|
this.options.maxPreviousTracks = this.QueueSaver?.options?.maxPreviousTracks ?? this.options.maxPreviousTracks;
|
|
@@ -4605,7 +4702,7 @@ var Queue = class {
|
|
|
4605
4702
|
))
|
|
4606
4703
|
this.previous.splice(
|
|
4607
4704
|
0,
|
|
4608
|
-
override ? this.
|
|
4705
|
+
override ? this.previous.length : 0,
|
|
4609
4706
|
...data.previous.filter(
|
|
4610
4707
|
(track) => this.managerUtils.isTrack(track) || this.managerUtils.isUnresolvedTrack(track)
|
|
4611
4708
|
)
|
|
@@ -4620,8 +4717,8 @@ var Queue = class {
|
|
|
4620
4717
|
* @returns {{current:Track|null, previous:Track[], tracks:Track[]}}The Queue, but in a raw State, which allows easier handling for the QueueStoreManager
|
|
4621
4718
|
*/
|
|
4622
4719
|
toJSON: () => {
|
|
4623
|
-
if (this.previous
|
|
4624
|
-
this.previous
|
|
4720
|
+
if (this.previous?.length > this.options?.maxPreviousTracks)
|
|
4721
|
+
this.previous?.splice(this.options?.maxPreviousTracks, this.previous.length);
|
|
4625
4722
|
return {
|
|
4626
4723
|
current: this.current ? { ...this.current } : null,
|
|
4627
4724
|
previous: this.previous ? [...this.previous] : [],
|
|
@@ -5437,6 +5534,17 @@ var Player = class {
|
|
|
5437
5534
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
5438
5535
|
return this;
|
|
5439
5536
|
}
|
|
5537
|
+
/**
|
|
5538
|
+
* The old JSON of the player, used for the "playerClientUpdate" event, which is emitted on every update of the player via a function call, so that you can compare the old data with the new data and do something with it if you want to.
|
|
5539
|
+
*/
|
|
5540
|
+
oldJSON = this.toJSON();
|
|
5541
|
+
/**
|
|
5542
|
+
* Emits the "playerClientUpdate" event, which is emitted on every update of the player via a function call, so that you can compare the old data with the new data and do something with it if you want to.
|
|
5543
|
+
*/
|
|
5544
|
+
triggerPlayerClientUpdate() {
|
|
5545
|
+
this.LavalinkManager.emit("playerClientUpdate", this.oldJSON, this);
|
|
5546
|
+
this.oldJSON = this.toJSON();
|
|
5547
|
+
}
|
|
5440
5548
|
/**
|
|
5441
5549
|
* Set the Volume for the Player
|
|
5442
5550
|
* @param volume The Volume in percent
|
|
@@ -5457,6 +5565,7 @@ var Player = class {
|
|
|
5457
5565
|
0
|
|
5458
5566
|
)
|
|
5459
5567
|
);
|
|
5568
|
+
this.triggerPlayerClientUpdate();
|
|
5460
5569
|
const now = performance.now();
|
|
5461
5570
|
if (this.LavalinkManager.options.playerOptions.applyVolumeAsFilter) {
|
|
5462
5571
|
this._emitDebugEvent("PlayerVolumeAsFilter" /* PlayerVolumeAsFilter */, {
|
|
@@ -5531,6 +5640,7 @@ var Player = class {
|
|
|
5531
5640
|
this.paused = true;
|
|
5532
5641
|
this.lastPositionChange = null;
|
|
5533
5642
|
const now = performance.now();
|
|
5643
|
+
this.triggerPlayerClientUpdate();
|
|
5534
5644
|
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { paused: true } });
|
|
5535
5645
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
5536
5646
|
this.LavalinkManager.emit("playerPaused", this, this.queue.current);
|
|
@@ -5543,6 +5653,7 @@ var Player = class {
|
|
|
5543
5653
|
if (!this.paused) throw new Error("Player isn't paused - not able to resume.");
|
|
5544
5654
|
this.paused = false;
|
|
5545
5655
|
const now = performance.now();
|
|
5656
|
+
this.triggerPlayerClientUpdate();
|
|
5546
5657
|
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { paused: false } });
|
|
5547
5658
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
5548
5659
|
this.LavalinkManager.emit("playerResumed", this, this.queue.current);
|
|
@@ -5563,6 +5674,7 @@ var Player = class {
|
|
|
5563
5674
|
this.lastPositionChange = Date.now();
|
|
5564
5675
|
this.lastPosition = position;
|
|
5565
5676
|
const now = performance.now();
|
|
5677
|
+
this.triggerPlayerClientUpdate();
|
|
5566
5678
|
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { position } });
|
|
5567
5679
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
5568
5680
|
return this;
|
|
@@ -5575,6 +5687,7 @@ var Player = class {
|
|
|
5575
5687
|
if (!["off", "track", "queue"].includes(repeatMode))
|
|
5576
5688
|
throw new RangeError("Repeatmode must be either 'off', 'track', or 'queue'");
|
|
5577
5689
|
this.repeatMode = repeatMode;
|
|
5690
|
+
this.triggerPlayerClientUpdate();
|
|
5578
5691
|
return this;
|
|
5579
5692
|
}
|
|
5580
5693
|
/**
|
|
@@ -5829,7 +5942,7 @@ var Player = class {
|
|
|
5829
5942
|
functionLayer: "Player > changeNode()"
|
|
5830
5943
|
});
|
|
5831
5944
|
});
|
|
5832
|
-
} else {
|
|
5945
|
+
} else if (this.LavalinkManager.options?.playerOptions?.enforceSponsorBlockRequestForEventEnablement !== false) {
|
|
5833
5946
|
await this.setSponsorBlock().catch((error) => {
|
|
5834
5947
|
this._emitDebugEvent("PlayerChangeNode" /* PlayerChangeNode */, {
|
|
5835
5948
|
state: "error",
|
|
@@ -5925,7 +6038,7 @@ var Player = class {
|
|
|
5925
6038
|
nodeId: this.node?.id,
|
|
5926
6039
|
nodeSessionId: this.node?.sessionId,
|
|
5927
6040
|
ping: this.ping,
|
|
5928
|
-
queue: this.queue
|
|
6041
|
+
queue: this.queue?.utils?.toJSON?.()
|
|
5929
6042
|
};
|
|
5930
6043
|
}
|
|
5931
6044
|
};
|
|
@@ -6008,6 +6121,7 @@ var LavalinkManager = class extends EventEmitter2 {
|
|
|
6008
6121
|
applyVolumeAsFilter: options?.playerOptions?.applyVolumeAsFilter ?? false,
|
|
6009
6122
|
clientBasedPositionUpdateInterval: options?.playerOptions?.clientBasedPositionUpdateInterval ?? 100,
|
|
6010
6123
|
defaultSearchPlatform: options?.playerOptions?.defaultSearchPlatform ?? "ytsearch",
|
|
6124
|
+
allowCustomSources: options?.playerOptions?.allowCustomSources ?? false,
|
|
6011
6125
|
onDisconnect: {
|
|
6012
6126
|
destroyPlayer: options?.playerOptions?.onDisconnect?.destroyPlayer ?? true,
|
|
6013
6127
|
autoReconnect: options?.playerOptions?.onDisconnect?.autoReconnect ?? false,
|
|
@@ -6024,7 +6138,8 @@ var LavalinkManager = class extends EventEmitter2 {
|
|
|
6024
6138
|
maxErrorsPerTime: {
|
|
6025
6139
|
threshold: options?.playerOptions?.maxErrorsPerTime?.threshold ?? 35e3,
|
|
6026
6140
|
maxAmount: options?.playerOptions?.maxErrorsPerTime?.maxAmount ?? 3
|
|
6027
|
-
}
|
|
6141
|
+
},
|
|
6142
|
+
enforceSponsorBlockRequestForEventEnablement: options?.playerOptions?.enforceSponsorBlockRequestForEventEnablement ?? true
|
|
6028
6143
|
},
|
|
6029
6144
|
linksWhitelist: options?.linksWhitelist ?? [],
|
|
6030
6145
|
linksBlacklist: options?.linksBlacklist ?? [],
|
|
@@ -6124,6 +6239,7 @@ var LavalinkManager = class extends EventEmitter2 {
|
|
|
6124
6239
|
* applyVolumeAsFilter: false,
|
|
6125
6240
|
* clientBasedPositionUpdateInterval: 150,
|
|
6126
6241
|
* defaultSearchPlatform: "ytmsearch",
|
|
6242
|
+
* allowCustomSources: false,
|
|
6127
6243
|
* volumeDecrementer: 0.75,
|
|
6128
6244
|
* //requesterTransformer: YourRequesterTransformerFunction,
|
|
6129
6245
|
* onDisconnect: {
|
package/package.json
CHANGED