lavalink-client 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,21 +14,34 @@ npm install tomato6966/lavalink-client
14
14
 
15
15
  # Features
16
16
 
17
- - Player-Destroy Reasons like:
17
+ - 💯 Lavalink v4 Supported only (with Lavalink Plugins)
18
+
19
+ - ✅ Player-Destroy Reasons like:
18
20
  - Channel got deleted, Player got disconnected...
19
- - Choose able queue stores (maps, collections, redis, databases, ...)
21
+
22
+ - ✨ Choose able queue stores (maps, collections, redis, databases, ...)
20
23
  - You can create your own queueStore, thus make it easy to sync queues accross multiple connections (e.g. dashboard-bot)
21
- - Included Filter & Equalizer Management
22
- - Multiple Player Options
24
+
25
+ - 😍 Included Filter & Equalizer Management
26
+
27
+ - 👍 Multiple Player Options *for easier use*
23
28
  - onDisconnect -> Player Destroy / auto Reconnect
24
29
  - onEmptyQueue -> Player Destroy / leave After x Time
25
30
  - instaFixFilter -> seek the player after applying a filter, to instantly apply it's effect (only works for little-durational-songs)
26
31
  - applyVolumeAsFilter -> instead of using lavalink.volume, it uses lavalink.filters.volume which is much different!
27
- - Lavalink Validations
32
+
33
+ - 🛡️ Lavalink Validations
28
34
  - It only let's you use the filters / plugins / sources, if Lavalink actually has it enabled
29
- - Memory friendly and easy style
35
+
36
+ - 🧑‍💻 Memory friendly and easy style
30
37
  - Only the required data is displayed, and the store-way & types match Lavalink#IMPLEMENTATION.md
31
- - Much much more!
38
+
39
+ - 😘 Automated Handlings
40
+ - Skips the songs, on TrackEnd, TrackStuck, TrackError,
41
+ - Destroys the player on channeldelete
42
+ - Pauses / resumes the player if it get's muted / unmuted (server-wide) [soon]
43
+ - ...
44
+ - 😁 Much much more!
32
45
 
33
46
  # Documentation
34
47
 
@@ -113,4 +126,13 @@ await player.play(); // you can provide specific track, or let the manager choos
113
126
 
114
127
  ## Example (typescript)
115
128
 
116
- Can be found in the [/testBot](https://github.com/Tomato6966/lavalink-client/blob/main/testBot/README.md) Directory
129
+ Can be found in the [`/testBot`](https://github.com/Tomato6966/lavalink-client/blob/main/testBot/README.md) Directory
130
+
131
+ It contains the following features:
132
+
133
+ - Example Use for `Redis based Queue`
134
+ - Example Use for `Queue Changes Watcher Logger`
135
+ - Example Use for `Filters`, `Audio Output`, `equalizers`
136
+ - How to make an easy, yet advanced `Slash Commands Only Bot`
137
+ - `Slim Memory Usage`
138
+ - `All lavalink-client events` displayments
@@ -18,15 +18,26 @@ export interface BotClientOptions {
18
18
  [x: string | number | symbol | undefined]: any;
19
19
  }
20
20
  export interface LavalinkPlayerOptions {
21
+ /** If the Lavalink Volume should be decremented by x number */
21
22
  volumeDecrementer?: number;
22
- clientBasedUpdateInterval?: number;
23
+ /** How often it should update the the player Position */
24
+ clientBasedPositionUpdateInterval?: number;
25
+ /** What should be used as a searchPlatform, if no source was provided during the query */
23
26
  defaultSearchPlatform?: SearchPlatform;
27
+ /** Applies the volume via a filter, not via the lavalink volume transformer */
24
28
  applyVolumeAsFilter?: boolean;
29
+ /** Transforms the saved data of a requested user */
30
+ requesterTransformer?: (requester: unknown) => unknown;
31
+ /** What lavalink-client should do when the player reconnects */
25
32
  onDisconnect?: {
33
+ /** Try to reconnect? -> If fails -> Destroy */
26
34
  autoReconnect?: boolean;
35
+ /** Instantly destroy player (overrides autoReconnect) */
27
36
  destroyPlayer?: boolean;
28
37
  };
29
38
  onEmptyQueue?: {
39
+ /** Get's executed onEmptyQueue -> You can do any track queue previous transformations, if you add a track to the queue -> it will play it, if not queueEnd will execute! */
40
+ autoPlayFunction?: (player: Player, lastPlayedTrack: Track) => Promise<void>;
30
41
  destroyAfterMs?: number;
31
42
  };
32
43
  }
@@ -40,6 +40,7 @@ exports.DefaultSources = {
40
40
  // speak PLUGIN
41
41
  "speak": "speak",
42
42
  "tts": "tts",
43
+ "ftts": "ftts"
43
44
  };
44
45
  exports.SourceLinksRegexes = {
45
46
  /** DEFAULT SUPPORTED BY LAVALINK */
@@ -449,15 +449,15 @@ class LavalinkNode {
449
449
  player.ping.ws = payload.state.ping >= 0 ? payload.state.ping : player.ping.ws <= 0 && player.connected ? null : player.ping.ws || 0;
450
450
  if (!player.createdTimeStamp && payload.state.time)
451
451
  player.createdTimeStamp = payload.state.time;
452
- if (typeof this.NodeManager.LavalinkManager.options.playerOptions.clientBasedUpdateInterval === "number" && this.NodeManager.LavalinkManager.options.playerOptions.clientBasedUpdateInterval >= 10) {
452
+ if (typeof this.NodeManager.LavalinkManager.options.playerOptions.clientBasedPositionUpdateInterval === "number" && this.NodeManager.LavalinkManager.options.playerOptions.clientBasedPositionUpdateInterval >= 10) {
453
453
  player.set("internal_updateInterval", setInterval(() => {
454
- player.position += this.NodeManager.LavalinkManager.options.playerOptions.clientBasedUpdateInterval || 250;
454
+ player.position += this.NodeManager.LavalinkManager.options.playerOptions.clientBasedPositionUpdateInterval || 250;
455
455
  if (player.filterManager.filterUpdatedState >= 1) {
456
456
  player.filterManager.filterUpdatedState++;
457
457
  const maxMins = 8;
458
458
  const currentDuration = player.queue.current?.info?.duration || 0;
459
459
  if (currentDuration <= maxMins * 6e4 || (0, path_1.isAbsolute)(player.queue.current?.info?.uri)) {
460
- if (player.filterManager.filterUpdatedState >= ((this.NodeManager.LavalinkManager.options.playerOptions.clientBasedUpdateInterval || 250) > 400 ? 2 : 3)) {
460
+ if (player.filterManager.filterUpdatedState >= ((this.NodeManager.LavalinkManager.options.playerOptions.clientBasedPositionUpdateInterval || 250) > 400 ? 2 : 3)) {
461
461
  player.filterManager.filterUpdatedState = 0;
462
462
  player.seek(player.position);
463
463
  }
@@ -466,7 +466,7 @@ class LavalinkNode {
466
466
  player.filterManager.filterUpdatedState = 0;
467
467
  }
468
468
  }
469
- }, this.NodeManager.LavalinkManager.options.playerOptions.clientBasedUpdateInterval || 250));
469
+ }, this.NodeManager.LavalinkManager.options.playerOptions.clientBasedPositionUpdateInterval || 250));
470
470
  }
471
471
  else {
472
472
  if (player.filterManager.filterUpdatedState >= 1) { // if no interval but instafix available, findable via the "filterUpdatedState" property
@@ -495,7 +495,6 @@ class LavalinkNode {
495
495
  const player = this.NodeManager.LavalinkManager.getPlayer(payload.guildId);
496
496
  if (!player)
497
497
  return;
498
- console.log(payload.type);
499
498
  switch (payload.type) {
500
499
  case "TrackStartEvent":
501
500
  this.trackStart(player, player.queue.current, payload);
@@ -555,6 +554,13 @@ class LavalinkNode {
555
554
  async queueEnd(player, track, payload) {
556
555
  player.queue.current = null;
557
556
  player.playing = false;
557
+ if (typeof this.NodeManager.LavalinkManager.options?.playerOptions?.onEmptyQueue?.autoPlayFunction === "function") {
558
+ await this.NodeManager.LavalinkManager.options?.playerOptions?.onEmptyQueue?.autoPlayFunction(player, track);
559
+ if (player.queue.tracks.length > 0)
560
+ await (0, Utils_1.queueTrackEnd)(player.queue, player.repeatMode === "queue");
561
+ if (player.queue.current)
562
+ return player.play({ track: player.queue.current, noReplace: true, paused: false });
563
+ }
558
564
  if (payload?.reason !== "stopped") {
559
565
  await player.queue.utils.save();
560
566
  }
@@ -203,8 +203,9 @@ class Player {
203
203
  Query.source = LavalinkManagerStatics_1.DefaultSources[foundSource]; // set the source to ytsearch:
204
204
  Query.query = Query.query.replace(`${foundSource}:`, ""); // remove ytsearch: from the query
205
205
  }
206
- // request the data
207
- const res = await this.node.request(`/loadtracks?identifier=${!/^https?:\/\//.test(Query.query) ? `${Query.source}:` : ""}${encodeURIComponent(Query.query)}`);
206
+ // ftts query parameters: ?voice=Olivia&audio_format=ogg_opus&translate=False&silence=1000&speed=1.0 | example raw get query: https://api.flowery.pw/v1/tts?voice=Olivia&audio_format=ogg_opus&translate=False&silence=0&speed=1.0&text=Hello%20World
207
+ // request the data
208
+ const res = await this.node.request(`/loadtracks?identifier=${!/^https?:\/\//.test(Query.query) ? `${Query.source}:${Query.source === "ftts" ? "//" : ""}` : ""}${encodeURIComponent(Query.query)}`);
208
209
  // transform the data which can be Error, Track or Track[] to enfore [Track]
209
210
  const resTracks = res.loadType === "playlist" ? res.data?.tracks : res.loadType === "track" ? [res.data] : res.loadType === "search" ? Array.isArray(res.data) ? res.data : [res.data] : [];
210
211
  return {
@@ -74,7 +74,6 @@ class Queue {
74
74
  this.current = this.managerUtils.isTrack(data.current) ? data.current : null;
75
75
  this.previous = Array.isArray(data.previous) && data.previous.some(track => this.managerUtils.isTrack(track)) ? data.previous.filter(track => this.managerUtils.isTrack(track)) : [];
76
76
  this.tracks = Array.isArray(data.tracks) && data.tracks.some(track => this.managerUtils.isTrack(track)) ? data.tracks.filter(track => this.managerUtils.isTrack(track)) : [];
77
- this.utils.sync(false, true);
78
77
  }
79
78
  /**
80
79
  * Utils for a Queue
@@ -1,4 +1,7 @@
1
1
  import { Base64 } from "./Utils";
2
+ type LavalinkSourceNames = "youtube" | "youtubemusic" | "soundcloud" | "bandcamp" | "twitch";
3
+ type LavalinkPlugin_LavaSrc_SourceNames = "deezer" | "spotify" | "applemusic" | "yandexmusic" | "flowery-tts";
4
+ type SourceNames = LavalinkSourceNames | LavalinkPlugin_LavaSrc_SourceNames;
2
5
  export interface TrackInfo {
3
6
  identifier: string;
4
7
  title: string;
@@ -6,7 +9,7 @@ export interface TrackInfo {
6
9
  duration: number;
7
10
  artworkUrl: string | null;
8
11
  uri: string;
9
- sourceName: string;
12
+ sourceName: SourceNames;
10
13
  isSeekable: boolean;
11
14
  isStream: boolean;
12
15
  isrc: string | null;
@@ -24,6 +27,10 @@ export interface PluginInfo {
24
27
  url?: string;
25
28
  /** The Url provided by a Plugin */
26
29
  uri?: string;
30
+ /** You can put specific track information here, to transform the tracks... */
31
+ clientData?: {
32
+ [key: string]: any;
33
+ };
27
34
  }
28
35
  export interface LavalinkTrack {
29
36
  /** The Base 64 encoded String */
@@ -45,3 +52,4 @@ export interface UnresolvedQuery {
45
52
  /** The Track's Requester */
46
53
  requester?: unknown;
47
54
  }
55
+ export {};
@@ -8,7 +8,7 @@ export declare const TrackSymbol: unique symbol;
8
8
  export declare const UnresolvedTrackSymbol: unique symbol;
9
9
  export declare const QueueSymbol: unique symbol;
10
10
  export declare const NodeSymbol: unique symbol;
11
- export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "sprec" | "ymsearch" | "speak" | "tts";
11
+ export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "sprec" | "ymsearch" | "speak" | "tts" | "ftts";
12
12
  export type ClientSearchPlatform = "youtube" | "yt" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "yandex music" | "sp" | "sprec" | "spsuggestion" | "spotify" | "dz" | "deezer" | "yandex" | "yandexmusic";
13
13
  export type SearchPlatform = LavalinkSearchPlatform | ClientSearchPlatform;
14
14
  export type SourcesRegex = "YoutubeRegex" | "YoutubeMusicRegex" | "SoundCloudRegex" | "SoundCloudMobileRegex" | "DeezerTrackRegex" | "DeezerArtistRegex" | "DeezerEpisodeRegex" | "DeezerMixesRegex" | "DeezerPageLinkRegex" | "DeezerPlaylistRegex" | "DeezerAlbumRegex" | "AllDeezerRegex" | "AllDeezerRegexWithoutPageLink" | "SpotifySongRegex" | "SpotifyPlaylistRegex" | "SpotifyArtistRegex" | "SpotifyEpisodeRegex" | "SpotifyShowRegex" | "SpotifyAlbumRegex" | "AllSpotifyRegex" | "mp3Url" | "m3uUrl" | "m3u8Url" | "mp4Url" | "m4aUrl" | "wavUrl" | "aacpUrl" | "tiktok" | "mixcloud" | "musicYandex" | "radiohost" | "bandcamp" | "appleMusic" | "TwitchTv" | "vimeo";
@@ -24,7 +24,7 @@ class ManagerUitls {
24
24
  title: data.info?.title,
25
25
  author: data.info?.author,
26
26
  duration: data.info?.length,
27
- artworkUrl: data.info?.artworkUrl || data.pluginInfo?.artworkUrl || data.plugin?.artworkUrl || ["youtube.", "youtu.be"].some(d => data.info?.uri?.includes?.(d)) ? `https://img.youtube.com/vi/${data.info?.identifier}/mqdefault.jpg` : undefined,
27
+ artworkUrl: data.info?.artworkUrl || data.pluginInfo?.artworkUrl || data.plugin?.artworkUrl,
28
28
  uri: data.info?.uri,
29
29
  sourceName: data.info?.sourceName,
30
30
  isSeekable: data.info?.isSeekable,
@@ -32,7 +32,7 @@ class ManagerUitls {
32
32
  isrc: data.info?.isrc,
33
33
  },
34
34
  pluginInfo: data.pluginInfo || data.plugin || {},
35
- requester: data?.requester || requester,
35
+ requester: typeof this.manager.options?.playerOptions?.requesterTransformer === "function" ? this.manager.options?.playerOptions?.requesterTransformer(data?.requester || requester) : requester,
36
36
  };
37
37
  Object.defineProperty(r, exports.TrackSymbol, { configurable: true, value: true });
38
38
  return r;
@@ -121,6 +121,10 @@ class ManagerUitls {
121
121
  if (source === "tts" && !node.info.sourceManagers.includes("tts")) {
122
122
  throw new Error("Lavalink Node has not 'tts' enabled, which is required to have 'tts' work");
123
123
  }
124
+ if (source === "ftts" && !node.info.sourceManagers.includes("ftts")) {
125
+ console.log(node.info.sourceManagers);
126
+ throw new Error("Lavalink Node has not 'ftts' enabled, which is required to have 'ftts' work");
127
+ }
124
128
  if (source === "ymsearch" && !node.info.sourceManagers.includes("yandexmusic")) {
125
129
  throw new Error("Lavalink Node has not 'yandexmusic' enabled, which is required to have 'ymsearch' work");
126
130
  }
@@ -18,15 +18,26 @@ export interface BotClientOptions {
18
18
  [x: string | number | symbol | undefined]: any;
19
19
  }
20
20
  export interface LavalinkPlayerOptions {
21
+ /** If the Lavalink Volume should be decremented by x number */
21
22
  volumeDecrementer?: number;
22
- clientBasedUpdateInterval?: number;
23
+ /** How often it should update the the player Position */
24
+ clientBasedPositionUpdateInterval?: number;
25
+ /** What should be used as a searchPlatform, if no source was provided during the query */
23
26
  defaultSearchPlatform?: SearchPlatform;
27
+ /** Applies the volume via a filter, not via the lavalink volume transformer */
24
28
  applyVolumeAsFilter?: boolean;
29
+ /** Transforms the saved data of a requested user */
30
+ requesterTransformer?: (requester: unknown) => unknown;
31
+ /** What lavalink-client should do when the player reconnects */
25
32
  onDisconnect?: {
33
+ /** Try to reconnect? -> If fails -> Destroy */
26
34
  autoReconnect?: boolean;
35
+ /** Instantly destroy player (overrides autoReconnect) */
27
36
  destroyPlayer?: boolean;
28
37
  };
29
38
  onEmptyQueue?: {
39
+ /** Get's executed onEmptyQueue -> You can do any track queue previous transformations, if you add a track to the queue -> it will play it, if not queueEnd will execute! */
40
+ autoPlayFunction?: (player: Player, lastPlayedTrack: Track) => Promise<void>;
30
41
  destroyAfterMs?: number;
31
42
  };
32
43
  }
@@ -37,6 +37,7 @@ export const DefaultSources = {
37
37
  // speak PLUGIN
38
38
  "speak": "speak",
39
39
  "tts": "tts",
40
+ "ftts": "ftts"
40
41
  };
41
42
  export const SourceLinksRegexes = {
42
43
  /** DEFAULT SUPPORTED BY LAVALINK */
@@ -445,15 +445,15 @@ export class LavalinkNode {
445
445
  player.ping.ws = payload.state.ping >= 0 ? payload.state.ping : player.ping.ws <= 0 && player.connected ? null : player.ping.ws || 0;
446
446
  if (!player.createdTimeStamp && payload.state.time)
447
447
  player.createdTimeStamp = payload.state.time;
448
- if (typeof this.NodeManager.LavalinkManager.options.playerOptions.clientBasedUpdateInterval === "number" && this.NodeManager.LavalinkManager.options.playerOptions.clientBasedUpdateInterval >= 10) {
448
+ if (typeof this.NodeManager.LavalinkManager.options.playerOptions.clientBasedPositionUpdateInterval === "number" && this.NodeManager.LavalinkManager.options.playerOptions.clientBasedPositionUpdateInterval >= 10) {
449
449
  player.set("internal_updateInterval", setInterval(() => {
450
- player.position += this.NodeManager.LavalinkManager.options.playerOptions.clientBasedUpdateInterval || 250;
450
+ player.position += this.NodeManager.LavalinkManager.options.playerOptions.clientBasedPositionUpdateInterval || 250;
451
451
  if (player.filterManager.filterUpdatedState >= 1) {
452
452
  player.filterManager.filterUpdatedState++;
453
453
  const maxMins = 8;
454
454
  const currentDuration = player.queue.current?.info?.duration || 0;
455
455
  if (currentDuration <= maxMins * 6e4 || isAbsolute(player.queue.current?.info?.uri)) {
456
- if (player.filterManager.filterUpdatedState >= ((this.NodeManager.LavalinkManager.options.playerOptions.clientBasedUpdateInterval || 250) > 400 ? 2 : 3)) {
456
+ if (player.filterManager.filterUpdatedState >= ((this.NodeManager.LavalinkManager.options.playerOptions.clientBasedPositionUpdateInterval || 250) > 400 ? 2 : 3)) {
457
457
  player.filterManager.filterUpdatedState = 0;
458
458
  player.seek(player.position);
459
459
  }
@@ -462,7 +462,7 @@ export class LavalinkNode {
462
462
  player.filterManager.filterUpdatedState = 0;
463
463
  }
464
464
  }
465
- }, this.NodeManager.LavalinkManager.options.playerOptions.clientBasedUpdateInterval || 250));
465
+ }, this.NodeManager.LavalinkManager.options.playerOptions.clientBasedPositionUpdateInterval || 250));
466
466
  }
467
467
  else {
468
468
  if (player.filterManager.filterUpdatedState >= 1) { // if no interval but instafix available, findable via the "filterUpdatedState" property
@@ -491,7 +491,6 @@ export class LavalinkNode {
491
491
  const player = this.NodeManager.LavalinkManager.getPlayer(payload.guildId);
492
492
  if (!player)
493
493
  return;
494
- console.log(payload.type);
495
494
  switch (payload.type) {
496
495
  case "TrackStartEvent":
497
496
  this.trackStart(player, player.queue.current, payload);
@@ -551,6 +550,13 @@ export class LavalinkNode {
551
550
  async queueEnd(player, track, payload) {
552
551
  player.queue.current = null;
553
552
  player.playing = false;
553
+ if (typeof this.NodeManager.LavalinkManager.options?.playerOptions?.onEmptyQueue?.autoPlayFunction === "function") {
554
+ await this.NodeManager.LavalinkManager.options?.playerOptions?.onEmptyQueue?.autoPlayFunction(player, track);
555
+ if (player.queue.tracks.length > 0)
556
+ await queueTrackEnd(player.queue, player.repeatMode === "queue");
557
+ if (player.queue.current)
558
+ return player.play({ track: player.queue.current, noReplace: true, paused: false });
559
+ }
554
560
  if (payload?.reason !== "stopped") {
555
561
  await player.queue.utils.save();
556
562
  }
@@ -200,8 +200,9 @@ export class Player {
200
200
  Query.source = DefaultSources[foundSource]; // set the source to ytsearch:
201
201
  Query.query = Query.query.replace(`${foundSource}:`, ""); // remove ytsearch: from the query
202
202
  }
203
- // request the data
204
- const res = await this.node.request(`/loadtracks?identifier=${!/^https?:\/\//.test(Query.query) ? `${Query.source}:` : ""}${encodeURIComponent(Query.query)}`);
203
+ // ftts query parameters: ?voice=Olivia&audio_format=ogg_opus&translate=False&silence=1000&speed=1.0 | example raw get query: https://api.flowery.pw/v1/tts?voice=Olivia&audio_format=ogg_opus&translate=False&silence=0&speed=1.0&text=Hello%20World
204
+ // request the data
205
+ const res = await this.node.request(`/loadtracks?identifier=${!/^https?:\/\//.test(Query.query) ? `${Query.source}:${Query.source === "ftts" ? "//" : ""}` : ""}${encodeURIComponent(Query.query)}`);
205
206
  // transform the data which can be Error, Track or Track[] to enfore [Track]
206
207
  const resTracks = res.loadType === "playlist" ? res.data?.tracks : res.loadType === "track" ? [res.data] : res.loadType === "search" ? Array.isArray(res.data) ? res.data : [res.data] : [];
207
208
  return {
@@ -68,7 +68,6 @@ export class Queue {
68
68
  this.current = this.managerUtils.isTrack(data.current) ? data.current : null;
69
69
  this.previous = Array.isArray(data.previous) && data.previous.some(track => this.managerUtils.isTrack(track)) ? data.previous.filter(track => this.managerUtils.isTrack(track)) : [];
70
70
  this.tracks = Array.isArray(data.tracks) && data.tracks.some(track => this.managerUtils.isTrack(track)) ? data.tracks.filter(track => this.managerUtils.isTrack(track)) : [];
71
- this.utils.sync(false, true);
72
71
  }
73
72
  /**
74
73
  * Utils for a Queue
@@ -1,4 +1,7 @@
1
1
  import { Base64 } from "./Utils";
2
+ type LavalinkSourceNames = "youtube" | "youtubemusic" | "soundcloud" | "bandcamp" | "twitch";
3
+ type LavalinkPlugin_LavaSrc_SourceNames = "deezer" | "spotify" | "applemusic" | "yandexmusic" | "flowery-tts";
4
+ type SourceNames = LavalinkSourceNames | LavalinkPlugin_LavaSrc_SourceNames;
2
5
  export interface TrackInfo {
3
6
  identifier: string;
4
7
  title: string;
@@ -6,7 +9,7 @@ export interface TrackInfo {
6
9
  duration: number;
7
10
  artworkUrl: string | null;
8
11
  uri: string;
9
- sourceName: string;
12
+ sourceName: SourceNames;
10
13
  isSeekable: boolean;
11
14
  isStream: boolean;
12
15
  isrc: string | null;
@@ -24,6 +27,10 @@ export interface PluginInfo {
24
27
  url?: string;
25
28
  /** The Url provided by a Plugin */
26
29
  uri?: string;
30
+ /** You can put specific track information here, to transform the tracks... */
31
+ clientData?: {
32
+ [key: string]: any;
33
+ };
27
34
  }
28
35
  export interface LavalinkTrack {
29
36
  /** The Base 64 encoded String */
@@ -45,3 +52,4 @@ export interface UnresolvedQuery {
45
52
  /** The Track's Requester */
46
53
  requester?: unknown;
47
54
  }
55
+ export {};
@@ -8,7 +8,7 @@ export declare const TrackSymbol: unique symbol;
8
8
  export declare const UnresolvedTrackSymbol: unique symbol;
9
9
  export declare const QueueSymbol: unique symbol;
10
10
  export declare const NodeSymbol: unique symbol;
11
- export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "sprec" | "ymsearch" | "speak" | "tts";
11
+ export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "sprec" | "ymsearch" | "speak" | "tts" | "ftts";
12
12
  export type ClientSearchPlatform = "youtube" | "yt" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "yandex music" | "sp" | "sprec" | "spsuggestion" | "spotify" | "dz" | "deezer" | "yandex" | "yandexmusic";
13
13
  export type SearchPlatform = LavalinkSearchPlatform | ClientSearchPlatform;
14
14
  export type SourcesRegex = "YoutubeRegex" | "YoutubeMusicRegex" | "SoundCloudRegex" | "SoundCloudMobileRegex" | "DeezerTrackRegex" | "DeezerArtistRegex" | "DeezerEpisodeRegex" | "DeezerMixesRegex" | "DeezerPageLinkRegex" | "DeezerPlaylistRegex" | "DeezerAlbumRegex" | "AllDeezerRegex" | "AllDeezerRegexWithoutPageLink" | "SpotifySongRegex" | "SpotifyPlaylistRegex" | "SpotifyArtistRegex" | "SpotifyEpisodeRegex" | "SpotifyShowRegex" | "SpotifyAlbumRegex" | "AllSpotifyRegex" | "mp3Url" | "m3uUrl" | "m3u8Url" | "mp4Url" | "m4aUrl" | "wavUrl" | "aacpUrl" | "tiktok" | "mixcloud" | "musicYandex" | "radiohost" | "bandcamp" | "appleMusic" | "TwitchTv" | "vimeo";
@@ -21,7 +21,7 @@ export class ManagerUitls {
21
21
  title: data.info?.title,
22
22
  author: data.info?.author,
23
23
  duration: data.info?.length,
24
- artworkUrl: data.info?.artworkUrl || data.pluginInfo?.artworkUrl || data.plugin?.artworkUrl || ["youtube.", "youtu.be"].some(d => data.info?.uri?.includes?.(d)) ? `https://img.youtube.com/vi/${data.info?.identifier}/mqdefault.jpg` : undefined,
24
+ artworkUrl: data.info?.artworkUrl || data.pluginInfo?.artworkUrl || data.plugin?.artworkUrl,
25
25
  uri: data.info?.uri,
26
26
  sourceName: data.info?.sourceName,
27
27
  isSeekable: data.info?.isSeekable,
@@ -29,7 +29,7 @@ export class ManagerUitls {
29
29
  isrc: data.info?.isrc,
30
30
  },
31
31
  pluginInfo: data.pluginInfo || data.plugin || {},
32
- requester: data?.requester || requester,
32
+ requester: typeof this.manager.options?.playerOptions?.requesterTransformer === "function" ? this.manager.options?.playerOptions?.requesterTransformer(data?.requester || requester) : requester,
33
33
  };
34
34
  Object.defineProperty(r, TrackSymbol, { configurable: true, value: true });
35
35
  return r;
@@ -118,6 +118,10 @@ export class ManagerUitls {
118
118
  if (source === "tts" && !node.info.sourceManagers.includes("tts")) {
119
119
  throw new Error("Lavalink Node has not 'tts' enabled, which is required to have 'tts' work");
120
120
  }
121
+ if (source === "ftts" && !node.info.sourceManagers.includes("ftts")) {
122
+ console.log(node.info.sourceManagers);
123
+ throw new Error("Lavalink Node has not 'ftts' enabled, which is required to have 'ftts' work");
124
+ }
121
125
  if (source === "ymsearch" && !node.info.sourceManagers.includes("yandexmusic")) {
122
126
  throw new Error("Lavalink Node has not 'yandexmusic' enabled, which is required to have 'ymsearch' work");
123
127
  }
@@ -17,7 +17,7 @@ export interface BotClientOptions {
17
17
  }
18
18
  export interface LavalinkPlayerOptions {
19
19
  volumeDecrementer?: number;
20
- clientBasedUpdateInterval?: number;
20
+ clientBasedPositionUpdateInterval?: number;
21
21
  defaultSearchPlatform?: SearchPlatform;
22
22
  applyVolumeAsFilter?: boolean;
23
23
  }
@@ -18,15 +18,26 @@ export interface BotClientOptions {
18
18
  [x: string | number | symbol | undefined]: any;
19
19
  }
20
20
  export interface LavalinkPlayerOptions {
21
+ /** If the Lavalink Volume should be decremented by x number */
21
22
  volumeDecrementer?: number;
22
- clientBasedUpdateInterval?: number;
23
+ /** How often it should update the the player Position */
24
+ clientBasedPositionUpdateInterval?: number;
25
+ /** What should be used as a searchPlatform, if no source was provided during the query */
23
26
  defaultSearchPlatform?: SearchPlatform;
27
+ /** Applies the volume via a filter, not via the lavalink volume transformer */
24
28
  applyVolumeAsFilter?: boolean;
29
+ /** Transforms the saved data of a requested user */
30
+ requesterTransformer?: (requester: unknown) => unknown;
31
+ /** What lavalink-client should do when the player reconnects */
25
32
  onDisconnect?: {
33
+ /** Try to reconnect? -> If fails -> Destroy */
26
34
  autoReconnect?: boolean;
35
+ /** Instantly destroy player (overrides autoReconnect) */
27
36
  destroyPlayer?: boolean;
28
37
  };
29
38
  onEmptyQueue?: {
39
+ /** Get's executed onEmptyQueue -> You can do any track queue previous transformations, if you add a track to the queue -> it will play it, if not queueEnd will execute! */
40
+ autoPlayFunction?: (player: Player, lastPlayedTrack: Track) => Promise<void>;
30
41
  destroyAfterMs?: number;
31
42
  };
32
43
  }
@@ -1,4 +1,7 @@
1
1
  import { Base64 } from "./Utils";
2
+ type LavalinkSourceNames = "youtube" | "youtubemusic" | "soundcloud" | "bandcamp" | "twitch";
3
+ type LavalinkPlugin_LavaSrc_SourceNames = "deezer" | "spotify" | "applemusic" | "yandexmusic" | "flowery-tts";
4
+ type SourceNames = LavalinkSourceNames | LavalinkPlugin_LavaSrc_SourceNames;
2
5
  export interface TrackInfo {
3
6
  identifier: string;
4
7
  title: string;
@@ -6,7 +9,7 @@ export interface TrackInfo {
6
9
  duration: number;
7
10
  artworkUrl: string | null;
8
11
  uri: string;
9
- sourceName: string;
12
+ sourceName: SourceNames;
10
13
  isSeekable: boolean;
11
14
  isStream: boolean;
12
15
  isrc: string | null;
@@ -24,6 +27,10 @@ export interface PluginInfo {
24
27
  url?: string;
25
28
  /** The Url provided by a Plugin */
26
29
  uri?: string;
30
+ /** You can put specific track information here, to transform the tracks... */
31
+ clientData?: {
32
+ [key: string]: any;
33
+ };
27
34
  }
28
35
  export interface LavalinkTrack {
29
36
  /** The Base 64 encoded String */
@@ -45,3 +52,4 @@ export interface UnresolvedQuery {
45
52
  /** The Track's Requester */
46
53
  requester?: unknown;
47
54
  }
55
+ export {};
@@ -8,7 +8,7 @@ export declare const TrackSymbol: unique symbol;
8
8
  export declare const UnresolvedTrackSymbol: unique symbol;
9
9
  export declare const QueueSymbol: unique symbol;
10
10
  export declare const NodeSymbol: unique symbol;
11
- export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "sprec" | "ymsearch" | "speak" | "tts";
11
+ export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "sprec" | "ymsearch" | "speak" | "tts" | "ftts";
12
12
  export type ClientSearchPlatform = "youtube" | "yt" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "yandex music" | "sp" | "sprec" | "spsuggestion" | "spotify" | "dz" | "deezer" | "yandex" | "yandexmusic";
13
13
  export type SearchPlatform = LavalinkSearchPlatform | ClientSearchPlatform;
14
14
  export type SourcesRegex = "YoutubeRegex" | "YoutubeMusicRegex" | "SoundCloudRegex" | "SoundCloudMobileRegex" | "DeezerTrackRegex" | "DeezerArtistRegex" | "DeezerEpisodeRegex" | "DeezerMixesRegex" | "DeezerPageLinkRegex" | "DeezerPlaylistRegex" | "DeezerAlbumRegex" | "AllDeezerRegex" | "AllDeezerRegexWithoutPageLink" | "SpotifySongRegex" | "SpotifyPlaylistRegex" | "SpotifyArtistRegex" | "SpotifyEpisodeRegex" | "SpotifyShowRegex" | "SpotifyAlbumRegex" | "AllSpotifyRegex" | "mp3Url" | "m3uUrl" | "m3u8Url" | "mp4Url" | "m4aUrl" | "wavUrl" | "aacpUrl" | "tiktok" | "mixcloud" | "musicYandex" | "radiohost" | "bandcamp" | "appleMusic" | "TwitchTv" | "vimeo";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lavalink-client",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Easy and advanced lavalink client. Use it with lavalink plugins as well as latest lavalink versions",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",