magmastream 2.10.3-alpha.4 → 2.10.3-alpha.5
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/dist/structures/Enums.d.ts +4 -0
- package/dist/structures/Enums.js +4 -0
- package/dist/structures/Filters.d.ts +33 -1
- package/dist/structures/Filters.js +71 -2
- package/dist/structures/Manager.js +23 -20
- package/dist/structures/Node.js +1 -1
- package/dist/structures/Rest.d.ts +45 -2
- package/dist/structures/Rest.js +84 -1
- package/dist/structures/Types.d.ts +100 -36
- package/dist/structures/Utils.js +17 -9
- package/package.json +1 -1
|
@@ -250,10 +250,14 @@ export declare enum AvailableFilters {
|
|
|
250
250
|
Party = "party",
|
|
251
251
|
Pop = "pop",
|
|
252
252
|
Radio = "radio",
|
|
253
|
+
PluginFilters = "pluginFilters",
|
|
254
|
+
SetChannelMix = "setChannelMix",
|
|
253
255
|
SetDistortion = "setDistortion",
|
|
254
256
|
SetKaraoke = "setKaraoke",
|
|
257
|
+
SetLowPass = "setLowPass",
|
|
255
258
|
SetRotation = "setRotation",
|
|
256
259
|
SetTimescale = "setTimescale",
|
|
260
|
+
SetTremolo = "setTremolo",
|
|
257
261
|
Slowmo = "slowmo",
|
|
258
262
|
Soft = "soft",
|
|
259
263
|
TrebleBass = "trebleBass",
|
package/dist/structures/Enums.js
CHANGED
|
@@ -267,10 +267,14 @@ var AvailableFilters;
|
|
|
267
267
|
AvailableFilters["Party"] = "party";
|
|
268
268
|
AvailableFilters["Pop"] = "pop";
|
|
269
269
|
AvailableFilters["Radio"] = "radio";
|
|
270
|
+
AvailableFilters["PluginFilters"] = "pluginFilters";
|
|
271
|
+
AvailableFilters["SetChannelMix"] = "setChannelMix";
|
|
270
272
|
AvailableFilters["SetDistortion"] = "setDistortion";
|
|
271
273
|
AvailableFilters["SetKaraoke"] = "setKaraoke";
|
|
274
|
+
AvailableFilters["SetLowPass"] = "setLowPass";
|
|
272
275
|
AvailableFilters["SetRotation"] = "setRotation";
|
|
273
276
|
AvailableFilters["SetTimescale"] = "setTimescale";
|
|
277
|
+
AvailableFilters["SetTremolo"] = "setTremolo";
|
|
274
278
|
AvailableFilters["Slowmo"] = "slowmo";
|
|
275
279
|
AvailableFilters["Soft"] = "soft";
|
|
276
280
|
AvailableFilters["TrebleBass"] = "trebleBass";
|
|
@@ -2,14 +2,18 @@ import { Band } from "../utils/filtersEqualizers";
|
|
|
2
2
|
import { AvailableFilters } from "./Enums";
|
|
3
3
|
import { Manager } from "./Manager";
|
|
4
4
|
import { Player } from "./Player";
|
|
5
|
-
import { DistortionOptions, KaraokeOptions, ReverbOptions, RotationOptions, TimescaleOptions, VibratoOptions } from "./Types";
|
|
5
|
+
import { ChannelMixOptions, DistortionOptions, KaraokeOptions, LowPassOptions, ReverbOptions, RotationOptions, TimescaleOptions, TremoloOptions, VibratoOptions } from "./Types";
|
|
6
6
|
export declare class Filters {
|
|
7
7
|
distortion: DistortionOptions | null;
|
|
8
8
|
equalizer: Band[];
|
|
9
9
|
karaoke: KaraokeOptions | null;
|
|
10
10
|
rotation: RotationOptions | null;
|
|
11
11
|
timescale: TimescaleOptions | null;
|
|
12
|
+
tremoloOptions: TremoloOptions | null;
|
|
12
13
|
vibrato: VibratoOptions | null;
|
|
14
|
+
channelMix: ChannelMixOptions | null;
|
|
15
|
+
lowPass: LowPassOptions | null;
|
|
16
|
+
pluginFilters: Record<string, unknown>;
|
|
13
17
|
reverb: ReverbOptions | null;
|
|
14
18
|
volume: number;
|
|
15
19
|
bassBoostlevel: number;
|
|
@@ -112,6 +116,34 @@ export declare class Filters {
|
|
|
112
116
|
* @returns {Promise<this>} - Returns the current instance of the Filters class for method chaining.
|
|
113
117
|
*/
|
|
114
118
|
setVibrato(vibrato?: VibratoOptions): Promise<this>;
|
|
119
|
+
/**
|
|
120
|
+
* Sets the tremolo options on the audio.
|
|
121
|
+
*
|
|
122
|
+
* @param {TremoloOptions} [tremolo] - The tremolo settings to apply (frequency, depth).
|
|
123
|
+
* @returns {Promise<this>} - Returns the current instance of the Filters class for method chaining.
|
|
124
|
+
*/
|
|
125
|
+
setTremolo(tremolo?: TremoloOptions): Promise<this>;
|
|
126
|
+
/**
|
|
127
|
+
* Sets the stereo channel mix options on the audio.
|
|
128
|
+
*
|
|
129
|
+
* @param {ChannelMixOptions} [channelMix] - The channel mix settings to apply.
|
|
130
|
+
* @returns {Promise<this>} - Returns the current instance of the Filters class for method chaining.
|
|
131
|
+
*/
|
|
132
|
+
setChannelMix(channelMix?: ChannelMixOptions): Promise<this>;
|
|
133
|
+
/**
|
|
134
|
+
* Sets the low pass filter options on the audio.
|
|
135
|
+
*
|
|
136
|
+
* @param {LowPassOptions} [lowPass] - The low pass settings to apply.
|
|
137
|
+
* @returns {Promise<this>} - Returns the current instance of the Filters class for method chaining.
|
|
138
|
+
*/
|
|
139
|
+
setLowPass(lowPass?: LowPassOptions): Promise<this>;
|
|
140
|
+
/**
|
|
141
|
+
* Sets plugin-provided filter options on the audio.
|
|
142
|
+
*
|
|
143
|
+
* @param {Record<string, unknown>} [pluginFilters] - Plugin filter settings keyed by plugin filter name.
|
|
144
|
+
* @returns {Promise<this>} - Returns the current instance of the Filters class for method chaining.
|
|
145
|
+
*/
|
|
146
|
+
setPluginFilters(pluginFilters?: Record<string, unknown>): Promise<this>;
|
|
115
147
|
/**
|
|
116
148
|
* Sets the own rotation options effect to the audio.
|
|
117
149
|
*
|
|
@@ -10,7 +10,11 @@ class Filters {
|
|
|
10
10
|
karaoke;
|
|
11
11
|
rotation;
|
|
12
12
|
timescale;
|
|
13
|
+
tremoloOptions;
|
|
13
14
|
vibrato;
|
|
15
|
+
channelMix;
|
|
16
|
+
lowPass;
|
|
17
|
+
pluginFilters;
|
|
14
18
|
reverb;
|
|
15
19
|
volume;
|
|
16
20
|
bassBoostlevel;
|
|
@@ -23,7 +27,11 @@ class Filters {
|
|
|
23
27
|
this.karaoke = null;
|
|
24
28
|
this.rotation = null;
|
|
25
29
|
this.timescale = null;
|
|
30
|
+
this.tremoloOptions = null;
|
|
26
31
|
this.vibrato = null;
|
|
32
|
+
this.channelMix = null;
|
|
33
|
+
this.lowPass = null;
|
|
34
|
+
this.pluginFilters = {};
|
|
27
35
|
this.reverb = null;
|
|
28
36
|
this.volume = 1.0;
|
|
29
37
|
this.bassBoostlevel = 0;
|
|
@@ -48,7 +56,7 @@ class Filters {
|
|
|
48
56
|
* of the Filters class for method chaining.
|
|
49
57
|
*/
|
|
50
58
|
async updateFilters() {
|
|
51
|
-
const { distortion, equalizer, karaoke, rotation, timescale, vibrato, volume } = this;
|
|
59
|
+
const { channelMix, distortion, equalizer, karaoke, lowPass, pluginFilters, rotation, timescale, tremoloOptions, vibrato, volume } = this;
|
|
52
60
|
try {
|
|
53
61
|
await this.player.node.rest.updatePlayer({
|
|
54
62
|
data: {
|
|
@@ -56,10 +64,14 @@ class Filters {
|
|
|
56
64
|
distortion,
|
|
57
65
|
equalizer,
|
|
58
66
|
karaoke,
|
|
67
|
+
lowPass,
|
|
68
|
+
pluginFilters,
|
|
59
69
|
rotation,
|
|
60
70
|
timescale,
|
|
71
|
+
tremolo: tremoloOptions,
|
|
61
72
|
vibrato,
|
|
62
73
|
volume,
|
|
74
|
+
channelMix,
|
|
63
75
|
},
|
|
64
76
|
},
|
|
65
77
|
guildId: this.player.guildId,
|
|
@@ -146,7 +158,11 @@ class Filters {
|
|
|
146
158
|
await this.setKaraoke(null);
|
|
147
159
|
await this.setRotation(null);
|
|
148
160
|
await this.setTimescale(null);
|
|
161
|
+
await this.setTremolo(null);
|
|
149
162
|
await this.setVibrato(null);
|
|
163
|
+
await this.setChannelMix(null);
|
|
164
|
+
await this.setLowPass(null);
|
|
165
|
+
await this.setPluginFilters({});
|
|
150
166
|
await this.updateFilters();
|
|
151
167
|
this.emitPlayersTasteUpdate(oldPlayer);
|
|
152
168
|
return this;
|
|
@@ -215,6 +231,59 @@ class Filters {
|
|
|
215
231
|
this.emitPlayersTasteUpdate(oldPlayer);
|
|
216
232
|
return this;
|
|
217
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Sets the tremolo options on the audio.
|
|
236
|
+
*
|
|
237
|
+
* @param {TremoloOptions} [tremolo] - The tremolo settings to apply (frequency, depth).
|
|
238
|
+
* @returns {Promise<this>} - Returns the current instance of the Filters class for method chaining.
|
|
239
|
+
*/
|
|
240
|
+
async setTremolo(tremolo) {
|
|
241
|
+
const oldPlayer = { ...this };
|
|
242
|
+
await this.applyFilter({ property: "tremoloOptions", value: tremolo ?? null });
|
|
243
|
+
this.setFilterStatus(Enums_1.AvailableFilters.SetTremolo, !!tremolo);
|
|
244
|
+
this.emitPlayersTasteUpdate(oldPlayer);
|
|
245
|
+
return this;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Sets the stereo channel mix options on the audio.
|
|
249
|
+
*
|
|
250
|
+
* @param {ChannelMixOptions} [channelMix] - The channel mix settings to apply.
|
|
251
|
+
* @returns {Promise<this>} - Returns the current instance of the Filters class for method chaining.
|
|
252
|
+
*/
|
|
253
|
+
async setChannelMix(channelMix) {
|
|
254
|
+
const oldPlayer = { ...this };
|
|
255
|
+
await this.applyFilter({ property: "channelMix", value: channelMix ?? null });
|
|
256
|
+
this.setFilterStatus(Enums_1.AvailableFilters.SetChannelMix, !!channelMix);
|
|
257
|
+
this.emitPlayersTasteUpdate(oldPlayer);
|
|
258
|
+
return this;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Sets the low pass filter options on the audio.
|
|
262
|
+
*
|
|
263
|
+
* @param {LowPassOptions} [lowPass] - The low pass settings to apply.
|
|
264
|
+
* @returns {Promise<this>} - Returns the current instance of the Filters class for method chaining.
|
|
265
|
+
*/
|
|
266
|
+
async setLowPass(lowPass) {
|
|
267
|
+
const oldPlayer = { ...this };
|
|
268
|
+
await this.applyFilter({ property: "lowPass", value: lowPass ?? null });
|
|
269
|
+
this.setFilterStatus(Enums_1.AvailableFilters.SetLowPass, !!lowPass);
|
|
270
|
+
this.emitPlayersTasteUpdate(oldPlayer);
|
|
271
|
+
return this;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Sets plugin-provided filter options on the audio.
|
|
275
|
+
*
|
|
276
|
+
* @param {Record<string, unknown>} [pluginFilters] - Plugin filter settings keyed by plugin filter name.
|
|
277
|
+
* @returns {Promise<this>} - Returns the current instance of the Filters class for method chaining.
|
|
278
|
+
*/
|
|
279
|
+
async setPluginFilters(pluginFilters) {
|
|
280
|
+
const oldPlayer = { ...this };
|
|
281
|
+
const nextPluginFilters = pluginFilters ?? {};
|
|
282
|
+
await this.applyFilter({ property: "pluginFilters", value: nextPluginFilters });
|
|
283
|
+
this.setFilterStatus(Enums_1.AvailableFilters.PluginFilters, Object.keys(nextPluginFilters).length > 0);
|
|
284
|
+
this.emitPlayersTasteUpdate(oldPlayer);
|
|
285
|
+
return this;
|
|
286
|
+
}
|
|
218
287
|
/**
|
|
219
288
|
* Sets the own rotation options effect to the audio.
|
|
220
289
|
*
|
|
@@ -557,7 +626,7 @@ class Filters {
|
|
|
557
626
|
*/
|
|
558
627
|
async tremolo(status) {
|
|
559
628
|
const oldPlayer = { ...this };
|
|
560
|
-
await this.applyFilter({ property: "
|
|
629
|
+
await this.applyFilter({ property: "tremoloOptions", value: status ? { frequency: 5, depth: 0.5 } : null });
|
|
561
630
|
this.setFilterStatus(Enums_1.AvailableFilters.Tremolo, status);
|
|
562
631
|
this.emitPlayersTasteUpdate(oldPlayer);
|
|
563
632
|
return this;
|
|
@@ -250,7 +250,8 @@ class Manager extends events_1.EventEmitter {
|
|
|
250
250
|
tracks,
|
|
251
251
|
playlist: {
|
|
252
252
|
name: playlistData.info.name,
|
|
253
|
-
playlistInfo: playlistData.
|
|
253
|
+
playlistInfo: playlistData.info,
|
|
254
|
+
pluginInfo: playlistData.pluginInfo,
|
|
254
255
|
requester: requester,
|
|
255
256
|
tracks,
|
|
256
257
|
duration: tracks.reduce((acc, cur) => acc + (cur.duration || 0), 0),
|
|
@@ -263,7 +264,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
263
264
|
}
|
|
264
265
|
if (this.options.normalizeYouTubeTitles && "tracks" in result) {
|
|
265
266
|
const processTrack = (track) => {
|
|
266
|
-
if (!YOUTUBE_URL_PATTERN.test(track.uri))
|
|
267
|
+
if (!track.uri || !YOUTUBE_URL_PATTERN.test(track.uri))
|
|
267
268
|
return track;
|
|
268
269
|
const { cleanTitle, cleanAuthor } = this.parseYouTubeTitle(track.title, track.author);
|
|
269
270
|
track.title = cleanTitle;
|
|
@@ -406,23 +407,21 @@ class Manager extends events_1.EventEmitter {
|
|
|
406
407
|
*/
|
|
407
408
|
async decodeTracks(tracks) {
|
|
408
409
|
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Decoding tracks: ${Utils_1.JSONUtils.safe(tracks, 2)}`);
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
return resolve(decodedTrackData);
|
|
425
|
-
});
|
|
410
|
+
const node = this.useableNode;
|
|
411
|
+
if (!node) {
|
|
412
|
+
throw new MagmastreamError_1.MagmaStreamError({
|
|
413
|
+
code: Enums_1.MagmaStreamErrorCode.MANAGER_NO_NODES,
|
|
414
|
+
message: "No available nodes to decode tracks.",
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
const decodedTrackData = await node.rest.decodeTracks(tracks);
|
|
418
|
+
if (!decodedTrackData) {
|
|
419
|
+
throw new MagmastreamError_1.MagmaStreamError({
|
|
420
|
+
code: Enums_1.MagmaStreamErrorCode.REST_REQUEST_FAILED,
|
|
421
|
+
message: "No decoded tracks returned from node.",
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
return decodedTrackData;
|
|
426
425
|
}
|
|
427
426
|
/**
|
|
428
427
|
* Decodes a base64 encoded track and returns a TrackData.
|
|
@@ -510,7 +509,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
510
509
|
const player = this.create(playerOptions);
|
|
511
510
|
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Recreating player: ${guildId}`);
|
|
512
511
|
if (state.isAutoplay) {
|
|
513
|
-
const savedUser = state.data?.clientUser;
|
|
512
|
+
const savedUser = (state.data?.Internal_AutoplayUser || state.data?.clientUser);
|
|
514
513
|
if (savedUser) {
|
|
515
514
|
const autoPlayUser = await player.manager.resolveUser(savedUser);
|
|
516
515
|
player.setAutoplay(true, autoPlayUser, state.autoplayTries);
|
|
@@ -607,14 +606,18 @@ class Manager extends events_1.EventEmitter {
|
|
|
607
606
|
const filterActions = {
|
|
608
607
|
bassboost: () => player.filters.bassBoost(state.filters.bassBoostlevel),
|
|
609
608
|
distort: (isEnabled) => player.filters.distort(isEnabled),
|
|
609
|
+
pluginFilters: () => player.filters.setPluginFilters(state.filters.pluginFilters),
|
|
610
|
+
setChannelMix: () => player.filters.setChannelMix(state.filters.channelMix),
|
|
610
611
|
setDistortion: () => player.filters.setDistortion(state.filters.distortion),
|
|
611
612
|
eightD: (isEnabled) => player.filters.eightD(isEnabled),
|
|
612
613
|
setKaraoke: () => player.filters.setKaraoke(state.filters.karaoke),
|
|
614
|
+
setLowPass: () => player.filters.setLowPass(state.filters.lowPass),
|
|
613
615
|
nightcore: (isEnabled) => player.filters.nightcore(isEnabled),
|
|
614
616
|
slowmo: (isEnabled) => player.filters.slowmo(isEnabled),
|
|
615
617
|
soft: (isEnabled) => player.filters.soft(isEnabled),
|
|
616
618
|
trebleBass: (isEnabled) => player.filters.trebleBass(isEnabled),
|
|
617
619
|
setTimescale: () => player.filters.setTimescale(state.filters.timescale),
|
|
620
|
+
setTremolo: () => player.filters.setTremolo(state.filters.tremolo),
|
|
618
621
|
tv: (isEnabled) => player.filters.tv(isEnabled),
|
|
619
622
|
vibrato: () => player.filters.setVibrato(state.filters.vibrato),
|
|
620
623
|
vaporwave: (isEnabled) => player.filters.vaporwave(isEnabled),
|
package/dist/structures/Node.js
CHANGED
|
@@ -1079,7 +1079,7 @@ class Node {
|
|
|
1079
1079
|
* @returns {Promise<LavalinkInfo>} A promise that resolves to the Lavalink node information.
|
|
1080
1080
|
*/
|
|
1081
1081
|
async fetchInfo() {
|
|
1082
|
-
return
|
|
1082
|
+
return await this.rest.getInfo();
|
|
1083
1083
|
}
|
|
1084
1084
|
/**
|
|
1085
1085
|
* Gets the current sponsorblock segments for a player.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Node } from "./Node";
|
|
2
2
|
import { Manager } from "./Manager";
|
|
3
|
-
import { LavalinkSession, LavaPlayer, RestPlayOptions } from "./Types";
|
|
3
|
+
import { LavalinkInfo, LavalinkSession, LavaPlayer, NodeStats, RestPlayOptions, RoutePlannerStatus, TrackData } from "./Types";
|
|
4
4
|
/** Handles the requests sent to the Lavalink REST API. */
|
|
5
5
|
export declare class Rest {
|
|
6
6
|
/** The Node that this Rest instance is connected to. */
|
|
@@ -32,6 +32,11 @@ export declare class Rest {
|
|
|
32
32
|
* @returns {Promise<LavaPlayer>} Returns the player.
|
|
33
33
|
*/
|
|
34
34
|
getPlayer(guildId: string): Promise<LavaPlayer>;
|
|
35
|
+
/**
|
|
36
|
+
* Retrieves all players that belong to the current session.
|
|
37
|
+
* @returns {Promise<LavaPlayer[]>} Returns the players.
|
|
38
|
+
*/
|
|
39
|
+
getPlayers(): Promise<LavaPlayer[]>;
|
|
35
40
|
/**
|
|
36
41
|
* Sends a PATCH request to update player related data.
|
|
37
42
|
* @param {RestPlayOptions} options The options to update the player with.
|
|
@@ -51,6 +56,44 @@ export declare class Rest {
|
|
|
51
56
|
* @returns {Promise<LavalinkSession>} The updated session.
|
|
52
57
|
*/
|
|
53
58
|
updateSession(resuming: boolean, timeout: number): Promise<LavalinkSession>;
|
|
59
|
+
/**
|
|
60
|
+
* Decodes a single Lavalink track.
|
|
61
|
+
* @param {string} encodedTrack The encoded track string.
|
|
62
|
+
* @returns {Promise<TrackData>} The decoded track.
|
|
63
|
+
*/
|
|
64
|
+
decodeTrack(encodedTrack: string): Promise<TrackData>;
|
|
65
|
+
/**
|
|
66
|
+
* Decodes multiple Lavalink tracks.
|
|
67
|
+
* @param {string[]} encodedTracks The encoded track strings.
|
|
68
|
+
* @returns {Promise<TrackData[]>} The decoded tracks.
|
|
69
|
+
*/
|
|
70
|
+
decodeTracks(encodedTracks: string[]): Promise<TrackData[]>;
|
|
71
|
+
/**
|
|
72
|
+
* Retrieves this node's Lavalink info.
|
|
73
|
+
* @returns {Promise<LavalinkInfo>} The node info.
|
|
74
|
+
*/
|
|
75
|
+
getInfo(): Promise<LavalinkInfo>;
|
|
76
|
+
/**
|
|
77
|
+
* Retrieves this node's current stats.
|
|
78
|
+
* @returns {Promise<NodeStats>} The node stats.
|
|
79
|
+
*/
|
|
80
|
+
getStats(): Promise<NodeStats>;
|
|
81
|
+
/**
|
|
82
|
+
* Retrieves the route planner status.
|
|
83
|
+
* @returns {Promise<RoutePlannerStatus>} The route planner status.
|
|
84
|
+
*/
|
|
85
|
+
getRoutePlannerStatus(): Promise<RoutePlannerStatus>;
|
|
86
|
+
/**
|
|
87
|
+
* Unmarks a failed route planner address.
|
|
88
|
+
* @param {string} address The address to free.
|
|
89
|
+
* @returns {Promise<void>} Void.
|
|
90
|
+
*/
|
|
91
|
+
freeRoutePlannerAddress(address: string): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Unmarks all failed route planner addresses.
|
|
94
|
+
* @returns {Promise<void>} Void.
|
|
95
|
+
*/
|
|
96
|
+
freeAllRoutePlannerAddresses(): Promise<void>;
|
|
54
97
|
/**
|
|
55
98
|
* Sends a request to the specified endpoint and returns the response data.
|
|
56
99
|
* @param {string} method The HTTP method to use for the request.
|
|
@@ -78,7 +121,7 @@ export declare class Rest {
|
|
|
78
121
|
* @param {unknown} body The data to send in the request body.
|
|
79
122
|
* @returns {Promise<T>} The response data of the POST request.
|
|
80
123
|
*/
|
|
81
|
-
post<T>(endpoint: string, body
|
|
124
|
+
post<T>(endpoint: string, body?: unknown): Promise<T>;
|
|
82
125
|
/**
|
|
83
126
|
* Sends a PUT request to the specified endpoint and returns the response data.
|
|
84
127
|
* @param {string} endpoint The endpoint to send the PUT request to.
|
package/dist/structures/Rest.js
CHANGED
|
@@ -55,6 +55,18 @@ class Rest {
|
|
|
55
55
|
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] Getting player on node: ${this.node.options.identifier} : ${Utils_1.JSONUtils.safe(result, 2)}`);
|
|
56
56
|
return result;
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Retrieves all players that belong to the current session.
|
|
60
|
+
* @returns {Promise<LavaPlayer[]>} Returns the players.
|
|
61
|
+
*/
|
|
62
|
+
async getPlayers() {
|
|
63
|
+
if (!this.sessionId) {
|
|
64
|
+
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] Skipping getPlayers - no session ID on node ${this.node.options.identifier}`);
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
const result = await this.get(`/v4/sessions/${this.sessionId}/players`);
|
|
68
|
+
return Array.isArray(result) ? result : (result?.players ?? []);
|
|
69
|
+
}
|
|
58
70
|
/**
|
|
59
71
|
* Sends a PATCH request to update player related data.
|
|
60
72
|
* @param {RestPlayOptions} options The options to update the player with.
|
|
@@ -95,6 +107,77 @@ class Rest {
|
|
|
95
107
|
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] Updating session: ${this.sessionId}`);
|
|
96
108
|
return await this.patch(`/v4/sessions/${this.sessionId}`, { resuming, timeout });
|
|
97
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Decodes a single Lavalink track.
|
|
112
|
+
* @param {string} encodedTrack The encoded track string.
|
|
113
|
+
* @returns {Promise<TrackData>} The decoded track.
|
|
114
|
+
*/
|
|
115
|
+
async decodeTrack(encodedTrack) {
|
|
116
|
+
if (typeof encodedTrack !== "string" || encodedTrack.length === 0) {
|
|
117
|
+
throw new MagmastreamError_1.MagmaStreamError({
|
|
118
|
+
code: Enums_1.MagmaStreamErrorCode.REST_REQUEST_FAILED,
|
|
119
|
+
message: "Cannot decode an empty track.",
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
return await this.get(`/v4/decodetrack?encodedTrack=${encodeURIComponent(encodedTrack)}`);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Decodes multiple Lavalink tracks.
|
|
126
|
+
* @param {string[]} encodedTracks The encoded track strings.
|
|
127
|
+
* @returns {Promise<TrackData[]>} The decoded tracks.
|
|
128
|
+
*/
|
|
129
|
+
async decodeTracks(encodedTracks) {
|
|
130
|
+
if (!Array.isArray(encodedTracks) || encodedTracks.length === 0) {
|
|
131
|
+
throw new MagmastreamError_1.MagmaStreamError({
|
|
132
|
+
code: Enums_1.MagmaStreamErrorCode.REST_REQUEST_FAILED,
|
|
133
|
+
message: "Cannot decode an empty track list.",
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
const result = await this.post("/v4/decodetracks", encodedTracks);
|
|
137
|
+
return Array.isArray(result) ? result : (result?.tracks ?? []);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Retrieves this node's Lavalink info.
|
|
141
|
+
* @returns {Promise<LavalinkInfo>} The node info.
|
|
142
|
+
*/
|
|
143
|
+
async getInfo() {
|
|
144
|
+
return await this.get("/v4/info");
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Retrieves this node's current stats.
|
|
148
|
+
* @returns {Promise<NodeStats>} The node stats.
|
|
149
|
+
*/
|
|
150
|
+
async getStats() {
|
|
151
|
+
return await this.get("/v4/stats");
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Retrieves the route planner status.
|
|
155
|
+
* @returns {Promise<RoutePlannerStatus>} The route planner status.
|
|
156
|
+
*/
|
|
157
|
+
async getRoutePlannerStatus() {
|
|
158
|
+
return await this.get("/v4/routeplanner/status");
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Unmarks a failed route planner address.
|
|
162
|
+
* @param {string} address The address to free.
|
|
163
|
+
* @returns {Promise<void>} Void.
|
|
164
|
+
*/
|
|
165
|
+
async freeRoutePlannerAddress(address) {
|
|
166
|
+
if (typeof address !== "string" || address.length === 0) {
|
|
167
|
+
throw new MagmastreamError_1.MagmaStreamError({
|
|
168
|
+
code: Enums_1.MagmaStreamErrorCode.REST_REQUEST_FAILED,
|
|
169
|
+
message: "Cannot free an empty route planner address.",
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
await this.post("/v4/routeplanner/free/address", { address });
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Unmarks all failed route planner addresses.
|
|
176
|
+
* @returns {Promise<void>} Void.
|
|
177
|
+
*/
|
|
178
|
+
async freeAllRoutePlannerAddresses() {
|
|
179
|
+
await this.post("/v4/routeplanner/free/all");
|
|
180
|
+
}
|
|
98
181
|
/**
|
|
99
182
|
* Sends a request to the specified endpoint and returns the response data.
|
|
100
183
|
* @param {string} method The HTTP method to use for the request.
|
|
@@ -132,7 +215,7 @@ class Rest {
|
|
|
132
215
|
return data;
|
|
133
216
|
}
|
|
134
217
|
if (status === 404) {
|
|
135
|
-
if (data?.message === "Guild not found") {
|
|
218
|
+
if (data?.message === "Guild not found" || data?.message === "Player not found") {
|
|
136
219
|
return [];
|
|
137
220
|
}
|
|
138
221
|
if (data?.message === "Session not found") {
|
|
@@ -388,13 +388,13 @@ export interface Track {
|
|
|
388
388
|
/** The duration of the track. */
|
|
389
389
|
readonly duration: number;
|
|
390
390
|
/** The ISRC of the track. */
|
|
391
|
-
readonly isrc: string;
|
|
391
|
+
readonly isrc: string | null;
|
|
392
392
|
/** If the track is seekable. */
|
|
393
393
|
readonly isSeekable: boolean;
|
|
394
394
|
/** If the track is a stream.. */
|
|
395
395
|
readonly isStream: boolean;
|
|
396
396
|
/** The uri of the track. */
|
|
397
|
-
readonly uri: string;
|
|
397
|
+
readonly uri: string | null;
|
|
398
398
|
/** The thumbnail of the track or null if it's a unsupported source. */
|
|
399
399
|
readonly thumbnail: string | null;
|
|
400
400
|
/** The user that requested the track. */
|
|
@@ -412,6 +412,7 @@ export interface Track {
|
|
|
412
412
|
* Track Plugin Info
|
|
413
413
|
*/
|
|
414
414
|
export interface TrackPluginInfo {
|
|
415
|
+
[key: string]: unknown;
|
|
415
416
|
albumName?: string;
|
|
416
417
|
albumUrl?: string;
|
|
417
418
|
artistArtworkUrl?: string;
|
|
@@ -433,7 +434,7 @@ export interface SearchQuery {
|
|
|
433
434
|
*/
|
|
434
435
|
export interface LavalinkResponse {
|
|
435
436
|
loadType: LoadTypes;
|
|
436
|
-
data:
|
|
437
|
+
data: LavalinkLoadResultData;
|
|
437
438
|
}
|
|
438
439
|
/**
|
|
439
440
|
* Track Data
|
|
@@ -444,7 +445,9 @@ export interface TrackData {
|
|
|
444
445
|
/** The detailed information of the track. */
|
|
445
446
|
info: TrackDataInfo;
|
|
446
447
|
/** Additional track info provided by plugins. */
|
|
447
|
-
pluginInfo: Record<string,
|
|
448
|
+
pluginInfo: Record<string, unknown>;
|
|
449
|
+
/** Additional track data sent back from Lavalink. */
|
|
450
|
+
userData: Record<string, unknown>;
|
|
448
451
|
}
|
|
449
452
|
/**
|
|
450
453
|
* Playlist Raw Data
|
|
@@ -453,12 +456,15 @@ export interface PlaylistRawData {
|
|
|
453
456
|
info: {
|
|
454
457
|
/** The playlist name. */
|
|
455
458
|
name: string;
|
|
459
|
+
/** The selected track index, or -1 if none is selected. */
|
|
460
|
+
selectedTrack: number;
|
|
456
461
|
};
|
|
457
462
|
/** Addition info provided by plugins. */
|
|
458
|
-
pluginInfo:
|
|
463
|
+
pluginInfo: Record<string, unknown>;
|
|
459
464
|
/** The tracks of the playlist */
|
|
460
465
|
tracks: TrackData[];
|
|
461
466
|
}
|
|
467
|
+
export type LavalinkLoadResultData = TrackData | TrackData[] | PlaylistRawData | Exception | null;
|
|
462
468
|
/**
|
|
463
469
|
* Track Data Info
|
|
464
470
|
*/
|
|
@@ -467,19 +473,20 @@ export interface TrackDataInfo {
|
|
|
467
473
|
isSeekable: boolean;
|
|
468
474
|
author: string;
|
|
469
475
|
length: number;
|
|
470
|
-
|
|
476
|
+
position: number;
|
|
477
|
+
isrc: string | null;
|
|
471
478
|
isStream: boolean;
|
|
472
479
|
title: string;
|
|
473
|
-
uri
|
|
474
|
-
artworkUrl
|
|
475
|
-
sourceName
|
|
480
|
+
uri: string | null;
|
|
481
|
+
artworkUrl: string | null;
|
|
482
|
+
sourceName: TrackSourceName;
|
|
476
483
|
}
|
|
477
484
|
/**
|
|
478
485
|
* LavaPlayer
|
|
479
486
|
*/
|
|
480
487
|
export interface LavaPlayer {
|
|
481
488
|
guildId: string;
|
|
482
|
-
track: TrackData;
|
|
489
|
+
track: TrackData | null;
|
|
483
490
|
volume: number;
|
|
484
491
|
paused: boolean;
|
|
485
492
|
state: {
|
|
@@ -489,7 +496,7 @@ export interface LavaPlayer {
|
|
|
489
496
|
ping: number;
|
|
490
497
|
};
|
|
491
498
|
voice: LavalinkVoiceStateResponse;
|
|
492
|
-
filters:
|
|
499
|
+
filters: LavalinkFilters;
|
|
493
500
|
}
|
|
494
501
|
/**
|
|
495
502
|
* Error or Empty Search Result
|
|
@@ -584,8 +591,10 @@ export interface PlaylistData {
|
|
|
584
591
|
name: string;
|
|
585
592
|
/** Requester of playlist. */
|
|
586
593
|
requester: AnyUser;
|
|
587
|
-
/**
|
|
588
|
-
playlistInfo: PlaylistInfoData
|
|
594
|
+
/** Lavalink playlist information. */
|
|
595
|
+
playlistInfo: PlaylistInfoData;
|
|
596
|
+
/** Additional playlist information provided by plugins. */
|
|
597
|
+
pluginInfo: PlaylistPluginInfo;
|
|
589
598
|
/** The length of the playlist. */
|
|
590
599
|
duration: number;
|
|
591
600
|
/** The songs of the playlist. */
|
|
@@ -595,16 +604,17 @@ export interface PlaylistData {
|
|
|
595
604
|
* Playlist Info Data
|
|
596
605
|
*/
|
|
597
606
|
export interface PlaylistInfoData {
|
|
598
|
-
/**
|
|
599
|
-
|
|
600
|
-
/**
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
607
|
+
/** The playlist name. */
|
|
608
|
+
name: string;
|
|
609
|
+
/** The selected track index, or -1 if none is selected. */
|
|
610
|
+
selectedTrack: number;
|
|
611
|
+
}
|
|
612
|
+
export interface PlaylistPluginInfo extends Record<string, unknown> {
|
|
613
|
+
url?: string;
|
|
614
|
+
type?: string;
|
|
615
|
+
artworkUrl?: string;
|
|
616
|
+
totalTracks?: number;
|
|
617
|
+
author?: string;
|
|
608
618
|
}
|
|
609
619
|
/**
|
|
610
620
|
* Manager Events
|
|
@@ -703,7 +713,7 @@ export interface NodeStats {
|
|
|
703
713
|
/** The cpu stats for the node. */
|
|
704
714
|
cpu: CPUStats;
|
|
705
715
|
/** The frame stats for the node. */
|
|
706
|
-
frameStats: FrameStats;
|
|
716
|
+
frameStats: FrameStats | null;
|
|
707
717
|
}
|
|
708
718
|
/**
|
|
709
719
|
* Node Message
|
|
@@ -725,9 +735,10 @@ export interface PlayerEvent {
|
|
|
725
735
|
* Exception interface
|
|
726
736
|
*/
|
|
727
737
|
export interface Exception {
|
|
728
|
-
message: string;
|
|
738
|
+
message: string | null;
|
|
729
739
|
severity: SeverityTypes;
|
|
730
740
|
cause: string;
|
|
741
|
+
causeStackTrace?: string;
|
|
731
742
|
}
|
|
732
743
|
/**
|
|
733
744
|
* TrackStartEvent interface
|
|
@@ -833,7 +844,7 @@ export interface NodeStats {
|
|
|
833
844
|
/** The cpu stats for the node. */
|
|
834
845
|
cpu: CPUStats;
|
|
835
846
|
/** The frame stats for the node. */
|
|
836
|
-
frameStats: FrameStats;
|
|
847
|
+
frameStats: FrameStats | null;
|
|
837
848
|
}
|
|
838
849
|
/**
|
|
839
850
|
* MemoryStats interface
|
|
@@ -879,7 +890,7 @@ export interface LavalinkInfo {
|
|
|
879
890
|
major: number;
|
|
880
891
|
minor: number;
|
|
881
892
|
patch: number;
|
|
882
|
-
preRelease: string;
|
|
893
|
+
preRelease: string | null;
|
|
883
894
|
};
|
|
884
895
|
buildTime: number;
|
|
885
896
|
git: {
|
|
@@ -1101,7 +1112,7 @@ export interface RestPlayOptions {
|
|
|
1101
1112
|
/** Whether the player is paused. */
|
|
1102
1113
|
paused?: boolean;
|
|
1103
1114
|
/** The audio effects. */
|
|
1104
|
-
filters?:
|
|
1115
|
+
filters?: LavalinkFilters;
|
|
1105
1116
|
/** voice payload. */
|
|
1106
1117
|
voice?: LavalinkVoiceStateUpdate;
|
|
1107
1118
|
};
|
|
@@ -1140,11 +1151,15 @@ export interface SerializedPlayerState {
|
|
|
1140
1151
|
filters: {
|
|
1141
1152
|
bassBoostlevel: number | null;
|
|
1142
1153
|
equalizer: EqualizerBand[];
|
|
1143
|
-
distortion: DistortionOptions;
|
|
1144
|
-
karaoke: KaraokeOptions;
|
|
1145
|
-
timescale: TimescaleOptions;
|
|
1146
|
-
|
|
1147
|
-
|
|
1154
|
+
distortion: DistortionOptions | null;
|
|
1155
|
+
karaoke: KaraokeOptions | null;
|
|
1156
|
+
timescale: TimescaleOptions | null;
|
|
1157
|
+
tremolo: TremoloOptions | null;
|
|
1158
|
+
vibrato: VibratoOptions | null;
|
|
1159
|
+
rotation: RotationOptions | null;
|
|
1160
|
+
channelMix: ChannelMixOptions | null;
|
|
1161
|
+
lowPass: LowPassOptions | null;
|
|
1162
|
+
pluginFilters: Record<string, unknown>;
|
|
1148
1163
|
reverb: ReverbOptions;
|
|
1149
1164
|
volume: number;
|
|
1150
1165
|
filterStatus: Record<string, boolean>;
|
|
@@ -1183,6 +1198,26 @@ export interface LavalinkSession {
|
|
|
1183
1198
|
resuming?: boolean;
|
|
1184
1199
|
timeout?: number;
|
|
1185
1200
|
}
|
|
1201
|
+
export interface RoutePlannerStatus {
|
|
1202
|
+
class: "RotatingIpRoutePlanner" | "NanoIpRoutePlanner" | "RotatingNanoIpRoutePlanner" | "BalancingIpRoutePlanner";
|
|
1203
|
+
details: RoutePlannerDetails;
|
|
1204
|
+
}
|
|
1205
|
+
export interface RoutePlannerDetails {
|
|
1206
|
+
ipBlock: {
|
|
1207
|
+
type: "Inet4Address" | "Inet6Address";
|
|
1208
|
+
size: string;
|
|
1209
|
+
};
|
|
1210
|
+
failingAddresses: {
|
|
1211
|
+
failingAddress: string;
|
|
1212
|
+
failingTimestamp: number;
|
|
1213
|
+
failingTime: string;
|
|
1214
|
+
}[];
|
|
1215
|
+
rotateIndex?: string;
|
|
1216
|
+
ipIndex?: string;
|
|
1217
|
+
currentAddress?: string;
|
|
1218
|
+
currentAddressIndex?: string;
|
|
1219
|
+
blockIndex?: string;
|
|
1220
|
+
}
|
|
1186
1221
|
/**
|
|
1187
1222
|
* ManagerInitOptions interface
|
|
1188
1223
|
*/
|
|
@@ -1205,10 +1240,15 @@ export interface TimescaleOptions {
|
|
|
1205
1240
|
pitch?: number;
|
|
1206
1241
|
rate?: number;
|
|
1207
1242
|
}
|
|
1243
|
+
/** Options for applying tremolo effect to audio. */
|
|
1244
|
+
export interface TremoloOptions {
|
|
1245
|
+
frequency?: number;
|
|
1246
|
+
depth?: number;
|
|
1247
|
+
}
|
|
1208
1248
|
/** Options for applying vibrato effect to audio. */
|
|
1209
1249
|
export interface VibratoOptions {
|
|
1210
|
-
frequency
|
|
1211
|
-
depth
|
|
1250
|
+
frequency?: number;
|
|
1251
|
+
depth?: number;
|
|
1212
1252
|
}
|
|
1213
1253
|
/** Options for applying rotation effect to audio. */
|
|
1214
1254
|
export interface RotationOptions {
|
|
@@ -1232,6 +1272,30 @@ export interface DistortionOptions {
|
|
|
1232
1272
|
offset?: number;
|
|
1233
1273
|
scale?: number;
|
|
1234
1274
|
}
|
|
1275
|
+
/** Options for mixing stereo channels. */
|
|
1276
|
+
export interface ChannelMixOptions {
|
|
1277
|
+
leftToLeft?: number;
|
|
1278
|
+
leftToRight?: number;
|
|
1279
|
+
rightToLeft?: number;
|
|
1280
|
+
rightToRight?: number;
|
|
1281
|
+
}
|
|
1282
|
+
/** Options for applying a low pass filter. */
|
|
1283
|
+
export interface LowPassOptions {
|
|
1284
|
+
smoothing?: number;
|
|
1285
|
+
}
|
|
1286
|
+
export interface LavalinkFilters {
|
|
1287
|
+
volume?: number;
|
|
1288
|
+
equalizer?: EqualizerBand[];
|
|
1289
|
+
karaoke?: KaraokeOptions | null;
|
|
1290
|
+
timescale?: TimescaleOptions | null;
|
|
1291
|
+
tremolo?: TremoloOptions | null;
|
|
1292
|
+
vibrato?: VibratoOptions | null;
|
|
1293
|
+
distortion?: DistortionOptions | null;
|
|
1294
|
+
rotation?: RotationOptions | null;
|
|
1295
|
+
channelMix?: ChannelMixOptions | null;
|
|
1296
|
+
lowPass?: LowPassOptions | null;
|
|
1297
|
+
pluginFilters?: Record<string, unknown>;
|
|
1298
|
+
}
|
|
1235
1299
|
/** Options for applying reverb effect to audio. */
|
|
1236
1300
|
export interface ReverbOptions {
|
|
1237
1301
|
wet?: number;
|
|
@@ -1305,7 +1369,7 @@ export type Sizes = "0" | "1" | "2" | "3" | "default" | "mqdefault" | "hqdefault
|
|
|
1305
1369
|
/**
|
|
1306
1370
|
* Track Source Name Enum type
|
|
1307
1371
|
*/
|
|
1308
|
-
export type TrackSourceName =
|
|
1372
|
+
export type TrackSourceName = `${TrackSourceTypes}` | string;
|
|
1309
1373
|
/**
|
|
1310
1374
|
* Use Node Option Enum type
|
|
1311
1375
|
*/
|
package/dist/structures/Utils.js
CHANGED
|
@@ -63,7 +63,7 @@ class TrackUtils {
|
|
|
63
63
|
if (typeof track !== "object" || track === null)
|
|
64
64
|
return false;
|
|
65
65
|
const trackRecord = track;
|
|
66
|
-
return REQUIRED_TRACK_KEYS.every((key) => typeof trackRecord[key] === "string");
|
|
66
|
+
return REQUIRED_TRACK_KEYS.every((key) => (key === "uri" ? typeof trackRecord[key] === "string" || trackRecord[key] === null : typeof trackRecord[key] === "string"));
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
69
|
* Checks if the provided argument is a valid Track array.
|
|
@@ -131,14 +131,14 @@ class TrackUtils {
|
|
|
131
131
|
uri: data.info.uri,
|
|
132
132
|
artworkUrl: data.info?.artworkUrl ?? null,
|
|
133
133
|
sourceName: sourceNameMap[data.info?.sourceName?.toLowerCase() ?? ""] ?? data.info?.sourceName,
|
|
134
|
-
thumbnail: data.info.uri
|
|
134
|
+
thumbnail: data.info.uri?.includes("youtube") ? `https://img.youtube.com/vi/${data.info.identifier}/default.jpg` : null,
|
|
135
135
|
displayThumbnail(size = "default") {
|
|
136
136
|
const finalSize = SIZES.find((s) => s === size) ?? "default";
|
|
137
|
-
return this.uri
|
|
137
|
+
return this.uri?.includes("youtube") ? `https://img.youtube.com/vi/${data.info.identifier}/${finalSize}.jpg` : null;
|
|
138
138
|
},
|
|
139
139
|
requester: requester,
|
|
140
140
|
pluginInfo: data.pluginInfo,
|
|
141
|
-
customData: {},
|
|
141
|
+
customData: data.userData ?? {},
|
|
142
142
|
isAutoplay: isAutoplay,
|
|
143
143
|
};
|
|
144
144
|
track.displayThumbnail = track.displayThumbnail.bind(track);
|
|
@@ -180,7 +180,7 @@ class TrackUtils {
|
|
|
180
180
|
return track;
|
|
181
181
|
track.displayThumbnail = function (size = "default") {
|
|
182
182
|
const finalSize = SIZES.find((s) => s === size) ?? "default";
|
|
183
|
-
return this.uri
|
|
183
|
+
return this.uri?.includes("youtube") ? `https://img.youtube.com/vi/${this.identifier}/${finalSize}.jpg` : null;
|
|
184
184
|
}.bind(track);
|
|
185
185
|
return track;
|
|
186
186
|
}
|
|
@@ -318,6 +318,8 @@ class AutoPlayUtils {
|
|
|
318
318
|
*/
|
|
319
319
|
static async getRecommendedTracksFromSource(track, platform) {
|
|
320
320
|
const requester = track.requester;
|
|
321
|
+
if (!track.uri)
|
|
322
|
+
return [];
|
|
321
323
|
const parsedURL = new URL(track.uri);
|
|
322
324
|
switch (platform) {
|
|
323
325
|
case Enums_1.AutoPlayPlatform.Spotify: {
|
|
@@ -412,14 +414,14 @@ class AutoPlayUtils {
|
|
|
412
414
|
}
|
|
413
415
|
case Enums_1.AutoPlayPlatform.YouTube: {
|
|
414
416
|
const allowedYouTubeHosts = ["youtube.com", "youtu.be"];
|
|
415
|
-
const hasYouTubeURL = allowedYouTubeHosts.some((url) => track.uri
|
|
417
|
+
const hasYouTubeURL = allowedYouTubeHosts.some((url) => track.uri?.includes(url));
|
|
416
418
|
let videoID = null;
|
|
417
419
|
if (hasYouTubeURL) {
|
|
418
|
-
videoID = track.uri
|
|
420
|
+
videoID = track.uri?.split("=").pop() ?? null;
|
|
419
421
|
}
|
|
420
422
|
else {
|
|
421
423
|
const resolvedTrack = await this.resolveFirstTrackFromQuery(`${track.author} - ${track.title}`, Enums_1.SearchPlatform.YouTube, requester);
|
|
422
|
-
if (!resolvedTrack)
|
|
424
|
+
if (!resolvedTrack?.uri)
|
|
423
425
|
return [];
|
|
424
426
|
videoID = resolvedTrack.uri.split("=").pop();
|
|
425
427
|
}
|
|
@@ -431,7 +433,7 @@ class AutoPlayUtils {
|
|
|
431
433
|
do {
|
|
432
434
|
randomIndex = Math.floor(Math.random() * 23) + 2;
|
|
433
435
|
searchURI = `https://www.youtube.com/watch?v=${videoID}&list=RD${videoID}&index=${randomIndex}`;
|
|
434
|
-
} while (track.uri
|
|
436
|
+
} while (track.uri?.includes(searchURI));
|
|
435
437
|
const resolvedTracks = await this.resolveTracksFromQuery(searchURI, Enums_1.SearchPlatform.YouTube, requester);
|
|
436
438
|
const filteredTracks = resolvedTracks.filter((resolvedTrack) => resolvedTrack.uri !== track.uri);
|
|
437
439
|
return filteredTracks;
|
|
@@ -721,6 +723,8 @@ class PlayerUtils {
|
|
|
721
723
|
paused: player.paused,
|
|
722
724
|
playing: player.playing,
|
|
723
725
|
position: player.position,
|
|
726
|
+
isAutoplay: player.isAutoplay,
|
|
727
|
+
autoplayTries: player.autoplayTries,
|
|
724
728
|
trackRepeat: player.trackRepeat,
|
|
725
729
|
queueRepeat: player.queueRepeat,
|
|
726
730
|
dynamicRepeat: player.dynamicRepeat,
|
|
@@ -737,7 +741,11 @@ class PlayerUtils {
|
|
|
737
741
|
karaoke: player.filters.karaoke ?? null,
|
|
738
742
|
rotation: player.filters.rotation ?? null,
|
|
739
743
|
timescale: player.filters.timescale ?? null,
|
|
744
|
+
tremolo: player.filters.tremoloOptions ?? null,
|
|
740
745
|
vibrato: player.filters.vibrato ?? null,
|
|
746
|
+
channelMix: player.filters.channelMix ?? null,
|
|
747
|
+
lowPass: player.filters.lowPass ?? null,
|
|
748
|
+
pluginFilters: player.filters.pluginFilters ?? {},
|
|
741
749
|
reverb: player.filters.reverb ?? null,
|
|
742
750
|
volume: player.filters.volume ?? 1.0,
|
|
743
751
|
bassBoostlevel: player.filters.bassBoostlevel ?? null,
|