discord-player
Version:
Complete framework to facilitate music commands using discord.js
1,524 lines (1,509 loc) • 736 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __typeError = (msg) => {
throw TypeError(msg);
};
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
// src/index.ts
var src_exports = {};
__export(src_exports, {
AF_NIGHTCORE_RATE: () => import_equalizer3.AF_NIGHTCORE_RATE,
AF_VAPORWAVE_RATE: () => import_equalizer3.AF_VAPORWAVE_RATE,
AFilterGraph: () => AFilterGraph,
AsyncQueue: () => AsyncQueue,
AsyncQueueEntry: () => AsyncQueueEntry,
AudioFilters: () => AudioFilters,
AudioPlayer: () => import_discord_voip6.AudioPlayer,
BASS_EQ_BANDS: () => import_equalizer3.BASS_EQ_BANDS,
BaseExtractor: () => BaseExtractor,
BiquadFilterType: () => import_equalizer3.FilterType,
Context: () => Context,
DependencyReportGenerator: () => DependencyReportGenerator,
DiscordPlayerQueryResultCache: () => DiscordPlayerQueryResultCache,
EqualizerConfigurationPreset: () => EqualizerConfigurationPreset,
ExtractorExecutionContext: () => ExtractorExecutionContext,
FFMPEG_ARGS_PIPED: () => FFMPEG_ARGS_PIPED,
FFMPEG_ARGS_STRING: () => FFMPEG_ARGS_STRING,
FFMPEG_SRATE_REGEX: () => FFMPEG_SRATE_REGEX,
FFmpegFilterer: () => FFmpegFilterer,
FiltersChain: () => import_equalizer3.FiltersChain,
GuildNodeManager: () => GuildNodeManager,
GuildQueue: () => GuildQueue5,
GuildQueueAudioFilters: () => GuildQueueAudioFilters,
GuildQueueEvent: () => GuildQueueEvent,
GuildQueueHistory: () => GuildQueueHistory,
GuildQueuePlayerNode: () => GuildQueuePlayerNode,
GuildQueueStatistics: () => GuildQueueStatistics,
InterceptedStream: () => InterceptedStream,
LrcLib: () => LrcLib,
PCMAudioFilters: () => import_equalizer3.AudioFilters,
Player: () => Player,
PlayerEvent: () => PlayerEvent,
PlayerEventsEmitter: () => PlayerEventsEmitter,
PlayerStreamInterceptor: () => PlayerStreamInterceptor,
Playlist: () => Playlist,
Q_BUTTERWORTH: () => import_equalizer3.Q_BUTTERWORTH,
QueryCache: () => QueryCache,
QueryResolver: () => QueryResolver,
QueryType: () => QueryType,
QueueRepeatMode: () => QueueRepeatMode,
SearchResult: () => SearchResult,
SequentialBucket: () => SequentialBucket,
SerializedType: () => SerializedType,
StreamDispatcher: () => StreamDispatcher,
StreamType: () => import_discord_voip6.StreamType,
Track: () => Track,
TrackSkipReason: () => TrackSkipReason,
TypeUtil: () => TypeUtil,
Util: () => Util,
VALIDATE_QUEUE_CAP: () => VALIDATE_QUEUE_CAP,
VoiceUtils: () => VoiceUtils,
VolumeTransformer: () => import_equalizer3.VolumeTransformer,
createAudioPlayer: () => import_discord_voip6.createAudioPlayer,
createAudioResource: () => import_discord_voip6.createAudioResource,
createContext: () => createContext,
createErisCompat: () => createErisCompat,
createFFmpegStream: () => createFFmpegStream,
decode: () => decode,
deserialize: () => deserialize,
encode: () => encode,
getVoiceConnection: () => import_discord_voip6.getVoiceConnection,
getVoiceConnections: () => import_discord_voip6.getVoiceConnections,
isErisProxy: () => isErisProxy,
joinVoiceChannel: () => import_discord_voip6.joinVoiceChannel,
onAfterCreateStream: () => onAfterCreateStream,
onBeforeCreateStream: () => onBeforeCreateStream,
serialize: () => serialize,
tryIntoThumbnailString: () => tryIntoThumbnailString,
useContext: () => useContext,
useHistory: () => useHistory,
useMainPlayer: () => useMainPlayer,
useMetadata: () => useMetadata,
usePlayer: () => usePlayer,
useQueue: () => useQueue,
useTimeline: () => useTimeline,
useVolume: () => useVolume,
version: () => version
});
module.exports = __toCommonJS(src_exports);
// src/compat/createErisCompat.ts
var import_v10 = require("discord-api-types/v10");
// src/utils/Util.ts
var import_promises = require("timers/promises");
// src/fabric/Track.ts
var import_discord = require("discord.js");
// src/errors/index.ts
var _DiscordPlayerError = class _DiscordPlayerError extends Error {
constructor(code, message) {
super(message);
__publicField(this, "code");
__publicField(this, "timestamp", Date.now());
this.name = this.constructor.name;
this.code = code;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
}
toJSON() {
return {
name: this.constructor.name,
code: this.code,
message: this.message,
timestamp: this.timestamp
};
}
};
__name(_DiscordPlayerError, "DiscordPlayerError");
var DiscordPlayerError = _DiscordPlayerError;
var _OutOfSpaceError = class _OutOfSpaceError extends DiscordPlayerError {
constructor(target, capacity, total) {
super(
ErrorCodes.ERR_OUT_OF_SPACE,
`Max capacity reached for ${target} (Capacity ${capacity}/Total ${total})`
);
}
};
__name(_OutOfSpaceError, "OutOfSpaceError");
var OutOfSpaceError = _OutOfSpaceError;
var _InvalidArgTypeError = class _InvalidArgTypeError extends DiscordPlayerError {
constructor(target, expectation, found) {
super(
ErrorCodes.ERR_INVALID_ARG_TYPE,
`Expected ${target} to be "${expectation}", received "${found}"`
);
}
};
__name(_InvalidArgTypeError, "InvalidArgTypeError");
var InvalidArgTypeError = _InvalidArgTypeError;
var _NoResultError = class _NoResultError extends DiscordPlayerError {
constructor(message) {
super(ErrorCodes.ERR_NO_RESULT, message);
}
};
__name(_NoResultError, "NoResultError");
var NoResultError = _NoResultError;
var _NotImplementedError = class _NotImplementedError extends DiscordPlayerError {
constructor(target) {
super(ErrorCodes.ERR_NOT_IMPLEMENTED, `${target} is not yet implemented`);
}
};
__name(_NotImplementedError, "NotImplementedError");
var NotImplementedError = _NotImplementedError;
var _NotExistingError = class _NotExistingError extends DiscordPlayerError {
constructor(target) {
super(ErrorCodes.ERR_NOT_EXISTING, `${target} does not exist`);
}
};
__name(_NotExistingError, "NotExistingError");
var NotExistingError = _NotExistingError;
var _OutOfRangeError = class _OutOfRangeError extends DiscordPlayerError {
constructor(target, value, minimum, maximum) {
super(
ErrorCodes.ERR_OUT_OF_RANGE,
`${target} is out of range (Expected minimum ${minimum} and maximum ${maximum}, got ${value})`
);
}
};
__name(_OutOfRangeError, "OutOfRangeError");
var OutOfRangeError = _OutOfRangeError;
var _NoVoiceConnectionError = class _NoVoiceConnectionError extends DiscordPlayerError {
constructor(message) {
super(
ErrorCodes.ERR_NO_VOICE_CONNECTION,
message || "No voice connection available, maybe connect to a voice channel first?"
);
}
};
__name(_NoVoiceConnectionError, "NoVoiceConnectionError");
var NoVoiceConnectionError = _NoVoiceConnectionError;
var _VoiceConnectionDestroyedError = class _VoiceConnectionDestroyedError extends DiscordPlayerError {
constructor() {
super(
ErrorCodes.ERR_VOICE_CONNECTION_DESTROYED,
"Cannot use destroyed voice connection"
);
}
};
__name(_VoiceConnectionDestroyedError, "VoiceConnectionDestroyedError");
var VoiceConnectionDestroyedError = _VoiceConnectionDestroyedError;
var _NoVoiceChannelError = class _NoVoiceChannelError extends DiscordPlayerError {
constructor() {
super(ErrorCodes.ERR_NO_VOICE_CHANNEL, "Could not get the voice channel");
}
};
__name(_NoVoiceChannelError, "NoVoiceChannelError");
var NoVoiceChannelError = _NoVoiceChannelError;
var _NoAudioResourceError = class _NoAudioResourceError extends DiscordPlayerError {
constructor(message) {
super(
ErrorCodes.ERR_NO_AUDIO_RESOURCE,
message || "Expected an audio resource"
);
}
};
__name(_NoAudioResourceError, "NoAudioResourceError");
var NoAudioResourceError = _NoAudioResourceError;
var _NoGuildQueueError = class _NoGuildQueueError extends DiscordPlayerError {
constructor(message) {
super(ErrorCodes.ERR_NO_GUILD_QUEUE, message || "Expected a guild queue");
}
};
__name(_NoGuildQueueError, "NoGuildQueueError");
var NoGuildQueueError = _NoGuildQueueError;
var _NoGuildError = class _NoGuildError extends DiscordPlayerError {
constructor(message) {
super(ErrorCodes.ERR_NO_GUILD, message || "Expected a guild");
}
};
__name(_NoGuildError, "NoGuildError");
var NoGuildError = _NoGuildError;
var _InfoRequiredError = class _InfoRequiredError extends DiscordPlayerError {
constructor(target, actual) {
super(
ErrorCodes.ERR_INFO_REQUIRED,
`Expected ${target}, found "${actual}"`
);
}
};
__name(_InfoRequiredError, "InfoRequiredError");
var InfoRequiredError = _InfoRequiredError;
var _SerializationError = class _SerializationError extends DiscordPlayerError {
constructor() {
super(
ErrorCodes.ERR_SERIALIZATION_FAILED,
"Don't know how to serialize this data"
);
}
};
__name(_SerializationError, "SerializationError");
var SerializationError = _SerializationError;
var _DeserializationError = class _DeserializationError extends DiscordPlayerError {
constructor() {
super(
ErrorCodes.ERR_DESERIALIZATION_FAILED,
"Don't know how to deserialize this data"
);
}
};
__name(_DeserializationError, "DeserializationError");
var DeserializationError = _DeserializationError;
var _IllegalHookInvocationError = class _IllegalHookInvocationError extends DiscordPlayerError {
constructor(target, message) {
super(
ErrorCodes.ERR_ILLEGAL_HOOK_INVOCATION,
`Illegal invocation of ${target} hook.${message ? ` ${message}` : ""}`
);
}
};
__name(_IllegalHookInvocationError, "IllegalHookInvocationError");
var IllegalHookInvocationError = _IllegalHookInvocationError;
var _BridgeFailedError = class _BridgeFailedError extends DiscordPlayerError {
constructor(id, error) {
super(
ErrorCodes.ERR_BRIDGE_FAILED,
`${id ? `(Extractor Execution Context ID is ${id})` : ""}Failed to bridge this query:
${error}`
);
}
};
__name(_BridgeFailedError, "BridgeFailedError");
var BridgeFailedError = _BridgeFailedError;
var ErrorCodes = {
ERR_OUT_OF_SPACE: "ERR_OUT_OF_SPACE",
ERR_INVALID_ARG_TYPE: "ERR_INVALID_ARG_TYPE",
ERR_NO_RESULT: "ERR_NO_RESULT",
ERR_NOT_IMPLEMENTED: "ERR_NOT_IMPLEMENTED",
ERR_NOT_EXISTING: "ERR_NOT_EXISTING",
ERR_OUT_OF_RANGE: "ERR_OUT_OF_RANGE",
ERR_NO_VOICE_CONNECTION: "ERR_NO_VOICE_CONNECTION",
ERR_VOICE_CONNECTION_DESTROYED: "ERR_VOICE_CONNECTION_DESTROYED",
ERR_NO_VOICE_CHANNEL: "ERR_NO_VOICE_CHANNEL",
ERR_INVALID_VOICE_CHANNEL: "ERR_INVALID_VOICE_CHANNEL",
ERR_NO_RECEIVER: "ERR_NO_RECEIVER",
ERR_FFMPEG_LOCATOR: "ERR_FFMPEG_LOCATOR",
ERR_NO_AUDIO_RESOURCE: "ERR_NO_AUDIO_RESOURCE",
ERR_NO_GUILD_QUEUE: "ERR_NO_GUILD_QUEUE",
ERR_NO_GUILD: "ERR_NO_GUILD",
ERR_INFO_REQUIRED: "ERR_INFO_REQUIRED",
ERR_SERIALIZATION_FAILED: "ERR_SERIALIZATION_FAILED",
ERR_DESERIALIZATION_FAILED: "ERR_DESERIALIZATION_FAILED",
ERR_ILLEGAL_HOOK_INVOCATION: "ERR_ILLEGAL_HOOK_INVOCATION",
ERR_NOT_EXISTING_MODULE: "ERR_NOT_EXISTING_MODULE",
ERR_BRIDGE_FAILED: "ERR_BRIDGE_FAILED"
};
function isDiscordPlayerError(error) {
return error != null && error instanceof DiscordPlayerError;
}
__name(isDiscordPlayerError, "isDiscordPlayerError");
// src/utils/TypeUtil.ts
var _TypeUtil = class _TypeUtil {
constructor() {
return _TypeUtil;
}
// eslint-disable-next-line @typescript-eslint/ban-types
static isFunction(t) {
return typeof t === "function";
}
static isNumber(t) {
return typeof t === "number" && !isNaN(t);
}
static isString(t) {
return typeof t === "string";
}
static isBoolean(t) {
return typeof t === "boolean";
}
static isNullish(t) {
return t == null;
}
static isArray(t) {
return Array.isArray(t);
}
static isError(t) {
return t instanceof Error;
}
static isDiscordPlayerError(t) {
return isDiscordPlayerError(t);
}
};
__name(_TypeUtil, "TypeUtil");
var TypeUtil = _TypeUtil;
// src/utils/serde.ts
var import_buffer = require("buffer");
var SerializedType = /* @__PURE__ */ ((SerializedType2) => {
SerializedType2["Track"] = "track";
SerializedType2["Playlist"] = "playlist";
return SerializedType2;
})(SerializedType || {});
var isTrack = /* @__PURE__ */ __name((data) => data.$type === "track" /* Track */, "isTrack");
var isPlaylist = /* @__PURE__ */ __name((data) => data.$type === "playlist" /* Playlist */, "isPlaylist");
function serialize(data) {
if (data instanceof Track) return data.serialize();
if (data instanceof Playlist) return data.serialize();
try {
return data.toJSON();
} catch {
throw new SerializationError();
}
}
__name(serialize, "serialize");
function deserialize(player, data) {
if (isTrack(data)) return Track.fromSerialized(player, data);
if (isPlaylist(data)) return Playlist.fromSerialized(player, data);
throw new DeserializationError();
}
__name(deserialize, "deserialize");
function encode(data) {
const str = JSON.stringify(data);
return import_buffer.Buffer.from(str).toString("base64");
}
__name(encode, "encode");
function decode(data) {
const str = import_buffer.Buffer.from(data, "base64").toString();
return JSON.parse(str);
}
__name(decode, "decode");
function tryIntoThumbnailString(data) {
if (!data) return null;
try {
if (TypeUtil.isString(data)) return data;
return data?.url ?? data?.thumbnail?.url ?? null;
} catch {
return null;
}
}
__name(tryIntoThumbnailString, "tryIntoThumbnailString");
// src/fabric/Track.ts
var _resource;
var _Track = class _Track {
/**
* Track constructor
* @param player The player that instantiated this Track
* @param data Track data
*/
constructor(player, data) {
this.player = player;
__publicField(this, "title");
__publicField(this, "description");
__publicField(this, "author");
__publicField(this, "url");
__publicField(this, "thumbnail");
__publicField(this, "duration");
__publicField(this, "views");
__publicField(this, "requestedBy", null);
__publicField(this, "playlist");
__publicField(this, "queryType", null);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
__publicField(this, "raw");
__publicField(this, "extractor", null);
__publicField(this, "id", import_discord.SnowflakeUtil.generate().toString());
__publicField(this, "__metadata", null);
__publicField(this, "__reqMetadataFn");
__publicField(this, "cleanTitle");
__publicField(this, "live", false);
__publicField(this, "bridgedExtractor", null);
__publicField(this, "bridgedTrack", null);
__privateAdd(this, _resource, null);
this.title = (0, import_discord.escapeMarkdown)(data.title ?? "");
this.author = data.author ?? "";
this.url = data.url ?? "";
this.thumbnail = data.thumbnail ?? "";
this.duration = data.duration ?? "";
this.views = data.views ?? 0;
this.queryType = data.queryType;
this.requestedBy = data.requestedBy || null;
this.playlist = data.playlist;
this.description = `${this.title} by ${this.author}`;
this.raw = Object.assign(
{},
{ source: data.raw?.source ?? data.source },
data.raw ?? data
);
this.__metadata = data.metadata ?? null;
this.__reqMetadataFn = data.requestMetadata || (() => Promise.resolve(null));
this.cleanTitle = data.cleanTitle ?? Util.cleanTitle(this.title, this.source);
this.live = data.live ?? false;
}
/**
* Sets audio resource for this track. This is not useful outside of the library.
* @param resource Audio resource
*/
setResource(resource) {
__privateSet(this, _resource, resource);
}
/**
* Gets audio resource for this track
*/
get resource() {
return __privateGet(this, _resource);
}
/**
* Whether this track has an audio resource
*/
get hasResource() {
return __privateGet(this, _resource) != null;
}
/**
* Request metadata for this track
*/
async requestMetadata() {
const res = await this.__reqMetadataFn();
this.setMetadata(res);
return res;
}
/**
* Set metadata for this track
*/
setMetadata(m) {
this.__metadata = m;
}
/**
* Metadata of this track
*/
get metadata() {
return this.__metadata;
}
/**
* If this track has metadata
*/
get hasMetadata() {
return this.metadata != null;
}
/**
* The queue in which this track is located
*/
get queue() {
return this.player.nodes.cache.find(
(q) => q.tracks.some((ab) => ab.id === this.id)
);
}
/**
* The track duration in millisecond
*/
get durationMS() {
const times = /* @__PURE__ */ __name((n, t) => {
let tn = 1;
for (let i = 0; i < t; i++) tn *= n;
return t <= 0 ? 1e3 : tn * 1e3;
}, "times");
return this.duration.split(":").reverse().map((m, i) => parseInt(m) * times(60, i)).reduce((a, c) => a + c, 0);
}
/**
* Discord hyperlink representation of this track
*/
toHyperlink() {
return `[${this.title}](${this.url})`;
}
/**
* Returns source of this track
*/
get source() {
return this.raw?.source ?? "arbitrary";
}
/**
* String representation of this track
*/
toString() {
return `${this.title} by ${this.author}`;
}
/**
* Raw JSON representation of this track
*/
toJSON(hidePlaylist) {
return {
id: this.id,
title: this.title,
description: this.description,
author: this.author,
url: this.url,
thumbnail: this.thumbnail,
duration: this.duration,
durationMS: this.durationMS,
views: this.views,
requestedBy: this.requestedBy?.id || null,
playlist: hidePlaylist ? null : this.playlist?.toJSON() ?? null
};
}
/**
* Serialized track data that can be reconstructed
*/
serialize() {
return {
title: this.title,
description: this.description,
author: this.author,
url: this.url,
thumbnail: TypeUtil.isString(this.thumbnail) ? this.thumbnail : tryIntoThumbnailString(this.thumbnail),
duration: this.duration,
views: this.views ?? 0,
requested_by: this.requestedBy?.toJSON() ?? null,
source: this.source,
live: false,
query_type: this.queryType,
extractor: this.extractor?.identifier ?? null,
metadata: this.metadata,
$type: "track" /* Track */,
$encoder_version: this.player.version
};
}
/**
* Construct a track from serialized data
* @param player Player instance
* @param data Serialized data
*/
static fromSerialized(player, data) {
if (data.$type !== "track" /* Track */)
throw new InvalidArgTypeError(
"data",
"SerializedTrack",
"malformed data"
);
const track = new _Track(player, {
...data,
requestedBy: data.requested_by ? (() => {
const res = data.requested_by;
try {
const resolved = player.client.users.resolve(res.id);
if (resolved) return resolved;
if (player.client.users.cache.has(res.id))
return player.client.users.cache.get(res.id);
const user = new import_discord.User(player.client, res);
return user;
} catch {
return null;
}
})() : null,
queryType: data.query_type ?? void 0
});
track.setMetadata(data.metadata);
return track;
}
/**
* Get belonging queues of this track
*/
getBelongingQueues() {
const nodes = this.player.nodes.cache.filter(
(node) => node.tracks.some((t) => t.id === this.id)
);
return nodes;
}
/**
* Play this track to the given voice channel. If queue exists and another track is being played, this track will be added to the queue.
* @param channel Voice channel on which this track shall be played
* @param options Node initialization options
*/
async play(channel, options) {
const fn = this.player.play.bind(this.player);
return await fn(channel, this, options);
}
};
_resource = new WeakMap();
__name(_Track, "Track");
var Track = _Track;
// src/fabric/Playlist.ts
var _Playlist = class _Playlist {
// eslint-disable-line @typescript-eslint/no-explicit-any
/**
* Playlist constructor
* @param {Player} player The player
* @param {PlaylistInitData} data The data
*/
constructor(player, data) {
__publicField(this, "player");
__publicField(this, "tracks");
__publicField(this, "title");
__publicField(this, "description");
__publicField(this, "thumbnail");
__publicField(this, "type");
__publicField(this, "source");
__publicField(this, "author");
__publicField(this, "id");
__publicField(this, "url");
__publicField(this, "rawPlaylist");
this.player = player;
this.tracks = data.tracks ?? [];
this.author = data.author;
this.description = data.description;
this.thumbnail = data.thumbnail;
this.type = data.type;
this.source = data.source;
this.id = data.id;
this.url = data.url;
this.title = data.title;
}
*[Symbol.iterator]() {
yield* this.tracks;
}
/**
* Estimated duration of this playlist
*/
get estimatedDuration() {
return this.tracks.reduce((p, c) => p + c.durationMS, 0);
}
/**
* Formatted estimated duration of this playlist
*/
get durationFormatted() {
return Util.buildTimeCode(Util.parseMS(this.estimatedDuration));
}
/**
* JSON representation of this playlist
* @param {boolean} [withTracks=true] If it should build json with tracks
* @returns {PlaylistJSON}
*/
toJSON(withTracks = true) {
const payload = {
id: this.id,
url: this.url,
title: this.title,
description: this.description,
thumbnail: this.thumbnail,
type: this.type,
source: this.source,
author: this.author,
tracks: []
};
if (withTracks) payload.tracks = this.tracks.map((m) => m.toJSON(true));
return payload;
}
/**
* Serialize this playlist into reconstructable data
*/
serialize() {
return {
tracks: this.tracks.map((m) => m.serialize()),
title: this.title,
description: this.description,
thumbnail: TypeUtil.isString(this.thumbnail) ? this.thumbnail : tryIntoThumbnailString(this.thumbnail),
type: this.type,
source: this.source,
author: this.author,
id: this.id,
url: this.url,
$type: "playlist" /* Playlist */,
$encoder_version: this.player.version
};
}
/**
* Deserialize this playlist from serialized data
* @param player Player instance
* @param data Serialized data
*/
static fromSerialized(player, data) {
if (data.$type !== "playlist" /* Playlist */)
throw new InvalidArgTypeError(
"data",
"SerializedPlaylist",
"malformed data"
);
return new _Playlist(player, {
...data,
tracks: data.tracks.map((m) => Track.fromSerialized(player, m))
});
}
/**
* Play this playlist to the given voice channel. If queue exists and another track is being played, this playlist will be added to the queue.
* @param channel Voice channel on which this playlist shall be played
* @param options Node initialization options
*/
async play(channel, options) {
const fn = this.player.play.bind(this.player);
return await fn(channel, this, options);
}
};
__name(_Playlist, "Playlist");
var Playlist = _Playlist;
// src/utils/QueryResolver.ts
var import_undici = require("undici");
var spotifySongRegex = /^https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(intl-([a-z]|[A-Z])+\/)?(?:track\/|\?uri=spotify:track:)((\w|-){22})(\?si=.+)?$/;
var spotifyPlaylistRegex = /^https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(intl-([a-z]|[A-Z])+\/)?(?:playlist\/|\?uri=spotify:playlist:)((\w|-){22})(\?si=.+)?$/;
var spotifyAlbumRegex = /^https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(intl-([a-z]|[A-Z])+\/)?(?:album\/|\?uri=spotify:album:)((\w|-){22})(\?si=.+)?$/;
var vimeoRegex = /^(http|https)?:\/\/(www\.|player\.)?vimeo\.com\/(?:channels\/(?:\w+\/)?|groups\/([^/]*)\/videos\/|video\/|)(\d+)(?:|\/\?)$/;
var reverbnationRegex = /^https:\/\/(www.)?reverbnation.com\/(.+)\/song\/(.+)$/;
var attachmentRegex = /^https?:\/\/.+$/;
var appleMusicSongRegex = /^https?:\/\/music\.apple\.com\/.+?\/(song|album)\/.+?(\/.+?\?i=|\/)([0-9]+)$/;
var appleMusicPlaylistRegex = /^https?:\/\/music\.apple\.com\/.+?\/playlist\/.+\/pl\.(u-|pm-)?[a-zA-Z0-9]+$/;
var appleMusicAlbumRegex = /^https?:\/\/music\.apple\.com\/.+?\/album\/.+\/([0-9]+)$/;
var soundcloudTrackRegex = /^https?:\/\/(m.|www.)?soundcloud.com\/(\w|-)+\/(\w|-)+(.+)?$/;
var soundcloudPlaylistRegex = /^https?:\/\/(m.|www.)?soundcloud.com\/(\w|-)+\/sets\/(\w|-)+(.+)?$/;
var youtubePlaylistRegex = /^https?:\/\/(www.)?youtube.com\/playlist\?list=((PL|FL|UU|LL|RD|OL)[a-zA-Z0-9-_]{16,41})$/;
var youtubeVideoURLRegex = /^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w-]+\?v=|embed\/|v\/)?)([\w-]+)(\S+)?$/;
var youtubeVideoIdRegex = /^[a-zA-Z0-9-_]{11}$/;
var discordPlayerBlobRegex = /^discord-player:\/\/blob\/\d+$/;
var DomainsMap = {
DiscordPlayer: ["discord-player"],
YouTube: [
"youtube.com",
"youtu.be",
"music.youtube.com",
"gaming.youtube.com",
"www.youtube.com",
"m.youtube.com"
],
Spotify: ["open.spotify.com", "embed.spotify.com"],
Vimeo: ["vimeo.com", "player.vimeo.com"],
ReverbNation: ["reverbnation.com"],
SoundCloud: ["soundcloud.com"],
AppleMusic: ["music.apple.com"]
};
var redirectDomains = /* @__PURE__ */ new Set(
[
/^https?:\/\/spotify.link\/[A-Za-z0-9]+$/,
/^https:\/\/on\.soundcloud\.com\/[a-zA-Z1-9]{0,17}$/
]
);
var QueryType = {
AUTO: "auto",
YOUTUBE: "youtube",
YOUTUBE_PLAYLIST: "youtubePlaylist",
SOUNDCLOUD_TRACK: "soundcloudTrack",
SOUNDCLOUD_PLAYLIST: "soundcloudPlaylist",
SOUNDCLOUD: "soundcloud",
SPOTIFY_SONG: "spotifySong",
SPOTIFY_ALBUM: "spotifyAlbum",
SPOTIFY_PLAYLIST: "spotifyPlaylist",
SPOTIFY_SEARCH: "spotifySearch",
FACEBOOK: "facebook",
VIMEO: "vimeo",
ARBITRARY: "arbitrary",
REVERBNATION: "reverbnation",
YOUTUBE_SEARCH: "youtubeSearch",
YOUTUBE_VIDEO: "youtubeVideo",
SOUNDCLOUD_SEARCH: "soundcloudSearch",
APPLE_MUSIC_SONG: "appleMusicSong",
APPLE_MUSIC_ALBUM: "appleMusicAlbum",
APPLE_MUSIC_PLAYLIST: "appleMusicPlaylist",
APPLE_MUSIC_SEARCH: "appleMusicSearch",
FILE: "file",
AUTO_SEARCH: "autoSearch",
DISCORD_PLAYER_BLOB: "discordPlayerBlob"
};
var _QueryResolver = class _QueryResolver {
/**
* Query resolver
*/
constructor() {
}
// eslint-disable-line @typescript-eslint/no-empty-function
static get regex() {
return {
spotifyAlbumRegex,
spotifyPlaylistRegex,
spotifySongRegex,
vimeoRegex,
reverbnationRegex,
attachmentRegex,
appleMusicAlbumRegex,
appleMusicPlaylistRegex,
appleMusicSongRegex,
soundcloudTrackRegex,
soundcloudPlaylistRegex,
youtubePlaylistRegex,
discordPlayerBlobRegex
};
}
/**
* Pre-resolve redirect urls
*/
static async preResolve(query, maxDepth = 5) {
if (!TypeUtil.isString(query))
throw new InvalidArgTypeError(query, "string", typeof query);
for (const domain of redirectDomains) {
if (domain.test(query)) {
try {
const res = await (0, import_undici.fetch)(query, {
method: "GET",
redirect: "follow"
});
if (!res.ok) break;
if (/^https?:\/\/spotify.app.link\/(.+)$/.test(res.url)) {
const body = await res.text();
const target = body.split("https://open.spotify.com/track/")[1].split("?si=")[0];
if (!target) break;
return `https://open.spotify.com/track/${target}`;
}
return maxDepth < 1 ? res.url : this.preResolve(res.url, maxDepth - 1);
} catch {
break;
}
}
}
return query;
}
/**
* Resolves the given search query
* @param {string} query The query
*/
static resolve(query, fallbackSearchEngine = QueryType.AUTO_SEARCH) {
if (!TypeUtil.isString(query))
throw new InvalidArgTypeError(query, "string", typeof query);
if (!query.length) throw new InfoRequiredError("query", String(query));
const resolver = /* @__PURE__ */ __name((type, query2) => ({
type,
query: query2
}), "resolver");
if (discordPlayerBlobRegex.test(query))
return resolver(QueryType.DISCORD_PLAYER_BLOB, query);
try {
const url = new URL(query);
if (DomainsMap.YouTube.includes(url.host)) {
query = query.replace(/(m(usic)?|gaming)\./, "").trim();
const playlistId = url.searchParams.get("list");
const videoId = url.searchParams.get("v");
if (playlistId) {
if (videoId && playlistId.startsWith("RD"))
return resolver(
QueryType.YOUTUBE_PLAYLIST,
`https://www.youtube.com/watch?v=${videoId}&list=${playlistId}`
);
return resolver(
QueryType.YOUTUBE_PLAYLIST,
`https://www.youtube.com/playlist?list=${playlistId}`
);
}
if (_QueryResolver.validateId(query) || _QueryResolver.validateURL(query))
return resolver(QueryType.YOUTUBE_VIDEO, query);
return resolver(fallbackSearchEngine, query);
} else if (DomainsMap.Spotify.includes(url.host)) {
query = query.replace(/intl-([a-zA-Z]+)\//, "");
if (spotifyPlaylistRegex.test(query))
return resolver(QueryType.SPOTIFY_PLAYLIST, query);
if (spotifyAlbumRegex.test(query))
return resolver(QueryType.SPOTIFY_ALBUM, query);
if (spotifySongRegex.test(query))
return resolver(QueryType.SPOTIFY_SONG, query);
return resolver(fallbackSearchEngine, query);
} else if (DomainsMap.Vimeo.includes(url.host)) {
if (vimeoRegex.test(query)) return resolver(QueryType.VIMEO, query);
return resolver(fallbackSearchEngine, query);
} else if (DomainsMap.ReverbNation.includes(url.host)) {
if (reverbnationRegex.test(query))
return resolver(QueryType.REVERBNATION, query);
return resolver(fallbackSearchEngine, query);
} else if (DomainsMap.SoundCloud.includes(url.host)) {
if (soundcloudPlaylistRegex.test(query))
return resolver(QueryType.SOUNDCLOUD_PLAYLIST, query);
if (soundcloudTrackRegex.test(query))
return resolver(QueryType.SOUNDCLOUD_TRACK, query);
return resolver(fallbackSearchEngine, query);
} else if (DomainsMap.AppleMusic.includes(url.host)) {
if (appleMusicAlbumRegex.test(query))
return resolver(QueryType.APPLE_MUSIC_ALBUM, query);
if (appleMusicPlaylistRegex.test(query))
return resolver(QueryType.APPLE_MUSIC_PLAYLIST, query);
if (appleMusicSongRegex.test(query))
return resolver(QueryType.APPLE_MUSIC_SONG, query);
return resolver(fallbackSearchEngine, query);
} else {
return resolver(QueryType.ARBITRARY, query);
}
} catch {
return resolver(fallbackSearchEngine, query);
}
}
/**
* Parses vimeo id from url
* @param {string} query The query
* @returns {string}
*/
static getVimeoID(query) {
return _QueryResolver.resolve(query).type === QueryType.VIMEO ? query.split("/").filter(Boolean).pop() : null;
}
static validateId(q) {
return youtubeVideoIdRegex.test(q);
}
static validateURL(q) {
return youtubeVideoURLRegex.test(q);
}
};
__name(_QueryResolver, "QueryResolver");
var QueryResolver = _QueryResolver;
// src/fabric/SearchResult.ts
var _SearchResult = class _SearchResult {
constructor(player, _data) {
this.player = player;
this._data = _data;
this._data.tracks?.forEach((track) => {
track.extractor ?? (track.extractor = this._data.extractor || null);
track.requestedBy ?? (track.requestedBy = _data.requestedBy || null);
});
}
setQueryType(type) {
this._data.queryType = type;
return this;
}
setRequestedBy(user) {
this._data.requestedBy = user;
this._data.tracks?.forEach((track) => {
track.requestedBy = user;
});
return this;
}
setExtractor(extractor) {
this._data.extractor = extractor;
this._data.tracks?.forEach((track) => {
track.extractor = extractor;
});
return this;
}
setTracks(tracks) {
this._data.tracks = tracks;
return this;
}
setQuery(query) {
this._data.query = query;
return this;
}
setPlaylist(playlist) {
this._data.playlist = playlist;
return this;
}
/**
* The search query
*/
get query() {
return this._data.query;
}
/**
* The search query type
*/
get queryType() {
return this._data.queryType || QueryType.AUTO;
}
/**
* The extractor
*/
get extractor() {
return this._data.extractor || null;
}
/**
* Playlist result
*/
get playlist() {
return this._data.playlist;
}
/**
* Tracks result
*/
get tracks() {
return this._data.tracks || [];
}
/**
* Requested by
*/
get requestedBy() {
return this._data.requestedBy || null;
}
/**
* Re-execute this search
*/
async execute() {
return this.player.search(this.query, {
searchEngine: this.queryType,
requestedBy: this.requestedBy
});
}
/**
* If this search result is empty
*/
isEmpty() {
return !this.tracks.length;
}
/**
* If this search result has playlist
*/
hasPlaylist() {
return this.playlist != null;
}
/**
* If this search result has tracks
*/
hasTracks() {
return this.tracks.length > 0;
}
/**
* JSON representation of this search
*/
toJSON() {
return {
query: this.query,
queryType: this.queryType,
playlist: this.playlist?.toJSON(false) || null,
tracks: this.tracks.map((m) => m.toJSON(true)),
extractor: this.extractor?.identifier || null,
requestedBy: this.requestedBy?.toJSON() || null
};
}
};
__name(_SearchResult, "SearchResult");
var SearchResult = _SearchResult;
// src/utils/AudioFilters.ts
var bass = /* @__PURE__ */ __name((g) => `bass=g=${g}:f=110:w=0.3`, "bass");
var _AudioFilters = class _AudioFilters {
constructor() {
return _AudioFilters;
}
static get(name) {
return this.filters[name] ?? name;
}
static has(name) {
return name in this.filters;
}
static *[Symbol.iterator]() {
for (const [k, v] of Object.entries(this.filters)) {
yield { name: k, value: v };
}
}
static get names() {
return Object.keys(this.filters);
}
// @ts-ignore
static get length() {
return this.names.length;
}
static toString() {
return this.names.map((m) => this[m]).join(",");
}
/**
* Create ffmpeg args from the specified filters name
* @param filter The filter name
* @returns
*/
static create(filters) {
if (!filters || !Array.isArray(filters)) return this.toString();
return filters.filter((predicate) => typeof predicate === "string").map((m) => this.get(m)).join(",");
}
/**
* Defines audio filter
* @param filterName The name of the filter
* @param value The ffmpeg args
*/
static define(filterName, value) {
this.filters[filterName] = value;
}
/**
* Defines multiple audio filters
* @param filtersArray Array of filters containing the filter name and ffmpeg args
*/
static defineBulk(filtersArray) {
filtersArray.forEach((arr) => this.define(arr.name, arr.value));
}
};
__name(_AudioFilters, "AudioFilters");
__publicField(_AudioFilters, "filters", {
bassboost_low: bass(15),
bassboost: bass(20),
bassboost_high: bass(30),
"8D": "apulsator=hz=0.09",
vaporwave: "aresample=48000,asetrate=48000*0.8",
nightcore: "aresample=48000,asetrate=48000*1.25",
lofi: "aresample=48000,asetrate=48000*0.9,extrastereo=m=2.5:c=disabled",
phaser: "aphaser=in_gain=0.4",
tremolo: "tremolo",
vibrato: "vibrato=f=6.5",
reverse: "areverse",
treble: "treble=g=5",
normalizer2: "dynaudnorm=g=101",
normalizer: "acompressor",
surrounding: "surround",
pulsator: "apulsator=hz=1",
subboost: "asubboost",
karaoke: "stereotools=mlev=0.03",
flanger: "flanger",
gate: "agate",
haas: "haas",
mcompand: "mcompand",
mono: "pan=mono|c0=.5*c0+.5*c1",
mstlr: "stereotools=mode=ms>lr",
mstrr: "stereotools=mode=ms>rr",
compressor: "compand=points=-80/-105|-62/-80|-15.4/-15.4|0/-12|20/-7.6",
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",
softlimiter: "compand=attacks=0:points=-80/-80|-12.4/-12.4|-6/-8|0/-6.8|20/-2.8",
chorus: "chorus=0.7:0.9:55:0.4:0.25:2",
chorus2d: "chorus=0.6:0.9:50|60:0.4|0.32:0.25|0.4:2|1.3",
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",
fadein: "afade=t=in:ss=0:d=10",
dim: `afftfilt="'real=re * (1-clip((b/nb)*b,0,1))':imag='im * (1-clip((b/nb)*b,0,1))'"`,
earrape: "channelsplit,sidechaingate=level_in=64",
silenceremove: "silenceremove=1:0:-50dB"
});
var AudioFilters = _AudioFilters;
// src/utils/Util.ts
var import_node_crypto = require("crypto");
var import_metadata_filter = require("@web-scrobbler/metadata-filter");
var _Util = class _Util {
/**
* Utils
*/
constructor() {
}
// eslint-disable-line @typescript-eslint/no-empty-function
/**
* Gets the runtime information
*/
static getRuntime() {
const version2 = typeof navigator !== "undefined" ? navigator.userAgent : null;
if (typeof Deno !== "undefined" && Deno.version) {
return { name: "deno", version: Deno.version.deno };
}
if (typeof Bun !== "undefined" && Bun.version) {
return { name: "bun", version: Bun.version };
}
if (typeof process !== "undefined" && process.version)
return { name: "node", version: process.version };
return { name: "unknown", version: version2 ?? "unknown" };
}
/**
* Creates duration string
* @param {object} durObj The duration object
* @returns {string}
*/
static durationString(durObj) {
return Object.values(durObj).map((m) => isNaN(m) ? 0 : m).join(":");
}
/**
* Parses milliseconds to consumable time object
* @param {number} milliseconds The time in ms
* @returns {TimeData}
*/
static parseMS(milliseconds) {
if (isNaN(milliseconds)) milliseconds = 0;
const round = milliseconds > 0 ? Math.floor : Math.ceil;
return {
days: round(milliseconds / 864e5),
hours: round(milliseconds / 36e5) % 24,
minutes: round(milliseconds / 6e4) % 60,
seconds: round(milliseconds / 1e3) % 60
};
}
/**
* Builds time code
* @param {TimeData} duration The duration object
* @returns {string}
*/
static buildTimeCode(duration) {
const items = Object.keys(duration);
const required = ["days", "hours", "minutes", "seconds"];
const parsed = items.filter((x) => required.includes(x)).map((m) => duration[m]);
const final = parsed.slice(parsed.findIndex((x) => x !== 0)).map((x) => x.toString().padStart(2, "0")).join(":");
return final.length <= 3 ? `0:${final.padStart(2, "0") || 0}` : final;
}
/**
* Formats duration
* @param {number} duration The duration in ms
*/
static formatDuration(duration) {
return this.buildTimeCode(this.parseMS(duration));
}
/**
* Picks last item of the given array
* @param {any[]} arr The array
* @returns {any}
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static last(arr) {
if (!Array.isArray(arr)) return arr;
return arr[arr.length - 1];
}
/**
* Checks if the voice channel is empty
* @param {VoiceChannel|StageChannel} channel The voice channel
* @returns {boolean}
*/
static isVoiceEmpty(channel) {
return channel && channel.members.filter((member) => !member.user.bot).size === 0;
}
/**
* Cleans the track title
* @param title The title
* @param source The source
* @returns Cleaned title
*/
static cleanTitle(title, source) {
try {
const filterOpts = {
// prettier-ignore
track: [
import_metadata_filter.removeRemastered,
import_metadata_filter.removeLive,
import_metadata_filter.fixTrackSuffix,
import_metadata_filter.removeZeroWidth,
import_metadata_filter.replaceNbsp,
import_metadata_filter.replaceSmartQuotes,
import_metadata_filter.removeCleanExplicit
]
};
const spotifyFilter = (0, import_metadata_filter.createFilter)(filterOpts);
spotifyFilter.extend((0, import_metadata_filter.createSpotifyFilter)());
const defaultFilter = (0, import_metadata_filter.createFilter)(filterOpts);
switch (source) {
case "youtube":
return (0, import_metadata_filter.youtube)(title);
case "spotify":
return spotifyFilter.filterField("track", title);
default:
return defaultFilter.filterField("track", title);
}
} catch {
return title;
}
}
/**
* Safer require
* @param {string} id Node require id
* @returns {any}
*/
static require(id) {
try {
return { module: require(id), error: null };
} catch (error) {
return { module: null, error };
}
}
static async import(id) {
try {
const mod = await import(id);
return { module: mod, error: null };
} catch (error) {
return { module: null, error };
}
}
/**
* Asynchronous timeout
* @param {number} time The time in ms to wait
* @returns {Promise<unknown>}
*/
static wait(time) {
return (0, import_promises.setTimeout)(time, void 0, { ref: false });
}
static noop() {
}
// eslint-disable-line @typescript-eslint/no-empty-function
static async getFetch() {
if ("fetch" in globalThis) return globalThis.fetch;
for (const lib of ["node-fetch", "undici"]) {
try {
return await import(lib).then(
(res) => res.fetch || res.default?.fetch || res.default
);
} catch {
try {
const res = require(lib);
if (res) return res.fetch || res.default?.fetch || res.default;
} catch {
}
}
}
}
static warn(message, code = "DeprecationWarning", detail) {
process.emitWarning(message, {
code,
detail
});
}
static randomChoice(src) {
return src[(0, import_node_crypto.randomInt)(src.length)];
}
static arrayCloneShuffle(src) {
const arr = src.slice();
let m = arr.length;
while (m) {
const i = Math.floor(Math.random() * m--);
[arr[m], arr[i]] = [arr[i], arr[m]];
}
return arr;
}
};
__name(_Util, "Util");
var Util = _Util;
var VALIDATE_QUEUE_CAP = /* @__PURE__ */ __name((queue, items) => {
const tracks = items instanceof Playlist ? items.tracks : Array.isArray(items) ? items : [items];
if (queue.maxSize < 1 || queue.maxSize === Infinity) return;
const maxCap = queue.getCapacity();
if (maxCap < tracks.length) {
throw new OutOfSpaceError("tracks queue", maxCap, tracks.length);
}
}, "VALIDATE_QUEUE_CAP");
// src/compat/createErisCompat.ts
var DiscordPlayerClientSymbol = Symbol("DiscordPlayerClient");
function isClientProxy(client) {
return Reflect.get(client, DiscordPlayerClientSymbol) != null;
}
__name(isClientProxy, "isClientProxy");
function getCompatName(client) {
return Reflect.get(client, DiscordPlayerClientSymbol) ?? null;
}
__name(getCompatName, "getCompatName");
function isErisProxy(client) {
return Reflect.get(client, DiscordPlayerClientSymbol) === "Eris";
}
__name(isErisProxy, "isErisProxy");
function declareProperty(target, key, value) {
Reflect.set(target, key, value);
}
__name(declareProperty, "declareProperty");
function getProperty(target, key) {
return Reflect.get(target, key);
}
__name(getProperty, "getProperty");
function createErisCompat(client) {
const { module: module2, error } = Util.require("eris");
if (error) throw error;
const eris = module2;
erisVoiceEventsHandler(client);
const erisProxy = new Proxy(client, {
get(target, p) {
switch (p) {
case "users":
return erisUsersProxy(target, eris);
case "guilds":
return erisGuildsProxy(target, eris);
case "channels":
return erisChannelsProxy(target, eris);
case "__dp_voiceStateUpdate_proxy":
return (handler) => erisVoiceStateUpdateProxy(target, erisProxy, handler);
case "incrementMaxListeners":
return () => {
client.setMaxListeners(client.getMaxListeners() + 1);
};
case "decrementMaxListeners":
return () => {
const listeners = client.getMaxListeners() - 1;
client.setMaxListeners(listeners < 0 ? 1 : listeners);
};
default:
return target[p];
}
}
});
Reflect.set(erisProxy, DiscordPlayerClientSymbol, "Eris");
return erisProxy;
}
__name(createErisCompat, "createErisCompat");
function erisVoiceStateUpdateProxy(client, proxy, handler) {
client.on("voiceStateUpdate", (member, oldState) => {
try {
const proxiedOldState = {
channelId: oldState.channelID,
serverMute: oldState.mute,
suppress: oldState.suppress,
guild: {
id: oldState.guild.id
},
member: {
id: oldState.user.id
}
};
const me = member.guild.members.get(client.user.id);
const resolvedChannel = member.guild.channels.get(
member.voiceState.channelID
);
const proxiedNewState = {
channelId: member.voiceState.channelID,
serverMute: member.voiceState.mute,
suppress: member.voiceState.suppress,
channel: erisResolvedChannelProxy(resolvedChannel, client),
member: {
id: member.id
},
guild: {
id: member.guild.id,
members: {
me: {
id: me?.id,
voice: {
async setRequestToSpeak(value) {
return me?.voiceState;
}
}
}
}
}
};
return handler(proxiedNewState, proxiedOldState);
} catch {
}
});
}
__name(erisVoiceStateUpdateProxy, "erisVoiceStateUpdateProxy");
function erisVoiceEventsHandler(client) {
let adapters = getProperty(client, "adapters");
if (!adapters) {
const collection = /* @__PURE__ */ new Map();
adapters = collection;
declareProperty(client, "adapters", collection);
}
client.on("shardDisconnect", (_, shardId) => {
for (const [guildId, adapter] of adapters.entries()) {
if (client.guilds.get(guildId)?.shard.id === shardId) {
adapter.destroy();
}
}
});
client.on("rawWS", (packet) => {
switch (packet.t) {
case import_v10.GatewayDispatchEvents.VoiceServerUpdate: {
const payload = packet.d;
adapters.get(payload.guild_id)?.onVoiceServerUpdate(payload);
return;
}
case import_v10.GatewayDispatchEvents.VoiceStateUpdate: {
const payload = packet.d;
if (payload.guild_id && payload.session_id && payload.user_id === client.user.id) {
adapters.get(payload.guild_id)?.onVoiceStateUpdate(payload);
}
return;
}
default:
break;
}
});
}
__name(erisVoiceEventsHandler, "erisVoiceEventsHandler");
function erisChannelsProxy(client, eris) {
const handler = {
client,
get cache() {
return {
get(id) {
return client.getChannel(id);
},
has(id) {
return id in client.channelGuildMap;
}
};
},
resolve(resolvable) {
if (typeof resolvable === "string") {
return erisResolvedChannelProxy(
this.client.getChannel(resolvable),
client
);
}
if (resolvable instanceof eris.GuildChannel) {
return erisResolvedChannelProxy(resolvable, client);
}