lavalink-client 1.1.25 → 1.2.1

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.
@@ -215,6 +215,15 @@ class Player {
215
215
  async lavaSearch(query, requestUser) {
216
216
  return this.node.lavaSearch(query, requestUser);
217
217
  }
218
+ async setSponsorBlock(segments = ["sponsor", "selfpromo"]) {
219
+ return this.node.setSponsorBlock(this, segments);
220
+ }
221
+ async getSponsorBlock() {
222
+ return this.node.getSponsorBlock(this);
223
+ }
224
+ async deleteSponsorBlock() {
225
+ return this.node.deleteSponsorBlock(this);
226
+ }
218
227
  /**
219
228
  *
220
229
  * @param query Query for your data
@@ -222,10 +231,6 @@ class Player {
222
231
  */
223
232
  async search(query, requestUser) {
224
233
  const Query = this.LavalinkManager.utils.transformQuery(query);
225
- if (/^https?:\/\//.test(Query.query))
226
- this.LavalinkManager.utils.validateQueryString(this.node, Query.source);
227
- else if (Query.source)
228
- this.LavalinkManager.utils.validateSourceString(this.node, Query.source);
229
234
  if (["bcsearch", "bandcamp"].includes(Query.source))
230
235
  return await (0, BandCampSearch_1.bandCampSearch)(this, Query.query, requestUser);
231
236
  return this.node.search(Query, requestUser);
@@ -289,8 +294,8 @@ class Player {
289
294
  * Skip the current song, or a specific amount of songs
290
295
  * @param amount provide the index of the next track to skip to
291
296
  */
292
- async skip(skipTo = 0) {
293
- if (!this.queue.tracks.length)
297
+ async skip(skipTo = 0, throwError = true) {
298
+ if (!this.queue.tracks.length && (throwError || (typeof skipTo === "boolean" && skipTo === true)))
294
299
  throw new RangeError("Can't skip more than the queue size");
295
300
  if (typeof skipTo === "number" && skipTo > 1) {
296
301
  if (skipTo > this.queue.tracks.length)
@@ -304,13 +309,33 @@ class Player {
304
309
  this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
305
310
  return this;
306
311
  }
312
+ /**
313
+ * Clears the queue and stops playing. Does not destroy the Player and not leave the channel
314
+ * @returns
315
+ */
316
+ async stopPlaying(clearQueue = true, executeAutoplay = false) {
317
+ // use internal_stopPlaying on true, so that it doesn't utilize current loop states. on trackEnd event
318
+ this.set("internal_stopPlaying", true);
319
+ // remove tracks from the queue
320
+ if (this.queue.tracks.length && clearQueue === true)
321
+ await this.queue.splice(0, this.queue.tracks.length);
322
+ if (executeAutoplay === false)
323
+ this.set("internal_autoplayStopPlaying", true);
324
+ else
325
+ this.set("internal_autoplayStopPlaying", undefined);
326
+ const now = performance.now();
327
+ // send to lavalink, that it should stop playing
328
+ await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { encodedTrack: null } });
329
+ this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
330
+ return this;
331
+ }
307
332
  /**
308
333
  * Connects the Player to the Voice Channel
309
334
  * @returns
310
335
  */
311
336
  async connect() {
312
337
  if (!this.options.voiceChannelId)
313
- throw new RangeError("No Voice Channel id has been set.");
338
+ throw new RangeError("No Voice Channel id has been set. (player.options.voiceChannelId)");
314
339
  await this.LavalinkManager.options.sendToShard(this.guildId, {
315
340
  op: 4,
316
341
  d: {
@@ -320,6 +345,26 @@ class Player {
320
345
  self_deaf: this.options.selfDeaf ?? true,
321
346
  }
322
347
  });
348
+ this.voiceChannelId = this.options.voiceChannelId;
349
+ return this;
350
+ }
351
+ async changeVoiceState(data) {
352
+ if (this.options.voiceChannelId === data.voiceChannelId)
353
+ throw new RangeError("New Channel can't be equal to the old Channel.");
354
+ await this.LavalinkManager.options.sendToShard(this.guildId, {
355
+ op: 4,
356
+ d: {
357
+ guild_id: this.guildId,
358
+ channel_id: data.voiceChannelId,
359
+ self_mute: data.selfMute ?? this.options.selfMute ?? false,
360
+ self_deaf: data.selfDeaf ?? this.options.selfDeaf ?? true,
361
+ }
362
+ });
363
+ // override the options
364
+ this.options.voiceChannelId = data.voiceChannelId;
365
+ this.options.selfMute = data.selfMute;
366
+ this.options.selfDeaf = data.selfDeaf;
367
+ this.voiceChannelId = data.voiceChannelId;
323
368
  return this;
324
369
  }
325
370
  /**
@@ -329,7 +374,7 @@ class Player {
329
374
  */
330
375
  async disconnect(force = false) {
331
376
  if (!force && !this.options.voiceChannelId)
332
- throw new RangeError("No Voice Channel id has been set.");
377
+ throw new RangeError("No Voice Channel id has been set. (player.options.voiceChannelId)");
333
378
  await this.LavalinkManager.options.sendToShard(this.guildId, {
334
379
  op: 4,
335
380
  d: {
@@ -346,10 +391,10 @@ class Player {
346
391
  * Destroy the player and disconnect from the voice channel
347
392
  */
348
393
  async destroy(reason, disconnect = true) {
349
- if (this.LavalinkManager.options.debugOptions.playerDestroy.debugLog)
394
+ if (this.LavalinkManager.options.advancedOptions?.debugOptions.playerDestroy.debugLog)
350
395
  console.log(`Lavalink-Client-Debug | PlayerDestroy [::] destroy Function, [guildId ${this.guildId}] - Destroy-Reason: ${String(reason)}`);
351
396
  if (this.get("internal_destroystatus") === true) {
352
- if (this.LavalinkManager.options.debugOptions.playerDestroy.debugLog)
397
+ if (this.LavalinkManager.options.advancedOptions?.debugOptions.playerDestroy.debugLog)
353
398
  console.log(`Lavalink-Client-Debug | PlayerDestroy [::] destroy Function, [guildId ${this.guildId}] - Already destroying somewhere else..`);
354
399
  return;
355
400
  }
@@ -365,7 +410,7 @@ class Player {
365
410
  this.LavalinkManager.deletePlayer(this.guildId);
366
411
  // destroy the player on lavalink side
367
412
  await this.node.destroyPlayer(this.guildId);
368
- if (this.LavalinkManager.options.debugOptions.playerDestroy.debugLog)
413
+ if (this.LavalinkManager.options.advancedOptions?.debugOptions.playerDestroy.debugLog)
369
414
  console.log(`Lavalink-Client-Debug | PlayerDestroy [::] destroy Function, [guildId ${this.guildId}] - Player got destroyed successfully`);
370
415
  // emit the event
371
416
  this.LavalinkManager.emit("playerDestroy", this, reason);
@@ -18,7 +18,7 @@ export interface QueueStoreManager extends Record<string, any> {
18
18
  parse: (value: unknown) => Promise<Partial<StoredQueue>>;
19
19
  }
20
20
  export interface ManagerQueueOptions {
21
- /** Maximum Amount of tracks for the queue.previous array */
21
+ /** Maximum Amount of tracks for the queue.previous array. Set to 0 to not save previous songs. Defaults to 25 Tracks */
22
22
  maxPreviousTracks?: number;
23
23
  /** Custom Queue Store option */
24
24
  queueStore?: QueueStoreManager;
@@ -51,6 +51,17 @@ export interface UnresolvedSearchResult {
51
51
  playlist: PlaylistInfo | null;
52
52
  tracks: UnresolvedTrack[];
53
53
  }
54
+ /**
55
+ * Parses Node Connection Url: "lavalink://<nodeId>:<nodeAuthorization(Password)>@<NodeHost>:<NodePort>"
56
+ * @param connectionUrl
57
+ * @returns
58
+ */
59
+ export declare function parseLavalinkConnUrl(connectionUrl: string): {
60
+ authorization: string;
61
+ id: string;
62
+ host: string;
63
+ port: number;
64
+ };
54
65
  export declare class ManagerUtils {
55
66
  LavalinkManager: LavalinkManager | null;
56
67
  constructor(LavalinkManager?: LavalinkManager);
@@ -152,7 +163,7 @@ export declare class MiniMap<K, V> extends Map<K, V> {
152
163
  map<T>(fn: (value: V, key: K, miniMap: this) => T): T[];
153
164
  map<This, T>(fn: (this: This, value: V, key: K, miniMap: this) => T, thisArg: This): T[];
154
165
  }
155
- export type PlayerEvents = TrackStartEvent | TrackEndEvent | TrackStuckEvent | TrackExceptionEvent | WebSocketClosedEvent;
166
+ export type PlayerEvents = TrackStartEvent | TrackEndEvent | TrackStuckEvent | TrackExceptionEvent | WebSocketClosedEvent | SponsorBlockSegmentEvents;
156
167
  export type Severity = "COMMON" | "SUSPICIOUS" | "FAULT";
157
168
  export interface Exception {
158
169
  severity: Severity;
@@ -188,9 +199,52 @@ export interface WebSocketClosedEvent extends PlayerEvent {
188
199
  byRemote: boolean;
189
200
  reason: string;
190
201
  }
202
+ /**
203
+ * Types & Events for Sponsorblock-plugin from Lavalink: https://github.com/topi314/Sponsorblock-Plugin#segmentsloaded
204
+ */
205
+ export type SponsorBlockSegmentEvents = SponsorBlockSegmentSkipped | SponsorBlockSegmentsLoaded | SponsorBlockChapterStarted | SponsorBlockChaptersLoaded;
206
+ export type SponsorBlockSegmentEventType = "SegmentSkipped" | "SegmentsLoaded" | "ChaptersLoaded" | "ChapterStarted";
207
+ export interface SponsorBlockSegmentsLoaded extends PlayerEvent {
208
+ type: "SegmentsLoaded";
209
+ segments: {
210
+ category: string;
211
+ start: number;
212
+ end: number;
213
+ }[];
214
+ }
215
+ export interface SponsorBlockSegmentSkipped extends PlayerEvent {
216
+ type: "SegmentSkipped";
217
+ segment: {
218
+ category: string;
219
+ start: number;
220
+ end: number;
221
+ };
222
+ }
223
+ export interface SponsorBlockChapterStarted extends PlayerEvent {
224
+ type: "ChapterStarted";
225
+ /** The Chapter which started */
226
+ chapter: {
227
+ /** The Name of the Chapter */
228
+ name: string;
229
+ start: number;
230
+ end: number;
231
+ duration: number;
232
+ };
233
+ }
234
+ export interface SponsorBlockChaptersLoaded extends PlayerEvent {
235
+ type: "ChaptersLoaded";
236
+ /** All Chapters loaded */
237
+ chapters: {
238
+ /** The Name of the Chapter */
239
+ name: string;
240
+ start: number;
241
+ end: number;
242
+ duration: number;
243
+ }[];
244
+ }
191
245
  export type LoadTypes = "track" | "playlist" | "search" | "error" | "empty";
192
246
  export type State = "CONNECTED" | "CONNECTING" | "DISCONNECTED" | "DISCONNECTING" | "DESTROYING";
193
- export type PlayerEventType = "TrackStartEvent" | "TrackEndEvent" | "TrackExceptionEvent" | "TrackStuckEvent" | "WebSocketClosedEvent";
247
+ export type PlayerEventType = "TrackStartEvent" | "TrackEndEvent" | "TrackExceptionEvent" | "TrackStuckEvent" | "WebSocketClosedEvent" | SponsorBlockSegmentEventType;
194
248
  export type TrackEndReason = "finished" | "loadFailed" | "stopped" | "replaced" | "cleanup";
195
249
  export interface InvalidLavalinkRestRequest {
196
250
  timestamp: number;
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.queueTrackEnd = exports.MiniMap = exports.ManagerUtils = exports.NodeSymbol = exports.QueueSymbol = exports.UnresolvedTrackSymbol = exports.TrackSymbol = void 0;
3
+ exports.queueTrackEnd = exports.MiniMap = exports.ManagerUtils = exports.parseLavalinkConnUrl = exports.NodeSymbol = exports.QueueSymbol = exports.UnresolvedTrackSymbol = exports.TrackSymbol = void 0;
4
+ const node_url_1 = require("node:url");
5
+ const types_1 = require("node:util/types");
4
6
  const LavalinkManagerStatics_1 = require("./LavalinkManagerStatics");
5
7
  exports.TrackSymbol = Symbol("LC-Track");
6
8
  exports.UnresolvedTrackSymbol = Symbol("LC-Track-Unresolved");
@@ -8,6 +10,23 @@ exports.QueueSymbol = Symbol("LC-Queue");
8
10
  exports.NodeSymbol = Symbol("LC-Node");
9
11
  /** @hidden */
10
12
  const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
13
+ /**
14
+ * Parses Node Connection Url: "lavalink://<nodeId>:<nodeAuthorization(Password)>@<NodeHost>:<NodePort>"
15
+ * @param connectionUrl
16
+ * @returns
17
+ */
18
+ function parseLavalinkConnUrl(connectionUrl) {
19
+ if (!connectionUrl.startsWith("lavalink://"))
20
+ throw new Error(`ConnectionUrl (${connectionUrl}) must start with 'lavalink://'`);
21
+ const parsed = new node_url_1.URL(connectionUrl);
22
+ return {
23
+ authorization: parsed.password,
24
+ id: parsed.username,
25
+ host: parsed.hostname,
26
+ port: Number(parsed.port),
27
+ };
28
+ }
29
+ exports.parseLavalinkConnUrl = parseLavalinkConnUrl;
11
30
  class ManagerUtils {
12
31
  LavalinkManager = null;
13
32
  constructor(LavalinkManager) {
@@ -166,6 +185,18 @@ class ManagerUtils {
166
185
  throw new Error("No Lavalink Node was provided");
167
186
  if (!node.info.sourceManagers?.length)
168
187
  throw new Error("Lavalink Node, has no sourceManagers enabled");
188
+ // checks for blacklisted links / domains / queries
189
+ if (this.LavalinkManager.options?.linksBlacklist?.length > 0 && this.LavalinkManager.options?.linksBlacklist.some(v => (typeof v === "string" && (queryString.toLowerCase().includes(v.toLowerCase()) || v.toLowerCase().includes(queryString.toLowerCase()))) || (0, types_1.isRegExp)(v) && v.test(queryString))) {
190
+ throw new Error(`Query string contains a link / word which is blacklisted.`);
191
+ }
192
+ if (!/^https?:\/\//.test(queryString))
193
+ return;
194
+ else if (this.LavalinkManager.options?.linksAllowed === false)
195
+ throw new Error("Using links to make a request is not allowed.");
196
+ // checks for if the query is whitelisted (should only work for links, so it skips the check for no link queries)
197
+ if (this.LavalinkManager.options?.linksWhitelist?.length > 0 && !this.LavalinkManager.options?.linksWhitelist.some(v => (typeof v === "string" && (queryString.toLowerCase().includes(v.toLowerCase()) || v.toLowerCase().includes(queryString.toLowerCase()))) || (0, types_1.isRegExp)(v) && v.test(queryString))) {
198
+ throw new Error(`Query string contains a link / word which isn't whitelisted.`);
199
+ }
169
200
  // missing links: beam.pro local getyarn.io clypit pornhub reddit ocreamix soundgasm
170
201
  if ((LavalinkManagerStatics_1.SourceLinksRegexes.YoutubeMusicRegex.test(queryString) || LavalinkManagerStatics_1.SourceLinksRegexes.YoutubeRegex.test(queryString)) && !node.info?.sourceManagers?.includes("youtube")) {
171
202
  throw new Error("Lavalink Node has not 'youtube' enabled");
@@ -2,6 +2,7 @@ import { fetch } from "undici";
2
2
  export const bandCampSearch = async (player, query, requestUser) => {
3
3
  let error = null;
4
4
  let tracks = [];
5
+ player.LavalinkManager.utils.validateQueryString(player.node, query);
5
6
  try {
6
7
  const data = await fetch(`https://bandcamp.com/api/nusearch/2/autocomplete?q=${encodeURIComponent(query)}`, {
7
8
  headers: {
@@ -5,7 +5,7 @@ import { NodeManager } from "./NodeManager";
5
5
  import { DestroyReasonsType, Player, PlayerJson, PlayerOptions } from "./Player";
6
6
  import { ManagerQueueOptions } from "./Queue";
7
7
  import { Track, UnresolvedTrack } from "./Track";
8
- import { ChannelDeletePacket, GuildShardPayload, ManagerUtils, MiniMap, SearchPlatform, TrackEndEvent, TrackExceptionEvent, TrackStartEvent, TrackStuckEvent, VoicePacket, VoiceServer, VoiceState, WebSocketClosedEvent } from "./Utils";
8
+ import { ChannelDeletePacket, GuildShardPayload, ManagerUtils, MiniMap, SearchPlatform, SponsorBlockChaptersLoaded, SponsorBlockChapterStarted, SponsorBlockSegmentSkipped, SponsorBlockSegmentsLoaded, TrackEndEvent, TrackExceptionEvent, TrackStartEvent, TrackStuckEvent, VoicePacket, VoiceServer, VoiceState, WebSocketClosedEvent } from "./Utils";
9
9
  export interface LavalinkManager {
10
10
  nodeManager: NodeManager;
11
11
  utils: ManagerUtils;
@@ -33,7 +33,7 @@ export interface ManagerPlayerOptions {
33
33
  onDisconnect?: {
34
34
  /** Try to reconnect? -> If fails -> Destroy */
35
35
  autoReconnect?: boolean;
36
- /** Instantly destroy player (overrides autoReconnect) */
36
+ /** Instantly destroy player (overrides autoReconnect) | Don't provide == disable feature*/
37
37
  destroyPlayer?: boolean;
38
38
  };
39
39
  onEmptyQueue?: {
@@ -56,16 +56,27 @@ export interface ManagerOptions {
56
56
  playerOptions?: ManagerPlayerOptions;
57
57
  /** If it should skip to the next Track on TrackEnd / TrackError etc. events */
58
58
  autoSkip?: boolean;
59
- /** optional */
60
- debugOptions?: {
61
- /** logs for debugging the "no-Audio" playing error */
62
- noAudio?: boolean;
63
- /** For Logging the Destroy function */
64
- playerDestroy?: {
65
- /** To show the debug reason at all times. */
66
- debugLog?: boolean;
67
- /** If you get 'Error: Use Player#destroy("reason") not LavalinkManager#deletePlayer() to stop the Player' put it on true */
68
- dontThrowError?: boolean;
59
+ /** If it should emit only new (unique) songs and not when a looping track (or similar) is plaid, default false */
60
+ emitNewSongsOnly?: boolean;
61
+ /** Only allow link requests with links either matching some of that regExp or including some of that string */
62
+ linksWhitelist?: (RegExp | string)[];
63
+ /** Never allow link requests with links either matching some of that regExp or including some of that string (doesn't even allow if it's whitelisted) */
64
+ linksBlacklist?: (RegExp | string)[];
65
+ /** If links should be allowed or not. If set to false, it will throw an error if a link was provided. */
66
+ linksAllowed?: boolean;
67
+ /** Advanced Options for the Library, which may or may not be "library breaking" */
68
+ advancedOptions?: {
69
+ /** optional */
70
+ debugOptions?: {
71
+ /** logs for debugging the "no-Audio" playing error */
72
+ noAudio?: boolean;
73
+ /** For Logging the Destroy function */
74
+ playerDestroy?: {
75
+ /** To show the debug reason at all times. */
76
+ debugLog?: boolean;
77
+ /** If you get 'Error: Use Player#destroy("reason") not LavalinkManager#deletePlayer() to stop the Player' put it on true */
78
+ dontThrowError?: boolean;
79
+ };
69
80
  };
70
81
  };
71
82
  }
@@ -125,6 +136,34 @@ interface LavalinkManagerEvents {
125
136
  * @event Manager#playerUpdate
126
137
  */
127
138
  "playerUpdate": (oldPlayerJson: PlayerJson, newPlayer: Player) => void;
139
+ /**
140
+ * SPONSORBLOCK-PLUGIN EVENT
141
+ * Emitted when Segments are loaded
142
+ * @link https://github.com/topi314/Sponsorblock-Plugin#segmentsloaded
143
+ * @event Manager#trackError
144
+ */
145
+ "SegmentsLoaded": (player: Player, track: Track | UnresolvedTrack, payload: SponsorBlockSegmentsLoaded) => void;
146
+ /**
147
+ * SPONSORBLOCK-PLUGIN EVENT
148
+ * Emitted when a specific Segment was skipped
149
+ * @link https://github.com/topi314/Sponsorblock-Plugin#segmentskipped
150
+ * @event Manager#trackError
151
+ */
152
+ "SegmentSkipped": (player: Player, track: Track | UnresolvedTrack, payload: SponsorBlockSegmentSkipped) => void;
153
+ /**
154
+ * SPONSORBLOCK-PLUGIN EVENT
155
+ * Emitted when a specific Chapter starts playing
156
+ * @link https://github.com/topi314/Sponsorblock-Plugin#chapterstarted
157
+ * @event Manager#trackError
158
+ */
159
+ "ChapterStarted": (player: Player, track: Track | UnresolvedTrack, payload: SponsorBlockChapterStarted) => void;
160
+ /**
161
+ * SPONSORBLOCK-PLUGIN EVENT
162
+ * Emitted when Chapters are loaded
163
+ * @link https://github.com/topi314/Sponsorblock-Plugin#chaptersloaded
164
+ * @event Manager#trackError
165
+ */
166
+ "ChaptersLoaded": (player: Player, track: Track | UnresolvedTrack, payload: SponsorBlockChaptersLoaded) => void;
128
167
  }
129
168
  export interface LavalinkManager {
130
169
  options: ManagerOptions;
@@ -34,17 +34,22 @@ export class LavalinkManager extends EventEmitter {
34
34
  requesterTransformer: options?.playerOptions?.requesterTransformer ?? null,
35
35
  useUnresolvedData: options?.playerOptions?.useUnresolvedData ?? false,
36
36
  },
37
+ linksWhitelist: options?.linksWhitelist ?? [],
38
+ linksBlacklist: options?.linksBlacklist ?? [],
37
39
  autoSkip: options?.autoSkip ?? true,
40
+ emitNewSongsOnly: options?.emitNewSongsOnly ?? false,
38
41
  queueOptions: {
39
42
  maxPreviousTracks: options?.queueOptions?.maxPreviousTracks ?? 25,
40
43
  queueChangesWatcher: options?.queueOptions?.queueChangesWatcher ?? null,
41
44
  queueStore: options?.queueOptions?.queueStore ?? new DefaultQueueStore(),
42
45
  },
43
- debugOptions: {
44
- noAudio: options?.debugOptions?.noAudio ?? false,
45
- playerDestroy: {
46
- dontThrowError: options?.debugOptions?.playerDestroy?.dontThrowError ?? false,
47
- debugLog: options?.debugOptions?.playerDestroy?.debugLog ?? false,
46
+ advancedOptions: {
47
+ debugOptions: {
48
+ noAudio: options?.advancedOptions?.debugOptions?.noAudio ?? false,
49
+ playerDestroy: {
50
+ dontThrowError: options?.advancedOptions?.debugOptions?.playerDestroy?.dontThrowError ?? false,
51
+ debugLog: options?.advancedOptions?.debugOptions?.playerDestroy?.debugLog ?? false,
52
+ }
48
53
  }
49
54
  }
50
55
  };
@@ -57,6 +62,8 @@ export class LavalinkManager extends EventEmitter {
57
62
  // if(typeof options?.client !== "object" || typeof options?.client.id !== "string") throw new SyntaxError("ManagerOption.client = { id: string, username?:string } was not provided, which is required");
58
63
  if (options?.autoSkip && typeof options?.autoSkip !== "boolean")
59
64
  throw new SyntaxError("ManagerOption.autoSkip must be either false | true aka boolean");
65
+ if (options?.emitNewSongsOnly && typeof options?.emitNewSongsOnly !== "boolean")
66
+ throw new SyntaxError("ManagerOption.emitNewSongsOnly must be either false | true aka boolean");
60
67
  if (!options?.nodes || !Array.isArray(options?.nodes) || !options?.nodes.every(node => this.utils.isNodeOptions(node)))
61
68
  throw new SyntaxError("ManagerOption.nodes must be an Array of NodeOptions and is required of at least 1 Node");
62
69
  /* QUEUE STORE */
@@ -110,7 +117,7 @@ export class LavalinkManager extends EventEmitter {
110
117
  return;
111
118
  // oldPlayer.connected is operational. you could also do oldPlayer.voice?.token
112
119
  if (oldPlayer.voiceChannelId === "string" && oldPlayer.connected && !oldPlayer.get("internal_destroywithoutdisconnect")) {
113
- if (!this.options?.debugOptions?.playerDestroy?.dontThrowError)
120
+ if (!this.options?.advancedOptions?.debugOptions?.playerDestroy?.dontThrowError)
114
121
  throw new Error(`Use Player#destroy() not LavalinkManager#deletePlayer() to stop the Player ${JSON.stringify(oldPlayer.toJSON?.())}`);
115
122
  else
116
123
  console.error("Use Player#destroy() not LavalinkManager#deletePlayer() to stop the Player", oldPlayer.toJSON?.());
@@ -156,12 +163,12 @@ export class LavalinkManager extends EventEmitter {
156
163
  */
157
164
  async sendRawData(data) {
158
165
  if (!this.initiated) {
159
- if (this.options?.debugOptions?.noAudio === true)
166
+ if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
160
167
  console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, manager is not initated yet");
161
168
  return;
162
169
  }
163
170
  if (!("t" in data)) {
164
- if (this.options?.debugOptions?.noAudio === true)
171
+ if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
165
172
  console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, no 't' in payload-data of the raw event:", data);
166
173
  return;
167
174
  }
@@ -178,23 +185,23 @@ export class LavalinkManager extends EventEmitter {
178
185
  if (["VOICE_STATE_UPDATE", "VOICE_SERVER_UPDATE"].includes(data.t)) {
179
186
  const update = ("d" in data ? data.d : data);
180
187
  if (!update) {
181
- if (this.options?.debugOptions?.noAudio === true)
188
+ if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
182
189
  console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, no update data found in payload:", data);
183
190
  return;
184
191
  }
185
192
  if (!("token" in update) && !("session_id" in update)) {
186
- if (this.options?.debugOptions?.noAudio === true)
193
+ if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
187
194
  console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, no 'token' nor 'session_id' found in payload:", data);
188
195
  return;
189
196
  }
190
197
  const player = this.getPlayer(update.guild_id);
191
198
  if (!player) {
192
- if (this.options?.debugOptions?.noAudio === true)
199
+ if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
193
200
  console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, No Lavalink Player found via key: 'guild_id' of update-data:", update);
194
201
  return;
195
202
  }
196
203
  if (player.get("internal_destroystatus") === true) {
197
- if (this.options?.debugOptions?.noAudio === true)
204
+ if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
198
205
  console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, Player is in a destroying state. can't signal the voice states");
199
206
  return;
200
207
  }
@@ -211,13 +218,13 @@ export class LavalinkManager extends EventEmitter {
211
218
  }
212
219
  }
213
220
  });
214
- if (this.options?.debugOptions?.noAudio === true)
221
+ if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
215
222
  console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, Sent updatePlayer for voice token session", { voice: { token: update.token, endpoint: update.endpoint, sessionId: player.voice?.sessionId, } });
216
223
  return;
217
224
  }
218
225
  /* voice state update */
219
226
  if (update.user_id !== this.options?.client.id) {
220
- if (this.options?.debugOptions?.noAudio === true)
227
+ if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
221
228
  console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, voice update user is not equal to provided client id of the manageroptions#client#id", "user:", update.user_id, "manager client id:", this.options?.client.id);
222
229
  return;
223
230
  }
@@ -2,11 +2,13 @@
2
2
  import internal from "stream";
3
3
  import { Dispatcher, Pool } from "undici";
4
4
  import { NodeManager } from "./NodeManager";
5
- import { DestroyReasonsType } from "./Player";
5
+ import { DestroyReasonsType, Player } from "./Player";
6
6
  import { Track } from "./Track";
7
7
  import { Base64, InvalidLavalinkRestRequest, LavalinkPlayer, LavaSearchQuery, LavaSearchResponse, PlayerUpdateInfo, RoutePlanner, SearchQuery, SearchResult, Session } from "./Utils";
8
8
  /** Modifies any outgoing REST requests. */
9
9
  export type ModifyRequest = (options: Dispatcher.RequestOptions) => void;
10
+ export declare const validSponsorBlocks: string[];
11
+ export type SponsorBlockSegment = "sponsor" | "selfpromo" | "interaction" | "intro" | "outro" | "preview" | "music_offtopic" | "filler";
10
12
  export interface LavalinkNodeOptions {
11
13
  /** The Lavalink Server-Ip / Domain-URL */
12
14
  host: string;
@@ -240,8 +242,15 @@ export declare class LavalinkNode {
240
242
  private handleEvent;
241
243
  private trackStart;
242
244
  private trackEnd;
243
- private queueEnd;
244
245
  private trackStuck;
245
246
  private trackError;
246
247
  private socketClosed;
248
+ private SponsorBlockSegmentLoaded;
249
+ private SponsorBlockSegmentkipped;
250
+ private SponsorBlockChaptersLoaded;
251
+ private SponsorBlockChapterStarted;
252
+ getSponsorBlock(player: Player): Promise<SponsorBlockSegment[]>;
253
+ setSponsorBlock(player: Player, segments?: SponsorBlockSegment[]): Promise<void>;
254
+ deleteSponsorBlock(player: Player): Promise<void>;
255
+ private queueEnd;
247
256
  }