aqualink 2.5.0 → 2.6.0
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/build/structures/Aqua.js
CHANGED
|
@@ -233,7 +233,7 @@ class Aqua extends EventEmitter {
|
|
|
233
233
|
const response = await requestNode.rest.makeRequest("GET", endpoint);
|
|
234
234
|
|
|
235
235
|
if (["empty", "NO_MATCHES"].includes(response.loadType)) {
|
|
236
|
-
return await this.handleNoMatches(
|
|
236
|
+
return await this.handleNoMatches(query);
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
return this.constructResponse(response, requester, requestNode);
|
|
@@ -244,33 +244,29 @@ class Aqua extends EventEmitter {
|
|
|
244
244
|
throw new Error(`Failed to resolve track: ${error.message}`);
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
|
-
|
|
247
|
+
|
|
248
248
|
getRequestNode(nodes) {
|
|
249
249
|
if (!nodes) return this.leastUsedNodes[0];
|
|
250
250
|
|
|
251
251
|
if (nodes instanceof Node) return nodes;
|
|
252
|
-
if (typeof nodes === "string")
|
|
252
|
+
if (typeof nodes === "string") {
|
|
253
|
+
const mappedNode = this.nodeMap.get(nodes);
|
|
254
|
+
return mappedNode || this.leastUsedNodes[0];
|
|
255
|
+
}
|
|
253
256
|
|
|
254
257
|
throw new TypeError(`'nodes' must be a string or Node instance, received: ${typeof nodes}`);
|
|
255
258
|
}
|
|
256
|
-
|
|
257
|
-
async handleNoMatches(
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
const spotifyEndpoint = `/v4/loadtracks?identifier=https://open.spotify.com/track/${query}`;
|
|
267
|
-
return await rest.makeRequest("GET", spotifyEndpoint);
|
|
268
|
-
} catch (error) {
|
|
269
|
-
console.error(`Failed to resolve track: ${error.message}`);
|
|
270
|
-
throw error;
|
|
271
|
-
}
|
|
259
|
+
|
|
260
|
+
async handleNoMatches(query) {
|
|
261
|
+
return {
|
|
262
|
+
loadType: "empty",
|
|
263
|
+
exception: null,
|
|
264
|
+
playlistInfo: null,
|
|
265
|
+
pluginInfo: {},
|
|
266
|
+
tracks: []
|
|
267
|
+
};
|
|
272
268
|
}
|
|
273
|
-
|
|
269
|
+
|
|
274
270
|
constructResponse(response, requester, requestNode) {
|
|
275
271
|
const baseResponse = {
|
|
276
272
|
loadType: response.loadType,
|
|
@@ -2,40 +2,44 @@
|
|
|
2
2
|
|
|
3
3
|
class Connection {
|
|
4
4
|
constructor(player) {
|
|
5
|
-
this.
|
|
5
|
+
this.player = player;
|
|
6
6
|
|
|
7
7
|
this.sessionId = null;
|
|
8
8
|
this.endpoint = null;
|
|
9
9
|
this.token = null;
|
|
10
|
-
|
|
11
10
|
this.region = null;
|
|
12
|
-
|
|
13
|
-
this.selfMute = false;
|
|
11
|
+
|
|
14
12
|
this.voiceChannel = player.voiceChannel;
|
|
15
13
|
this.guildId = player.guildId;
|
|
16
|
-
|
|
17
14
|
this.aqua = player.aqua;
|
|
18
15
|
this.nodes = player.nodes;
|
|
16
|
+
|
|
17
|
+
this.selfDeaf = false;
|
|
18
|
+
this.selfMute = false;
|
|
19
|
+
|
|
20
|
+
this.hasDebugListeners = this.aqua.listenerCount('debug') > 0;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
setServerUpdate(data) {
|
|
22
|
-
if (!data
|
|
24
|
+
if (!data || !data.endpoint) return;
|
|
23
25
|
|
|
24
26
|
const { endpoint, token } = data;
|
|
25
|
-
const dotIndex = endpoint.indexOf('.');
|
|
26
27
|
|
|
28
|
+
const dotIndex = endpoint.indexOf('.');
|
|
27
29
|
if (dotIndex === -1) return;
|
|
30
|
+
|
|
28
31
|
const newRegion = endpoint.substring(0, dotIndex);
|
|
29
32
|
|
|
30
33
|
if (this.region !== newRegion) {
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
this.endpoint = endpoint;
|
|
35
|
+
this.token = token;
|
|
36
|
+
this.region = newRegion;
|
|
33
37
|
|
|
34
|
-
if (this.
|
|
38
|
+
if (this.hasDebugListeners) {
|
|
35
39
|
this.aqua.emit(
|
|
36
40
|
"debug",
|
|
37
41
|
`[Player ${this.guildId} - CONNECTION] Voice Server: ${
|
|
38
|
-
|
|
42
|
+
this.region ? `Changed from ${this.region} to ${newRegion}` : newRegion
|
|
39
43
|
}`
|
|
40
44
|
);
|
|
41
45
|
}
|
|
@@ -45,10 +49,12 @@ class Connection {
|
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
setStateUpdate(data) {
|
|
48
|
-
|
|
52
|
+
if (!data) return this.player?.destroy();
|
|
53
|
+
|
|
54
|
+
const { channel_id, session_id, self_deaf, self_mute } = data;
|
|
49
55
|
|
|
50
56
|
if (!channel_id || !session_id) {
|
|
51
|
-
this.
|
|
57
|
+
this.player?.destroy();
|
|
52
58
|
return;
|
|
53
59
|
}
|
|
54
60
|
|
|
@@ -57,36 +63,35 @@ class Connection {
|
|
|
57
63
|
this.voiceChannel = channel_id;
|
|
58
64
|
}
|
|
59
65
|
|
|
60
|
-
this.selfDeaf =
|
|
61
|
-
this.selfMute =
|
|
66
|
+
this.selfDeaf = Boolean(self_deaf);
|
|
67
|
+
this.selfMute = Boolean(self_mute);
|
|
62
68
|
this.sessionId = session_id;
|
|
63
69
|
}
|
|
64
70
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
71
|
+
_updatePlayerVoiceData() {
|
|
72
|
+
if (!this.player) return;
|
|
73
|
+
|
|
74
|
+
const voiceData = {
|
|
75
|
+
sessionId: this.sessionId,
|
|
76
|
+
endpoint: this.endpoint,
|
|
77
|
+
token: this.token
|
|
78
|
+
};
|
|
68
79
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
},
|
|
78
|
-
volume: player.volume
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
} catch (error) {
|
|
82
|
-
if (this.aqua.listenerCount('apiError')) {
|
|
80
|
+
this.nodes.rest.updatePlayer({
|
|
81
|
+
guildId: this.guildId,
|
|
82
|
+
data: {
|
|
83
|
+
voice: voiceData,
|
|
84
|
+
volume: this.player.volume
|
|
85
|
+
}
|
|
86
|
+
}).catch(error => {
|
|
87
|
+
if (this.aqua.listenerCount('apiError') > 0) {
|
|
83
88
|
this.aqua.emit("apiError", "updatePlayer", {
|
|
84
89
|
error,
|
|
85
90
|
guildId: this.guildId,
|
|
86
|
-
voiceData
|
|
91
|
+
voiceData
|
|
87
92
|
});
|
|
88
93
|
}
|
|
89
|
-
}
|
|
94
|
+
});
|
|
90
95
|
}
|
|
91
96
|
}
|
|
92
97
|
|
|
@@ -3,205 +3,165 @@
|
|
|
3
3
|
class Filters {
|
|
4
4
|
constructor(player, options = {}) {
|
|
5
5
|
this.player = player;
|
|
6
|
-
this.volume = options.volume || 1;
|
|
7
|
-
this.equalizer = options.equalizer || [];
|
|
8
|
-
this.karaoke = options.karaoke || null;
|
|
9
|
-
this.timescale = options.timescale || null;
|
|
10
|
-
this.tremolo = options.tremolo || null;
|
|
11
|
-
this.vibrato = options.vibrato || null;
|
|
12
|
-
this.rotation = options.rotation || null;
|
|
13
|
-
this.distortion = options.distortion || null;
|
|
14
|
-
this.channelMix = options.channelMix || null;
|
|
15
|
-
this.lowPass = options.lowPass || null;
|
|
16
|
-
this.bassboost = options.bassboost || null;
|
|
17
|
-
this.slowmode = options.slowmode || null;
|
|
18
|
-
this.nightcore = options.nightcore || null;
|
|
19
|
-
this.vaporwave = options.vaporwave || null;
|
|
20
|
-
this._8d = options._8d || null;
|
|
21
6
|
|
|
22
|
-
this.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
channelMix: null,
|
|
32
|
-
lowPass: null
|
|
7
|
+
this.defaults = {
|
|
8
|
+
karaoke: { level: 1.0, monoLevel: 1.0, filterBand: 220.0, filterWidth: 100.0 },
|
|
9
|
+
timescale: { speed: 1.0, pitch: 1.0, rate: 1.0 },
|
|
10
|
+
tremolo: { frequency: 2.0, depth: 0.5 },
|
|
11
|
+
vibrato: { frequency: 2.0, depth: 0.5 },
|
|
12
|
+
rotation: { rotationHz: 0.0 },
|
|
13
|
+
distortion: { sinOffset: 0.0, sinScale: 1.0, cosOffset: 0.0, cosScale: 1.0, tanOffset: 0.0, tanScale: 1.0, offset: 0.0, scale: 1.0 },
|
|
14
|
+
channelMix: { leftToLeft: 1.0, leftToRight: 0.0, rightToLeft: 0.0, rightToRight: 1.0 },
|
|
15
|
+
lowPass: { smoothing: 20.0 }
|
|
33
16
|
};
|
|
17
|
+
|
|
18
|
+
this.filters = {
|
|
19
|
+
volume: options.volume || 1,
|
|
20
|
+
equalizer: options.equalizer || [],
|
|
21
|
+
karaoke: options.karaoke || null,
|
|
22
|
+
timescale: options.timescale || null,
|
|
23
|
+
tremolo: options.tremolo || null,
|
|
24
|
+
vibrato: options.vibrato || null,
|
|
25
|
+
rotation: options.rotation || null,
|
|
26
|
+
distortion: options.distortion || null,
|
|
27
|
+
channelMix: options.channelMix || null,
|
|
28
|
+
lowPass: options.lowPass || null
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
this.presets = {
|
|
32
|
+
bassboost: options.bassboost !== undefined ? options.bassboost : null,
|
|
33
|
+
slowmode: options.slowmode !== undefined ? options.slowmode : null,
|
|
34
|
+
nightcore: options.nightcore !== undefined ? options.nightcore : null,
|
|
35
|
+
vaporwave: options.vaporwave !== undefined ? options.vaporwave : null,
|
|
36
|
+
_8d: options._8d !== undefined ? options._8d : null
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
this._pendingUpdate = false;
|
|
40
|
+
this._updateTimeout = null;
|
|
34
41
|
}
|
|
35
42
|
|
|
36
|
-
_setFilter(filterName, enabled, options,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
_setFilter(filterName, enabled, options = {}, defaultKey = filterName) {
|
|
44
|
+
this.filters[filterName] = enabled ? { ...this.defaults[defaultKey], ...options } : null;
|
|
45
|
+
return this._scheduleUpdate();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
_scheduleUpdate() {
|
|
49
|
+
this._pendingUpdate = true;
|
|
41
50
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
filterObj[key] = options[key] !== undefined ? options[key] : defaultValue;
|
|
51
|
+
if (this._updateTimeout) {
|
|
52
|
+
clearTimeout(this._updateTimeout);
|
|
45
53
|
}
|
|
46
54
|
|
|
47
|
-
this
|
|
48
|
-
return this
|
|
55
|
+
this._updateTimeout = setTimeout(() => this.updateFilters(), 0);
|
|
56
|
+
return this;
|
|
49
57
|
}
|
|
50
58
|
|
|
51
59
|
setEqualizer(bands) {
|
|
52
|
-
this.equalizer = bands;
|
|
53
|
-
return this.
|
|
60
|
+
this.filters.equalizer = bands || [];
|
|
61
|
+
return this._scheduleUpdate();
|
|
54
62
|
}
|
|
55
63
|
|
|
56
64
|
setKaraoke(enabled, options = {}) {
|
|
57
|
-
return this._setFilter('karaoke', enabled, options
|
|
58
|
-
level: 1.0,
|
|
59
|
-
monoLevel: 1.0,
|
|
60
|
-
filterBand: 220.0,
|
|
61
|
-
filterWidth: 100.0
|
|
62
|
-
});
|
|
65
|
+
return this._setFilter('karaoke', enabled, options);
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
setTimescale(enabled, options = {}) {
|
|
66
|
-
return this._setFilter('timescale', enabled, options
|
|
67
|
-
speed: 1.0,
|
|
68
|
-
pitch: 1.0,
|
|
69
|
-
rate: 1.0
|
|
70
|
-
});
|
|
69
|
+
return this._setFilter('timescale', enabled, options);
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
setTremolo(enabled, options = {}) {
|
|
74
|
-
return this._setFilter('tremolo', enabled, options
|
|
75
|
-
frequency: 2.0,
|
|
76
|
-
depth: 0.5
|
|
77
|
-
});
|
|
73
|
+
return this._setFilter('tremolo', enabled, options);
|
|
78
74
|
}
|
|
79
75
|
|
|
80
76
|
setVibrato(enabled, options = {}) {
|
|
81
|
-
return this._setFilter('vibrato', enabled, options
|
|
82
|
-
frequency: 2.0,
|
|
83
|
-
depth: 0.5
|
|
84
|
-
});
|
|
77
|
+
return this._setFilter('vibrato', enabled, options);
|
|
85
78
|
}
|
|
86
79
|
|
|
87
80
|
setRotation(enabled, options = {}) {
|
|
88
|
-
return this._setFilter('rotation', enabled, options
|
|
89
|
-
rotationHz: 0.0
|
|
90
|
-
});
|
|
81
|
+
return this._setFilter('rotation', enabled, options);
|
|
91
82
|
}
|
|
92
83
|
|
|
93
84
|
setDistortion(enabled, options = {}) {
|
|
94
|
-
return this._setFilter('distortion', enabled, options
|
|
95
|
-
sinOffset: 0.0,
|
|
96
|
-
sinScale: 1.0,
|
|
97
|
-
cosOffset: 0.0,
|
|
98
|
-
cosScale: 1.0,
|
|
99
|
-
tanOffset: 0.0,
|
|
100
|
-
tanScale: 1.0,
|
|
101
|
-
offset: 0.0,
|
|
102
|
-
scale: 1.0
|
|
103
|
-
});
|
|
85
|
+
return this._setFilter('distortion', enabled, options);
|
|
104
86
|
}
|
|
105
87
|
|
|
106
88
|
setChannelMix(enabled, options = {}) {
|
|
107
|
-
return this._setFilter('channelMix', enabled, options
|
|
108
|
-
leftToLeft: 1.0,
|
|
109
|
-
leftToRight: 0.0,
|
|
110
|
-
rightToLeft: 0.0,
|
|
111
|
-
rightToRight: 1.0
|
|
112
|
-
});
|
|
89
|
+
return this._setFilter('channelMix', enabled, options);
|
|
113
90
|
}
|
|
114
91
|
|
|
115
92
|
setLowPass(enabled, options = {}) {
|
|
116
|
-
return this._setFilter('lowPass', enabled, options
|
|
117
|
-
smoothing: 20.0
|
|
118
|
-
});
|
|
93
|
+
return this._setFilter('lowPass', enabled, options);
|
|
119
94
|
}
|
|
120
95
|
|
|
121
96
|
setBassboost(enabled, options = {}) {
|
|
122
97
|
if (!enabled) {
|
|
123
|
-
this.bassboost = null;
|
|
98
|
+
this.presets.bassboost = null;
|
|
124
99
|
return this.setEqualizer([]);
|
|
125
100
|
}
|
|
126
101
|
|
|
127
102
|
const value = options.value || 5;
|
|
128
103
|
if (value < 0 || value > 5) throw new Error("Bassboost value must be between 0 and 5");
|
|
129
104
|
|
|
130
|
-
this.bassboost = value;
|
|
131
|
-
const
|
|
105
|
+
this.presets.bassboost = value;
|
|
106
|
+
const gain = (value - 1) * (1.25 / 9) - 0.25;
|
|
132
107
|
|
|
133
|
-
const eq =
|
|
134
|
-
for (let i = 0; i < 13; i++) {
|
|
135
|
-
eq[i] = { band: i, gain: num };
|
|
136
|
-
}
|
|
108
|
+
const eq = Array.from({ length: 13 }, (_, i) => ({ band: i, gain }));
|
|
137
109
|
|
|
138
110
|
return this.setEqualizer(eq);
|
|
139
111
|
}
|
|
140
112
|
|
|
141
113
|
setSlowmode(enabled, options = {}) {
|
|
142
|
-
this.slowmode = enabled;
|
|
114
|
+
this.presets.slowmode = enabled;
|
|
143
115
|
return this.setTimescale(enabled, { rate: enabled ? (options.rate || 0.8) : 1.0 });
|
|
144
116
|
}
|
|
145
117
|
|
|
146
118
|
setNightcore(enabled, options = {}) {
|
|
147
|
-
this.nightcore = enabled;
|
|
119
|
+
this.presets.nightcore = enabled;
|
|
148
120
|
return this.setTimescale(enabled, { rate: enabled ? (options.rate || 1.5) : 1.0 });
|
|
149
121
|
}
|
|
150
122
|
|
|
151
123
|
setVaporwave(enabled, options = {}) {
|
|
152
|
-
this.vaporwave = enabled;
|
|
124
|
+
this.presets.vaporwave = enabled;
|
|
153
125
|
return this.setTimescale(enabled, { pitch: enabled ? (options.pitch || 0.5) : 1.0 });
|
|
154
126
|
}
|
|
155
127
|
|
|
156
128
|
set8D(enabled, options = {}) {
|
|
157
|
-
this._8d = enabled;
|
|
129
|
+
this.presets._8d = enabled;
|
|
158
130
|
return this.setRotation(enabled, { rotationHz: enabled ? (options.rotationHz || 0.2) : 0.0 });
|
|
159
131
|
}
|
|
160
132
|
|
|
161
133
|
async clearFilters() {
|
|
162
|
-
this.
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
this.
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
this.distortion = null;
|
|
170
|
-
this.channelMix = null;
|
|
171
|
-
this.lowPass = null;
|
|
172
|
-
this.bassboost = null;
|
|
173
|
-
this.slowmode = null;
|
|
174
|
-
this.nightcore = null;
|
|
175
|
-
this.vaporwave = null;
|
|
176
|
-
this._8d = null;
|
|
134
|
+
Object.keys(this.filters).forEach(key => {
|
|
135
|
+
this.filters[key] = key === 'volume' ? 1 : (key === 'equalizer' ? [] : null);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
Object.keys(this.presets).forEach(key => {
|
|
139
|
+
this.presets[key] = null;
|
|
140
|
+
});
|
|
177
141
|
|
|
178
|
-
this.
|
|
179
|
-
this.
|
|
142
|
+
this._pendingUpdate = false;
|
|
143
|
+
if (this._updateTimeout) {
|
|
144
|
+
clearTimeout(this._updateTimeout);
|
|
145
|
+
this._updateTimeout = null;
|
|
146
|
+
}
|
|
180
147
|
|
|
181
148
|
await this.updateFilters();
|
|
182
149
|
return this;
|
|
183
150
|
}
|
|
184
151
|
|
|
185
152
|
async updateFilters() {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
distortion: this.distortion,
|
|
196
|
-
channelMix: this.channelMix,
|
|
197
|
-
lowPass: this.lowPass
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
this._filterDataTemplate = { ...filterData };
|
|
201
|
-
|
|
153
|
+
if (!this._pendingUpdate && this._updateTimeout) {
|
|
154
|
+
clearTimeout(this._updateTimeout);
|
|
155
|
+
this._updateTimeout = null;
|
|
156
|
+
return this;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
this._pendingUpdate = false;
|
|
160
|
+
this._updateTimeout = null;
|
|
161
|
+
|
|
202
162
|
await this.player.nodes.rest.updatePlayer({
|
|
203
163
|
guildId: this.player.guildId,
|
|
204
|
-
data: { filters:
|
|
164
|
+
data: { filters: { ...this.filters } }
|
|
205
165
|
});
|
|
206
166
|
|
|
207
167
|
return this;
|
|
@@ -37,8 +37,8 @@ class Player extends EventEmitter {
|
|
|
37
37
|
|
|
38
38
|
this.volume = Math.min(Math.max(options.defaultVolume ?? 100, 0), 200);
|
|
39
39
|
this.loop = Player.validModes.has(options.loop) ? options.loop : Player.LOOP_MODES.NONE;
|
|
40
|
-
this.shouldDeleteMessage =
|
|
41
|
-
this.leaveOnEnd =
|
|
40
|
+
this.shouldDeleteMessage = !!this.aqua.options.shouldDeleteMessage;
|
|
41
|
+
this.leaveOnEnd = !!this.aqua.options.leaveOnEnd;
|
|
42
42
|
|
|
43
43
|
this.previousTracks = new Array(50);
|
|
44
44
|
this.previousTracksIndex = 0;
|
|
@@ -38,23 +38,32 @@ class Queue extends Array {
|
|
|
38
38
|
remove(track) {
|
|
39
39
|
const index = this.indexOf(track);
|
|
40
40
|
if (index !== -1) {
|
|
41
|
-
|
|
41
|
+
if (index === this.length - 1) {
|
|
42
|
+
this.pop();
|
|
43
|
+
} else {
|
|
44
|
+
this.splice(index, 1);
|
|
45
|
+
}
|
|
46
|
+
return true;
|
|
42
47
|
}
|
|
48
|
+
return false;
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
// Clear all tracks from the queue
|
|
46
52
|
clear() {
|
|
47
|
-
this.length = 0;
|
|
53
|
+
this.length = 0;
|
|
48
54
|
}
|
|
49
55
|
|
|
50
56
|
// Shuffle the tracks in the queue
|
|
51
57
|
shuffle() {
|
|
52
|
-
|
|
58
|
+
const length = this.length;
|
|
59
|
+
for (let i = length - 1; i > 0; i--) {
|
|
53
60
|
const j = Math.floor(Math.random() * (i + 1));
|
|
54
|
-
|
|
61
|
+
if (i !== j) {
|
|
62
|
+
[this[i], this[j]] = [this[j], this[i]];
|
|
63
|
+
}
|
|
55
64
|
}
|
|
65
|
+
return this;
|
|
56
66
|
}
|
|
57
|
-
|
|
58
67
|
// Peek at the element at the front of the queue without removing it
|
|
59
68
|
peek() {
|
|
60
69
|
return this.first;
|
|
@@ -62,7 +71,7 @@ class Queue extends Array {
|
|
|
62
71
|
|
|
63
72
|
// Get all tracks in the queue as an array
|
|
64
73
|
toArray() {
|
|
65
|
-
return
|
|
74
|
+
return this.slice();
|
|
66
75
|
}
|
|
67
76
|
|
|
68
77
|
/**
|
|
@@ -71,9 +80,8 @@ class Queue extends Array {
|
|
|
71
80
|
* @returns {*} The track at the specified index or null if out of bounds.
|
|
72
81
|
*/
|
|
73
82
|
at(index) {
|
|
74
|
-
return
|
|
83
|
+
return (index >= 0 && index < this.length) ? this[index] : null;
|
|
75
84
|
}
|
|
76
|
-
|
|
77
85
|
// Remove the first track from the queue
|
|
78
86
|
dequeue() {
|
|
79
87
|
return this.shift(); // Removes and returns the first element
|
|
@@ -10,7 +10,8 @@ class Track {
|
|
|
10
10
|
this.identifier = info.identifier || '';
|
|
11
11
|
this.isSeekable = Boolean(info.isSeekable);
|
|
12
12
|
this.author = info.author || '';
|
|
13
|
-
this.length = info.length
|
|
13
|
+
this.length = info.length || 0;
|
|
14
|
+
this.duration = info.length || 0;
|
|
14
15
|
this.isStream = Boolean(info.isStream);
|
|
15
16
|
this.title = info.title || '';
|
|
16
17
|
this.uri = info.uri || '';
|