discord-player 6.0.0-dev.0 → 6.0.0-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,788 +0,0 @@
1
- "use strict";
2
- var _Queue_instances, _Queue_lastVolume, _Queue_destroyed, _Queue_watchDestroyed, _Queue_getBufferingTimeout;
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.Queue = void 0;
5
- const tslib_1 = require("tslib");
6
- const discord_js_1 = require("discord.js");
7
- const Track_1 = tslib_1.__importDefault(require("./Track"));
8
- const types_1 = require("../types/types");
9
- const discord_ytdl_core_1 = tslib_1.__importDefault(require("discord-ytdl-core"));
10
- const voice_1 = require("@discordjs/voice");
11
- const Util_1 = require("../utils/Util");
12
- const youtube_sr_1 = tslib_1.__importDefault(require("youtube-sr"));
13
- const AudioFilters_1 = tslib_1.__importDefault(require("../utils/AudioFilters"));
14
- const PlayerError_1 = require("./PlayerError");
15
- class Queue {
16
- /**
17
- * Queue constructor
18
- * @param {Player} player The player that instantiated this queue
19
- * @param {Guild} guild The guild that instantiated this queue
20
- * @param {PlayerOptions} [options={}] Player options for the queue
21
- */
22
- constructor(player, guild, options = {}) {
23
- _Queue_instances.add(this);
24
- this.tracks = [];
25
- this.previousTracks = [];
26
- this.playing = false;
27
- this.metadata = null;
28
- this.repeatMode = 0;
29
- this.id = discord_js_1.SnowflakeUtil.generate().toString();
30
- this._streamTime = 0;
31
- this._cooldownsTimeout = new discord_js_1.Collection();
32
- this._activeFilters = []; // eslint-disable-line @typescript-eslint/no-explicit-any
33
- this._filtersUpdate = false;
34
- _Queue_lastVolume.set(this, 0);
35
- _Queue_destroyed.set(this, false);
36
- this.onBeforeCreateStream = null;
37
- /**
38
- * The player that instantiated this queue
39
- * @type {Player}
40
- * @readonly
41
- */
42
- this.player = player;
43
- /**
44
- * The guild that instantiated this queue
45
- * @type {Guild}
46
- * @readonly
47
- */
48
- this.guild = guild;
49
- /**
50
- * The player options for this queue
51
- * @type {PlayerOptions}
52
- */
53
- this.options = {};
54
- /**
55
- * Queue repeat mode
56
- * @type {QueueRepeatMode}
57
- * @name Queue#repeatMode
58
- */
59
- /**
60
- * Queue metadata
61
- * @type {any}
62
- * @name Queue#metadata
63
- */
64
- /**
65
- * Previous tracks
66
- * @type {Track[]}
67
- * @name Queue#previousTracks
68
- */
69
- /**
70
- * Regular tracks
71
- * @type {Track[]}
72
- * @name Queue#tracks
73
- */
74
- /**
75
- * The connection
76
- * @type {StreamDispatcher}
77
- * @name Queue#connection
78
- */
79
- /**
80
- * The ID of this queue
81
- * @type {Snowflake}
82
- * @name Queue#id
83
- */
84
- Object.assign(this.options, {
85
- leaveOnEnd: true,
86
- leaveOnStop: true,
87
- leaveOnEmpty: true,
88
- leaveOnEmptyCooldown: 1000,
89
- autoSelfDeaf: true,
90
- ytdlOptions: {
91
- highWaterMark: 1 << 25
92
- },
93
- initialVolume: 100,
94
- bufferingTimeout: 3000,
95
- spotifyBridge: true,
96
- disableVolume: false
97
- }, options);
98
- if ("onBeforeCreateStream" in this.options)
99
- this.onBeforeCreateStream = this.options.onBeforeCreateStream;
100
- this.player.emit("debug", this, `Queue initialized:\n\n${this.player.scanDeps()}`);
101
- }
102
- /**
103
- * Returns current track
104
- * @type {Track}
105
- */
106
- get current() {
107
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
108
- return;
109
- return this.connection.audioResource?.metadata ?? this.tracks[0];
110
- }
111
- /**
112
- * If this queue is destroyed
113
- * @type {boolean}
114
- */
115
- get destroyed() {
116
- return tslib_1.__classPrivateFieldGet(this, _Queue_destroyed, "f");
117
- }
118
- /**
119
- * Returns current track
120
- * @returns {Track}
121
- */
122
- nowPlaying() {
123
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
124
- return;
125
- return this.current;
126
- }
127
- /**
128
- * Connects to a voice channel
129
- * @param {GuildChannelResolvable} channel The voice/stage channel
130
- * @returns {Promise<Queue>}
131
- */
132
- async connect(channel) {
133
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
134
- return;
135
- const _channel = this.guild.channels.resolve(channel);
136
- if (![discord_js_1.ChannelType.GuildStageVoice, discord_js_1.ChannelType.GuildVoice].includes(_channel?.type))
137
- throw new PlayerError_1.PlayerError(`Channel type must be GuildVoice or GuildStageVoice, got ${_channel?.type}!`, PlayerError_1.ErrorStatusCode.INVALID_ARG_TYPE);
138
- const connection = await this.player.voiceUtils.connect(_channel, {
139
- deaf: this.options.autoSelfDeaf
140
- });
141
- this.connection = connection;
142
- if (_channel.type === discord_js_1.ChannelType.GuildStageVoice) {
143
- await _channel.guild.members.me.voice.setSuppressed(false).catch(async () => {
144
- return await _channel.guild.members.me.voice.setRequestToSpeak(true).catch(Util_1.Util.noop);
145
- });
146
- }
147
- this.connection.on("error", (err) => {
148
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this, false))
149
- return;
150
- this.player.emit("connectionError", this, err);
151
- });
152
- this.connection.on("debug", (msg) => {
153
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this, false))
154
- return;
155
- this.player.emit("debug", this, msg);
156
- });
157
- this.player.emit("connectionCreate", this, this.connection);
158
- this.connection.on("start", (resource) => {
159
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this, false))
160
- return;
161
- this.playing = true;
162
- if (!this._filtersUpdate && resource?.metadata)
163
- this.player.emit("trackStart", this, resource?.metadata ?? this.current);
164
- this._filtersUpdate = false;
165
- });
166
- this.connection.on("finish", async (resource) => {
167
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this, false))
168
- return;
169
- this.playing = false;
170
- if (this._filtersUpdate)
171
- return;
172
- this._streamTime = 0;
173
- if (resource && resource.metadata)
174
- this.previousTracks.push(resource.metadata);
175
- this.player.emit("trackEnd", this, resource.metadata);
176
- if (!this.tracks.length && this.repeatMode === types_1.QueueRepeatMode.OFF) {
177
- if (this.options.leaveOnEnd)
178
- this.destroy();
179
- this.player.emit("queueEnd", this);
180
- }
181
- else if (!this.tracks.length && this.repeatMode === types_1.QueueRepeatMode.AUTOPLAY) {
182
- this._handleAutoplay(Util_1.Util.last(this.previousTracks));
183
- }
184
- else {
185
- if (this.repeatMode === types_1.QueueRepeatMode.TRACK)
186
- return void this.play(Util_1.Util.last(this.previousTracks), { immediate: true });
187
- if (this.repeatMode === types_1.QueueRepeatMode.QUEUE)
188
- this.tracks.push(Util_1.Util.last(this.previousTracks));
189
- const nextTrack = this.tracks.shift();
190
- this.play(nextTrack, { immediate: true });
191
- return;
192
- }
193
- });
194
- await this.player.voiceUtils.enterReady(this.connection.voiceConnection, {
195
- maxTime: this.player.options.connectionTimeout || 30000
196
- });
197
- return this;
198
- }
199
- /**
200
- * Destroys this queue
201
- * @param {boolean} [disconnect=this.options.leaveOnStop] If it should leave on destroy
202
- * @returns {void}
203
- */
204
- destroy(disconnect = this.options.leaveOnStop) {
205
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
206
- return;
207
- if (this.connection)
208
- this.connection.end();
209
- if (disconnect)
210
- this.connection?.disconnect();
211
- this.player.queues.delete(this.guild.id);
212
- this.player.voiceUtils.cache.delete(this.guild.id);
213
- tslib_1.__classPrivateFieldSet(this, _Queue_destroyed, true, "f");
214
- }
215
- /**
216
- * Skips current track
217
- * @returns {boolean}
218
- */
219
- skip() {
220
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
221
- return;
222
- if (!this.connection)
223
- return false;
224
- this._filtersUpdate = false;
225
- this.connection.end();
226
- return true;
227
- }
228
- /**
229
- * Adds single track to the queue
230
- * @param {Track} track The track to add
231
- * @returns {void}
232
- */
233
- addTrack(track) {
234
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
235
- return;
236
- if (!(track instanceof Track_1.default))
237
- throw new PlayerError_1.PlayerError("invalid track", PlayerError_1.ErrorStatusCode.INVALID_TRACK);
238
- this.tracks.push(track);
239
- this.player.emit("trackAdd", this, track);
240
- }
241
- /**
242
- * Adds multiple tracks to the queue
243
- * @param {Track[]} tracks Array of tracks to add
244
- */
245
- addTracks(tracks) {
246
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
247
- return;
248
- if (!tracks.every((y) => y instanceof Track_1.default))
249
- throw new PlayerError_1.PlayerError("invalid track", PlayerError_1.ErrorStatusCode.INVALID_TRACK);
250
- this.tracks.push(...tracks);
251
- this.player.emit("tracksAdd", this, tracks);
252
- }
253
- /**
254
- * Sets paused state
255
- * @param {boolean} paused The paused state
256
- * @returns {boolean}
257
- */
258
- setPaused(paused) {
259
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
260
- return;
261
- if (!this.connection)
262
- return false;
263
- return paused ? this.connection.pause(true) : this.connection.resume();
264
- }
265
- /**
266
- * Sets bitrate
267
- * @param {number|auto} bitrate bitrate to set
268
- * @returns {void}
269
- */
270
- setBitrate(bitrate) {
271
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
272
- return;
273
- if (!this.connection?.audioResource?.encoder)
274
- return;
275
- if (bitrate === "auto")
276
- bitrate = this.connection.channel?.bitrate ?? 64000;
277
- this.connection.audioResource.encoder.setBitrate(bitrate);
278
- }
279
- /**
280
- * Sets volume
281
- * @param {number} amount The volume amount
282
- * @returns {boolean}
283
- */
284
- setVolume(amount) {
285
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
286
- return;
287
- if (!this.connection)
288
- return false;
289
- tslib_1.__classPrivateFieldSet(this, _Queue_lastVolume, amount, "f");
290
- this.options.initialVolume = amount;
291
- return this.connection.setVolume(amount);
292
- }
293
- /**
294
- * Sets repeat mode
295
- * @param {QueueRepeatMode} mode The repeat mode
296
- * @returns {boolean}
297
- */
298
- setRepeatMode(mode) {
299
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
300
- return;
301
- if (![types_1.QueueRepeatMode.OFF, types_1.QueueRepeatMode.QUEUE, types_1.QueueRepeatMode.TRACK, types_1.QueueRepeatMode.AUTOPLAY].includes(mode))
302
- throw new PlayerError_1.PlayerError(`Unknown repeat mode "${mode}"!`, PlayerError_1.ErrorStatusCode.UNKNOWN_REPEAT_MODE);
303
- if (mode === this.repeatMode)
304
- return false;
305
- this.repeatMode = mode;
306
- return true;
307
- }
308
- /**
309
- * The current volume amount
310
- * @type {number}
311
- */
312
- get volume() {
313
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
314
- return;
315
- if (!this.connection)
316
- return 100;
317
- return this.connection.volume;
318
- }
319
- set volume(amount) {
320
- this.setVolume(amount);
321
- }
322
- /**
323
- * The stream time of this queue
324
- * @type {number}
325
- */
326
- get streamTime() {
327
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
328
- return;
329
- if (!this.connection)
330
- return 0;
331
- const playbackTime = this._streamTime + this.connection.streamTime;
332
- const NC = this._activeFilters.includes("nightcore") ? 1.25 : null;
333
- const VW = this._activeFilters.includes("vaporwave") ? 0.8 : null;
334
- if (NC && VW)
335
- return playbackTime * (NC + VW);
336
- return NC ? playbackTime * NC : VW ? playbackTime * VW : playbackTime;
337
- }
338
- set streamTime(time) {
339
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
340
- return;
341
- this.seek(time);
342
- }
343
- /**
344
- * Returns enabled filters
345
- * @returns {AudioFilters}
346
- */
347
- getFiltersEnabled() {
348
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
349
- return;
350
- return AudioFilters_1.default.names.filter((x) => this._activeFilters.includes(x));
351
- }
352
- /**
353
- * Returns disabled filters
354
- * @returns {AudioFilters}
355
- */
356
- getFiltersDisabled() {
357
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
358
- return;
359
- return AudioFilters_1.default.names.filter((x) => !this._activeFilters.includes(x));
360
- }
361
- /**
362
- * Sets filters
363
- * @param {QueueFilters} filters Queue filters
364
- * @returns {Promise<void>}
365
- */
366
- async setFilters(filters) {
367
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
368
- return;
369
- if (!filters || !Object.keys(filters).length) {
370
- // reset filters
371
- const streamTime = this.streamTime;
372
- this._activeFilters = [];
373
- return await this.play(this.current, {
374
- immediate: true,
375
- filtersUpdate: true,
376
- seek: streamTime,
377
- encoderArgs: []
378
- });
379
- }
380
- const _filters = []; // eslint-disable-line @typescript-eslint/no-explicit-any
381
- for (const filter in filters) {
382
- if (filters[filter] === true)
383
- _filters.push(filter);
384
- }
385
- if (this._activeFilters.join("") === _filters.join(""))
386
- return;
387
- const newFilters = AudioFilters_1.default.create(_filters).trim();
388
- const streamTime = this.streamTime;
389
- this._activeFilters = _filters;
390
- return await this.play(this.current, {
391
- immediate: true,
392
- filtersUpdate: true,
393
- seek: streamTime,
394
- encoderArgs: !_filters.length ? undefined : ["-af", newFilters]
395
- });
396
- }
397
- /**
398
- * Seeks to the given time
399
- * @param {number} position The position
400
- * @returns {boolean}
401
- */
402
- async seek(position) {
403
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
404
- return;
405
- if (!this.playing || !this.current)
406
- return false;
407
- if (position < 1)
408
- position = 0;
409
- if (position >= this.current.durationMS)
410
- return this.skip();
411
- await this.play(this.current, {
412
- immediate: true,
413
- filtersUpdate: true,
414
- seek: position
415
- });
416
- return true;
417
- }
418
- /**
419
- * Plays previous track
420
- * @returns {Promise<void>}
421
- */
422
- async back() {
423
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
424
- return;
425
- const prev = this.previousTracks[this.previousTracks.length - 2]; // because last item is the current track
426
- if (!prev)
427
- throw new PlayerError_1.PlayerError("Could not find previous track", PlayerError_1.ErrorStatusCode.TRACK_NOT_FOUND);
428
- return await this.play(prev, { immediate: true });
429
- }
430
- /**
431
- * Clear this queue
432
- */
433
- clear() {
434
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
435
- return;
436
- this.tracks = [];
437
- this.previousTracks = [];
438
- }
439
- /**
440
- * Stops the player
441
- * @returns {void}
442
- */
443
- stop() {
444
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
445
- return;
446
- return this.destroy();
447
- }
448
- /**
449
- * Shuffles this queue
450
- * @returns {boolean}
451
- */
452
- shuffle() {
453
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
454
- return;
455
- if (!this.tracks.length || this.tracks.length < 3)
456
- return false;
457
- const currentTrack = this.tracks.shift();
458
- for (let i = this.tracks.length - 1; i > 0; i--) {
459
- const j = Math.floor(Math.random() * (i + 1));
460
- [this.tracks[i], this.tracks[j]] = [this.tracks[j], this.tracks[i]];
461
- }
462
- this.tracks.unshift(currentTrack);
463
- return true;
464
- }
465
- /**
466
- * Removes a track from the queue
467
- * @param {Track|string|number} track The track to remove
468
- * @returns {Track}
469
- */
470
- remove(track) {
471
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
472
- return;
473
- let trackFound = null;
474
- if (typeof track === "number") {
475
- trackFound = this.tracks[track];
476
- if (trackFound) {
477
- this.tracks = this.tracks.filter((t) => t.id !== trackFound.id);
478
- }
479
- }
480
- else {
481
- trackFound = this.tracks.find((s) => s.id === (track instanceof Track_1.default ? track.id : track));
482
- if (trackFound) {
483
- this.tracks = this.tracks.filter((s) => s.id !== trackFound.id);
484
- }
485
- }
486
- return trackFound;
487
- }
488
- /**
489
- * Returns the index of the specified track. If found, returns the track index else returns -1.
490
- * @param {number|Track|string} track The track
491
- * @returns {number}
492
- */
493
- getTrackPosition(track) {
494
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
495
- return;
496
- if (typeof track === "number")
497
- return this.tracks[track] != null ? track : -1;
498
- return this.tracks.findIndex((pred) => pred.id === (track instanceof Track_1.default ? track.id : track));
499
- }
500
- /**
501
- * Jumps to particular track
502
- * @param {Track|number} track The track
503
- * @returns {void}
504
- */
505
- jump(track) {
506
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
507
- return;
508
- const foundTrack = this.remove(track);
509
- if (!foundTrack)
510
- throw new PlayerError_1.PlayerError("Track not found", PlayerError_1.ErrorStatusCode.TRACK_NOT_FOUND);
511
- this.tracks.splice(0, 0, foundTrack);
512
- return void this.skip();
513
- }
514
- /**
515
- * Jumps to particular track, removing other tracks on the way
516
- * @param {Track|number} track The track
517
- * @returns {void}
518
- */
519
- skipTo(track) {
520
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
521
- return;
522
- const trackIndex = this.getTrackPosition(track);
523
- const removedTrack = this.remove(track);
524
- if (!removedTrack)
525
- throw new PlayerError_1.PlayerError("Track not found", PlayerError_1.ErrorStatusCode.TRACK_NOT_FOUND);
526
- this.tracks.splice(0, trackIndex, removedTrack);
527
- return void this.skip();
528
- }
529
- /**
530
- * Inserts the given track to specified index
531
- * @param {Track} track The track to insert
532
- * @param {number} [index=0] The index where this track should be
533
- */
534
- insert(track, index = 0) {
535
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
536
- return;
537
- if (!track || !(track instanceof Track_1.default))
538
- throw new PlayerError_1.PlayerError("track must be the instance of Track", PlayerError_1.ErrorStatusCode.INVALID_TRACK);
539
- if (typeof index !== "number" || index < 0 || !Number.isFinite(index))
540
- throw new PlayerError_1.PlayerError(`Invalid index "${index}"`, PlayerError_1.ErrorStatusCode.INVALID_ARG_TYPE);
541
- this.tracks.splice(index, 0, track);
542
- this.player.emit("trackAdd", this, track);
543
- }
544
- /**
545
- * @typedef {object} PlayerTimestamp
546
- * @property {string} current The current progress
547
- * @property {string} end The total time
548
- * @property {number} progress Progress in %
549
- */
550
- /**
551
- * Returns player stream timestamp
552
- * @returns {PlayerTimestamp}
553
- */
554
- getPlayerTimestamp() {
555
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
556
- return;
557
- const currentStreamTime = this.streamTime;
558
- const totalTime = this.current.durationMS;
559
- const currentTimecode = Util_1.Util.buildTimeCode(Util_1.Util.parseMS(currentStreamTime));
560
- const endTimecode = Util_1.Util.buildTimeCode(Util_1.Util.parseMS(totalTime));
561
- return {
562
- current: currentTimecode,
563
- end: endTimecode,
564
- progress: Math.round((currentStreamTime / totalTime) * 100)
565
- };
566
- }
567
- /**
568
- * Creates progress bar string
569
- * @param {PlayerProgressbarOptions} options The progress bar options
570
- * @returns {string}
571
- */
572
- createProgressBar(options = { timecodes: true }) {
573
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
574
- return;
575
- const length = typeof options.length === "number" ? (options.length <= 0 || options.length === Infinity ? 15 : options.length) : 15;
576
- const index = Math.round((this.streamTime / this.current.durationMS) * length);
577
- const indicator = typeof options.indicator === "string" && options.indicator.length > 0 ? options.indicator : "🔘";
578
- const line = typeof options.line === "string" && options.line.length > 0 ? options.line : "▬";
579
- if (index >= 1 && index <= length) {
580
- const bar = line.repeat(length - 1).split("");
581
- bar.splice(index, 0, indicator);
582
- if (options.timecodes) {
583
- const timestamp = this.getPlayerTimestamp();
584
- return `${timestamp.current} ┃ ${bar.join("")} ┃ ${timestamp.end}`;
585
- }
586
- else {
587
- return `${bar.join("")}`;
588
- }
589
- }
590
- else {
591
- if (options.timecodes) {
592
- const timestamp = this.getPlayerTimestamp();
593
- return `${timestamp.current} ┃ ${indicator}${line.repeat(length - 1)} ┃ ${timestamp.end}`;
594
- }
595
- else {
596
- return `${indicator}${line.repeat(length - 1)}`;
597
- }
598
- }
599
- }
600
- /**
601
- * Total duration
602
- * @type {Number}
603
- */
604
- get totalTime() {
605
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
606
- return;
607
- return this.tracks.length > 0 ? this.tracks.map((t) => t.durationMS).reduce((p, c) => p + c) : 0;
608
- }
609
- /**
610
- * Play stream in a voice/stage channel
611
- * @param {Track} [src] The track to play (if empty, uses first track from the queue)
612
- * @param {PlayOptions} [options={}] The options
613
- * @returns {Promise<void>}
614
- */
615
- async play(src, options = {}) {
616
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this, false))
617
- return;
618
- if (!this.connection || !this.connection.voiceConnection)
619
- throw new PlayerError_1.PlayerError("Voice connection is not available, use <Queue>.connect()!", PlayerError_1.ErrorStatusCode.NO_CONNECTION);
620
- if (src && (this.playing || this.tracks.length) && !options.immediate)
621
- return this.addTrack(src);
622
- const track = options.filtersUpdate && !options.immediate ? src || this.current : src ?? this.tracks.shift();
623
- if (!track)
624
- return;
625
- this.player.emit("debug", this, "Received play request");
626
- if (!options.filtersUpdate) {
627
- this.previousTracks = this.previousTracks.filter((x) => x.id !== track.id);
628
- this.previousTracks.push(track);
629
- }
630
- let stream = null;
631
- const customDownloader = typeof this.onBeforeCreateStream === "function";
632
- if (["youtube", "spotify"].includes(track.raw.source)) {
633
- let spotifyResolved = false;
634
- if (this.options.spotifyBridge && track.raw.source === "spotify" && !track.raw.engine) {
635
- track.raw.engine = await youtube_sr_1.default.search(`${track.author} ${track.title}`, { type: "video" })
636
- .then((x) => x[0].url)
637
- .catch(() => null);
638
- spotifyResolved = true;
639
- }
640
- const link = track.raw.source === "spotify" ? track.raw.engine : track.url;
641
- if (!link)
642
- return void this.play(this.tracks.shift(), { immediate: true });
643
- if (customDownloader) {
644
- stream = (await this.onBeforeCreateStream(track, spotifyResolved ? "youtube" : track.raw.source, this)) ?? null;
645
- if (stream)
646
- stream = discord_ytdl_core_1.default
647
- .arbitraryStream(stream, {
648
- opusEncoded: false,
649
- fmt: "s16le",
650
- encoderArgs: options.encoderArgs ?? this._activeFilters.length ? ["-af", AudioFilters_1.default.create(this._activeFilters)] : [],
651
- seek: options.seek ? options.seek / 1000 : 0
652
- })
653
- .on("error", (err) => {
654
- return err.message.toLowerCase().includes("premature close") ? null : this.player.emit("error", this, err);
655
- });
656
- }
657
- else {
658
- stream = (0, discord_ytdl_core_1.default)(link, {
659
- ...this.options.ytdlOptions,
660
- // discord-ytdl-core
661
- opusEncoded: false,
662
- fmt: "s16le",
663
- encoderArgs: options.encoderArgs ?? this._activeFilters.length ? ["-af", AudioFilters_1.default.create(this._activeFilters)] : [],
664
- seek: options.seek ? options.seek / 1000 : 0
665
- }).on("error", (err) => {
666
- return err.message.toLowerCase().includes("premature close") ? null : this.player.emit("error", this, err);
667
- });
668
- }
669
- }
670
- else {
671
- const tryArb = (customDownloader && (await this.onBeforeCreateStream(track, track.raw.source || track.raw.engine, this))) || null;
672
- const arbitrarySource = tryArb
673
- ? tryArb
674
- : track.raw.source === "soundcloud"
675
- ? await track.raw.engine.downloadProgressive()
676
- : typeof track.raw.engine === "function"
677
- ? await track.raw.engine()
678
- : track.raw.engine;
679
- stream = discord_ytdl_core_1.default
680
- .arbitraryStream(arbitrarySource, {
681
- opusEncoded: false,
682
- fmt: "s16le",
683
- encoderArgs: options.encoderArgs ?? this._activeFilters.length ? ["-af", AudioFilters_1.default.create(this._activeFilters)] : [],
684
- seek: options.seek ? options.seek / 1000 : 0
685
- })
686
- .on("error", (err) => {
687
- return err.message.toLowerCase().includes("premature close") ? null : this.player.emit("error", this, err);
688
- });
689
- }
690
- const resource = this.connection.createStream(stream, {
691
- type: voice_1.StreamType.Raw,
692
- data: track,
693
- disableVolume: Boolean(this.options.disableVolume)
694
- });
695
- if (options.seek)
696
- this._streamTime = options.seek;
697
- this._filtersUpdate = options.filtersUpdate;
698
- const volumeTransformer = resource.volume;
699
- if (volumeTransformer?.hasSmoothness && typeof this.options.volumeSmoothness === "number") {
700
- if (typeof volumeTransformer.setSmoothness === "function")
701
- volumeTransformer.setSmoothness(this.options.volumeSmoothness || 0);
702
- }
703
- this.setVolume(this.options.initialVolume);
704
- setTimeout(() => {
705
- this.connection.playStream(resource);
706
- }, tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_getBufferingTimeout).call(this)).unref();
707
- }
708
- /**
709
- * Private method to handle autoplay
710
- * @param {Track} track The source track to find its similar track for autoplay
711
- * @returns {Promise<void>}
712
- * @private
713
- */
714
- async _handleAutoplay(track) {
715
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
716
- return;
717
- if (!track || ![track.source, track.raw?.source].includes("youtube")) {
718
- if (this.options.leaveOnEnd)
719
- this.destroy();
720
- return void this.player.emit("queueEnd", this);
721
- }
722
- const info = await youtube_sr_1.default.getVideo(track.url)
723
- .then((x) => x.videos[0])
724
- .catch(Util_1.Util.noop);
725
- if (!info) {
726
- if (this.options.leaveOnEnd)
727
- this.destroy();
728
- return void this.player.emit("queueEnd", this);
729
- }
730
- const nextTrack = new Track_1.default(this.player, {
731
- title: info.title,
732
- url: `https://www.youtube.com/watch?v=${info.id}`,
733
- duration: info.durationFormatted ? Util_1.Util.buildTimeCode(Util_1.Util.parseMS(info.duration * 1000)) : "0:00",
734
- description: "",
735
- thumbnail: typeof info.thumbnail === "string" ? info.thumbnail : info.thumbnail.url,
736
- views: info.views,
737
- author: info.channel.name,
738
- requestedBy: track.requestedBy,
739
- source: "youtube"
740
- });
741
- this.play(nextTrack, { immediate: true });
742
- }
743
- *[(_Queue_lastVolume = new WeakMap(), _Queue_destroyed = new WeakMap(), _Queue_instances = new WeakSet(), Symbol.iterator)]() {
744
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
745
- return;
746
- yield* this.tracks;
747
- }
748
- /**
749
- * JSON representation of this queue
750
- * @returns {object}
751
- */
752
- toJSON() {
753
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
754
- return;
755
- return {
756
- id: this.id,
757
- guild: this.guild.id,
758
- voiceChannel: this.connection?.channel?.id,
759
- options: this.options,
760
- tracks: this.tracks.map((m) => m.toJSON())
761
- };
762
- }
763
- /**
764
- * String representation of this queue
765
- * @returns {string}
766
- */
767
- toString() {
768
- if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
769
- return;
770
- if (!this.tracks.length)
771
- return "No songs available to display!";
772
- return `**Upcoming Songs:**\n${this.tracks.map((m, i) => `${i + 1}. **${m.title}**`).join("\n")}`;
773
- }
774
- }
775
- exports.Queue = Queue;
776
- _Queue_watchDestroyed = function _Queue_watchDestroyed(emit = true) {
777
- if (tslib_1.__classPrivateFieldGet(this, _Queue_destroyed, "f")) {
778
- if (emit)
779
- this.player.emit("error", this, new PlayerError_1.PlayerError("Cannot use destroyed queue", PlayerError_1.ErrorStatusCode.DESTROYED_QUEUE));
780
- return true;
781
- }
782
- return false;
783
- }, _Queue_getBufferingTimeout = function _Queue_getBufferingTimeout() {
784
- const timeout = this.options.bufferingTimeout;
785
- if (isNaN(timeout) || timeout < 0 || !Number.isFinite(timeout))
786
- return 1000;
787
- return timeout;
788
- };