discord-player 5.4.0 → 5.4.1-dev.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/LICENSE +1 -1
- package/dist/index.d.ts +1492 -1281
- package/dist/index.js +2072 -36
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2039 -22
- package/dist/index.mjs.map +1 -0
- package/package.json +15 -31
- package/dist/Player.js +0 -623
- package/dist/Structures/ExtractorModel.js +0 -65
- package/dist/Structures/PlayerError.js +0 -48
- package/dist/Structures/Playlist.js +0 -108
- package/dist/Structures/Queue.js +0 -917
- package/dist/Structures/Track.js +0 -155
- package/dist/VoiceInterface/StreamDispatcher.js +0 -238
- package/dist/VoiceInterface/VoiceUtils.js +0 -65
- package/dist/VoiceInterface/VolumeTransformer.js +0 -120
- package/dist/smoothVolume.js +0 -15
- package/dist/types/types.js +0 -58
- package/dist/utils/AudioFilters.js +0 -95
- package/dist/utils/FFmpegStream.js +0 -53
- package/dist/utils/QueryResolver.js +0 -68
- package/dist/utils/Util.js +0 -136
package/dist/index.mjs
CHANGED
|
@@ -1,22 +1,2039 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
+
}) : x)(function(x) {
|
|
6
|
+
if (typeof require !== "undefined")
|
|
7
|
+
return require.apply(this, arguments);
|
|
8
|
+
throw new Error('Dynamic require of "' + x + '" is not supported');
|
|
9
|
+
});
|
|
10
|
+
var __accessCheck = (obj, member, msg) => {
|
|
11
|
+
if (!member.has(obj))
|
|
12
|
+
throw TypeError("Cannot " + msg);
|
|
13
|
+
};
|
|
14
|
+
var __privateGet = (obj, member, getter) => {
|
|
15
|
+
__accessCheck(obj, member, "read from private field");
|
|
16
|
+
return getter ? getter.call(obj) : member.get(obj);
|
|
17
|
+
};
|
|
18
|
+
var __privateAdd = (obj, member, value) => {
|
|
19
|
+
if (member.has(obj))
|
|
20
|
+
throw TypeError("Cannot add the same private member more than once");
|
|
21
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
22
|
+
};
|
|
23
|
+
var __privateSet = (obj, member, value, setter) => {
|
|
24
|
+
__accessCheck(obj, member, "write to private field");
|
|
25
|
+
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
26
|
+
return value;
|
|
27
|
+
};
|
|
28
|
+
var __privateMethod = (obj, member, method) => {
|
|
29
|
+
__accessCheck(obj, member, "access private method");
|
|
30
|
+
return method;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// src/VoiceInterface/VolumeTransformer.ts
|
|
34
|
+
import { Transform } from "stream";
|
|
35
|
+
var VolumeTransformer = class extends Transform {
|
|
36
|
+
constructor(options = {}) {
|
|
37
|
+
super(options);
|
|
38
|
+
switch (options.type) {
|
|
39
|
+
case "s16le":
|
|
40
|
+
this._readInt = (buffer, index) => buffer.readInt16LE(index);
|
|
41
|
+
this._writeInt = (buffer, int, index) => buffer.writeInt16LE(int, index);
|
|
42
|
+
this._bits = 16;
|
|
43
|
+
break;
|
|
44
|
+
case "s16be":
|
|
45
|
+
this._readInt = (buffer, index) => buffer.readInt16BE(index);
|
|
46
|
+
this._writeInt = (buffer, int, index) => buffer.writeInt16BE(int, index);
|
|
47
|
+
this._bits = 16;
|
|
48
|
+
break;
|
|
49
|
+
case "s32le":
|
|
50
|
+
this._readInt = (buffer, index) => buffer.readInt32LE(index);
|
|
51
|
+
this._writeInt = (buffer, int, index) => buffer.writeInt32LE(int, index);
|
|
52
|
+
this._bits = 32;
|
|
53
|
+
break;
|
|
54
|
+
case "s32be":
|
|
55
|
+
this._readInt = (buffer, index) => buffer.readInt32BE(index);
|
|
56
|
+
this._writeInt = (buffer, int, index) => buffer.writeInt32BE(int, index);
|
|
57
|
+
this._bits = 32;
|
|
58
|
+
break;
|
|
59
|
+
default:
|
|
60
|
+
throw new Error("VolumeTransformer type should be one of s16le, s16be, s32le, s32be");
|
|
61
|
+
}
|
|
62
|
+
this.type = options.type;
|
|
63
|
+
this._bytes = this._bits / 8;
|
|
64
|
+
this._extremum = Math.pow(2, this._bits - 1);
|
|
65
|
+
this.volume = Number.isNaN(options.volume) ? 1 : Number(options.volume);
|
|
66
|
+
if (!Number.isFinite(this.volume))
|
|
67
|
+
this.volume = 1;
|
|
68
|
+
this._targetVolume = this.volume;
|
|
69
|
+
this._chunk = Buffer.alloc(0);
|
|
70
|
+
this._smoothing = options.smoothness || 0;
|
|
71
|
+
}
|
|
72
|
+
_readInt(buffer, index) {
|
|
73
|
+
return index;
|
|
74
|
+
}
|
|
75
|
+
_writeInt(buffer, int, index) {
|
|
76
|
+
return index;
|
|
77
|
+
}
|
|
78
|
+
_applySmoothness() {
|
|
79
|
+
if (this.volume < this._targetVolume) {
|
|
80
|
+
this.volume = this.volume + this._smoothing >= this._targetVolume ? this._targetVolume : this.volume + this._smoothing;
|
|
81
|
+
} else if (this.volume > this._targetVolume) {
|
|
82
|
+
this.volume = this.volume - this._smoothing <= this._targetVolume ? this._targetVolume : this.volume - this._smoothing;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
_transform(chunk, encoding, done) {
|
|
86
|
+
if (this.smoothingEnabled() && this.volume !== this._targetVolume)
|
|
87
|
+
this._applySmoothness();
|
|
88
|
+
if (this.volume === 1) {
|
|
89
|
+
this.push(chunk);
|
|
90
|
+
return done();
|
|
91
|
+
}
|
|
92
|
+
const { _bytes, _extremum } = this;
|
|
93
|
+
chunk = this._chunk = Buffer.concat([this._chunk, chunk]);
|
|
94
|
+
if (chunk.length < _bytes)
|
|
95
|
+
return done();
|
|
96
|
+
const complete = Math.floor(chunk.length / _bytes) * _bytes;
|
|
97
|
+
for (let i = 0; i < complete; i += _bytes) {
|
|
98
|
+
const int = Math.min(_extremum - 1, Math.max(-_extremum, Math.floor(this.volume * this._readInt(chunk, i))));
|
|
99
|
+
this._writeInt(chunk, int, i);
|
|
100
|
+
}
|
|
101
|
+
this._chunk = chunk.slice(complete);
|
|
102
|
+
this.push(chunk.slice(0, complete));
|
|
103
|
+
return done();
|
|
104
|
+
}
|
|
105
|
+
_destroy(err, cb) {
|
|
106
|
+
super._destroy(err, cb);
|
|
107
|
+
this._chunk = null;
|
|
108
|
+
}
|
|
109
|
+
setVolume(volume) {
|
|
110
|
+
if (Number.isNaN(volume))
|
|
111
|
+
volume = 1;
|
|
112
|
+
if (typeof volume !== "number")
|
|
113
|
+
volume = Number(volume);
|
|
114
|
+
if (!Number.isFinite(volume))
|
|
115
|
+
volume = volume < 0 ? 0 : 1;
|
|
116
|
+
this._targetVolume = volume;
|
|
117
|
+
if (this._smoothing <= 0)
|
|
118
|
+
this.volume = volume;
|
|
119
|
+
}
|
|
120
|
+
setVolumeDecibels(db) {
|
|
121
|
+
this.setVolume(Math.pow(10, db / 20));
|
|
122
|
+
}
|
|
123
|
+
setVolumeLogarithmic(value) {
|
|
124
|
+
this.setVolume(Math.pow(value, 1.660964));
|
|
125
|
+
}
|
|
126
|
+
get volumeDecibels() {
|
|
127
|
+
return Math.log10(this.volume) * 20;
|
|
128
|
+
}
|
|
129
|
+
get volumeLogarithmic() {
|
|
130
|
+
return Math.pow(this.volume, 1 / 1.660964);
|
|
131
|
+
}
|
|
132
|
+
get smoothness() {
|
|
133
|
+
return this._smoothing;
|
|
134
|
+
}
|
|
135
|
+
setSmoothness(smoothness) {
|
|
136
|
+
this._smoothing = smoothness;
|
|
137
|
+
}
|
|
138
|
+
smoothingEnabled() {
|
|
139
|
+
return typeof this._smoothing === "number" && !Number.isNaN(this._smoothing) && Number.isFinite(this._smoothing) && this._smoothing > 0;
|
|
140
|
+
}
|
|
141
|
+
get hasSmoothness() {
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
static get hasSmoothing() {
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
__name(VolumeTransformer, "VolumeTransformer");
|
|
149
|
+
|
|
150
|
+
// src/smoothVolume.ts
|
|
151
|
+
if (!("DISABLE_DISCORD_PLAYER_SMOOTH_VOLUME" in process.env)) {
|
|
152
|
+
try {
|
|
153
|
+
const mod = __require("prism-media");
|
|
154
|
+
if (typeof mod.VolumeTransformer.hasSmoothing !== "boolean") {
|
|
155
|
+
Reflect.set(mod, "VolumeTransformer", VolumeTransformer);
|
|
156
|
+
}
|
|
157
|
+
} catch {
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// src/index.ts
|
|
162
|
+
import { version as djsVersion } from "discord.js";
|
|
163
|
+
|
|
164
|
+
// src/utils/AudioFilters.ts
|
|
165
|
+
var bass = /* @__PURE__ */ __name((g) => `bass=g=${g}:f=110:w=0.3`, "bass");
|
|
166
|
+
var _AudioFilters = class {
|
|
167
|
+
constructor() {
|
|
168
|
+
return _AudioFilters;
|
|
169
|
+
}
|
|
170
|
+
static get(name) {
|
|
171
|
+
return this.filters[name];
|
|
172
|
+
}
|
|
173
|
+
static has(name) {
|
|
174
|
+
return name in this.filters;
|
|
175
|
+
}
|
|
176
|
+
static *[Symbol.iterator]() {
|
|
177
|
+
for (const [k, v] of Object.entries(this.filters)) {
|
|
178
|
+
yield { name: k, value: v };
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
static get names() {
|
|
182
|
+
return Object.keys(this.filters);
|
|
183
|
+
}
|
|
184
|
+
static get length() {
|
|
185
|
+
return this.names.length;
|
|
186
|
+
}
|
|
187
|
+
static toString() {
|
|
188
|
+
return this.names.map((m) => this[m]).join(",");
|
|
189
|
+
}
|
|
190
|
+
static create(filters) {
|
|
191
|
+
if (!filters || !Array.isArray(filters))
|
|
192
|
+
return this.toString();
|
|
193
|
+
return filters.filter((predicate) => typeof predicate === "string").map((m) => this.get(m)).join(",");
|
|
194
|
+
}
|
|
195
|
+
static define(filterName, value) {
|
|
196
|
+
this.filters[filterName] = value;
|
|
197
|
+
}
|
|
198
|
+
static defineBulk(filtersArray) {
|
|
199
|
+
filtersArray.forEach((arr) => this.define(arr.name, arr.value));
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
var AudioFilters = _AudioFilters;
|
|
203
|
+
__name(AudioFilters, "AudioFilters");
|
|
204
|
+
AudioFilters.filters = {
|
|
205
|
+
bassboost_low: bass(15),
|
|
206
|
+
bassboost: bass(20),
|
|
207
|
+
bassboost_high: bass(30),
|
|
208
|
+
"8D": "apulsator=hz=0.09",
|
|
209
|
+
vaporwave: "aresample=48000,asetrate=48000*0.8",
|
|
210
|
+
nightcore: "aresample=48000,asetrate=48000*1.25",
|
|
211
|
+
phaser: "aphaser=in_gain=0.4",
|
|
212
|
+
tremolo: "tremolo",
|
|
213
|
+
vibrato: "vibrato=f=6.5",
|
|
214
|
+
reverse: "areverse",
|
|
215
|
+
treble: "treble=g=5",
|
|
216
|
+
normalizer2: "dynaudnorm=g=101",
|
|
217
|
+
normalizer: "acompressor",
|
|
218
|
+
surrounding: "surround",
|
|
219
|
+
pulsator: "apulsator=hz=1",
|
|
220
|
+
subboost: "asubboost",
|
|
221
|
+
karaoke: "stereotools=mlev=0.03",
|
|
222
|
+
flanger: "flanger",
|
|
223
|
+
gate: "agate",
|
|
224
|
+
haas: "haas",
|
|
225
|
+
mcompand: "mcompand",
|
|
226
|
+
mono: "pan=mono|c0=.5*c0+.5*c1",
|
|
227
|
+
mstlr: "stereotools=mode=ms>lr",
|
|
228
|
+
mstrr: "stereotools=mode=ms>rr",
|
|
229
|
+
compressor: "compand=points=-80/-105|-62/-80|-15.4/-15.4|0/-12|20/-7.6",
|
|
230
|
+
expander: "compand=attacks=0:points=-80/-169|-54/-80|-49.5/-64.6|-41.1/-41.1|-25.8/-15|-10.8/-4.5|0/0|20/8.3",
|
|
231
|
+
softlimiter: "compand=attacks=0:points=-80/-80|-12.4/-12.4|-6/-8|0/-6.8|20/-2.8",
|
|
232
|
+
chorus: "chorus=0.7:0.9:55:0.4:0.25:2",
|
|
233
|
+
chorus2d: "chorus=0.6:0.9:50|60:0.4|0.32:0.25|0.4:2|1.3",
|
|
234
|
+
chorus3d: "chorus=0.5:0.9:50|60|40:0.4|0.32|0.3:0.25|0.4|0.3:2|2.3|1.3",
|
|
235
|
+
fadein: "afade=t=in:ss=0:d=10",
|
|
236
|
+
dim: `afftfilt="'real=re * (1-clip((b/nb)*b,0,1))':imag='im * (1-clip((b/nb)*b,0,1))'"`,
|
|
237
|
+
earrape: "channelsplit,sidechaingate=level_in=64"
|
|
238
|
+
};
|
|
239
|
+
var AudioFilters_default = AudioFilters;
|
|
240
|
+
|
|
241
|
+
// src/extractors/BaseExtractor.ts
|
|
242
|
+
var BaseExtractor = class {
|
|
243
|
+
constructor(context) {
|
|
244
|
+
this.context = context;
|
|
245
|
+
}
|
|
246
|
+
get identifier() {
|
|
247
|
+
return this.constructor.identifier;
|
|
248
|
+
}
|
|
249
|
+
async activate() {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
async deactivate() {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
async validate(query, type) {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
async stream(info) {
|
|
259
|
+
throw new Error("Not Implemented");
|
|
260
|
+
}
|
|
261
|
+
async handle(query, context) {
|
|
262
|
+
throw new Error("Not Implemented");
|
|
263
|
+
}
|
|
264
|
+
handlePostStream(stream, next) {
|
|
265
|
+
return next(null, stream);
|
|
266
|
+
}
|
|
267
|
+
emit(event, ...args) {
|
|
268
|
+
return this.context.player.emit(event, ...args);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
__name(BaseExtractor, "BaseExtractor");
|
|
272
|
+
BaseExtractor.identifier = "com.discord-player.extractor";
|
|
273
|
+
|
|
274
|
+
// src/extractors/ExtractorExecutionContext.ts
|
|
275
|
+
import { Collection } from "@discord-player/utils";
|
|
276
|
+
var ExtractorExecutionContext = class {
|
|
277
|
+
constructor(player) {
|
|
278
|
+
this.player = player;
|
|
279
|
+
this.store = new Collection();
|
|
280
|
+
}
|
|
281
|
+
isRegistered(identifier) {
|
|
282
|
+
return this.store.has(identifier);
|
|
283
|
+
}
|
|
284
|
+
get size() {
|
|
285
|
+
return this.store.size;
|
|
286
|
+
}
|
|
287
|
+
get(identifier) {
|
|
288
|
+
return this.store.get(identifier);
|
|
289
|
+
}
|
|
290
|
+
async register(_extractor) {
|
|
291
|
+
if (typeof _extractor.identifier !== "string" || this.store.has(_extractor.identifier))
|
|
292
|
+
return;
|
|
293
|
+
const extractor = new _extractor(this);
|
|
294
|
+
try {
|
|
295
|
+
this.store.set(_extractor.identifier, extractor);
|
|
296
|
+
await extractor.activate();
|
|
297
|
+
} catch {
|
|
298
|
+
this.store.delete(_extractor.identifier);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
async unregister(_extractor) {
|
|
302
|
+
const extractor = typeof _extractor === "string" ? this.store.get(_extractor) : this.store.find((r) => r === _extractor);
|
|
303
|
+
if (!extractor)
|
|
304
|
+
return;
|
|
305
|
+
try {
|
|
306
|
+
const key = extractor.identifier || this.store.findKey((e) => e === extractor);
|
|
307
|
+
this.store.delete(key);
|
|
308
|
+
await extractor.deactivate();
|
|
309
|
+
} catch {
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
async unregisterAll() {
|
|
313
|
+
try {
|
|
314
|
+
await Promise.all(
|
|
315
|
+
this.store.map((e, k) => {
|
|
316
|
+
this.store.delete(k);
|
|
317
|
+
return e.deactivate();
|
|
318
|
+
})
|
|
319
|
+
);
|
|
320
|
+
} catch {
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
async run(fn) {
|
|
324
|
+
for (const ext of this.store.values()) {
|
|
325
|
+
const result = await fn(ext).catch(() => {
|
|
326
|
+
return false;
|
|
327
|
+
});
|
|
328
|
+
if (result)
|
|
329
|
+
return {
|
|
330
|
+
extractor: ext,
|
|
331
|
+
result
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
__name(ExtractorExecutionContext, "ExtractorExecutionContext");
|
|
338
|
+
|
|
339
|
+
// src/Structures/Playlist.ts
|
|
340
|
+
var Playlist = class {
|
|
341
|
+
constructor(player, data) {
|
|
342
|
+
this.player = player;
|
|
343
|
+
this.tracks = data.tracks ?? [];
|
|
344
|
+
this.author = data.author;
|
|
345
|
+
this.description = data.description;
|
|
346
|
+
this.thumbnail = data.thumbnail;
|
|
347
|
+
this.type = data.type;
|
|
348
|
+
this.source = data.source;
|
|
349
|
+
this.id = data.id;
|
|
350
|
+
this.url = data.url;
|
|
351
|
+
this.title = data.title;
|
|
352
|
+
}
|
|
353
|
+
*[Symbol.iterator]() {
|
|
354
|
+
yield* this.tracks;
|
|
355
|
+
}
|
|
356
|
+
toJSON(withTracks = true) {
|
|
357
|
+
const payload = {
|
|
358
|
+
id: this.id,
|
|
359
|
+
url: this.url,
|
|
360
|
+
title: this.title,
|
|
361
|
+
description: this.description,
|
|
362
|
+
thumbnail: this.thumbnail,
|
|
363
|
+
type: this.type,
|
|
364
|
+
source: this.source,
|
|
365
|
+
author: this.author,
|
|
366
|
+
tracks: []
|
|
367
|
+
};
|
|
368
|
+
if (withTracks)
|
|
369
|
+
payload.tracks = this.tracks.map((m) => m.toJSON(true));
|
|
370
|
+
return payload;
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
__name(Playlist, "Playlist");
|
|
374
|
+
|
|
375
|
+
// src/Player.ts
|
|
376
|
+
import { IntentsBitField, ChannelType as ChannelType2 } from "discord.js";
|
|
377
|
+
import { TypedEmitter as EventEmitter2 } from "tiny-typed-emitter";
|
|
378
|
+
|
|
379
|
+
// src/Structures/Queue.ts
|
|
380
|
+
import { SnowflakeUtil as SnowflakeUtil2, ChannelType } from "discord.js";
|
|
381
|
+
|
|
382
|
+
// src/Structures/Track.ts
|
|
383
|
+
import { escapeMarkdown, SnowflakeUtil } from "discord.js";
|
|
384
|
+
var Track = class {
|
|
385
|
+
constructor(player, data) {
|
|
386
|
+
this.requestedBy = null;
|
|
387
|
+
this.queryType = null;
|
|
388
|
+
this.raw = {};
|
|
389
|
+
this.id = SnowflakeUtil.generate().toString();
|
|
390
|
+
Object.defineProperty(this, "player", { value: player, enumerable: false });
|
|
391
|
+
void this._patch(data);
|
|
392
|
+
}
|
|
393
|
+
_patch(data) {
|
|
394
|
+
this.title = escapeMarkdown(data.title ?? "");
|
|
395
|
+
this.author = data.author ?? "";
|
|
396
|
+
this.url = data.url ?? "";
|
|
397
|
+
this.thumbnail = data.thumbnail ?? "";
|
|
398
|
+
this.duration = data.duration ?? "";
|
|
399
|
+
this.views = data.views ?? 0;
|
|
400
|
+
this.queryType = data.queryType;
|
|
401
|
+
this.requestedBy = data.requestedBy || null;
|
|
402
|
+
this.playlist = data.playlist;
|
|
403
|
+
Object.defineProperty(this, "raw", { value: Object.assign({}, { source: data.raw?.source ?? data.source }, data.raw ?? data), enumerable: false });
|
|
404
|
+
}
|
|
405
|
+
get queue() {
|
|
406
|
+
return this.player.queues.find((q) => q.tracks.some((ab) => ab.id === this.id));
|
|
407
|
+
}
|
|
408
|
+
get durationMS() {
|
|
409
|
+
const times = /* @__PURE__ */ __name((n, t) => {
|
|
410
|
+
let tn = 1;
|
|
411
|
+
for (let i = 0; i < t; i++)
|
|
412
|
+
tn *= n;
|
|
413
|
+
return t <= 0 ? 1e3 : tn * 1e3;
|
|
414
|
+
}, "times");
|
|
415
|
+
return this.duration.split(":").reverse().map((m, i) => parseInt(m) * times(60, i)).reduce((a, c) => a + c, 0);
|
|
416
|
+
}
|
|
417
|
+
get source() {
|
|
418
|
+
return this.raw.source ?? "arbitrary";
|
|
419
|
+
}
|
|
420
|
+
toString() {
|
|
421
|
+
return `${this.title} by ${this.author}`;
|
|
422
|
+
}
|
|
423
|
+
toJSON(hidePlaylist) {
|
|
424
|
+
return {
|
|
425
|
+
id: this.id,
|
|
426
|
+
title: this.title,
|
|
427
|
+
description: this.description,
|
|
428
|
+
author: this.author,
|
|
429
|
+
url: this.url,
|
|
430
|
+
thumbnail: this.thumbnail,
|
|
431
|
+
duration: this.duration,
|
|
432
|
+
durationMS: this.durationMS,
|
|
433
|
+
views: this.views,
|
|
434
|
+
requestedBy: this.requestedBy?.id || null,
|
|
435
|
+
playlist: hidePlaylist ? null : this.playlist?.toJSON() ?? null
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
__name(Track, "Track");
|
|
440
|
+
var Track_default = Track;
|
|
441
|
+
|
|
442
|
+
// src/types/types.ts
|
|
443
|
+
var QueryType = {
|
|
444
|
+
AUTO: "auto",
|
|
445
|
+
YOUTUBE: "youtube",
|
|
446
|
+
YOUTUBE_PLAYLIST: "youtubePlaylist",
|
|
447
|
+
SOUNDCLOUD_TRACK: "soundcloudTrack",
|
|
448
|
+
SOUNDCLOUD_PLAYLIST: "soundcloudPlaylist",
|
|
449
|
+
SOUNDCLOUD: "soundcloud",
|
|
450
|
+
SPOTIFY_SONG: "spotifySong",
|
|
451
|
+
SPOTIFY_ALBUM: "spotifyAlbum",
|
|
452
|
+
SPOTIFY_PLAYLIST: "spotifyPlaylist",
|
|
453
|
+
FACEBOOK: "facebook",
|
|
454
|
+
VIMEO: "vimeo",
|
|
455
|
+
ARBITRARY: "arbitrary",
|
|
456
|
+
REVERBNATION: "reverbnation",
|
|
457
|
+
YOUTUBE_SEARCH: "youtubeSearch",
|
|
458
|
+
YOUTUBE_VIDEO: "youtubeVideo",
|
|
459
|
+
SOUNDCLOUD_SEARCH: "soundcloudSearch",
|
|
460
|
+
APPLE_MUSIC_SONG: "appleMusicSong",
|
|
461
|
+
APPLE_MUSIC_ALBUM: "appleMusicAlbum",
|
|
462
|
+
APPLE_MUSIC_PLAYLIST: "appleMusicPlaylist",
|
|
463
|
+
FILE: "file"
|
|
464
|
+
};
|
|
465
|
+
var QueueRepeatMode = /* @__PURE__ */ ((QueueRepeatMode2) => {
|
|
466
|
+
QueueRepeatMode2[QueueRepeatMode2["OFF"] = 0] = "OFF";
|
|
467
|
+
QueueRepeatMode2[QueueRepeatMode2["TRACK"] = 1] = "TRACK";
|
|
468
|
+
QueueRepeatMode2[QueueRepeatMode2["QUEUE"] = 2] = "QUEUE";
|
|
469
|
+
QueueRepeatMode2[QueueRepeatMode2["AUTOPLAY"] = 3] = "AUTOPLAY";
|
|
470
|
+
return QueueRepeatMode2;
|
|
471
|
+
})(QueueRepeatMode || {});
|
|
472
|
+
|
|
473
|
+
// src/Structures/Queue.ts
|
|
474
|
+
import { StreamType } from "@discordjs/voice";
|
|
475
|
+
|
|
476
|
+
// src/utils/Util.ts
|
|
477
|
+
import { setTimeout as setTimeout2 } from "timers/promises";
|
|
478
|
+
var Util = class {
|
|
479
|
+
constructor() {
|
|
480
|
+
}
|
|
481
|
+
static durationString(durObj) {
|
|
482
|
+
return Object.values(durObj).map((m) => isNaN(m) ? 0 : m).join(":");
|
|
483
|
+
}
|
|
484
|
+
static parseMS(milliseconds) {
|
|
485
|
+
if (isNaN(milliseconds))
|
|
486
|
+
milliseconds = 0;
|
|
487
|
+
const round = milliseconds > 0 ? Math.floor : Math.ceil;
|
|
488
|
+
return {
|
|
489
|
+
days: round(milliseconds / 864e5),
|
|
490
|
+
hours: round(milliseconds / 36e5) % 24,
|
|
491
|
+
minutes: round(milliseconds / 6e4) % 60,
|
|
492
|
+
seconds: round(milliseconds / 1e3) % 60
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
static buildTimeCode(duration) {
|
|
496
|
+
const items = Object.keys(duration);
|
|
497
|
+
const required = ["days", "hours", "minutes", "seconds"];
|
|
498
|
+
const parsed = items.filter((x) => required.includes(x)).map((m) => duration[m]);
|
|
499
|
+
const final = parsed.slice(parsed.findIndex((x) => x !== 0)).map((x) => x.toString().padStart(2, "0")).join(":");
|
|
500
|
+
return final.length <= 3 ? `0:${final.padStart(2, "0") || 0}` : final;
|
|
501
|
+
}
|
|
502
|
+
static last(arr) {
|
|
503
|
+
if (!Array.isArray(arr))
|
|
504
|
+
return arr;
|
|
505
|
+
return arr[arr.length - 1];
|
|
506
|
+
}
|
|
507
|
+
static isVoiceEmpty(channel) {
|
|
508
|
+
return channel.members.filter((member) => !member.user.bot).size === 0;
|
|
509
|
+
}
|
|
510
|
+
static require(id) {
|
|
511
|
+
try {
|
|
512
|
+
return __require(id);
|
|
513
|
+
} catch {
|
|
514
|
+
return null;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
static wait(time) {
|
|
518
|
+
return setTimeout2(time, void 0, { ref: false });
|
|
519
|
+
}
|
|
520
|
+
static noop() {
|
|
521
|
+
}
|
|
522
|
+
static async getFetch() {
|
|
523
|
+
if ("fetch" in globalThis)
|
|
524
|
+
return globalThis.fetch;
|
|
525
|
+
for (const lib of ["node-fetch", "undici"]) {
|
|
526
|
+
try {
|
|
527
|
+
return await import(lib).then((res) => res.fetch || res.default?.fetch || res.default);
|
|
528
|
+
} catch {
|
|
529
|
+
try {
|
|
530
|
+
const res = __require(lib);
|
|
531
|
+
if (res)
|
|
532
|
+
return res.fetch || res.default?.fetch || res.default;
|
|
533
|
+
} catch {
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
__name(Util, "Util");
|
|
540
|
+
|
|
541
|
+
// src/Structures/PlayerError.ts
|
|
542
|
+
var ErrorStatusCode = /* @__PURE__ */ ((ErrorStatusCode2) => {
|
|
543
|
+
ErrorStatusCode2["STREAM_ERROR"] = "StreamError";
|
|
544
|
+
ErrorStatusCode2["AUDIO_PLAYER_ERROR"] = "AudioPlayerError";
|
|
545
|
+
ErrorStatusCode2["PLAYER_ERROR"] = "PlayerError";
|
|
546
|
+
ErrorStatusCode2["NO_AUDIO_RESOURCE"] = "NoAudioResource";
|
|
547
|
+
ErrorStatusCode2["UNKNOWN_GUILD"] = "UnknownGuild";
|
|
548
|
+
ErrorStatusCode2["INVALID_ARG_TYPE"] = "InvalidArgType";
|
|
549
|
+
ErrorStatusCode2["UNKNOWN_EXTRACTOR"] = "UnknownExtractor";
|
|
550
|
+
ErrorStatusCode2["INVALID_EXTRACTOR"] = "InvalidExtractor";
|
|
551
|
+
ErrorStatusCode2["INVALID_CHANNEL_TYPE"] = "InvalidChannelType";
|
|
552
|
+
ErrorStatusCode2["INVALID_TRACK"] = "InvalidTrack";
|
|
553
|
+
ErrorStatusCode2["UNKNOWN_REPEAT_MODE"] = "UnknownRepeatMode";
|
|
554
|
+
ErrorStatusCode2["TRACK_NOT_FOUND"] = "TrackNotFound";
|
|
555
|
+
ErrorStatusCode2["NO_CONNECTION"] = "NoConnection";
|
|
556
|
+
ErrorStatusCode2["DESTROYED_QUEUE"] = "DestroyedQueue";
|
|
557
|
+
return ErrorStatusCode2;
|
|
558
|
+
})(ErrorStatusCode || {});
|
|
559
|
+
var PlayerError = class extends Error {
|
|
560
|
+
constructor(message, code = "PlayerError" /* PLAYER_ERROR */) {
|
|
561
|
+
super();
|
|
562
|
+
this.createdAt = new Date();
|
|
563
|
+
this.message = `[${code}] ${message}`;
|
|
564
|
+
this.statusCode = code;
|
|
565
|
+
this.name = code;
|
|
566
|
+
Error.captureStackTrace(this);
|
|
567
|
+
}
|
|
568
|
+
get createdTimestamp() {
|
|
569
|
+
return this.createdAt.getTime();
|
|
570
|
+
}
|
|
571
|
+
valueOf() {
|
|
572
|
+
return this.statusCode;
|
|
573
|
+
}
|
|
574
|
+
toJSON() {
|
|
575
|
+
return {
|
|
576
|
+
stack: this.stack,
|
|
577
|
+
code: this.statusCode,
|
|
578
|
+
message: this.message,
|
|
579
|
+
created: this.createdTimestamp
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
toString() {
|
|
583
|
+
return this.stack;
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
__name(PlayerError, "PlayerError");
|
|
587
|
+
|
|
588
|
+
// src/utils/FFmpegStream.ts
|
|
589
|
+
import { FFmpeg } from "prism-media";
|
|
590
|
+
function FFMPEG_ARGS_STRING(stream, fmt) {
|
|
591
|
+
return [
|
|
592
|
+
"-reconnect",
|
|
593
|
+
"1",
|
|
594
|
+
"-reconnect_streamed",
|
|
595
|
+
"1",
|
|
596
|
+
"-reconnect_delay_max",
|
|
597
|
+
"5",
|
|
598
|
+
"-i",
|
|
599
|
+
stream,
|
|
600
|
+
"-analyzeduration",
|
|
601
|
+
"0",
|
|
602
|
+
"-loglevel",
|
|
603
|
+
"0",
|
|
604
|
+
"-f",
|
|
605
|
+
`${typeof fmt === "string" ? fmt : "s16le"}`,
|
|
606
|
+
"-ar",
|
|
607
|
+
"48000",
|
|
608
|
+
"-ac",
|
|
609
|
+
"2"
|
|
610
|
+
];
|
|
611
|
+
}
|
|
612
|
+
__name(FFMPEG_ARGS_STRING, "FFMPEG_ARGS_STRING");
|
|
613
|
+
function FFMPEG_ARGS_PIPED(fmt) {
|
|
614
|
+
return [
|
|
615
|
+
"-analyzeduration",
|
|
616
|
+
"0",
|
|
617
|
+
"-loglevel",
|
|
618
|
+
"0",
|
|
619
|
+
"-f",
|
|
620
|
+
`${typeof fmt === "string" ? fmt : "s16le"}`,
|
|
621
|
+
"-ar",
|
|
622
|
+
"48000",
|
|
623
|
+
"-ac",
|
|
624
|
+
"2"
|
|
625
|
+
];
|
|
626
|
+
}
|
|
627
|
+
__name(FFMPEG_ARGS_PIPED, "FFMPEG_ARGS_PIPED");
|
|
628
|
+
function createFFmpegStream(stream, options) {
|
|
629
|
+
if (options?.skip && typeof stream !== "string")
|
|
630
|
+
return stream;
|
|
631
|
+
options ?? (options = {});
|
|
632
|
+
const args = typeof stream === "string" ? FFMPEG_ARGS_STRING(stream, options.fmt) : FFMPEG_ARGS_PIPED(options.fmt);
|
|
633
|
+
if (!Number.isNaN(options.seek))
|
|
634
|
+
args.unshift("-ss", String(options.seek));
|
|
635
|
+
if (Array.isArray(options.encoderArgs))
|
|
636
|
+
args.push(...options.encoderArgs);
|
|
637
|
+
const transcoder = new FFmpeg({ shell: false, args });
|
|
638
|
+
transcoder.on("close", () => transcoder.destroy());
|
|
639
|
+
if (typeof stream !== "string") {
|
|
640
|
+
stream.on("error", () => transcoder.destroy());
|
|
641
|
+
stream.pipe(transcoder);
|
|
642
|
+
}
|
|
643
|
+
return transcoder;
|
|
644
|
+
}
|
|
645
|
+
__name(createFFmpegStream, "createFFmpegStream");
|
|
646
|
+
|
|
647
|
+
// src/Structures/Queue.ts
|
|
648
|
+
import os from "os";
|
|
649
|
+
import { parentPort } from "worker_threads";
|
|
650
|
+
import { Collection as Collection2 } from "@discord-player/utils";
|
|
651
|
+
|
|
652
|
+
// src/utils/QueryResolver.ts
|
|
653
|
+
import { YouTube } from "youtube-sr";
|
|
654
|
+
import { validateURL as SoundcloudValidateURL } from "soundcloud-scraper";
|
|
655
|
+
var spotifySongRegex = /^https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:track\/|\?uri=spotify:track:)((\w|-){22})(\?si=.+)?$/;
|
|
656
|
+
var spotifyPlaylistRegex = /^https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:playlist\/|\?uri=spotify:playlist:)((\w|-){22})(\?si=.+)?$/;
|
|
657
|
+
var spotifyAlbumRegex = /^https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:album\/|\?uri=spotify:album:)((\w|-){22})(\?si=.+)?$/;
|
|
658
|
+
var vimeoRegex = /^(http|https)?:\/\/(www\.|player\.)?vimeo\.com\/(?:channels\/(?:\w+\/)?|groups\/([^/]*)\/videos\/|video\/|)(\d+)(?:|\/\?)$/;
|
|
659
|
+
var reverbnationRegex = /^https:\/\/(www.)?reverbnation.com\/(.+)\/song\/(.+)$/;
|
|
660
|
+
var attachmentRegex = /^https?:\/\/.+$/;
|
|
661
|
+
var appleMusicSongRegex = /^https?:\/\/music\.apple\.com\/.+?\/(song|album)\/.+?(\/.+?\?i=|\/)([0-9]+)$/;
|
|
662
|
+
var appleMusicPlaylistRegex = /^https?:\/\/music\.apple\.com\/.+?\/playlist\/.+\/pl\.[a-f0-9]+$/;
|
|
663
|
+
var appleMusicAlbumRegex = /^https?:\/\/music\.apple\.com\/.+?\/album\/.+\/([0-9]+)$/;
|
|
664
|
+
var QueryResolver = class {
|
|
665
|
+
constructor() {
|
|
666
|
+
}
|
|
667
|
+
static get regex() {
|
|
668
|
+
return {
|
|
669
|
+
spotifyAlbumRegex,
|
|
670
|
+
spotifyPlaylistRegex,
|
|
671
|
+
spotifySongRegex,
|
|
672
|
+
vimeoRegex,
|
|
673
|
+
reverbnationRegex,
|
|
674
|
+
attachmentRegex,
|
|
675
|
+
appleMusicAlbumRegex,
|
|
676
|
+
appleMusicPlaylistRegex,
|
|
677
|
+
appleMusicSongRegex
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
static resolve(query) {
|
|
681
|
+
query = query.trim();
|
|
682
|
+
if (SoundcloudValidateURL(query, "track"))
|
|
683
|
+
return QueryType.SOUNDCLOUD_TRACK;
|
|
684
|
+
if (SoundcloudValidateURL(query, "playlist") || query.includes("/sets/"))
|
|
685
|
+
return QueryType.SOUNDCLOUD_PLAYLIST;
|
|
686
|
+
if (YouTube.isPlaylist(query))
|
|
687
|
+
return QueryType.YOUTUBE_PLAYLIST;
|
|
688
|
+
if (QueryResolver.validateId(query) || QueryResolver.validateURL(query))
|
|
689
|
+
return QueryType.YOUTUBE_VIDEO;
|
|
690
|
+
if (spotifySongRegex.test(query))
|
|
691
|
+
return QueryType.SPOTIFY_SONG;
|
|
692
|
+
if (spotifyPlaylistRegex.test(query))
|
|
693
|
+
return QueryType.SPOTIFY_PLAYLIST;
|
|
694
|
+
if (spotifyAlbumRegex.test(query))
|
|
695
|
+
return QueryType.SPOTIFY_ALBUM;
|
|
696
|
+
if (vimeoRegex.test(query))
|
|
697
|
+
return QueryType.VIMEO;
|
|
698
|
+
if (reverbnationRegex.test(query))
|
|
699
|
+
return QueryType.REVERBNATION;
|
|
700
|
+
if (appleMusicAlbumRegex.test(query))
|
|
701
|
+
return QueryType.APPLE_MUSIC_ALBUM;
|
|
702
|
+
if (appleMusicPlaylistRegex.test(query))
|
|
703
|
+
return QueryType.APPLE_MUSIC_PLAYLIST;
|
|
704
|
+
if (appleMusicSongRegex.test(query))
|
|
705
|
+
return QueryType.APPLE_MUSIC_SONG;
|
|
706
|
+
if (attachmentRegex.test(query))
|
|
707
|
+
return QueryType.ARBITRARY;
|
|
708
|
+
return QueryType.YOUTUBE_SEARCH;
|
|
709
|
+
}
|
|
710
|
+
static getVimeoID(query) {
|
|
711
|
+
return QueryResolver.resolve(query) === QueryType.VIMEO ? query.split("/").filter((x) => !!x).pop() : null;
|
|
712
|
+
}
|
|
713
|
+
static validateId(q) {
|
|
714
|
+
return YouTube.Regex.VIDEO_ID.test(q);
|
|
715
|
+
}
|
|
716
|
+
static validateURL(q) {
|
|
717
|
+
return YouTube.Regex.VIDEO_URL.test(q);
|
|
718
|
+
}
|
|
719
|
+
};
|
|
720
|
+
__name(QueryResolver, "QueryResolver");
|
|
721
|
+
|
|
722
|
+
// src/Structures/Queue.ts
|
|
723
|
+
import { YouTube as YouTube2 } from "youtube-sr";
|
|
724
|
+
var OBCS_DEFAULT = /* @__PURE__ */ __name(async () => {
|
|
725
|
+
return void 0;
|
|
726
|
+
}, "OBCS_DEFAULT");
|
|
727
|
+
var _destroyed, _watchDestroyed, watchDestroyed_fn, _getBufferingTimeout, getBufferingTimeout_fn;
|
|
728
|
+
var Queue = class {
|
|
729
|
+
constructor(player, guild, options = {}) {
|
|
730
|
+
__privateAdd(this, _watchDestroyed);
|
|
731
|
+
__privateAdd(this, _getBufferingTimeout);
|
|
732
|
+
this.tracks = [];
|
|
733
|
+
this.previousTracks = [];
|
|
734
|
+
this.playing = false;
|
|
735
|
+
this.metadata = null;
|
|
736
|
+
this.repeatMode = 0;
|
|
737
|
+
this.id = SnowflakeUtil2.generate().toString();
|
|
738
|
+
this._streamTime = 0;
|
|
739
|
+
this._cooldownsTimeout = new Collection2();
|
|
740
|
+
this._activeFilters = [];
|
|
741
|
+
this._filtersUpdate = false;
|
|
742
|
+
this._lastEQBands = [];
|
|
743
|
+
this._lastAudioFilters = [];
|
|
744
|
+
__privateAdd(this, _destroyed, false);
|
|
745
|
+
this.onBeforeCreateStream = OBCS_DEFAULT;
|
|
746
|
+
this.player = player;
|
|
747
|
+
this.guild = guild;
|
|
748
|
+
this.options = {};
|
|
749
|
+
Object.assign(
|
|
750
|
+
this.options,
|
|
751
|
+
{
|
|
752
|
+
leaveOnEnd: true,
|
|
753
|
+
leaveOnStop: true,
|
|
754
|
+
leaveOnEmpty: true,
|
|
755
|
+
leaveOnEndCooldown: 1e3,
|
|
756
|
+
leaveOnEmptyCooldown: 1e3,
|
|
757
|
+
autoSelfDeaf: true,
|
|
758
|
+
ytdlOptions: {
|
|
759
|
+
highWaterMark: 1 << 25
|
|
760
|
+
},
|
|
761
|
+
initialVolume: 100,
|
|
762
|
+
bufferingTimeout: 3e3,
|
|
763
|
+
spotifyBridge: true,
|
|
764
|
+
disableVolume: false,
|
|
765
|
+
disableEqualizer: false,
|
|
766
|
+
equalizerBands: [],
|
|
767
|
+
disableBiquad: false,
|
|
768
|
+
disableFilters: false,
|
|
769
|
+
defaultFilters: []
|
|
770
|
+
},
|
|
771
|
+
options
|
|
772
|
+
);
|
|
773
|
+
if (Array.isArray(options.equalizerBands))
|
|
774
|
+
this._lastEQBands = options.equalizerBands;
|
|
775
|
+
if (Array.isArray(options.defaultFilters))
|
|
776
|
+
this._lastAudioFilters = options.defaultFilters;
|
|
777
|
+
if (options.biquadFilter != null)
|
|
778
|
+
this._lastBiquadFilter = options.biquadFilter;
|
|
779
|
+
if ("onBeforeCreateStream" in this.options)
|
|
780
|
+
this.onBeforeCreateStream = this.options.onBeforeCreateStream;
|
|
781
|
+
this.player.emit("debug", this, `Queue initialized:
|
|
782
|
+
|
|
783
|
+
${this.player.scanDeps()}`);
|
|
784
|
+
}
|
|
785
|
+
isFiltersAvailable() {
|
|
786
|
+
return this.connection.audioFilters != null;
|
|
787
|
+
}
|
|
788
|
+
get filters() {
|
|
789
|
+
return this.connection.audioFilters;
|
|
790
|
+
}
|
|
791
|
+
isBiquadEnabled() {
|
|
792
|
+
return this.connection.biquad != null;
|
|
793
|
+
}
|
|
794
|
+
isBiquadOff() {
|
|
795
|
+
return this.isBiquadEnabled() && !this.connection.biquad.disabled;
|
|
796
|
+
}
|
|
797
|
+
toggleBiquad() {
|
|
798
|
+
const eq = this.connection.biquad;
|
|
799
|
+
if (!eq)
|
|
800
|
+
return false;
|
|
801
|
+
eq.toggle();
|
|
802
|
+
return !eq.disabled;
|
|
803
|
+
}
|
|
804
|
+
enableBiquad() {
|
|
805
|
+
const eq = this.connection.biquad;
|
|
806
|
+
if (!eq)
|
|
807
|
+
return false;
|
|
808
|
+
eq.enable();
|
|
809
|
+
return !eq.disabled;
|
|
810
|
+
}
|
|
811
|
+
disableBiquad() {
|
|
812
|
+
const eq = this.connection.biquad;
|
|
813
|
+
if (!eq)
|
|
814
|
+
return false;
|
|
815
|
+
eq.disable();
|
|
816
|
+
return eq.disabled;
|
|
817
|
+
}
|
|
818
|
+
setBiquadFilter(filter) {
|
|
819
|
+
if (!this.isBiquadEnabled())
|
|
820
|
+
return;
|
|
821
|
+
this.connection.biquad.setFilter(filter);
|
|
822
|
+
this._lastBiquadFilter = filter;
|
|
823
|
+
}
|
|
824
|
+
getBiquadFilterName() {
|
|
825
|
+
return this.connection.biquad?.getFilterName();
|
|
826
|
+
}
|
|
827
|
+
getBiquadFilter() {
|
|
828
|
+
return this.connection.biquad?.filter;
|
|
829
|
+
}
|
|
830
|
+
setBiquadGain(gain) {
|
|
831
|
+
return this.connection.biquad?.setGain(gain);
|
|
832
|
+
}
|
|
833
|
+
setBiquadCutoff(val) {
|
|
834
|
+
return this.connection.biquad?.setCutoff(val);
|
|
835
|
+
}
|
|
836
|
+
setBiquadSampleRate(val) {
|
|
837
|
+
return this.connection.biquad?.setSample(val);
|
|
838
|
+
}
|
|
839
|
+
setBiquadQ(val) {
|
|
840
|
+
return this.connection.biquad?.setQ(val);
|
|
841
|
+
}
|
|
842
|
+
setEqualizer(bands) {
|
|
843
|
+
if (!this.connection.equalizer)
|
|
844
|
+
return false;
|
|
845
|
+
if (!Array.isArray(bands) || !bands.length) {
|
|
846
|
+
this.connection.equalizer.resetEQ();
|
|
847
|
+
this._lastEQBands = this.getEqualizer();
|
|
848
|
+
} else {
|
|
849
|
+
this.connection.equalizer.setEQ(bands);
|
|
850
|
+
this._lastEQBands = this.getEqualizer();
|
|
851
|
+
}
|
|
852
|
+
return true;
|
|
853
|
+
}
|
|
854
|
+
setEqualizerBand(band, gain) {
|
|
855
|
+
if (!this.connection.equalizer)
|
|
856
|
+
return null;
|
|
857
|
+
this.connection.equalizer.equalizer.setGain(band, gain);
|
|
858
|
+
this._lastEQBands = this.getEqualizer();
|
|
859
|
+
return true;
|
|
860
|
+
}
|
|
861
|
+
getEqualizerBand(band) {
|
|
862
|
+
if (!this.connection.equalizer)
|
|
863
|
+
return null;
|
|
864
|
+
return this.connection.equalizer.equalizer.getGain(band);
|
|
865
|
+
}
|
|
866
|
+
getEqualizer() {
|
|
867
|
+
if (!this.connection.equalizer)
|
|
868
|
+
return [];
|
|
869
|
+
return this.connection.equalizer.getEQ();
|
|
870
|
+
}
|
|
871
|
+
isEqualizerEnabled() {
|
|
872
|
+
return this.connection.equalizer != null;
|
|
873
|
+
}
|
|
874
|
+
isEqualizerOff() {
|
|
875
|
+
return this.isEqualizerEnabled() && !this.connection.equalizer.disabled;
|
|
876
|
+
}
|
|
877
|
+
toggleEqualizer() {
|
|
878
|
+
const eq = this.connection.equalizer;
|
|
879
|
+
if (!eq)
|
|
880
|
+
return false;
|
|
881
|
+
eq.toggle();
|
|
882
|
+
return !eq.disabled;
|
|
883
|
+
}
|
|
884
|
+
enableEqualizer() {
|
|
885
|
+
const eq = this.connection.equalizer;
|
|
886
|
+
if (!eq)
|
|
887
|
+
return false;
|
|
888
|
+
eq.enable();
|
|
889
|
+
return !eq.disabled;
|
|
890
|
+
}
|
|
891
|
+
disableEqualizer() {
|
|
892
|
+
const eq = this.connection.equalizer;
|
|
893
|
+
if (!eq)
|
|
894
|
+
return false;
|
|
895
|
+
eq.disable();
|
|
896
|
+
return eq.disabled;
|
|
897
|
+
}
|
|
898
|
+
async forceNext() {
|
|
899
|
+
if (this.connection.audioResource) {
|
|
900
|
+
this.connection.emit("finish", this.connection.audioResource);
|
|
901
|
+
} else if (this.tracks.length) {
|
|
902
|
+
await this.play();
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
get current() {
|
|
906
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
907
|
+
return;
|
|
908
|
+
return this.connection.audioResource?.metadata ?? this.tracks[0];
|
|
909
|
+
}
|
|
910
|
+
get destroyed() {
|
|
911
|
+
return __privateGet(this, _destroyed);
|
|
912
|
+
}
|
|
913
|
+
nowPlaying() {
|
|
914
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
915
|
+
return;
|
|
916
|
+
return this.current;
|
|
917
|
+
}
|
|
918
|
+
async connect(channel) {
|
|
919
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
920
|
+
return;
|
|
921
|
+
const _channel = this.guild.channels.resolve(channel);
|
|
922
|
+
if (![ChannelType.GuildStageVoice, ChannelType.GuildVoice].includes(_channel?.type))
|
|
923
|
+
throw new PlayerError(`Channel type must be GuildVoice or GuildStageVoice, got ${_channel?.type}!`, "InvalidArgType" /* INVALID_ARG_TYPE */);
|
|
924
|
+
const connection = await this.player.voiceUtils.connect(_channel, {
|
|
925
|
+
deaf: this.options.autoSelfDeaf
|
|
926
|
+
});
|
|
927
|
+
this.connection = connection;
|
|
928
|
+
if (_channel.type === ChannelType.GuildStageVoice) {
|
|
929
|
+
await _channel.guild.members.me.voice.setSuppressed(false).catch(async () => {
|
|
930
|
+
return await _channel.guild.members.me.voice.setRequestToSpeak(true).catch(Util.noop);
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
this.connection.on("audioFilters", (filters) => {
|
|
934
|
+
this._lastAudioFilters = filters;
|
|
935
|
+
});
|
|
936
|
+
this.connection.on("error", (err) => {
|
|
937
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this, false))
|
|
938
|
+
return;
|
|
939
|
+
this.player.emit("connectionError", this, err);
|
|
940
|
+
});
|
|
941
|
+
this.connection.on("debug", (msg) => {
|
|
942
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this, false))
|
|
943
|
+
return;
|
|
944
|
+
this.player.emit("debug", this, msg);
|
|
945
|
+
});
|
|
946
|
+
this.player.emit("connectionCreate", this, this.connection);
|
|
947
|
+
this.connection.on("start", (resource) => {
|
|
948
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this, false))
|
|
949
|
+
return;
|
|
950
|
+
this.playing = true;
|
|
951
|
+
if (!this._filtersUpdate)
|
|
952
|
+
this.player.emit("trackStart", this, resource?.metadata ?? this.current);
|
|
953
|
+
this._filtersUpdate = false;
|
|
954
|
+
});
|
|
955
|
+
this.connection.on("finish", async (resource) => {
|
|
956
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this, false))
|
|
957
|
+
return;
|
|
958
|
+
this.playing = false;
|
|
959
|
+
if (this._filtersUpdate)
|
|
960
|
+
return;
|
|
961
|
+
this._streamTime = 0;
|
|
962
|
+
this.player.emit("trackEnd", this, resource.metadata);
|
|
963
|
+
if (!this.tracks.length && this.repeatMode === 0 /* OFF */) {
|
|
964
|
+
this.emitEnd();
|
|
965
|
+
} else if (!this.tracks.length && this.repeatMode === 3 /* AUTOPLAY */) {
|
|
966
|
+
this._handleAutoplay(Util.last(this.previousTracks));
|
|
967
|
+
} else {
|
|
968
|
+
if (this.repeatMode === 1 /* TRACK */)
|
|
969
|
+
return void this.play(Util.last(this.previousTracks), { immediate: true });
|
|
970
|
+
if (this.repeatMode === 2 /* QUEUE */)
|
|
971
|
+
this.tracks.push(Util.last(this.previousTracks));
|
|
972
|
+
const nextTrack = this.tracks.shift();
|
|
973
|
+
this.play(nextTrack, { immediate: true });
|
|
974
|
+
return;
|
|
975
|
+
}
|
|
976
|
+
});
|
|
977
|
+
return this;
|
|
978
|
+
}
|
|
979
|
+
emitEnd() {
|
|
980
|
+
const timeout = setTimeout(() => {
|
|
981
|
+
if (!this.player.queues.has(this.guild.id))
|
|
982
|
+
return;
|
|
983
|
+
if (this.tracks.length || this.current)
|
|
984
|
+
return;
|
|
985
|
+
if (this.options.leaveOnEnd)
|
|
986
|
+
this.destroy();
|
|
987
|
+
this.player.emit("queueEnd", this);
|
|
988
|
+
}, this.options.leaveOnEndCooldown || 0).unref();
|
|
989
|
+
this._cooldownsTimeout.set(`queueEnd_${this.guild.id}`, timeout);
|
|
990
|
+
}
|
|
991
|
+
refreshEndCooldown() {
|
|
992
|
+
const existingTimeout = this._cooldownsTimeout.get(`queueEnd_${this.guild.id}`);
|
|
993
|
+
if (this.tracks.length || this.current) {
|
|
994
|
+
clearTimeout(existingTimeout);
|
|
995
|
+
this._cooldownsTimeout.delete(`queueEnd_${this.guild.id}`);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
destroy(disconnect = this.options.leaveOnStop) {
|
|
999
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1000
|
+
return;
|
|
1001
|
+
if (this.connection)
|
|
1002
|
+
this.connection.end();
|
|
1003
|
+
if (disconnect)
|
|
1004
|
+
this.connection?.disconnect();
|
|
1005
|
+
this.player.queues.delete(this.guild.id);
|
|
1006
|
+
this.player.voiceUtils.cache.delete(this.guild.id);
|
|
1007
|
+
__privateSet(this, _destroyed, true);
|
|
1008
|
+
}
|
|
1009
|
+
skip() {
|
|
1010
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1011
|
+
return;
|
|
1012
|
+
if (!this.connection)
|
|
1013
|
+
return false;
|
|
1014
|
+
this._filtersUpdate = false;
|
|
1015
|
+
this.connection.end();
|
|
1016
|
+
return true;
|
|
1017
|
+
}
|
|
1018
|
+
addTrack(track) {
|
|
1019
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1020
|
+
return;
|
|
1021
|
+
if (!(track instanceof Track_default))
|
|
1022
|
+
throw new PlayerError("invalid track", "InvalidTrack" /* INVALID_TRACK */);
|
|
1023
|
+
this.tracks.push(track);
|
|
1024
|
+
this.refreshEndCooldown();
|
|
1025
|
+
this.player.emit("trackAdd", this, track);
|
|
1026
|
+
}
|
|
1027
|
+
addTracks(tracks) {
|
|
1028
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1029
|
+
return;
|
|
1030
|
+
if (!tracks.every((y) => y instanceof Track_default))
|
|
1031
|
+
throw new PlayerError("invalid track", "InvalidTrack" /* INVALID_TRACK */);
|
|
1032
|
+
this.tracks.push(...tracks);
|
|
1033
|
+
this.refreshEndCooldown();
|
|
1034
|
+
this.player.emit("tracksAdd", this, tracks);
|
|
1035
|
+
}
|
|
1036
|
+
setPaused(paused) {
|
|
1037
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1038
|
+
return false;
|
|
1039
|
+
if (!this.connection)
|
|
1040
|
+
return false;
|
|
1041
|
+
return paused ? this.connection.pause(true) : this.connection.resume();
|
|
1042
|
+
}
|
|
1043
|
+
get paused() {
|
|
1044
|
+
return this.connection.paused;
|
|
1045
|
+
}
|
|
1046
|
+
set paused(val) {
|
|
1047
|
+
this.setPaused(val);
|
|
1048
|
+
}
|
|
1049
|
+
pause() {
|
|
1050
|
+
return this.setPaused(true);
|
|
1051
|
+
}
|
|
1052
|
+
resume() {
|
|
1053
|
+
return this.setPaused(false);
|
|
1054
|
+
}
|
|
1055
|
+
setBitrate(bitrate) {
|
|
1056
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1057
|
+
return;
|
|
1058
|
+
if (!this.connection?.audioResource?.encoder)
|
|
1059
|
+
return;
|
|
1060
|
+
if (bitrate === "auto")
|
|
1061
|
+
bitrate = this.connection.channel?.bitrate ?? 64e3;
|
|
1062
|
+
this.connection.audioResource.encoder.setBitrate(bitrate);
|
|
1063
|
+
}
|
|
1064
|
+
setVolume(amount) {
|
|
1065
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1066
|
+
return;
|
|
1067
|
+
if (!this.connection)
|
|
1068
|
+
return false;
|
|
1069
|
+
this.options.initialVolume = amount;
|
|
1070
|
+
return this.connection.setVolume(amount);
|
|
1071
|
+
}
|
|
1072
|
+
setRepeatMode(mode) {
|
|
1073
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1074
|
+
return;
|
|
1075
|
+
if (![0 /* OFF */, 2 /* QUEUE */, 1 /* TRACK */, 3 /* AUTOPLAY */].includes(mode))
|
|
1076
|
+
throw new PlayerError(`Unknown repeat mode "${mode}"!`, "UnknownRepeatMode" /* UNKNOWN_REPEAT_MODE */);
|
|
1077
|
+
if (mode === this.repeatMode)
|
|
1078
|
+
return false;
|
|
1079
|
+
this.repeatMode = mode;
|
|
1080
|
+
return true;
|
|
1081
|
+
}
|
|
1082
|
+
get volume() {
|
|
1083
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1084
|
+
return 100;
|
|
1085
|
+
if (!this.connection)
|
|
1086
|
+
return 100;
|
|
1087
|
+
return this.connection.volume;
|
|
1088
|
+
}
|
|
1089
|
+
set volume(amount) {
|
|
1090
|
+
this.setVolume(amount);
|
|
1091
|
+
}
|
|
1092
|
+
get streamTime() {
|
|
1093
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1094
|
+
return 0;
|
|
1095
|
+
if (!this.connection)
|
|
1096
|
+
return 0;
|
|
1097
|
+
const playbackTime = this._streamTime + this.connection.streamTime;
|
|
1098
|
+
const NC = this._activeFilters.includes("nightcore") ? 1.25 : null;
|
|
1099
|
+
const VW = this._activeFilters.includes("vaporwave") ? 0.8 : null;
|
|
1100
|
+
if (NC && VW)
|
|
1101
|
+
return playbackTime * (NC + VW);
|
|
1102
|
+
return NC ? playbackTime * NC : VW ? playbackTime * VW : playbackTime;
|
|
1103
|
+
}
|
|
1104
|
+
set streamTime(time) {
|
|
1105
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1106
|
+
return;
|
|
1107
|
+
this.seek(time);
|
|
1108
|
+
}
|
|
1109
|
+
getFiltersEnabled() {
|
|
1110
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1111
|
+
return;
|
|
1112
|
+
return AudioFilters_default.names.filter((x) => this._activeFilters.includes(x));
|
|
1113
|
+
}
|
|
1114
|
+
getFiltersDisabled() {
|
|
1115
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1116
|
+
return;
|
|
1117
|
+
return AudioFilters_default.names.filter((x) => !this._activeFilters.includes(x));
|
|
1118
|
+
}
|
|
1119
|
+
async setFilters(filters) {
|
|
1120
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1121
|
+
return;
|
|
1122
|
+
if (!filters || !Object.keys(filters).length) {
|
|
1123
|
+
const streamTime2 = this.streamTime;
|
|
1124
|
+
this._activeFilters = [];
|
|
1125
|
+
return await this.play(this.current, {
|
|
1126
|
+
immediate: true,
|
|
1127
|
+
filtersUpdate: true,
|
|
1128
|
+
seek: streamTime2,
|
|
1129
|
+
encoderArgs: []
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
const _filters = [];
|
|
1133
|
+
for (const filter in filters) {
|
|
1134
|
+
if (filters[filter] === true)
|
|
1135
|
+
_filters.push(filter);
|
|
1136
|
+
}
|
|
1137
|
+
if (this._activeFilters.join("") === _filters.join(""))
|
|
1138
|
+
return;
|
|
1139
|
+
const newFilters = AudioFilters_default.create(_filters).trim();
|
|
1140
|
+
const streamTime = this.streamTime;
|
|
1141
|
+
this._activeFilters = _filters;
|
|
1142
|
+
return await this.play(this.current, {
|
|
1143
|
+
immediate: true,
|
|
1144
|
+
filtersUpdate: true,
|
|
1145
|
+
seek: streamTime,
|
|
1146
|
+
encoderArgs: !_filters.length ? void 0 : ["-af", newFilters]
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1149
|
+
async seek(position) {
|
|
1150
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1151
|
+
return;
|
|
1152
|
+
if (!this.playing || !this.current)
|
|
1153
|
+
return false;
|
|
1154
|
+
if (position < 1)
|
|
1155
|
+
position = 0;
|
|
1156
|
+
if (position >= this.current.durationMS)
|
|
1157
|
+
return this.skip();
|
|
1158
|
+
await this.play(this.current, {
|
|
1159
|
+
immediate: true,
|
|
1160
|
+
filtersUpdate: true,
|
|
1161
|
+
seek: position
|
|
1162
|
+
});
|
|
1163
|
+
return true;
|
|
1164
|
+
}
|
|
1165
|
+
async back() {
|
|
1166
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1167
|
+
return;
|
|
1168
|
+
const prev = this.previousTracks[this.previousTracks.length - 2];
|
|
1169
|
+
if (!prev)
|
|
1170
|
+
throw new PlayerError("Could not find previous track", "TrackNotFound" /* TRACK_NOT_FOUND */);
|
|
1171
|
+
return await this.play(prev, { immediate: true });
|
|
1172
|
+
}
|
|
1173
|
+
clear() {
|
|
1174
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1175
|
+
return;
|
|
1176
|
+
this.tracks = [];
|
|
1177
|
+
this.previousTracks = [];
|
|
1178
|
+
}
|
|
1179
|
+
stop() {
|
|
1180
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1181
|
+
return;
|
|
1182
|
+
return this.destroy();
|
|
1183
|
+
}
|
|
1184
|
+
shuffle() {
|
|
1185
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1186
|
+
return;
|
|
1187
|
+
if (!this.tracks.length || this.tracks.length < 2)
|
|
1188
|
+
return false;
|
|
1189
|
+
for (let i = this.tracks.length - 1; i > 0; i--) {
|
|
1190
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
1191
|
+
[this.tracks[i], this.tracks[j]] = [this.tracks[j], this.tracks[i]];
|
|
1192
|
+
}
|
|
1193
|
+
return true;
|
|
1194
|
+
}
|
|
1195
|
+
remove(track) {
|
|
1196
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1197
|
+
return;
|
|
1198
|
+
let trackFound = null;
|
|
1199
|
+
if (typeof track === "number") {
|
|
1200
|
+
trackFound = this.tracks[track];
|
|
1201
|
+
if (trackFound) {
|
|
1202
|
+
this.tracks = this.tracks.filter((t) => t.id !== trackFound.id);
|
|
1203
|
+
}
|
|
1204
|
+
} else {
|
|
1205
|
+
trackFound = this.tracks.find((s) => s.id === (track instanceof Track_default ? track.id : track));
|
|
1206
|
+
if (trackFound) {
|
|
1207
|
+
this.tracks = this.tracks.filter((s) => s.id !== trackFound.id);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
return trackFound;
|
|
1211
|
+
}
|
|
1212
|
+
getTrackPosition(track) {
|
|
1213
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1214
|
+
return;
|
|
1215
|
+
if (typeof track === "number")
|
|
1216
|
+
return this.tracks[track] != null ? track : -1;
|
|
1217
|
+
return this.tracks.findIndex((pred) => pred.id === (track instanceof Track_default ? track.id : track));
|
|
1218
|
+
}
|
|
1219
|
+
jump(track) {
|
|
1220
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1221
|
+
return;
|
|
1222
|
+
const foundTrack = this.remove(track);
|
|
1223
|
+
if (!foundTrack)
|
|
1224
|
+
throw new PlayerError("Track not found", "TrackNotFound" /* TRACK_NOT_FOUND */);
|
|
1225
|
+
this.tracks.splice(0, 0, foundTrack);
|
|
1226
|
+
return void this.skip();
|
|
1227
|
+
}
|
|
1228
|
+
skipTo(track) {
|
|
1229
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1230
|
+
return;
|
|
1231
|
+
const trackIndex = this.getTrackPosition(track);
|
|
1232
|
+
const removedTrack = this.remove(track);
|
|
1233
|
+
if (!removedTrack)
|
|
1234
|
+
throw new PlayerError("Track not found", "TrackNotFound" /* TRACK_NOT_FOUND */);
|
|
1235
|
+
this.tracks.splice(0, trackIndex, removedTrack);
|
|
1236
|
+
return void this.skip();
|
|
1237
|
+
}
|
|
1238
|
+
insert(track, index = 0) {
|
|
1239
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1240
|
+
return;
|
|
1241
|
+
if (!track || !(track instanceof Track_default))
|
|
1242
|
+
throw new PlayerError("track must be the instance of Track", "InvalidTrack" /* INVALID_TRACK */);
|
|
1243
|
+
if (typeof index !== "number" || index < 0 || !Number.isFinite(index))
|
|
1244
|
+
throw new PlayerError(`Invalid index "${index}"`, "InvalidArgType" /* INVALID_ARG_TYPE */);
|
|
1245
|
+
this.tracks.splice(index, 0, track);
|
|
1246
|
+
this.player.emit("trackAdd", this, track);
|
|
1247
|
+
}
|
|
1248
|
+
getPlayerTimestamp() {
|
|
1249
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1250
|
+
return;
|
|
1251
|
+
const currentStreamTime = this.streamTime;
|
|
1252
|
+
const totalTime = this.current.durationMS;
|
|
1253
|
+
const currentTimecode = Util.buildTimeCode(Util.parseMS(currentStreamTime));
|
|
1254
|
+
const endTimecode = Util.buildTimeCode(Util.parseMS(totalTime));
|
|
1255
|
+
return {
|
|
1256
|
+
current: currentTimecode,
|
|
1257
|
+
end: endTimecode,
|
|
1258
|
+
progress: Math.round(currentStreamTime / totalTime * 100)
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1261
|
+
createProgressBar(options = { timecodes: true }) {
|
|
1262
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1263
|
+
return;
|
|
1264
|
+
const length = typeof options.length === "number" ? options.length <= 0 || options.length === Infinity ? 15 : options.length : 15;
|
|
1265
|
+
const index = Math.round(this.streamTime / this.current.durationMS * length);
|
|
1266
|
+
const indicator = typeof options.indicator === "string" && options.indicator.length > 0 ? options.indicator : "\u{1F518}";
|
|
1267
|
+
const line = typeof options.line === "string" && options.line.length > 0 ? options.line : "\u25AC";
|
|
1268
|
+
if (index >= 1 && index <= length) {
|
|
1269
|
+
const bar = line.repeat(length - 1).split("");
|
|
1270
|
+
bar.splice(index, 0, indicator);
|
|
1271
|
+
if (options.timecodes) {
|
|
1272
|
+
const timestamp = this.getPlayerTimestamp();
|
|
1273
|
+
return `${timestamp.current} \u2503 ${bar.join("")} \u2503 ${timestamp.end}`;
|
|
1274
|
+
} else {
|
|
1275
|
+
return `${bar.join("")}`;
|
|
1276
|
+
}
|
|
1277
|
+
} else {
|
|
1278
|
+
if (options.timecodes) {
|
|
1279
|
+
const timestamp = this.getPlayerTimestamp();
|
|
1280
|
+
return `${timestamp.current} \u2503 ${indicator}${line.repeat(length - 1)} \u2503 ${timestamp.end}`;
|
|
1281
|
+
} else {
|
|
1282
|
+
return `${indicator}${line.repeat(length - 1)}`;
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
get totalTime() {
|
|
1287
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1288
|
+
return 0;
|
|
1289
|
+
return this.tracks.length > 0 ? this.tracks.map((t) => t.durationMS).reduce((p, c) => p + c) : 0;
|
|
1290
|
+
}
|
|
1291
|
+
generateStatistics() {
|
|
1292
|
+
return {
|
|
1293
|
+
guild: this.guild.id,
|
|
1294
|
+
memory: process.memoryUsage(),
|
|
1295
|
+
tracks: this.tracks.length,
|
|
1296
|
+
os: {
|
|
1297
|
+
cpuCount: os.cpus().length,
|
|
1298
|
+
totalMem: os.totalmem(),
|
|
1299
|
+
freeMem: os.freemem(),
|
|
1300
|
+
platform: process.platform
|
|
1301
|
+
},
|
|
1302
|
+
isShard: typeof process.send === "function" || parentPort != null,
|
|
1303
|
+
latency: {
|
|
1304
|
+
client: this.player.client.ws.ping,
|
|
1305
|
+
udp: this.connection.voiceConnection.ping.udp,
|
|
1306
|
+
ws: this.connection.voiceConnection.ping.ws,
|
|
1307
|
+
eventLoop: this.player.eventLoopLag
|
|
1308
|
+
},
|
|
1309
|
+
subscribers: this.player.queues.size,
|
|
1310
|
+
connections: this.player.queues.filter((x) => x.connection?.voiceConnection != null).size,
|
|
1311
|
+
extractors: this.player.extractors.size
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
get ping() {
|
|
1315
|
+
return this.connection.voiceConnection.ping.udp;
|
|
1316
|
+
}
|
|
1317
|
+
async play(src, options = {}) {
|
|
1318
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this, false))
|
|
1319
|
+
return;
|
|
1320
|
+
if (!this.connection || !this.connection.voiceConnection)
|
|
1321
|
+
throw new PlayerError("Voice connection is not available, use <Queue>.connect()!", "NoConnection" /* NO_CONNECTION */);
|
|
1322
|
+
if (src && (this.playing || this.tracks.length) && !options.immediate)
|
|
1323
|
+
return this.addTrack(src);
|
|
1324
|
+
const track = options.filtersUpdate && !options.immediate ? src || this.current : src ?? this.tracks.shift();
|
|
1325
|
+
if (!track)
|
|
1326
|
+
return;
|
|
1327
|
+
this.player.emit("debug", this, "Received play request");
|
|
1328
|
+
if (!options.filtersUpdate) {
|
|
1329
|
+
this.previousTracks = this.previousTracks.filter((x) => x.id !== track.id);
|
|
1330
|
+
this.previousTracks.push(track);
|
|
1331
|
+
}
|
|
1332
|
+
let stream = null;
|
|
1333
|
+
const hasCustomDownloader = typeof this.onBeforeCreateStream === "function";
|
|
1334
|
+
if (hasCustomDownloader) {
|
|
1335
|
+
const qt = track.queryType || (track.raw.source === "spotify" ? "spotifySong" : track.raw.source === "apple_music" ? "appleMusicSong" : track.raw.source) || "arbitrary";
|
|
1336
|
+
stream = await this.onBeforeCreateStream(track, qt, this) || null;
|
|
1337
|
+
}
|
|
1338
|
+
if (!stream) {
|
|
1339
|
+
const streamInfo = await this.player.extractors.run(async (extractor) => {
|
|
1340
|
+
const canStream = await extractor.validate(track.url, track.queryType || QueryResolver.resolve(track.url));
|
|
1341
|
+
if (!canStream)
|
|
1342
|
+
return false;
|
|
1343
|
+
return await extractor.stream(track);
|
|
1344
|
+
});
|
|
1345
|
+
if (!streamInfo || !streamInfo.result) {
|
|
1346
|
+
this.player.emit("error", this, new Error("No stream extractors are available for this track"));
|
|
1347
|
+
return void this.play(this.tracks.shift(), { immediate: true });
|
|
1348
|
+
}
|
|
1349
|
+
stream = streamInfo.result;
|
|
1350
|
+
}
|
|
1351
|
+
const ffmpegStream = createFFmpegStream(stream, {
|
|
1352
|
+
encoderArgs: options.encoderArgs || this._activeFilters.length ? ["-af", AudioFilters_default.create(this._activeFilters)] : [],
|
|
1353
|
+
seek: options.seek ? options.seek / 1e3 : 0,
|
|
1354
|
+
fmt: "s16le"
|
|
1355
|
+
}).on("error", (err) => {
|
|
1356
|
+
if (!`${err}`.toLowerCase().includes("premature close"))
|
|
1357
|
+
this.player.emit("error", this, err);
|
|
1358
|
+
});
|
|
1359
|
+
const resource = this.connection.createStream(ffmpegStream, {
|
|
1360
|
+
type: StreamType.Raw,
|
|
1361
|
+
data: track,
|
|
1362
|
+
disableVolume: Boolean(this.options.disableVolume),
|
|
1363
|
+
disableEqualizer: Boolean(this.options.disableEqualizer),
|
|
1364
|
+
eq: this._lastEQBands,
|
|
1365
|
+
disableBiquad: Boolean(this.options.disableBiquad),
|
|
1366
|
+
biquadFilter: this._lastBiquadFilter,
|
|
1367
|
+
defaultFilters: this._lastAudioFilters,
|
|
1368
|
+
disableFilters: Boolean(this.options.disableFilters)
|
|
1369
|
+
});
|
|
1370
|
+
if (options.seek)
|
|
1371
|
+
this._streamTime = options.seek;
|
|
1372
|
+
this._filtersUpdate = options.filtersUpdate;
|
|
1373
|
+
const volumeTransformer = resource.volume;
|
|
1374
|
+
if (volumeTransformer && typeof this.options.initialVolume === "number")
|
|
1375
|
+
volumeTransformer.setVolume(Math.pow(this.options.initialVolume / 100, 1.660964));
|
|
1376
|
+
if (volumeTransformer?.hasSmoothness && typeof this.options.volumeSmoothness === "number") {
|
|
1377
|
+
if (typeof volumeTransformer.setSmoothness === "function")
|
|
1378
|
+
volumeTransformer.setSmoothness(this.options.volumeSmoothness || 0);
|
|
1379
|
+
}
|
|
1380
|
+
setTimeout(() => {
|
|
1381
|
+
this.connection.playStream(resource);
|
|
1382
|
+
}, __privateMethod(this, _getBufferingTimeout, getBufferingTimeout_fn).call(this)).unref();
|
|
1383
|
+
}
|
|
1384
|
+
async _handleAutoplay(track) {
|
|
1385
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1386
|
+
return;
|
|
1387
|
+
if (!track || ![track.source, track.raw?.source].includes("youtube")) {
|
|
1388
|
+
return this.emitEnd();
|
|
1389
|
+
}
|
|
1390
|
+
let info = await YouTube2.getVideo(track.url).then((x) => x.videos[0]).catch(Util.noop);
|
|
1391
|
+
if (!info)
|
|
1392
|
+
info = await YouTube2.search(track.author).then((x) => x[0]).catch(Util.noop);
|
|
1393
|
+
if (!info) {
|
|
1394
|
+
return this.emitEnd();
|
|
1395
|
+
}
|
|
1396
|
+
const nextTrack = new Track_default(this.player, {
|
|
1397
|
+
title: info.title,
|
|
1398
|
+
url: `https://www.youtube.com/watch?v=${info.id}`,
|
|
1399
|
+
duration: info.durationFormatted || Util.buildTimeCode(Util.parseMS(info.duration * 1e3)),
|
|
1400
|
+
description: "",
|
|
1401
|
+
thumbnail: typeof info.thumbnail === "string" ? info.thumbnail : info.thumbnail.url,
|
|
1402
|
+
views: info.views,
|
|
1403
|
+
author: info.channel.name,
|
|
1404
|
+
requestedBy: track.requestedBy,
|
|
1405
|
+
source: "youtube",
|
|
1406
|
+
queryType: "youtubeVideo"
|
|
1407
|
+
});
|
|
1408
|
+
this.play(nextTrack, { immediate: true });
|
|
1409
|
+
}
|
|
1410
|
+
*[Symbol.iterator]() {
|
|
1411
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1412
|
+
return;
|
|
1413
|
+
yield* this.tracks;
|
|
1414
|
+
}
|
|
1415
|
+
toJSON() {
|
|
1416
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1417
|
+
return;
|
|
1418
|
+
return {
|
|
1419
|
+
id: this.id,
|
|
1420
|
+
guild: this.guild.id,
|
|
1421
|
+
voiceChannel: this.connection?.channel?.id,
|
|
1422
|
+
options: this.options,
|
|
1423
|
+
tracks: this.tracks.map((m) => m.toJSON())
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
toString() {
|
|
1427
|
+
if (__privateMethod(this, _watchDestroyed, watchDestroyed_fn).call(this))
|
|
1428
|
+
return;
|
|
1429
|
+
if (!this.tracks.length)
|
|
1430
|
+
return "No songs available to display!";
|
|
1431
|
+
return `**Upcoming Songs:**
|
|
1432
|
+
${this.tracks.map((m, i) => `${i + 1}. **${m.title}**`).join("\n")}`;
|
|
1433
|
+
}
|
|
1434
|
+
};
|
|
1435
|
+
__name(Queue, "Queue");
|
|
1436
|
+
_destroyed = new WeakMap();
|
|
1437
|
+
_watchDestroyed = new WeakSet();
|
|
1438
|
+
watchDestroyed_fn = /* @__PURE__ */ __name(function(emit = true) {
|
|
1439
|
+
if (__privateGet(this, _destroyed)) {
|
|
1440
|
+
if (emit)
|
|
1441
|
+
this.player.emit("error", this, new PlayerError("Cannot use destroyed queue", "DestroyedQueue" /* DESTROYED_QUEUE */));
|
|
1442
|
+
return true;
|
|
1443
|
+
}
|
|
1444
|
+
return false;
|
|
1445
|
+
}, "#watchDestroyed");
|
|
1446
|
+
_getBufferingTimeout = new WeakSet();
|
|
1447
|
+
getBufferingTimeout_fn = /* @__PURE__ */ __name(function() {
|
|
1448
|
+
const timeout = this.options.bufferingTimeout;
|
|
1449
|
+
if (isNaN(timeout) || timeout < 0 || !Number.isFinite(timeout))
|
|
1450
|
+
return 1e3;
|
|
1451
|
+
return timeout;
|
|
1452
|
+
}, "#getBufferingTimeout");
|
|
1453
|
+
|
|
1454
|
+
// src/VoiceInterface/VoiceUtils.ts
|
|
1455
|
+
import { joinVoiceChannel } from "@discordjs/voice";
|
|
1456
|
+
|
|
1457
|
+
// src/VoiceInterface/StreamDispatcher.ts
|
|
1458
|
+
import {
|
|
1459
|
+
AudioPlayerStatus,
|
|
1460
|
+
createAudioPlayer,
|
|
1461
|
+
createAudioResource,
|
|
1462
|
+
entersState,
|
|
1463
|
+
StreamType as StreamType2,
|
|
1464
|
+
VoiceConnectionStatus,
|
|
1465
|
+
VoiceConnectionDisconnectReason
|
|
1466
|
+
} from "@discordjs/voice";
|
|
1467
|
+
import { TypedEmitter as EventEmitter } from "tiny-typed-emitter";
|
|
1468
|
+
import { EqualizerStream, BiquadStream, AudioFilter } from "@discord-player/equalizer";
|
|
1469
|
+
var StreamDispatcher = class extends EventEmitter {
|
|
1470
|
+
constructor(connection, channel, connectionTimeout = 2e4) {
|
|
1471
|
+
super();
|
|
1472
|
+
this.connectionTimeout = connectionTimeout;
|
|
1473
|
+
this.readyLock = false;
|
|
1474
|
+
this.equalizer = null;
|
|
1475
|
+
this.biquad = null;
|
|
1476
|
+
this.audioFilters = null;
|
|
1477
|
+
this.voiceConnection = connection;
|
|
1478
|
+
this.audioPlayer = createAudioPlayer();
|
|
1479
|
+
this.channel = channel;
|
|
1480
|
+
this.voiceConnection.on("stateChange", async (_, newState) => {
|
|
1481
|
+
if (newState.status === VoiceConnectionStatus.Disconnected) {
|
|
1482
|
+
if (newState.reason === VoiceConnectionDisconnectReason.WebSocketClose && newState.closeCode === 4014) {
|
|
1483
|
+
try {
|
|
1484
|
+
await entersState(this.voiceConnection, VoiceConnectionStatus.Connecting, this.connectionTimeout);
|
|
1485
|
+
} catch {
|
|
1486
|
+
try {
|
|
1487
|
+
this.voiceConnection.destroy();
|
|
1488
|
+
} catch (err) {
|
|
1489
|
+
this.emit("error", err);
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
} else if (this.voiceConnection.rejoinAttempts < 5) {
|
|
1493
|
+
await Util.wait((this.voiceConnection.rejoinAttempts + 1) * 5e3);
|
|
1494
|
+
this.voiceConnection.rejoin();
|
|
1495
|
+
} else {
|
|
1496
|
+
try {
|
|
1497
|
+
this.voiceConnection.destroy();
|
|
1498
|
+
} catch (err) {
|
|
1499
|
+
this.emit("error", err);
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
} else if (newState.status === VoiceConnectionStatus.Destroyed) {
|
|
1503
|
+
this.end();
|
|
1504
|
+
} else if (!this.readyLock && (newState.status === VoiceConnectionStatus.Connecting || newState.status === VoiceConnectionStatus.Signalling)) {
|
|
1505
|
+
this.readyLock = true;
|
|
1506
|
+
try {
|
|
1507
|
+
await entersState(this.voiceConnection, VoiceConnectionStatus.Ready, this.connectionTimeout);
|
|
1508
|
+
} catch {
|
|
1509
|
+
if (this.voiceConnection.state.status !== VoiceConnectionStatus.Destroyed) {
|
|
1510
|
+
try {
|
|
1511
|
+
this.voiceConnection.destroy();
|
|
1512
|
+
} catch (err) {
|
|
1513
|
+
this.emit("error", err);
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
} finally {
|
|
1517
|
+
this.readyLock = false;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
});
|
|
1521
|
+
this.audioPlayer.on("stateChange", (oldState, newState) => {
|
|
1522
|
+
if (newState.status === AudioPlayerStatus.Playing) {
|
|
1523
|
+
if (!this.paused)
|
|
1524
|
+
return void this.emit("start", this.audioResource);
|
|
1525
|
+
} else if (newState.status === AudioPlayerStatus.Idle && oldState.status !== AudioPlayerStatus.Idle) {
|
|
1526
|
+
if (!this.paused) {
|
|
1527
|
+
void this.emit("finish", this.audioResource);
|
|
1528
|
+
if (this.equalizer) {
|
|
1529
|
+
this.equalizer.destroy();
|
|
1530
|
+
this.equalizer = null;
|
|
1531
|
+
}
|
|
1532
|
+
if (this.biquad) {
|
|
1533
|
+
this.biquad.destroy();
|
|
1534
|
+
this.biquad = null;
|
|
1535
|
+
}
|
|
1536
|
+
if (this.audioFilters) {
|
|
1537
|
+
this.audioFilters.destroy();
|
|
1538
|
+
this.audioFilters = null;
|
|
1539
|
+
}
|
|
1540
|
+
this.audioResource = null;
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
});
|
|
1544
|
+
this.audioPlayer.on("debug", (m) => void this.emit("debug", m));
|
|
1545
|
+
this.audioPlayer.on("error", (error) => void this.emit("error", error));
|
|
1546
|
+
this.voiceConnection.subscribe(this.audioPlayer);
|
|
1547
|
+
}
|
|
1548
|
+
get paused() {
|
|
1549
|
+
return this.audioPlayer.state.status === AudioPlayerStatus.Paused;
|
|
1550
|
+
}
|
|
1551
|
+
set paused(val) {
|
|
1552
|
+
val ? this.pause(true) : this.resume();
|
|
1553
|
+
}
|
|
1554
|
+
isPaused() {
|
|
1555
|
+
return this.paused || this.audioPlayer.state.status === AudioPlayerStatus.AutoPaused;
|
|
1556
|
+
}
|
|
1557
|
+
isBuffering() {
|
|
1558
|
+
return this.audioPlayer.state.status === AudioPlayerStatus.Buffering;
|
|
1559
|
+
}
|
|
1560
|
+
isPlaying() {
|
|
1561
|
+
return this.audioPlayer.state.status === AudioPlayerStatus.Playing;
|
|
1562
|
+
}
|
|
1563
|
+
isIdle() {
|
|
1564
|
+
return this.audioPlayer.state.status === AudioPlayerStatus.Idle;
|
|
1565
|
+
}
|
|
1566
|
+
createStream(src, ops) {
|
|
1567
|
+
if (!ops?.disableEqualizer) {
|
|
1568
|
+
this.equalizer = new EqualizerStream({
|
|
1569
|
+
channels: 1,
|
|
1570
|
+
disabled: false,
|
|
1571
|
+
bandMultiplier: ops?.eq || []
|
|
1572
|
+
});
|
|
1573
|
+
}
|
|
1574
|
+
if (!ops?.disableBiquad) {
|
|
1575
|
+
this.biquad = new BiquadStream({
|
|
1576
|
+
filter: ops?.biquadFilter
|
|
1577
|
+
});
|
|
1578
|
+
}
|
|
1579
|
+
if (!ops?.disableFilters) {
|
|
1580
|
+
this.audioFilters = new AudioFilter({
|
|
1581
|
+
filters: ops?.defaultFilters
|
|
1582
|
+
});
|
|
1583
|
+
this.audioFilters.onUpdate = () => {
|
|
1584
|
+
if (this.audioFilters)
|
|
1585
|
+
this.emit("audioFilters", this.audioFilters.filters);
|
|
1586
|
+
};
|
|
1587
|
+
}
|
|
1588
|
+
let stream = this.equalizer && typeof src !== "string" ? src.pipe(this.equalizer) : src;
|
|
1589
|
+
if (this.biquad && typeof stream !== "string")
|
|
1590
|
+
stream = stream.pipe(this.biquad);
|
|
1591
|
+
if (this.audioFilters && typeof stream !== "string")
|
|
1592
|
+
stream = stream.pipe(this.audioFilters);
|
|
1593
|
+
this.audioResource = createAudioResource(stream, {
|
|
1594
|
+
inputType: ops?.type ?? StreamType2.Arbitrary,
|
|
1595
|
+
metadata: ops?.data,
|
|
1596
|
+
inlineVolume: !ops?.disableVolume
|
|
1597
|
+
});
|
|
1598
|
+
return this.audioResource;
|
|
1599
|
+
}
|
|
1600
|
+
get status() {
|
|
1601
|
+
return this.audioPlayer.state.status;
|
|
1602
|
+
}
|
|
1603
|
+
disconnect() {
|
|
1604
|
+
try {
|
|
1605
|
+
this.audioPlayer.stop(true);
|
|
1606
|
+
this.voiceConnection.destroy();
|
|
1607
|
+
} catch {
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
end() {
|
|
1611
|
+
this.audioPlayer.stop();
|
|
1612
|
+
}
|
|
1613
|
+
pause(interpolateSilence) {
|
|
1614
|
+
const success = this.audioPlayer.pause(interpolateSilence);
|
|
1615
|
+
return success;
|
|
1616
|
+
}
|
|
1617
|
+
resume() {
|
|
1618
|
+
const success = this.audioPlayer.unpause();
|
|
1619
|
+
return success;
|
|
1620
|
+
}
|
|
1621
|
+
async playStream(resource = this.audioResource) {
|
|
1622
|
+
if (!resource)
|
|
1623
|
+
throw new PlayerError("Audio resource is not available!", "NoAudioResource" /* NO_AUDIO_RESOURCE */);
|
|
1624
|
+
if (resource.ended) {
|
|
1625
|
+
return void this.emit("finish", resource);
|
|
1626
|
+
}
|
|
1627
|
+
if (!this.audioResource)
|
|
1628
|
+
this.audioResource = resource;
|
|
1629
|
+
if (this.voiceConnection.state.status !== VoiceConnectionStatus.Ready) {
|
|
1630
|
+
try {
|
|
1631
|
+
await entersState(this.voiceConnection, VoiceConnectionStatus.Ready, this.connectionTimeout);
|
|
1632
|
+
} catch (err) {
|
|
1633
|
+
return void this.emit("error", err);
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
try {
|
|
1637
|
+
this.audioPlayer.play(resource);
|
|
1638
|
+
} catch (e) {
|
|
1639
|
+
this.emit("error", e);
|
|
1640
|
+
}
|
|
1641
|
+
return this;
|
|
1642
|
+
}
|
|
1643
|
+
setVolume(value) {
|
|
1644
|
+
if (!this.audioResource?.volume || isNaN(value) || value < 0 || value > Infinity)
|
|
1645
|
+
return false;
|
|
1646
|
+
this.audioResource.volume.setVolumeLogarithmic(value / 100);
|
|
1647
|
+
return true;
|
|
1648
|
+
}
|
|
1649
|
+
get volume() {
|
|
1650
|
+
if (!this.audioResource?.volume)
|
|
1651
|
+
return 100;
|
|
1652
|
+
const currentVol = this.audioResource.volume.volume;
|
|
1653
|
+
return Math.round(Math.pow(currentVol, 1 / 1.660964) * 100);
|
|
1654
|
+
}
|
|
1655
|
+
get streamTime() {
|
|
1656
|
+
if (!this.audioResource)
|
|
1657
|
+
return 0;
|
|
1658
|
+
return this.audioResource.playbackDuration;
|
|
1659
|
+
}
|
|
1660
|
+
};
|
|
1661
|
+
__name(StreamDispatcher, "StreamDispatcher");
|
|
1662
|
+
|
|
1663
|
+
// src/VoiceInterface/VoiceUtils.ts
|
|
1664
|
+
import { Collection as Collection3 } from "@discord-player/utils";
|
|
1665
|
+
var VoiceUtils = class {
|
|
1666
|
+
constructor() {
|
|
1667
|
+
this.cache = new Collection3();
|
|
1668
|
+
}
|
|
1669
|
+
async connect(channel, options) {
|
|
1670
|
+
const conn = await this.join(channel, options);
|
|
1671
|
+
const sub = new StreamDispatcher(conn, channel, options?.maxTime);
|
|
1672
|
+
this.cache.set(channel.guild.id, sub);
|
|
1673
|
+
return sub;
|
|
1674
|
+
}
|
|
1675
|
+
async join(channel, options) {
|
|
1676
|
+
const conn = joinVoiceChannel({
|
|
1677
|
+
guildId: channel.guild.id,
|
|
1678
|
+
channelId: channel.id,
|
|
1679
|
+
adapterCreator: channel.guild.voiceAdapterCreator,
|
|
1680
|
+
selfDeaf: Boolean(options?.deaf)
|
|
1681
|
+
});
|
|
1682
|
+
return conn;
|
|
1683
|
+
}
|
|
1684
|
+
disconnect(connection) {
|
|
1685
|
+
if (connection instanceof StreamDispatcher)
|
|
1686
|
+
return connection.voiceConnection.destroy();
|
|
1687
|
+
return connection.destroy();
|
|
1688
|
+
}
|
|
1689
|
+
getConnection(guild) {
|
|
1690
|
+
return this.cache.get(guild);
|
|
1691
|
+
}
|
|
1692
|
+
};
|
|
1693
|
+
__name(VoiceUtils, "VoiceUtils");
|
|
1694
|
+
|
|
1695
|
+
// src/Player.ts
|
|
1696
|
+
import { generateDependencyReport } from "@discordjs/voice";
|
|
1697
|
+
import { Collection as Collection4 } from "@discord-player/utils";
|
|
1698
|
+
|
|
1699
|
+
// src/Structures/SearchResult.ts
|
|
1700
|
+
var SearchResult = class {
|
|
1701
|
+
constructor(player, _data) {
|
|
1702
|
+
this.player = player;
|
|
1703
|
+
this._data = _data;
|
|
1704
|
+
}
|
|
1705
|
+
get query() {
|
|
1706
|
+
return this._data.query;
|
|
1707
|
+
}
|
|
1708
|
+
get queryType() {
|
|
1709
|
+
return this._data.queryType || QueryType.AUTO;
|
|
1710
|
+
}
|
|
1711
|
+
get extractor() {
|
|
1712
|
+
return this._data.extractor || null;
|
|
1713
|
+
}
|
|
1714
|
+
get playlist() {
|
|
1715
|
+
return this._data.playlist;
|
|
1716
|
+
}
|
|
1717
|
+
get tracks() {
|
|
1718
|
+
return this._data.tracks || [];
|
|
1719
|
+
}
|
|
1720
|
+
get requestedBy() {
|
|
1721
|
+
return this._data.requestedBy || null;
|
|
1722
|
+
}
|
|
1723
|
+
async execute() {
|
|
1724
|
+
return this.player.search(this.query, {
|
|
1725
|
+
searchEngine: this.queryType,
|
|
1726
|
+
requestedBy: this.requestedBy
|
|
1727
|
+
});
|
|
1728
|
+
}
|
|
1729
|
+
isEmpty() {
|
|
1730
|
+
return !this.tracks.length;
|
|
1731
|
+
}
|
|
1732
|
+
hasPlaylist() {
|
|
1733
|
+
return this.playlist != null;
|
|
1734
|
+
}
|
|
1735
|
+
hasTracks() {
|
|
1736
|
+
return this.tracks.length > 0;
|
|
1737
|
+
}
|
|
1738
|
+
toJSON() {
|
|
1739
|
+
return {
|
|
1740
|
+
query: this.query,
|
|
1741
|
+
queryType: this.queryType,
|
|
1742
|
+
playlist: this.playlist?.toJSON(false) || null,
|
|
1743
|
+
tracks: this.tracks.map((m) => m.toJSON(true)),
|
|
1744
|
+
extractor: this.extractor?.identifier || null,
|
|
1745
|
+
requestedBy: this.requestedBy?.toJSON() || null
|
|
1746
|
+
};
|
|
1747
|
+
}
|
|
1748
|
+
};
|
|
1749
|
+
__name(SearchResult, "SearchResult");
|
|
1750
|
+
|
|
1751
|
+
// src/Player.ts
|
|
1752
|
+
var _lastLatency;
|
|
1753
|
+
var Player = class extends EventEmitter2 {
|
|
1754
|
+
constructor(client, options = {}) {
|
|
1755
|
+
super();
|
|
1756
|
+
this.options = {
|
|
1757
|
+
autoRegisterExtractor: true,
|
|
1758
|
+
ytdlOptions: {
|
|
1759
|
+
highWaterMark: 1 << 25
|
|
1760
|
+
},
|
|
1761
|
+
connectionTimeout: 2e4,
|
|
1762
|
+
smoothVolume: true,
|
|
1763
|
+
lagMonitor: 3e4
|
|
1764
|
+
};
|
|
1765
|
+
this.queues = new Collection4();
|
|
1766
|
+
this.voiceUtils = new VoiceUtils();
|
|
1767
|
+
this.requiredEvents = ["error", "connectionError"];
|
|
1768
|
+
this.extractors = new ExtractorExecutionContext(this);
|
|
1769
|
+
__privateAdd(this, _lastLatency, -1);
|
|
1770
|
+
this.client = client;
|
|
1771
|
+
if (this.client?.options?.intents && !new IntentsBitField(this.client?.options?.intents).has(IntentsBitField.Flags.GuildVoiceStates)) {
|
|
1772
|
+
throw new PlayerError('client is missing "GuildVoiceStates" intent');
|
|
1773
|
+
}
|
|
1774
|
+
this.options = Object.assign(this.options, options);
|
|
1775
|
+
this.client.on("voiceStateUpdate", this._handleVoiceState.bind(this));
|
|
1776
|
+
if (this.options?.autoRegisterExtractor) {
|
|
1777
|
+
let nv;
|
|
1778
|
+
if (nv = Util.require("@discord-player/extractor")) {
|
|
1779
|
+
["YouTubeExtractor", "SoundCloudExtractor", "ReverbnationExtractor", "VimeoExtractor", "AttachmentExtractor"].forEach((ext) => void this.extractors.register(nv[ext]));
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
if (typeof this.options.lagMonitor === "number" && this.options.lagMonitor > 0) {
|
|
1783
|
+
setInterval(() => {
|
|
1784
|
+
const start = performance.now();
|
|
1785
|
+
setTimeout(() => {
|
|
1786
|
+
__privateSet(this, _lastLatency, performance.now() - start);
|
|
1787
|
+
}, 0).unref();
|
|
1788
|
+
}, this.options.lagMonitor).unref();
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
get eventLoopLag() {
|
|
1792
|
+
return __privateGet(this, _lastLatency);
|
|
1793
|
+
}
|
|
1794
|
+
generateStatistics() {
|
|
1795
|
+
return this.queues.map((m) => m.generateStatistics());
|
|
1796
|
+
}
|
|
1797
|
+
_handleVoiceState(oldState, newState) {
|
|
1798
|
+
const queue = this.getQueue(oldState.guild.id);
|
|
1799
|
+
if (!queue || !queue.connection)
|
|
1800
|
+
return;
|
|
1801
|
+
this.emit("voiceStateUpdate", queue, oldState, newState);
|
|
1802
|
+
if (oldState.channelId && !newState.channelId && newState.member.id === newState.guild.members.me.id) {
|
|
1803
|
+
try {
|
|
1804
|
+
queue.destroy();
|
|
1805
|
+
} catch {
|
|
1806
|
+
}
|
|
1807
|
+
return void this.emit("botDisconnect", queue);
|
|
1808
|
+
}
|
|
1809
|
+
if (!oldState.channelId && newState.channelId && newState.member.id === newState.guild.members.me.id) {
|
|
1810
|
+
if (newState.serverMute != null && oldState.serverMute !== newState.serverMute) {
|
|
1811
|
+
queue.setPaused(newState.serverMute);
|
|
1812
|
+
} else if (newState.channel?.type === ChannelType2.GuildStageVoice && newState.suppress != null && oldState.suppress !== newState.suppress) {
|
|
1813
|
+
queue.setPaused(newState.suppress);
|
|
1814
|
+
if (newState.suppress) {
|
|
1815
|
+
newState.guild.members.me.voice.setRequestToSpeak(true).catch(Util.noop);
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
if (!newState.channelId && oldState.channelId === queue.connection.channel.id) {
|
|
1820
|
+
if (!Util.isVoiceEmpty(queue.connection.channel))
|
|
1821
|
+
return;
|
|
1822
|
+
const timeout = setTimeout(() => {
|
|
1823
|
+
if (!Util.isVoiceEmpty(queue.connection.channel))
|
|
1824
|
+
return;
|
|
1825
|
+
if (!this.queues.has(queue.guild.id))
|
|
1826
|
+
return;
|
|
1827
|
+
if (queue.options.leaveOnEmpty)
|
|
1828
|
+
queue.destroy(true);
|
|
1829
|
+
this.emit("channelEmpty", queue);
|
|
1830
|
+
}, queue.options.leaveOnEmptyCooldown || 0).unref();
|
|
1831
|
+
queue._cooldownsTimeout.set(`empty_${oldState.guild.id}`, timeout);
|
|
1832
|
+
}
|
|
1833
|
+
if (newState.channelId && newState.channelId === queue.connection.channel.id) {
|
|
1834
|
+
const emptyTimeout = queue._cooldownsTimeout.get(`empty_${oldState.guild.id}`);
|
|
1835
|
+
const channelEmpty = Util.isVoiceEmpty(queue.connection.channel);
|
|
1836
|
+
if (!channelEmpty && emptyTimeout) {
|
|
1837
|
+
clearTimeout(emptyTimeout);
|
|
1838
|
+
queue._cooldownsTimeout.delete(`empty_${oldState.guild.id}`);
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
if (oldState.channelId && newState.channelId && oldState.channelId !== newState.channelId) {
|
|
1842
|
+
if (newState.member.id === newState.guild.members.me.id) {
|
|
1843
|
+
if (queue.connection && newState.member.id === newState.guild.members.me.id)
|
|
1844
|
+
queue.connection.channel = newState.channel;
|
|
1845
|
+
const emptyTimeout = queue._cooldownsTimeout.get(`empty_${oldState.guild.id}`);
|
|
1846
|
+
const channelEmpty = Util.isVoiceEmpty(queue.connection.channel);
|
|
1847
|
+
if (!channelEmpty && emptyTimeout) {
|
|
1848
|
+
clearTimeout(emptyTimeout);
|
|
1849
|
+
queue._cooldownsTimeout.delete(`empty_${oldState.guild.id}`);
|
|
1850
|
+
} else {
|
|
1851
|
+
const timeout = setTimeout(() => {
|
|
1852
|
+
if (queue.connection && !Util.isVoiceEmpty(queue.connection.channel))
|
|
1853
|
+
return;
|
|
1854
|
+
if (!this.queues.has(queue.guild.id))
|
|
1855
|
+
return;
|
|
1856
|
+
if (queue.options.leaveOnEmpty)
|
|
1857
|
+
queue.destroy(true);
|
|
1858
|
+
this.emit("channelEmpty", queue);
|
|
1859
|
+
}, queue.options.leaveOnEmptyCooldown || 0).unref();
|
|
1860
|
+
queue._cooldownsTimeout.set(`empty_${oldState.guild.id}`, timeout);
|
|
1861
|
+
}
|
|
1862
|
+
} else {
|
|
1863
|
+
if (newState.channelId !== queue.connection.channel.id) {
|
|
1864
|
+
if (!Util.isVoiceEmpty(queue.connection.channel))
|
|
1865
|
+
return;
|
|
1866
|
+
if (queue._cooldownsTimeout.has(`empty_${oldState.guild.id}`))
|
|
1867
|
+
return;
|
|
1868
|
+
const timeout = setTimeout(() => {
|
|
1869
|
+
if (!Util.isVoiceEmpty(queue.connection.channel))
|
|
1870
|
+
return;
|
|
1871
|
+
if (!this.queues.has(queue.guild.id))
|
|
1872
|
+
return;
|
|
1873
|
+
if (queue.options.leaveOnEmpty)
|
|
1874
|
+
queue.destroy(true);
|
|
1875
|
+
this.emit("channelEmpty", queue);
|
|
1876
|
+
}, queue.options.leaveOnEmptyCooldown || 0).unref();
|
|
1877
|
+
queue._cooldownsTimeout.set(`empty_${oldState.guild.id}`, timeout);
|
|
1878
|
+
} else {
|
|
1879
|
+
const emptyTimeout = queue._cooldownsTimeout.get(`empty_${oldState.guild.id}`);
|
|
1880
|
+
const channelEmpty = Util.isVoiceEmpty(queue.connection.channel);
|
|
1881
|
+
if (!channelEmpty && emptyTimeout) {
|
|
1882
|
+
clearTimeout(emptyTimeout);
|
|
1883
|
+
queue._cooldownsTimeout.delete(`empty_${oldState.guild.id}`);
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
createQueue(guild, queueInitOptions = {}) {
|
|
1890
|
+
guild = this.client.guilds.resolve(guild);
|
|
1891
|
+
if (!guild)
|
|
1892
|
+
throw new PlayerError("Unknown Guild", "UnknownGuild" /* UNKNOWN_GUILD */);
|
|
1893
|
+
if (this.queues.has(guild.id))
|
|
1894
|
+
return this.queues.get(guild.id);
|
|
1895
|
+
const _meta = queueInitOptions.metadata;
|
|
1896
|
+
delete queueInitOptions["metadata"];
|
|
1897
|
+
queueInitOptions.volumeSmoothness ?? (queueInitOptions.volumeSmoothness = this.options.smoothVolume ? 0.08 : 0);
|
|
1898
|
+
queueInitOptions.ytdlOptions ?? (queueInitOptions.ytdlOptions = this.options.ytdlOptions);
|
|
1899
|
+
const queue = new Queue(this, guild, queueInitOptions);
|
|
1900
|
+
queue.metadata = _meta;
|
|
1901
|
+
this.queues.set(guild.id, queue);
|
|
1902
|
+
return queue;
|
|
1903
|
+
}
|
|
1904
|
+
getQueue(guild) {
|
|
1905
|
+
guild = this.client.guilds.resolve(guild);
|
|
1906
|
+
if (!guild)
|
|
1907
|
+
throw new PlayerError("Unknown Guild", "UnknownGuild" /* UNKNOWN_GUILD */);
|
|
1908
|
+
return this.queues.get(guild.id);
|
|
1909
|
+
}
|
|
1910
|
+
deleteQueue(guild) {
|
|
1911
|
+
guild = this.client.guilds.resolve(guild);
|
|
1912
|
+
if (!guild)
|
|
1913
|
+
throw new PlayerError("Unknown Guild", "UnknownGuild" /* UNKNOWN_GUILD */);
|
|
1914
|
+
const prev = this.getQueue(guild);
|
|
1915
|
+
try {
|
|
1916
|
+
prev.destroy();
|
|
1917
|
+
} catch {
|
|
1918
|
+
}
|
|
1919
|
+
this.queues.delete(guild.id);
|
|
1920
|
+
return prev;
|
|
1921
|
+
}
|
|
1922
|
+
async search(query, options) {
|
|
1923
|
+
if (options.requestedBy != null)
|
|
1924
|
+
options.requestedBy = this.client.users.resolve(options.requestedBy);
|
|
1925
|
+
if (query instanceof Track_default)
|
|
1926
|
+
return new SearchResult(this, {
|
|
1927
|
+
playlist: query.playlist || null,
|
|
1928
|
+
tracks: [query],
|
|
1929
|
+
query: query.toString(),
|
|
1930
|
+
extractor: null,
|
|
1931
|
+
queryType: QueryType.AUTO,
|
|
1932
|
+
requestedBy: options.requestedBy
|
|
1933
|
+
});
|
|
1934
|
+
if (!options)
|
|
1935
|
+
throw new PlayerError("DiscordPlayer#search needs search options!", "InvalidArgType" /* INVALID_ARG_TYPE */);
|
|
1936
|
+
let extractor = null;
|
|
1937
|
+
options.searchEngine ?? (options.searchEngine = QueryType.AUTO);
|
|
1938
|
+
const queryType = options.searchEngine === QueryType.AUTO ? QueryResolver.resolve(query) : options.searchEngine;
|
|
1939
|
+
if (options.searchEngine.startsWith("ext:")) {
|
|
1940
|
+
extractor = this.extractors.get(options.searchEngine.substring(4));
|
|
1941
|
+
if (!extractor)
|
|
1942
|
+
return new SearchResult(this, { query, queryType });
|
|
1943
|
+
}
|
|
1944
|
+
if (!extractor) {
|
|
1945
|
+
extractor = (await this.extractors.run((ext) => ext.validate(query, queryType)))?.extractor || null;
|
|
1946
|
+
}
|
|
1947
|
+
if (!extractor) {
|
|
1948
|
+
return new SearchResult(this, { query, queryType });
|
|
1949
|
+
}
|
|
1950
|
+
const res = await extractor.handle(query, {
|
|
1951
|
+
type: queryType,
|
|
1952
|
+
requestedBy: options.requestedBy
|
|
1953
|
+
}).catch(() => null);
|
|
1954
|
+
if (res) {
|
|
1955
|
+
return new SearchResult(this, {
|
|
1956
|
+
query,
|
|
1957
|
+
queryType,
|
|
1958
|
+
playlist: res.playlist,
|
|
1959
|
+
tracks: res.tracks,
|
|
1960
|
+
extractor
|
|
1961
|
+
});
|
|
1962
|
+
}
|
|
1963
|
+
const result = await this.extractors.run(
|
|
1964
|
+
async (ext) => await ext.validate(query) && ext.handle(query, {
|
|
1965
|
+
type: queryType,
|
|
1966
|
+
requestedBy: options.requestedBy
|
|
1967
|
+
})
|
|
1968
|
+
);
|
|
1969
|
+
if (!result?.result)
|
|
1970
|
+
return new SearchResult(this, { query, queryType });
|
|
1971
|
+
return new SearchResult(this, {
|
|
1972
|
+
query,
|
|
1973
|
+
queryType,
|
|
1974
|
+
playlist: result.result.playlist,
|
|
1975
|
+
tracks: result.result.tracks,
|
|
1976
|
+
extractor: result.extractor
|
|
1977
|
+
});
|
|
1978
|
+
}
|
|
1979
|
+
scanDeps() {
|
|
1980
|
+
const line = "-".repeat(50);
|
|
1981
|
+
const depsReport = generateDependencyReport();
|
|
1982
|
+
const extractorReport = this.extractors.store.map((m) => {
|
|
1983
|
+
return m.identifier;
|
|
1984
|
+
}).join("\n");
|
|
1985
|
+
return `${depsReport}
|
|
1986
|
+
${line}
|
|
1987
|
+
Loaded Extractors:
|
|
1988
|
+
${extractorReport || "None"}`;
|
|
1989
|
+
}
|
|
1990
|
+
emit(eventName, ...args) {
|
|
1991
|
+
if (this.requiredEvents.includes(eventName) && !super.eventNames().includes(eventName)) {
|
|
1992
|
+
console.error(...args);
|
|
1993
|
+
process.emitWarning(`[DiscordPlayerWarning] Unhandled "${eventName}" event! Events ${this.requiredEvents.map((m) => `"${m}"`).join(", ")} must have event listeners!`);
|
|
1994
|
+
return false;
|
|
1995
|
+
} else {
|
|
1996
|
+
return super.emit(eventName, ...args);
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
resolveQueue(queueLike) {
|
|
2000
|
+
return this.getQueue(queueLike instanceof Queue ? queueLike.guild : queueLike);
|
|
2001
|
+
}
|
|
2002
|
+
*[Symbol.iterator]() {
|
|
2003
|
+
yield* Array.from(this.queues.values());
|
|
2004
|
+
}
|
|
2005
|
+
createPlaylist(data) {
|
|
2006
|
+
return new Playlist(this, data);
|
|
2007
|
+
}
|
|
2008
|
+
};
|
|
2009
|
+
__name(Player, "Player");
|
|
2010
|
+
_lastLatency = new WeakMap();
|
|
2011
|
+
|
|
2012
|
+
// src/index.ts
|
|
2013
|
+
var version = "5.4.1-dev.0";
|
|
2014
|
+
if (!djsVersion.startsWith("14")) {
|
|
2015
|
+
process.emitWarning(`Discord.js v${djsVersion} is incompatible with Discord Player v${version}! Please use >=v14.x of Discord.js`);
|
|
2016
|
+
}
|
|
2017
|
+
export {
|
|
2018
|
+
AudioFilters,
|
|
2019
|
+
BaseExtractor,
|
|
2020
|
+
ErrorStatusCode,
|
|
2021
|
+
ExtractorExecutionContext,
|
|
2022
|
+
FFMPEG_ARGS_PIPED,
|
|
2023
|
+
FFMPEG_ARGS_STRING,
|
|
2024
|
+
Player,
|
|
2025
|
+
PlayerError,
|
|
2026
|
+
Playlist,
|
|
2027
|
+
QueryResolver,
|
|
2028
|
+
QueryType,
|
|
2029
|
+
Queue,
|
|
2030
|
+
QueueRepeatMode,
|
|
2031
|
+
StreamDispatcher,
|
|
2032
|
+
Track,
|
|
2033
|
+
Util,
|
|
2034
|
+
VoiceUtils,
|
|
2035
|
+
VolumeTransformer,
|
|
2036
|
+
createFFmpegStream,
|
|
2037
|
+
version
|
|
2038
|
+
};
|
|
2039
|
+
//# sourceMappingURL=index.mjs.map
|