New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

discord-player

Package Overview
Dependencies
Maintainers
2
Versions
367
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

discord-player - npm Package Compare versions

Comparing version 5.0.0-dev.8e2f50cfb5cf1b077f98cb2c7d6d6a5dfddd2609 to 5.0.0-dev.92a3409.1625911434

lib/VoiceInterface/AdapterCreator.d.ts

5

lib/index.d.ts

@@ -5,6 +5,9 @@ export { AudioFilters } from "./utils/AudioFilters";

export { Player } from "./Player";
export { QueryResolver } from "./utils/QueryResolver";
export { Queue } from "./Structures/Queue";
export { Track } from "./Structures/Track";
export { Util } from "./utils/Util";
export { VoiceUtils } from "./VoiceInterface/VoiceUtils";
export { VoiceEvents, StreamDispatcher } from "./VoiceInterface/BasicStreamDispatcher";
export { VoiceEvents, StreamDispatcher } from "./VoiceInterface/StreamDispatcher";
export { VoiceAdapterCreator } from "./VoiceInterface/AdapterCreator";
export * from "./types/types";

12

lib/index.js

@@ -13,3 +13,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.StreamDispatcher = exports.VoiceUtils = exports.Track = exports.Queue = exports.Player = exports.Playlist = exports.ExtractorModel = exports.AudioFilters = void 0;
exports.VoiceAdapterCreator = exports.StreamDispatcher = exports.VoiceUtils = exports.Util = exports.Track = exports.Queue = exports.QueryResolver = exports.Player = exports.Playlist = exports.ExtractorModel = exports.AudioFilters = void 0;
var AudioFilters_1 = require("./utils/AudioFilters");

@@ -23,2 +23,4 @@ Object.defineProperty(exports, "AudioFilters", { enumerable: true, get: function () { return AudioFilters_1.AudioFilters; } });

Object.defineProperty(exports, "Player", { enumerable: true, get: function () { return Player_1.Player; } });
var QueryResolver_1 = require("./utils/QueryResolver");
Object.defineProperty(exports, "QueryResolver", { enumerable: true, get: function () { return QueryResolver_1.QueryResolver; } });
var Queue_1 = require("./Structures/Queue");

@@ -28,6 +30,10 @@ Object.defineProperty(exports, "Queue", { enumerable: true, get: function () { return Queue_1.Queue; } });

Object.defineProperty(exports, "Track", { enumerable: true, get: function () { return Track_1.Track; } });
var Util_1 = require("./utils/Util");
Object.defineProperty(exports, "Util", { enumerable: true, get: function () { return Util_1.Util; } });
var VoiceUtils_1 = require("./VoiceInterface/VoiceUtils");
Object.defineProperty(exports, "VoiceUtils", { enumerable: true, get: function () { return VoiceUtils_1.VoiceUtils; } });
var BasicStreamDispatcher_1 = require("./VoiceInterface/BasicStreamDispatcher");
Object.defineProperty(exports, "StreamDispatcher", { enumerable: true, get: function () { return BasicStreamDispatcher_1.StreamDispatcher; } });
var StreamDispatcher_1 = require("./VoiceInterface/StreamDispatcher");
Object.defineProperty(exports, "StreamDispatcher", { enumerable: true, get: function () { return StreamDispatcher_1.StreamDispatcher; } });
var AdapterCreator_1 = require("./VoiceInterface/AdapterCreator");
Object.defineProperty(exports, "VoiceAdapterCreator", { enumerable: true, get: function () { return AdapterCreator_1.VoiceAdapterCreator; } });
__exportStar(require("./types/types"), exports);

@@ -5,3 +5,3 @@ import { Client, Collection, GuildResolvable } from "discord.js";

import { VoiceUtils } from "./VoiceInterface/VoiceUtils";
import { PlayerEvents, PlayerOptions, SearchOptions, DiscordPlayerInitOptions } from "./types/types";
import { PlayerEvents, PlayerOptions, SearchOptions, PlayerInitOptions } from "./types/types";
import Track from "./Structures/Track";

@@ -12,3 +12,3 @@ import { Playlist } from "./Structures/Playlist";

readonly client: Client;
readonly options: DiscordPlayerInitOptions;
readonly options: PlayerInitOptions;
readonly queues: Collection<`${bigint}`, Queue<unknown>>;

@@ -20,4 +20,5 @@ readonly voiceUtils: VoiceUtils;

* @param {Client} client The Discord Client
* @param {PlayerInitOptions} [options={}] The player init options
*/
constructor(client: Client, options?: DiscordPlayerInitOptions);
constructor(client: Client, options?: PlayerInitOptions);
/**

@@ -53,6 +54,11 @@ * Handles voice state update

/**
* @typedef {object} SearchResult
* @property {Playlist} [playlist] The playlist (if any)
* @property {Track[]} tracks The tracks
*/
/**
* Search tracks
* @param {string|Track} query The search query
* @param {UserResolvable} requestedBy The person who requested track search
* @returns {Promise<object>}
* @param {SearchOptions} options The search options
* @returns {Promise<SearchResult>}
*/

@@ -64,2 +70,3 @@ search(query: string | Track, options: SearchOptions): Promise<{

/**
* Registers extractor
* @param {string} extractorName The extractor name

@@ -82,56 +89,10 @@ * @param {ExtractorModel|any} extractor The extractor object

scanDeps(): string;
/**
* Resolves qeuue
* @param {GuildResolvable|Queue} queueLike Queue like object
* @returns {Queue}
*/
resolveQueue<T>(queueLike: GuildResolvable | Queue): Queue<T>;
[Symbol.iterator](): Generator<Queue<unknown>, void, undefined>;
}
/**
* Emitted when bot gets disconnected from a voice channel
* @event Player#botDisconnect
* @param {Queue} queue The queue
*/
/**
* Emitted when the voice channel is empty
* @event Player#channelEmpty
* @param {Queue} queue The queue
*/
/**
* Emitted when bot connects to a voice channel
* @event Player#connectionCreate
* @param {Queue} queue The queue
* @param {StreamDispatcher} connection The discord player connection object
*/
/**
* Debug information
* @event Player#debug
* @param {Queue} queue The queue
* @param {string} message The message
*/
/**
* Emitted on error
* <warn>This event should handled properly otherwise it may crash your process!</warn>
* @event Player#error
* @param {Queue} queue The queue
* @param {Error} error The error
*/
/**
* Emitted when queue ends
* @event Player#queueEnd
* @param {Queue} queue The queue
*/
/**
* Emitted when a single track is added
* @event Player#trackAdd
* @param {Queue} queue The queue
* @param {Track} track The track
*/
/**
* Emitted when multiple tracks are added
* @event Player#tracksAdd
* @param {Queue} queue The queue
* @param {Track[]} tracks The tracks
*/
/**
* Emitted when a track starts playing
* @event Player#trackStart
* @param {Queue} queue The queue
* @param {Track} track The track
*/
export { Player };

@@ -26,2 +26,3 @@ "use strict";

const spotify_url_info_1 = __importDefault(require("spotify-url-info"));
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore

@@ -37,2 +38,3 @@ const soundcloud_scraper_1 = require("soundcloud-scraper");

* @param {Client} client The Discord Client
* @param {PlayerInitOptions} [options={}] The player init options
*/

@@ -61,3 +63,3 @@ constructor(client, options = {}) {

if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.autoRegisterExtractor) {
let nv;
let nv; // eslint-disable-line @typescript-eslint/no-explicit-any
if ((nv = Util_1.Util.require("@discord-player/extractor"))) {

@@ -79,3 +81,26 @@ ["Attachment", "Facebook", "Reverbnation", "Vimeo"].forEach((ext) => void this.use(ext, nv[ext]));

return;
if (oldState.member.id === this.client.user.id && !newState.channelID) {
if (oldState.channelId && newState.channelId && oldState.channelId !== newState.channelId) {
queue.connection.channel = newState.channel;
}
if (!oldState.channelId && newState.channelId && newState.member.id === newState.guild.me.id) {
if (newState.serverMute || !newState.serverMute) {
queue.setPaused(newState.serverMute);
}
else if (newState.suppress || !newState.suppress) {
if (newState.suppress)
newState.guild.me.voice.setRequestToSpeak(true).catch(Util_1.Util.noop);
queue.setPaused(newState.suppress);
}
}
if (oldState.channelId === newState.channelId && oldState.member.id === newState.guild.me.id) {
if (oldState.serverMute !== newState.serverMute) {
queue.setPaused(newState.serverMute);
}
else if (oldState.suppress !== newState.suppress) {
if (newState.suppress)
newState.guild.me.voice.setRequestToSpeak(true).catch(Util_1.Util.noop);
queue.setPaused(newState.suppress);
}
}
if (oldState.member.id === this.client.user.id && !newState.channelId) {
queue.destroy();

@@ -86,3 +111,3 @@ return void this.emit("botDisconnect", queue);

return;
if (!oldState.channelID || newState.channelID) {
if (!oldState.channelId || newState.channelId) {
const emptyTimeout = queue._cooldownsTimeout.get(`empty_${oldState.guild.id}`);

@@ -115,3 +140,3 @@ const channelEmpty = Util_1.Util.isVoiceEmpty(queue.connection.channel);

*/
createQueue(guild, queueInitOptions) {
createQueue(guild, queueInitOptions = {}) {
var _a;

@@ -155,3 +180,3 @@ guild = this.client.guilds.resolve(guild);

}
catch (_a) { }
catch (_a) { } // eslint-disable-line no-empty
this.queues.delete(guild.id);

@@ -161,6 +186,11 @@ return prev;

/**
* @typedef {object} SearchResult
* @property {Playlist} [playlist] The playlist (if any)
* @property {Track[]} tracks The tracks
*/
/**
* Search tracks
* @param {string|Track} query The search query
* @param {UserResolvable} requestedBy The person who requested track search
* @returns {Promise<object>}
* @param {SearchOptions} options The search options
* @returns {Promise<SearchResult>}
*/

@@ -177,3 +207,6 @@ search(query, options) {

options.searchEngine = types_1.QueryType.AUTO;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const [_, extractor] of this.extractors) {
if (options.blockExtractor)
break;
if (!extractor.validate(query))

@@ -197,3 +230,3 @@ continue;

type: "video"
}).catch(() => { });
}).catch(Util_1.Util.noop);
if (!videos)

@@ -203,3 +236,3 @@ return { playlist: null, tracks: [] };

var _a, _b;
m.source = "youtube";
m.source = "youtube"; // eslint-disable-line @typescript-eslint/no-explicit-any
return new Track_1.default(this, {

@@ -221,3 +254,4 @@ title: m.title,

case types_1.QueryType.SOUNDCLOUD_SEARCH: {
const result = QueryResolver_1.QueryResolver.resolve(query) === types_1.QueryType.SOUNDCLOUD_TRACK ? [{ url: query }] : yield soundcloud.search(query, "track").catch(() => { });
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-function
const result = QueryResolver_1.QueryResolver.resolve(query) === types_1.QueryType.SOUNDCLOUD_TRACK ? [{ url: query }] : yield soundcloud.search(query, "track").catch(Util_1.Util.noop);
if (!result || !result.length)

@@ -227,3 +261,3 @@ return { playlist: null, tracks: [] };

for (const r of result) {
const trackInfo = yield soundcloud.getSongInfo(r.url).catch(() => { });
const trackInfo = yield soundcloud.getSongInfo(r.url).catch(Util_1.Util.noop);
if (!trackInfo)

@@ -248,3 +282,3 @@ continue;

case types_1.QueryType.SPOTIFY_SONG: {
const spotifyData = yield spotify_url_info_1.default.getData(query).catch(() => { });
const spotifyData = yield spotify_url_info_1.default.getData(query).catch(Util_1.Util.noop);
if (!spotifyData)

@@ -269,3 +303,3 @@ return { playlist: null, tracks: [] };

case types_1.QueryType.SPOTIFY_ALBUM: {
const spotifyPlaylist = yield spotify_url_info_1.default.getData(query).catch(() => { });
const spotifyPlaylist = yield spotify_url_info_1.default.getData(query).catch(Util_1.Util.noop);
if (!spotifyPlaylist)

@@ -294,2 +328,3 @@ return { playlist: null, tracks: [] };

if (spotifyPlaylist.type !== "playlist") {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
playlist.tracks = spotifyPlaylist.tracks.items.map((m) => {

@@ -313,2 +348,3 @@ var _a, _b, _c, _d, _e, _f, _g, _h;

else {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
playlist.tracks = spotifyPlaylist.tracks.items.map((m) => {

@@ -334,3 +370,3 @@ var _a, _b, _c, _d, _e, _f, _g, _h, _j;

case types_1.QueryType.SOUNDCLOUD_PLAYLIST: {
const data = yield soundcloud_scraper_1.Client.getPlaylist(query).catch(() => { });
const data = yield soundcloud_scraper_1.Client.getPlaylist(query).catch(Util_1.Util.noop);
if (!data)

@@ -372,7 +408,6 @@ return { playlist: null, tracks: [] };

case types_1.QueryType.YOUTUBE_PLAYLIST: {
const ytpl = yield youtube_sr_1.default.getPlaylist(query).catch(() => { });
const ytpl = yield youtube_sr_1.default.getPlaylist(query).catch(Util_1.Util.noop);
if (!ytpl)
return { playlist: null, tracks: [] };
// @todo: better way of handling large playlists
yield ytpl.fetch().catch(() => { });
yield ytpl.fetch().catch(Util_1.Util.noop);
const playlist = new Playlist_1.Playlist(this, {

@@ -417,2 +452,3 @@ title: ytpl.title,

/**
* Registers extractor
* @param {string} extractorName The extractor name

@@ -423,2 +459,3 @@ * @param {ExtractorModel|any} extractor The extractor object

*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
use(extractorName, extractor, force = false) {

@@ -460,2 +497,10 @@ if (!extractorName)

}
/**
* Resolves qeuue
* @param {GuildResolvable|Queue} queueLike Queue like object
* @returns {Queue}
*/
resolveQueue(queueLike) {
return this.getQueue(queueLike instanceof Queue_1.Queue ? queueLike.guild : queueLike);
}
*[Symbol.iterator]() {

@@ -462,0 +507,0 @@ yield* Array.from(this.queues.values());

@@ -19,2 +19,3 @@ "use strict";

*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor(extractorName, data) {

@@ -47,3 +48,5 @@ /**

playlist: (_a = data.playlist) !== null && _a !== void 0 ? _a : null,
data: (_c = (_b = data.info) === null || _b === void 0 ? void 0 : _b.map((m) => ({
data:
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(_c = (_b = data.info) === null || _b === void 0 ? void 0 : _b.map((m) => ({
title: m.title,

@@ -50,0 +53,0 @@ duration: m.duration,

/// <reference types="node" />
import { Collection, Guild, StageChannel, VoiceChannel } from "discord.js";
import { Collection, Guild, Snowflake, GuildChannelResolvable } from "discord.js";
import { Player } from "../Player";
import { StreamDispatcher } from "../VoiceInterface/BasicStreamDispatcher";
import { StreamDispatcher } from "../VoiceInterface/StreamDispatcher";
import Track from "./Track";
import { PlayerOptions, PlayOptions, QueueFilters, QueueRepeatMode } from "../types/types";
import { PlayerOptions, PlayerProgressbarOptions, PlayOptions, QueueFilters, QueueRepeatMode } from "../types/types";
declare class Queue<T = unknown> {
#private;
readonly guild: Guild;

@@ -17,5 +18,7 @@ readonly player: Player;

repeatMode: QueueRepeatMode;
readonly id: Snowflake;
private _streamTime;
_cooldownsTimeout: Collection<string, NodeJS.Timeout>;
private _activeFilters;
private _filtersUpdate;
/**

@@ -34,2 +37,7 @@ * Queue constructor

/**
* If this queue is destroyed
* @type {boolean}
*/
get destroyed(): boolean;
/**
* Returns current track

@@ -41,6 +49,6 @@ * @returns {Track}

* Connects to a voice channel
* @param {StageChannel|VoiceChannel} channel The voice/stage channel
* @param {GuildChannelResolvable} channel The voice/stage channel
* @returns {Promise<Queue>}
*/
connect(channel: StageChannel | VoiceChannel): Promise<this>;
connect(channel: GuildChannelResolvable): Promise<this>;
/**

@@ -76,3 +84,3 @@ * Destroys this queue

* Sets bitrate
* @param {number|"auto"} bitrate bitrate to set
* @param {number|auto} bitrate bitrate to set
* @returns {void}

@@ -100,2 +108,12 @@ */

/**
* Mutes the playback
* @returns {void}
*/
mute(): void;
/**
* Unmutes the playback. If the last volume was set to 0, unmute will produce no effect.
* @returns {void}
*/
unmute(): void;
/**
* The stream time of this queue

@@ -105,2 +123,3 @@ * @type {number}

get streamTime(): number;
set streamTime(time: number);
/**

@@ -110,3 +129,3 @@ * Returns enabled filters

*/
getFiltersEnabled(): string[];
getFiltersEnabled(): (keyof QueueFilters)[];
/**

@@ -116,3 +135,3 @@ * Returns disabled filters

*/
getFiltersDisabled(): string[];
getFiltersDisabled(): (keyof QueueFilters)[];
/**

@@ -136,2 +155,60 @@ * Sets filters

/**
* Clear this queue
*/
clear(): void;
/**
* Stops the player
* @returns {void}
*/
stop(): void;
/**
* Shuffles this queue
* @returns {boolean}
*/
shuffle(): boolean;
/**
* Removes a track from the queue
* @param {Track|Snowflake|number} track The track to remove
* @returns {Track}
*/
remove(track: Track | Snowflake | number): Track;
/**
* Jumps to particular track
* @param {Track|number} track The track
* @returns {void}
*/
jump(track: Track | number): void;
/**
* Inserts the given track to specified index
* @param {Track} track The track to insert
* @param {number} [index=0] The index where this track should be
*/
insert(track: Track, index?: number): void;
/**
* @typedef {object} PlayerTimestamp
* @property {string} current The current progress
* @property {string} end The total time
* @property {number} progress Progress in %
*/
/**
* Returns player stream timestamp
* @returns {PlayerTimestamp}
*/
getPlayerTimestamp(): {
current: string;
end: string;
progress: number;
};
/**
* Creates progress bar string
* @param {PlayerProgressbarOptions} options The progress bar options
* @returns {string}
*/
createProgressBar(options?: PlayerProgressbarOptions): string;
/**
* Total duration
* @type {Number}
*/
get totalTime(): number;
/**
* Play stream in a voice/stage channel

@@ -143,2 +220,9 @@ * @param {Track} [src] The track to play (if empty, uses first track from the queue)

play(src?: Track, options?: PlayOptions): Promise<void>;
/**
* Private method to handle autoplay
* @param {Track} track The source track to find its similar track for autoplay
* @returns {Promise<void>}
* @private
*/
private _handleAutoplay;
[Symbol.iterator](): Generator<Track, void, undefined>;

@@ -150,2 +234,3 @@ /**

toJSON(): {
id: `${bigint}`;
guild: `${bigint}`;

@@ -152,0 +237,0 @@ voiceChannel: `${bigint}`;

@@ -11,5 +11,17 @@ "use strict";

};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _Queue_instances, _Queue_lastVolume, _Queue_destroyed, _Queue_watchDestroyed;
Object.defineProperty(exports, "__esModule", { value: true });

@@ -33,2 +45,3 @@ exports.Queue = void 0;

constructor(player, guild, options = {}) {
_Queue_instances.add(this);
this.tracks = [];

@@ -39,5 +52,9 @@ this.previousTracks = [];

this.repeatMode = 0;
this.id = discord_js_1.SnowflakeUtil.generate();
this._streamTime = 0;
this._cooldownsTimeout = new discord_js_1.Collection();
this._activeFilters = [];
this._activeFilters = []; // eslint-disable-line @typescript-eslint/no-explicit-any
this._filtersUpdate = false;
_Queue_lastVolume.set(this, 0);
_Queue_destroyed.set(this, false);
/**

@@ -60,2 +77,32 @@ * The player that instantiated this queue

this.options = {};
/**
* Queue repeat mode
* @type {QueueRepeatMode}
* @name Queue#repeatMode
*/
/**
* Queue metadata
* @type {any}
* @name Queue#metadata
*/
/**
* Previous tracks
* @type {Track[]}
* @name Queue#previousTracks
*/
/**
* Regular tracks
* @type {Track[]}
* @name Queue#tracks
*/
/**
* The connection
* @type {StreamDispatcher}
* @name Queue#connection
*/
/**
* The ID of this queue
* @type {Snowflake}
* @name Queue#id
*/
Object.assign(this.options, {

@@ -67,7 +114,3 @@ leaveOnEnd: true,

autoSelfDeaf: true,
enableLive: false,
ytdlOptions: {},
useSafeSearch: false,
disableAutoRegister: false,
fetchBeforeQueued: false,
initialVolume: 100

@@ -82,5 +125,13 @@ }, options);

var _a, _b;
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
return (_b = (_a = this.connection.audioResource) === null || _a === void 0 ? void 0 : _a.metadata) !== null && _b !== void 0 ? _b : this.tracks[0];
}
/**
* If this queue is destroyed
* @type {boolean}
*/
get destroyed() {
return __classPrivateFieldGet(this, _Queue_destroyed, "f");
}
/**
* Returns current track

@@ -90,2 +141,3 @@ * @returns {Track}

nowPlaying() {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
return this.current;

@@ -95,3 +147,3 @@ }

* Connects to a voice channel
* @param {StageChannel|VoiceChannel} channel The voice/stage channel
* @param {GuildChannelResolvable} channel The voice/stage channel
* @returns {Promise<Queue>}

@@ -101,15 +153,52 @@ */

return __awaiter(this, void 0, void 0, function* () {
if (!["stage", "voice"].includes(channel === null || channel === void 0 ? void 0 : channel.type))
throw new TypeError(`Channel type must be voice or stage, got ${channel === null || channel === void 0 ? void 0 : channel.type}!`);
const connection = yield this.player.voiceUtils.connect(channel, {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
const _channel = this.guild.channels.resolve(channel);
if (!["GUILD_STAGE_VOICE", "GUILD_VOICE"].includes(_channel === null || _channel === void 0 ? void 0 : _channel.type))
throw new TypeError(`Channel type must be GUILD_VOICE or GUILD_STAGE_VOICE, got ${_channel === null || _channel === void 0 ? void 0 : _channel.type}!`);
const connection = yield this.player.voiceUtils.connect(_channel, {
deaf: this.options.autoSelfDeaf
});
this.connection = connection;
// it's ok to use this here since Queue listens to the events 1 time per play and destroys the listener
this.connection.setMaxListeners(Infinity);
if (channel.type === "stage")
yield channel.guild.me.voice.setRequestToSpeak(true).catch(() => { });
this.connection.on("error", (err) => this.player.emit("error", this, err));
if (_channel.type === "GUILD_STAGE_VOICE") {
yield _channel.guild.me.voice.setSuppressed(false).catch(() => __awaiter(this, void 0, void 0, function* () {
return yield _channel.guild.me.voice.setRequestToSpeak(true).catch(Util_1.Util.noop);
}));
}
this.connection.on("error", (err) => this.player.emit("connectionError", this, err));
this.connection.on("debug", (msg) => this.player.emit("debug", this, msg));
this.player.emit("connectionCreate", this, this.connection);
this.connection.on("start", (resource) => {
var _a;
this.playing = true;
if (!this._filtersUpdate && (resource === null || resource === void 0 ? void 0 : resource.metadata))
this.player.emit("trackStart", this, (_a = resource === null || resource === void 0 ? void 0 : resource.metadata) !== null && _a !== void 0 ? _a : this.current);
this._filtersUpdate = false;
});
this.connection.on("finish", (resource) => __awaiter(this, void 0, void 0, function* () {
this.playing = false;
if (this._filtersUpdate)
return;
this._streamTime = 0;
if (resource && resource.metadata)
this.previousTracks.push(resource.metadata);
if (!this.tracks.length && this.repeatMode === types_1.QueueRepeatMode.OFF) {
if (this.options.leaveOnEnd)
this.destroy();
this.player.emit("queueEnd", this);
}
else {
if (this.repeatMode !== types_1.QueueRepeatMode.AUTOPLAY) {
if (this.repeatMode === types_1.QueueRepeatMode.TRACK)
return void this.play(Util_1.Util.last(this.previousTracks), { immediate: true });
if (this.repeatMode === types_1.QueueRepeatMode.QUEUE)
this.tracks.push(Util_1.Util.last(this.previousTracks));
const nextTrack = this.tracks.shift();
this.play(nextTrack, { immediate: true });
return;
}
else {
this._handleAutoplay(Util_1.Util.last(this.previousTracks));
}
}
}));
return this;

@@ -124,6 +213,11 @@ });

destroy(disconnect = this.options.leaveOnStop) {
this.connection.end();
var _a;
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (this.connection)
this.connection.end();
if (disconnect)
this.connection.disconnect();
(_a = this.connection) === null || _a === void 0 ? void 0 : _a.disconnect();
this.player.queues.delete(this.guild.id);
this.player.voiceUtils.cache.delete(this.guild.id);
__classPrivateFieldSet(this, _Queue_destroyed, true, "f");
}

@@ -135,4 +229,6 @@ /**

skip() {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (!this.connection)
return false;
this._filtersUpdate = false;
this.connection.end();

@@ -147,2 +243,5 @@ return true;

addTrack(track) {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (!(track instanceof Track_1.default))
throw new Error("invalid track");
this.tracks.push(track);

@@ -156,2 +255,5 @@ this.player.emit("trackAdd", this, track);

addTracks(tracks) {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (!tracks.every((y) => y instanceof Track_1.default))
throw new Error("invalid track");
this.tracks.push(...tracks);

@@ -166,2 +268,3 @@ this.player.emit("tracksAdd", this, tracks);

setPaused(paused) {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (!this.connection)

@@ -173,3 +276,3 @@ return false;

* Sets bitrate
* @param {number|"auto"} bitrate bitrate to set
* @param {number|auto} bitrate bitrate to set
* @returns {void}

@@ -179,2 +282,3 @@ */

var _a, _b, _c, _d;
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (!((_b = (_a = this.connection) === null || _a === void 0 ? void 0 : _a.audioResource) === null || _b === void 0 ? void 0 : _b.encoder))

@@ -192,4 +296,6 @@ return;

setVolume(amount) {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (!this.connection)
return false;
__classPrivateFieldSet(this, _Queue_lastVolume, amount, "f");
this.options.initialVolume = amount;

@@ -204,2 +310,3 @@ return this.connection.setVolume(amount);

setRepeatMode(mode) {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (![types_1.QueueRepeatMode.OFF, types_1.QueueRepeatMode.QUEUE, types_1.QueueRepeatMode.TRACK, types_1.QueueRepeatMode.AUTOPLAY].includes(mode))

@@ -217,2 +324,3 @@ throw new Error(`Unknown repeat mode "${mode}"!`);

get volume() {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (!this.connection)

@@ -226,2 +334,18 @@ return 100;

/**
* Mutes the playback
* @returns {void}
*/
mute() {
const lv = __classPrivateFieldGet(this, _Queue_lastVolume, "f");
this.volume = 0;
__classPrivateFieldSet(this, _Queue_lastVolume, lv, "f");
}
/**
* Unmutes the playback. If the last volume was set to 0, unmute will produce no effect.
* @returns {void}
*/
unmute() {
this.volume = __classPrivateFieldGet(this, _Queue_lastVolume, "f");
}
/**
* The stream time of this queue

@@ -231,2 +355,3 @@ * @type {number}

get streamTime() {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (!this.connection)

@@ -241,2 +366,6 @@ return 0;

}
set streamTime(time) {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
this.seek(time);
}
/**

@@ -247,2 +376,3 @@ * Returns enabled filters

getFiltersEnabled() {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
return AudioFilters_1.default.names.filter((x) => this._activeFilters.includes(x));

@@ -255,2 +385,3 @@ }

getFiltersDisabled() {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
return AudioFilters_1.default.names.filter((x) => !this._activeFilters.includes(x));

@@ -265,2 +396,3 @@ }

return __awaiter(this, void 0, void 0, function* () {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (!filters || !Object.keys(filters).length) {

@@ -277,3 +409,3 @@ // reset filters

}
const _filters = [];
const _filters = []; // eslint-disable-line @typescript-eslint/no-explicit-any
for (const filter in filters) {

@@ -303,2 +435,3 @@ if (filters[filter] === true)

return __awaiter(this, void 0, void 0, function* () {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (!this.playing || !this.current)

@@ -324,6 +457,152 @@ return false;

return __awaiter(this, void 0, void 0, function* () {
return yield this.play(Util_1.Util.last(this.previousTracks), { immediate: true });
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
const prev = this.previousTracks[this.previousTracks.length - 2]; // because last item is the current track
if (!prev)
throw new Error("Could not find previous track");
return yield this.play(prev, { immediate: true });
});
}
/**
* Clear this queue
*/
clear() {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
this.tracks = [];
this.previousTracks = [];
}
/**
* Stops the player
* @returns {void}
*/
stop() {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
return this.destroy();
}
/**
* Shuffles this queue
* @returns {boolean}
*/
shuffle() {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (!this.tracks.length || this.tracks.length < 3)
return false;
const currentTrack = this.tracks.shift();
for (let i = this.tracks.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[this.tracks[i], this.tracks[j]] = [this.tracks[j], this.tracks[i]];
}
this.tracks.unshift(currentTrack);
return true;
}
/**
* Removes a track from the queue
* @param {Track|Snowflake|number} track The track to remove
* @returns {Track}
*/
remove(track) {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
let trackFound = null;
if (typeof track === "number") {
trackFound = this.tracks[track];
if (trackFound) {
this.tracks = this.tracks.filter((t) => t.id !== trackFound.id);
}
}
else {
trackFound = this.tracks.find((s) => s.id === (track instanceof Track_1.default ? track.id : track));
if (trackFound) {
this.tracks = this.tracks.filter((s) => s.id !== trackFound.id);
}
}
return trackFound;
}
/**
* Jumps to particular track
* @param {Track|number} track The track
* @returns {void}
*/
jump(track) {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
const foundTrack = this.remove(track);
if (!foundTrack)
throw new Error("Track not found");
this.tracks.splice(1, 0, foundTrack);
return void this.skip();
}
/**
* Inserts the given track to specified index
* @param {Track} track The track to insert
* @param {number} [index=0] The index where this track should be
*/
insert(track, index = 0) {
if (!track || !(track instanceof Track_1.default))
throw new TypeError("track must be the instance of Track");
if (typeof index !== "number" || index < 0 || !Number.isFinite(index))
throw new Error(`Invalid index "${index}"`);
this.tracks.splice(index, 0, track);
this.player.emit("trackAdd", this, track);
}
/**
* @typedef {object} PlayerTimestamp
* @property {string} current The current progress
* @property {string} end The total time
* @property {number} progress Progress in %
*/
/**
* Returns player stream timestamp
* @returns {PlayerTimestamp}
*/
getPlayerTimestamp() {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
const currentStreamTime = this.streamTime;
const totalTime = this.current.durationMS;
const currentTimecode = Util_1.Util.buildTimeCode(Util_1.Util.parseMS(currentStreamTime));
const endTimecode = Util_1.Util.buildTimeCode(Util_1.Util.parseMS(totalTime));
return {
current: currentTimecode,
end: endTimecode,
progress: Math.round((currentStreamTime / totalTime) * 100)
};
}
/**
* Creates progress bar string
* @param {PlayerProgressbarOptions} options The progress bar options
* @returns {string}
*/
createProgressBar(options = { timecodes: true }) {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
const length = typeof options.length === "number" ? (options.length <= 0 || options.length === Infinity ? 15 : options.length) : 15;
const index = Math.round((this.streamTime / this.current.durationMS) * length);
const indicator = typeof options.indicator === "string" && options.indicator.length > 0 ? options.indicator : "🔘";
const line = typeof options.line === "string" && options.line.length > 0 ? options.line : "▬";
if (index >= 1 && index <= length) {
const bar = line.repeat(length - 1).split("");
bar.splice(index, 0, indicator);
if (options.timecodes) {
const timestamp = this.getPlayerTimestamp();
return `${timestamp.current} ┃ ${bar.join("")} ┃ ${timestamp.end}`;
}
else {
return `${bar.join("")}`;
}
}
else {
if (options.timecodes) {
const timestamp = this.getPlayerTimestamp();
return `${timestamp.current} ┃ ${indicator}${line.repeat(length - 1)} ┃ ${timestamp.end}`;
}
else {
return `${indicator}${line.repeat(length - 1)}`;
}
}
}
/**
* Total duration
* @type {Number}
*/
get totalTime() {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
return this.tracks.length > 0 ? this.tracks.map((t) => t.durationMS).reduce((p, c) => p + c) : 0;
}
/**
* Play stream in a voice/stage channel

@@ -337,2 +616,4 @@ * @param {Track} [src] The track to play (if empty, uses first track from the queue)

return __awaiter(this, void 0, void 0, function* () {
if (!this.destroyed)
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (!this.connection || !this.connection.voiceConnection)

@@ -345,7 +626,8 @@ throw new Error("Voice connection is not available, use <Queue>.connect()!");

return;
this.player.emit("debug", this, "Received play request");
if (!options.filtersUpdate) {
this.previousTracks = this.previousTracks.filter((x) => x._trackID !== track._trackID);
this.previousTracks = this.previousTracks.filter((x) => x.id !== track.id);
this.previousTracks.push(track);
}
let stream, pauseEvent = false;
let stream;
if (["youtube", "spotify"].includes(track.raw.source)) {

@@ -363,3 +645,2 @@ if (track.raw.source === "spotify" && !track.raw.engine) {

opusEncoded: false, fmt: "s16le", encoderArgs: ((_a = options.encoderArgs) !== null && _a !== void 0 ? _a : this._activeFilters.length) ? ["-af", AudioFilters_1.default.create(this._activeFilters)] : [], seek: options.seek ? options.seek / 1000 : 0 })).on("error", (err) => {
pauseEvent = true;
return err.message.toLowerCase().includes("premature close") ? null : this.player.emit("error", this, err);

@@ -377,3 +658,2 @@ });

.on("error", (err) => {
pauseEvent = true;
return err.message.toLowerCase().includes("premature close") ? null : this.player.emit("error", this, err);

@@ -388,65 +668,47 @@ });

this._streamTime = options.seek;
const dispatcher = yield this.connection.playStream(resource);
dispatcher.setVolume(this.options.initialVolume);
// need to use these events here
dispatcher.once("start", () => {
this.playing = true;
if (options.filtersUpdate || pauseEvent)
return;
this.player.emit("trackStart", this, this.current);
this._filtersUpdate = options.filtersUpdate;
this.connection.playStream(resource).then(() => {
this.setVolume(this.options.initialVolume);
});
dispatcher.once("finish", () => __awaiter(this, void 0, void 0, function* () {
var _c;
this.playing = false;
if (options.filtersUpdate || pauseEvent)
return;
this._streamTime = 0;
if (!this.tracks.length && this.repeatMode === types_1.QueueRepeatMode.OFF) {
if (this.options.leaveOnEnd)
this.destroy();
this.player.emit("queueEnd", this);
}
else {
if (this.repeatMode !== types_1.QueueRepeatMode.AUTOPLAY) {
if (this.repeatMode === types_1.QueueRepeatMode.TRACK)
return void this.play(Util_1.Util.last(this.previousTracks), { immediate: true });
if (this.repeatMode === types_1.QueueRepeatMode.QUEUE)
this.tracks.push(Util_1.Util.last(this.previousTracks));
const nextTrack = this.tracks.shift();
this.play(nextTrack, { immediate: true });
return;
}
else {
if (![track.source, (_c = track.raw) === null || _c === void 0 ? void 0 : _c.source].includes("youtube")) {
if (this.options.leaveOnEnd)
this.destroy();
return void this.player.emit("queueEnd", this);
}
const info = yield discord_ytdl_core_1.default
.getInfo(track.url)
.then((x) => x.related_videos[0])
.catch(() => { });
if (!info) {
if (this.options.leaveOnEnd)
this.destroy();
return void this.player.emit("queueEnd", this);
}
const nextTrack = new Track_1.default(this.player, {
title: info.title,
url: `https://www.youtube.com/watch?v=${info.id}`,
duration: info.length_seconds ? Util_1.Util.buildTimeCode(Util_1.Util.parseMS(info.length_seconds * 1000)) : "0:00",
description: "",
thumbnail: Util_1.Util.last(info.thumbnails).url,
views: parseInt(info.view_count.replace(/[^0-9]/g, "")),
author: typeof info.author === "string" ? info.author : info.author.name,
requestedBy: track.requestedBy,
source: "youtube"
});
this.play(nextTrack, { immediate: true });
}
}
}));
});
}
*[Symbol.iterator]() {
/**
* Private method to handle autoplay
* @param {Track} track The source track to find its similar track for autoplay
* @returns {Promise<void>}
* @private
*/
_handleAutoplay(track) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (!track || ![track.source, (_a = track.raw) === null || _a === void 0 ? void 0 : _a.source].includes("youtube")) {
if (this.options.leaveOnEnd)
this.destroy();
return void this.player.emit("queueEnd", this);
}
const info = yield youtube_sr_1.default.getVideo(track.url)
.then((x) => x.videos[0])
.catch(Util_1.Util.noop);
if (!info) {
if (this.options.leaveOnEnd)
this.destroy();
return void this.player.emit("queueEnd", this);
}
const nextTrack = new Track_1.default(this.player, {
title: info.title,
url: `https://www.youtube.com/watch?v=${info.id}`,
duration: info.durationFormatted ? Util_1.Util.buildTimeCode(Util_1.Util.parseMS(info.duration * 1000)) : "0:00",
description: "",
thumbnail: typeof info.thumbnail === "string" ? info.thumbnail : info.thumbnail.url,
views: info.views,
author: info.channel.name,
requestedBy: track.requestedBy,
source: "youtube"
});
this.play(nextTrack, { immediate: true });
});
}
*[(_Queue_lastVolume = new WeakMap(), _Queue_destroyed = new WeakMap(), _Queue_instances = new WeakSet(), Symbol.iterator)]() {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
yield* this.tracks;

@@ -460,3 +722,5 @@ }

var _a, _b;
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
return {
id: this.id,
guild: this.guild.id,

@@ -473,2 +737,3 @@ voiceChannel: (_b = (_a = this.connection) === null || _a === void 0 ? void 0 : _a.channel) === null || _b === void 0 ? void 0 : _b.id,

toString() {
__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this);
if (!this.tracks.length)

@@ -480,1 +745,5 @@ return "No songs available to display!";

exports.Queue = Queue;
_Queue_watchDestroyed = function _Queue_watchDestroyed() {
if (__classPrivateFieldGet(this, _Queue_destroyed, "f"))
throw new Error("Cannot use destroyed queue");
};

@@ -1,2 +0,2 @@

import { User } from "discord.js";
import { User, Snowflake } from "discord.js";
import { Player } from "../Player";

@@ -18,3 +18,3 @@ import { RawTrackData, TrackJSON } from "../types/types";

readonly raw: RawTrackData;
readonly _trackID: number;
readonly id: Snowflake;
/**

@@ -21,0 +21,0 @@ * Track constructor

@@ -13,3 +13,3 @@ "use strict";

this.raw = {};
this._trackID = Date.now();
this.id = discord_js_1.SnowflakeUtil.generate();
/**

@@ -74,4 +74,4 @@ * The player that instantiated this Track

* The track id
* @name Track#_trackID
* @type {number}
* @name Track#id
* @type {Snowflake}
* @readonly

@@ -140,2 +140,3 @@ */

return {
id: this.id,
title: this.title,

@@ -142,0 +143,0 @@ description: this.description,

@@ -7,7 +7,12 @@ /// <reference types="node" />

import { Playlist } from "../Structures/Playlist";
import { StreamDispatcher } from "../VoiceInterface/BasicStreamDispatcher";
import { StreamDispatcher } from "../VoiceInterface/StreamDispatcher";
import { downloadOptions } from "ytdl-core";
export declare type FiltersName = keyof QueueFilters;
export declare type QueueFilters = {
/**
* @typedef {AudioFilters} QueueFilters
*/
export interface QueueFilters {
bassboost_low?: boolean;
bassboost?: boolean;
bassboost_high?: boolean;
"8D"?: boolean;

@@ -43,4 +48,28 @@ vaporwave?: boolean;

earrape?: boolean;
};
}
/**
* The track source:
* - soundcloud
* - youtube
* - spotify
* - arbitrary
* @typedef {string} TrackSource
*/
export declare type TrackSource = "soundcloud" | "youtube" | "spotify" | "arbitrary";
/**
* @typedef {object} RawTrackData
* @property {string} title The title
* @property {string} description The description
* @property {string} author The author
* @property {string} url The url
* @property {string} thumbnail The thumbnail
* @property {string} duration The duration
* @property {number} views The views
* @property {User} requestedBy The user who requested this track
* @property {Playlist} [playlist] The playlist
* @property {TrackSource} [source="arbitrary"] The source
* @property {any} [engine] The engine
* @property {boolean} [live] If this track is live
* @property {any} [raw] The raw data
*/
export interface RawTrackData {

@@ -61,2 +90,9 @@ title: string;

}
/**
* @typedef {object} TimeData
* @property {number} days Time in days
* @property {number} hours Time in hours
* @property {number} minutes Time in minutes
* @property {number} seconds Time in seconds
*/
export interface TimeData {

@@ -68,5 +104,12 @@ days: number;

}
/**
* @typedef {object} PlayerProgressbarOptions
* @property {boolean} [timecodes] If it should render time codes
* @property {boolean} [queue] If it should create progress bar for the whole queue
* @property {number} [length] The bar length
* @property {string} [line] The bar track
* @property {string} [indicator] The indicator
*/
export interface PlayerProgressbarOptions {
timecodes?: boolean;
queue?: boolean;
length?: number;

@@ -76,2 +119,12 @@ line?: string;

}
/**
* @typedef {object} PlayerOptions
* @property {boolean} [leaveOnEnd=true] If it should leave on end
* @property {boolean} [leaveOnStop=true] If it should leave on stop
* @property {boolean} [leaveOnEmpty=true] If it should leave on empty
* @property {number} [leaveOnEmptyCooldown=1000] The cooldown in ms
* @property {boolean} [autoSelfDeaf=true] If it should set the bot in deaf mode
* @property {YTDLDownloadOptions} [ytdlOptions={}] The youtube download options
* @property {number} [initialVolume=100] The initial player volume
*/
export interface PlayerOptions {

@@ -83,9 +136,34 @@ leaveOnEnd?: boolean;

autoSelfDeaf?: boolean;
enableLive?: boolean;
ytdlOptions?: downloadOptions;
useSafeSearch?: boolean;
disableAutoRegister?: boolean;
fetchBeforeQueued?: boolean;
initialVolume?: number;
}
/**
* @typedef {object} ExtractorModelData
* @property {object} [playlist] The playlist info (if any)
* @property {string} [playlist.title] The playlist title
* @property {string} [playlist.description] The playlist description
* @property {string} [playlist.thumbnail] The playlist thumbnail
* @property {album|playlist} [playlist.type] The playlist type: `album` | `playlist`
* @property {TrackSource} [playlist.source] The playlist source
* @property {object} [playlist.author] The playlist author
* @property {string} [playlist.author.name] The author name
* @property {string} [playlist.author.url] The author url
* @property {string} [playlist.id] The playlist id
* @property {string} [playlist.url] The playlist url
* @property {any} [playlist.rawPlaylist] The raw data
* @property {ExtractorData[]} data The data
*/
/**
* @typedef {object} ExtractorData
* @property {string} title The title
* @property {number} duration The duration
* @property {string} thumbnail The thumbnail
* @property {string|Readable|Duplex} engine The stream engine
* @property {number} views The views count
* @property {string} author The author
* @property {string} description The description
* @property {string} url The url
* @property {string} [version] The extractor version
* @property {TrackSource} [source="arbitrary"] The source
*/
export interface ExtractorModelData {

@@ -116,6 +194,25 @@ playlist?: {

version?: string;
important?: boolean;
source?: TrackSource;
}[];
}
/**
* The search query type
* This can be one of:
* - AUTO
* - YOUTUBE
* - YOUTUBE_PLAYLIST
* - SOUNDCLOUD_TRACK
* - SOUNDCLOUD_PLAYLIST
* - SOUNDCLOUD
* - SPOTIFY_SONG
* - SPOTIFY_ALBUM
* - SPOTIFY_PLAYLIST
* - FACEBOOK
* - VIMEO
* - ARBITRARY
* - REVERBNATION
* - YOUTUBE_SEARCH
* - SOUNDCLOUD_SEARCH
* @typedef {string} QueryType
*/
export declare enum QueryType {

@@ -138,2 +235,60 @@ AUTO = "auto",

}
/**
* Emitted when bot gets disconnected from a voice channel
* @event Player#botDisconnect
* @param {Queue} queue The queue
*/
/**
* Emitted when the voice channel is empty
* @event Player#channelEmpty
* @param {Queue} queue The queue
*/
/**
* Emitted when bot connects to a voice channel
* @event Player#connectionCreate
* @param {Queue} queue The queue
* @param {StreamDispatcher} connection The discord player connection object
*/
/**
* Debug information
* @event Player#debug
* @param {Queue} queue The queue
* @param {string} message The message
*/
/**
* Emitted on error
* <warn>This event should handled properly otherwise it may crash your process!</warn>
* @event Player#error
* @param {Queue} queue The queue
* @param {Error} error The error
*/
/**
* Emitted on connection error. Sometimes stream errors are emitted here as well.
* @event Player#connectionError
* @param {Queue} queue The queue
* @param {Error} error The error
*/
/**
* Emitted when queue ends
* @event Player#queueEnd
* @param {Queue} queue The queue
*/
/**
* Emitted when a single track is added
* @event Player#trackAdd
* @param {Queue} queue The queue
* @param {Track} track The track
*/
/**
* Emitted when multiple tracks are added
* @event Player#tracksAdd
* @param {Queue} queue The queue
* @param {Track[]} tracks The tracks
*/
/**
* Emitted when a track starts playing
* @event Player#trackStart
* @param {Queue} queue The queue
* @param {Track} track The track
*/
export interface PlayerEvents {

@@ -145,2 +300,3 @@ botDisconnect: (queue: Queue) => any;

error: (queue: Queue, error: Error) => any;
connectionError: (queue: Queue, error: Error) => any;
queueEnd: (queue: Queue) => any;

@@ -151,16 +307,34 @@ trackAdd: (queue: Queue, track: Track) => any;

}
/**
* @typedef {object} PlayOptions
* @property {boolean} [filtersUpdate=false] If this play was triggered for filters update
* @property {string[]} [encoderArgs=[]] FFmpeg args passed to encoder
* @property {number} [seek] Time to seek to before playing
* @property {boolean} [immediate=false] If it should start playing the provided track immediately
*/
export interface PlayOptions {
/** If this play is triggered for filters update */
filtersUpdate?: boolean;
/** ffmpeg args passed to encoder */
encoderArgs?: string[];
/** Time to seek to before playing */
seek?: number;
/** If it should start playing provided track immediately */
immediate?: boolean;
}
/**
* @typedef {object} SearchOptions
* @property {UserResolvable} requestedBy The user who requested this search
* @property {QueryType} [searchEngine=QueryType.AUTO] The query search engine
* @property {boolean} [blockExtractor=false] If it should block custom extractors
*/
export interface SearchOptions {
requestedBy: UserResolvable;
searchEngine?: QueryType;
blockExtractor?: boolean;
}
/**
* The queue repeat mode. This can be one of:
* - OFF
* - TRACK
* - QUEUE
* - AUTOPLAY
* @typedef {number} QueueRepeatMode
*/
export declare enum QueueRepeatMode {

@@ -172,2 +346,17 @@ OFF = 0,

}
/**
* @typedef {object} PlaylistInitData
* @property {Track[]} tracks The tracks of this playlist
* @property {string} title The playlist title
* @property {string} description The description
* @property {string} thumbnail The thumbnail
* @property {album|playlist} type The playlist type: `album` | `playlist`
* @property {TrackSource} source The playlist source
* @property {object} author The playlist author
* @property {string} [author.name] The author name
* @property {string} [author.url] The author url
* @property {string} id The playlist id
* @property {string} url The playlist url
* @property {any} [rawPlaylist] The raw playlist data
*/
export interface PlaylistInitData {

@@ -188,3 +377,17 @@ tracks: Track[];

}
/**
* @typedef {object} TrackJSON
* @property {string} title The track title
* @property {string} description The track description
* @property {string} author The author
* @property {string} url The url
* @property {string} thumbnail The thumbnail
* @property {string} duration The duration
* @property {number} durationMS The duration in ms
* @property {number} views The views count
* @property {Snowflake} requestedBy The id of the user who requested this track
* @property {PlaylistJSON} [playlist] The playlist info (if any)
*/
export interface TrackJSON {
id: Snowflake;
title: string;

@@ -201,2 +404,16 @@ description: string;

}
/**
* @typedef {object} PlaylistJSON
* @property {string} id The playlist id
* @property {string} url The playlist url
* @property {string} title The playlist title
* @property {string} description The playlist description
* @property {string} thumbnail The thumbnail
* @property {album|playlist} type The playlist type: `album` | `playlist`
* @property {TrackSource} source The track source
* @property {object} author The playlist author
* @property {string} [author.name] The author name
* @property {string} [author.url] The author url
* @property {TrackJSON[]} tracks The tracks data (if any)
*/
export interface PlaylistJSON {

@@ -216,5 +433,10 @@ id: string;

}
export interface DiscordPlayerInitOptions {
/**
* @typedef {object} PlayerInitOptions
* @property {boolean} [autoRegisterExtractor=true] If it should automatically register `@discord-player/extractor`
* @property {YTDLDownloadOptions} [ytdlOptions={}] The options passed to `ytdl-core`
*/
export interface PlayerInitOptions {
autoRegisterExtractor?: boolean;
ytdlOptions?: downloadOptions;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueueRepeatMode = exports.QueryType = void 0;
/**
* The search query type
* This can be one of:
* - AUTO
* - YOUTUBE
* - YOUTUBE_PLAYLIST
* - SOUNDCLOUD_TRACK
* - SOUNDCLOUD_PLAYLIST
* - SOUNDCLOUD
* - SPOTIFY_SONG
* - SPOTIFY_ALBUM
* - SPOTIFY_PLAYLIST
* - FACEBOOK
* - VIMEO
* - ARBITRARY
* - REVERBNATION
* - YOUTUBE_SEARCH
* - SOUNDCLOUD_SEARCH
* @typedef {string} QueryType
*/
var QueryType;

@@ -22,2 +42,10 @@ (function (QueryType) {

})(QueryType = exports.QueryType || (exports.QueryType = {}));
/**
* The queue repeat mode. This can be one of:
* - OFF
* - TRACK
* - QUEUE
* - AUTOPLAY
* @typedef {number} QueueRepeatMode
*/
var QueueRepeatMode;

@@ -24,0 +52,0 @@ (function (QueueRepeatMode) {

@@ -5,3 +5,5 @@ import { FiltersName } from "../types/types";

* @typedef {object} AudioFilters
* @property {string} bassboost The bassboost filter
* @property {string} bassboost_low The bassboost filter (+15dB)
* @property {string} bassboost The bassboost filter (+20dB)
* @property {string} bassboost_high The bassboost filter (+30dB)
* @property {string} 8D The 8D filter

@@ -39,3 +41,5 @@ * @property {string} vaporwave The vaporwave filter

declare const FilterList: {
bassboost_low: string;
bassboost: string;
bassboost_high: string;
"8D": string;

@@ -75,3 +79,3 @@ vaporwave: string;

}>;
readonly names: string[];
readonly names: (keyof import("../types/types").QueueFilters)[];
readonly length: number;

@@ -78,0 +82,0 @@ toString(): string;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AudioFilters = void 0;
const bass = (g) => `bass=g=${g}:f=110:w=0.3`;
/**
* The available audio filters
* @typedef {object} AudioFilters
* @property {string} bassboost The bassboost filter
* @property {string} bassboost_low The bassboost filter (+15dB)
* @property {string} bassboost The bassboost filter (+20dB)
* @property {string} bassboost_high The bassboost filter (+30dB)
* @property {string} 8D The 8D filter

@@ -40,3 +43,5 @@ * @property {string} vaporwave The vaporwave filter

const FilterList = {
bassboost: "bass=g=20:f=110:w=0.3",
bassboost_low: bass(15),
bassboost: bass(20),
bassboost_high: bass(30),
"8D": "apulsator=hz=0.09",

@@ -85,3 +90,3 @@ vaporwave: "aresample=48000,asetrate=48000*0.8",

toString() {
return this.names.map((m) => this[m]).join(",");
return this.names.map((m) => this[m]).join(","); // eslint-disable-line @typescript-eslint/no-explicit-any
},

@@ -88,0 +93,0 @@ create(filter) {

import { QueryType } from "../types/types";
declare class QueryResolver {
declare class QueryResolver extends null {
/**
* Query resolver
*/
constructor();
private constructor();
/**

@@ -8,0 +8,0 @@ * Resolves the given search query

@@ -7,2 +7,3 @@ "use strict";

const types_1 = require("../types/types");
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore

@@ -19,9 +20,7 @@ const soundcloud_scraper_1 = require("soundcloud-scraper");

// scary things above *sigh*
class QueryResolver {
class QueryResolver extends null {
/**
* Query resolver
*/
constructor() {
throw new Error("Cannot instantiate static class!");
}
constructor() { } // eslint-disable-line @typescript-eslint/no-empty-function
/**

@@ -28,0 +27,0 @@ * Resolves the given search query

import { StageChannel, VoiceChannel } from "discord.js";
import { TimeData } from "../types/types";
declare class Util {
declare class Util extends null {
/**
* Utils
*/
constructor();
private constructor();
/**

@@ -13,3 +13,3 @@ * Creates duration string

*/
static durationString(durObj: object): string;
static durationString(durObj: Record<string, number>): string;
/**

@@ -51,3 +51,4 @@ * Parses milliseconds to consumable time object

static wait(time: number): Promise<unknown>;
static get noop(): () => void;
}
export { Util };
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Util = void 0;
class Util {
class Util extends null {
/**
* Utils
*/
constructor() {
throw new Error("Cannot instantiate static class");
}
constructor() { } // eslint-disable-line @typescript-eslint/no-empty-function
/**

@@ -55,2 +53,3 @@ * Creates duration string

*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static last(arr) {

@@ -88,5 +87,8 @@ if (!Array.isArray(arr))

static wait(time) {
return new Promise((r) => setTimeout(r, time).unref());
return new Promise((r) => setTimeout(r, time));
}
static get noop() {
return () => { }; // eslint-disable-line @typescript-eslint/no-empty-function
}
}
exports.Util = Util;
import { VoiceChannel, StageChannel, Collection, Snowflake } from "discord.js";
import { VoiceConnection } from "@discordjs/voice";
import { StreamDispatcher } from "./BasicStreamDispatcher";
import { DiscordGatewayAdapterCreator, VoiceConnection } from "@discordjs/voice";
import { StreamDispatcher } from "./StreamDispatcher";
declare class VoiceUtils {

@@ -8,2 +8,3 @@ cache: Collection<Snowflake, StreamDispatcher>;

* The voice utils
* @private
*/

@@ -30,2 +31,3 @@ constructor();

maxTime?: number;
adapter?: DiscordGatewayAdapterCreator;
}): Promise<VoiceConnection>;

@@ -32,0 +34,0 @@ /**

@@ -15,6 +15,8 @@ "use strict";

const voice_1 = require("@discordjs/voice");
const BasicStreamDispatcher_1 = require("./BasicStreamDispatcher");
const StreamDispatcher_1 = require("./StreamDispatcher");
const AdapterCreator_1 = require("./AdapterCreator");
class VoiceUtils {
/**
* The voice utils
* @private
*/

@@ -37,3 +39,3 @@ constructor() {

const conn = yield this.join(channel, options);
const sub = new BasicStreamDispatcher_1.StreamDispatcher(conn, channel);
const sub = new StreamDispatcher_1.StreamDispatcher(conn, channel);
this.cache.set(channel.guild.id, sub);

@@ -50,3 +52,3 @@ return sub;

join(channel, options) {
var _a;
var _a, _b, _c;
return __awaiter(this, void 0, void 0, function* () {

@@ -56,7 +58,7 @@ let conn = voice_1.joinVoiceChannel({

channelId: channel.id,
adapterCreator: channel.guild.voiceAdapterCreator,
adapterCreator: (_b = (_a = options.adapter) !== null && _a !== void 0 ? _a : channel.guild.voiceAdapterCreator) !== null && _b !== void 0 ? _b : AdapterCreator_1.VoiceAdapterCreator(channel),
selfDeaf: Boolean(options.deaf)
});
try {
conn = yield voice_1.entersState(conn, voice_1.VoiceConnectionStatus.Ready, (_a = options === null || options === void 0 ? void 0 : options.maxTime) !== null && _a !== void 0 ? _a : 20000);
conn = yield voice_1.entersState(conn, voice_1.VoiceConnectionStatus.Ready, (_c = options === null || options === void 0 ? void 0 : options.maxTime) !== null && _c !== void 0 ? _c : 20000);
return conn;

@@ -76,3 +78,3 @@ }

disconnect(connection) {
if (connection instanceof BasicStreamDispatcher_1.StreamDispatcher)
if (connection instanceof StreamDispatcher_1.StreamDispatcher)
return connection.voiceConnection.destroy();

@@ -79,0 +81,0 @@ return connection.destroy();

{
"name": "discord-player",
"version": "5.0.0-dev.8e2f50cfb5cf1b077f98cb2c7d6d6a5dfddd2609",
"version": "5.0.0-dev.92a3409.1625911434",
"description": "Complete framework to facilitate music commands using discord.js",

@@ -13,6 +13,8 @@ "main": "lib/index.js",

"build": "rimraf lib && tsc",
"build:check": "tsc --noEmit --incremental false",
"format": "prettier --write \"src/**/*.ts\" \"example/**/*.ts\"",
"lint": "tslint -p tsconfig.json",
"docs": "docgen --jsdoc jsdoc.json --source src/*.ts src/**/*.ts --custom docs/index.yml --output docs/docs.json",
"docs:test": "docgen --jsdoc jsdoc.json --source src/*.ts src/**/*.ts --custom docs/index.yml"
"docs:test": "docgen --jsdoc jsdoc.json --source src/*.ts src/**/*.ts --custom docs/index.yml",
"lint": "eslint src --ext .ts",
"lint:fix": "eslint src --ext .ts --fix"
},

@@ -54,3 +56,3 @@ "funding": "https://github.com/Androz2091/discord-player?sponsor=1",

"dependencies": {
"@discordjs/voice": "^0.5.0",
"@discordjs/voice": "^0.5.3",
"discord-ytdl-core": "^5.0.4",

@@ -61,25 +63,26 @@ "libsodium-wrappers": "^0.7.9",

"tiny-typed-emitter": "^2.0.3",
"youtube-sr": "^4.1.4",
"ytdl-core": "^4.8.2"
"youtube-sr": "^4.1.7",
"ytdl-core": "^4.8.3"
},
"devDependencies": {
"@babel/cli": "^7.14.5",
"@babel/core": "^7.14.5",
"@babel/preset-env": "^7.14.5",
"@babel/core": "^7.14.6",
"@babel/preset-env": "^7.14.7",
"@babel/preset-typescript": "^7.14.5",
"@devsnowflake/docgen": "devsnowflake/docgen#ts-patch",
"@discord-player/extractor": "^3.0.2",
"@discordjs/opus": "^0.5.3",
"@types/node": "^15.12.2",
"@types/ws": "^7.4.4",
"@types/node": "^16.0.0",
"@types/ws": "^7.4.6",
"@typescript-eslint/eslint-plugin": "^4.28.1",
"@typescript-eslint/parser": "^4.28.1",
"discord-api-types": "^0.18.1",
"discord.js": "^13.0.0-dev.1f8f3ab0f8dbd346154bbfa14a98726b8df25d57",
"discord.js-docgen": "discordjs/docgen#ts-patch",
"discord.js": "^13.0.0-dev.d6c43a5.1625875428",
"eslint": "^7.30.0",
"jsdoc-babel": "^0.5.0",
"prettier": "^2.3.1",
"prettier": "^2.3.2",
"rimraf": "^3.0.2",
"ts-node": "^10.0.0",
"tslint": "^6.1.3",
"tslint-config-prettier": "^1.18.0",
"typescript": "^4.3.2"
"typescript": "^4.3.5"
}
}

@@ -8,5 +8,4 @@ # Discord Player

[![wakatime](https://wakatime.com/badge/github/Androz2091/discord-player.svg)](https://wakatime.com/badge/github/Androz2091/discord-player)
[![CodeFactor](https://www.codefactor.io/repository/github/androz2091/discord-player/badge/v5)](https://www.codefactor.io/repository/github/androz2091/discord-player/overview/v5)
> V5 WIP
## Installation

@@ -96,3 +95,3 @@

const track = await client.player.search(args[0], {
searchEngine: QueryType.YOUTUBE_SEARCH
requestedBy: message.author
}).then(x => x.tracks[1]);

@@ -99,0 +98,0 @@ if (!track) return void message.reply("Track not found!");

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc