UNPKG

disrexom

Version:

A Discord.js module to simplify your music commands and play songs with audio filters on Discord without any API key. Support YouTube, SoundCloud, Bandcamp, Facebook, and 700+ more sites

236 lines 8.32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DisTubeVoice = void 0; const tiny_typed_emitter_1 = require("tiny-typed-emitter"); const __1 = require("../.."); const voice_1 = require("@discordjs/voice"); /** * Create a voice connection to the voice channel */ class DisTubeVoice extends tiny_typed_emitter_1.TypedEmitter { constructor(voiceManager, channel) { super(); if (!(0, __1.isSupportedVoiceChannel)(channel)) throw new __1.DisTubeError("NOT_SUPPORTED_VOICE"); if (!channel.joinable) { if (channel.full) throw new __1.DisTubeError("VOICE_FULL"); else throw new __1.DisTubeError("VOICE_MISSING_PERMS"); } this.isDisconnected = false; this.id = channel.guild.id; this.channel = channel; /** * The voice manager that instantiated this connection * @type {DisTubeVoiceManager} */ this.voices = voiceManager; this.voices.add(this.id, this); this._volume = 0.5; this.audioPlayer = (0, voice_1.createAudioPlayer)() .on(voice_1.AudioPlayerStatus.Idle, oldState => { if (oldState.status !== voice_1.AudioPlayerStatus.Idle) { delete this.audioResource; this.emit("finish"); } }) .on("error", error => { if (this.emittedError) return; this.emittedError = true; this.emit("error", error); }); this.connection .on(voice_1.VoiceConnectionStatus.Disconnected, (_, newState) => { if (newState.reason === voice_1.VoiceConnectionDisconnectReason.WebSocketClose && newState.closeCode === 4014) { (0, voice_1.entersState)(this.connection, voice_1.VoiceConnectionStatus.Connecting, 5e3).catch(() => { this.leave(); }); } else if (this.connection.rejoinAttempts < 5) { setTimeout(() => { this.connection.rejoin(); }, (this.connection.rejoinAttempts + 1) * 5e3).unref(); } else if (this.connection.state.status !== voice_1.VoiceConnectionStatus.Destroyed) { this.leave(new __1.DisTubeError("VOICE_RECONNECT_FAILED")); } }) .on(voice_1.VoiceConnectionStatus.Destroyed, () => { this.leave(); }) // eslint-disable-next-line no-console .on("error", console.warn); this.connection.subscribe(this.audioPlayer); /** * Get or set the volume percentage * @name DisTubeVoice#volume * @type {number} */ } get channel() { return this._channel; } set channel(channel) { if (!(0, __1.isSupportedVoiceChannel)(channel)) throw new __1.DisTubeError("NOT_SUPPORTED_VOICE"); if (channel.guild.id !== this.id) throw new __1.DisTubeError("VOICE_CHANGE_GUILD"); this.connection = this._join(channel); this._channel = channel; } _join(channel) { return (0, voice_1.joinVoiceChannel)({ channelId: channel.id, guildId: this.id, adapterCreator: channel.guild.voiceAdapterCreator || (0, __1.createDiscordJSAdapter)(channel), }); } /** * Join a voice channel with this connection * @param {Discord.VoiceChannel|Discord.StageChannel} [channel] A voice channel * @private * @returns {Promise<DisTubeVoice>} */ async join(channel) { const TIMEOUT = 30e3; if (channel) { this.channel = channel; } try { await (0, voice_1.entersState)(this.connection, voice_1.VoiceConnectionStatus.Ready, TIMEOUT); } catch { if (this.connection.state.status !== voice_1.VoiceConnectionStatus.Destroyed) { this.connection.destroy(); } this.voices.delete(this.id); throw new __1.DisTubeError("VOICE_CONNECT_FAILED", TIMEOUT / 1e3); } return this; } /** * Leave the voice channel of this connection * @param {Error} [error] Optional, an error to emit with 'error' event. */ leave(error) { this.stop(); if (!this.isDisconnected) { this.emit("disconnect", error); this.isDisconnected = true; } if (this.connection.state.status !== voice_1.VoiceConnectionStatus.Destroyed) this.connection.destroy(); this.voices.delete(this.id); } /** * Stop the playing stream * @private */ stop() { this.audioPlayer.stop(); } /** * Play a readable stream * @private * @param {DisTubeStream} stream Readable stream */ play(stream) { this.emittedError = false; stream.stream.on("error", (error) => { if (this.emittedError || error.code === "ERR_STREAM_PREMATURE_CLOSE") return; this.emittedError = true; this.emit("error", error); }); this.audioResource = (0, voice_1.createAudioResource)(stream.stream, { inputType: stream.type, inlineVolume: true, }); // eslint-disable-next-line no-self-assign this.volume = this.volume; this.audioPlayer.play(this.audioResource); } set volume(volume) { var _a, _b; if (typeof volume !== "number" || isNaN(volume)) { throw new __1.DisTubeError("INVALID_TYPE", "number", volume, "volume"); } if (volume < 0) { throw new __1.DisTubeError("NUMBER_COMPARE", "Volume", "bigger or equal to", 0); } this._volume = volume / 100; (_b = (_a = this.audioResource) === null || _a === void 0 ? void 0 : _a.volume) === null || _b === void 0 ? void 0 : _b.setVolume(Math.pow(this._volume, 0.5 / Math.log10(2))); } get volume() { return this._volume * 100; } /** * Playback duration of the audio resource in seconds * @type {number} */ get playbackDuration() { var _a; return (((_a = this.audioResource) === null || _a === void 0 ? void 0 : _a.playbackDuration) || 0) / 1000; } pause() { this.audioPlayer.pause(); } unpause() { this.audioPlayer.unpause(); } /** * Whether the bot is self-deafened * @type {boolean} */ get selfDeaf() { return this.connection.joinConfig.selfDeaf; } /** * Whether the bot is self-muted * @type {boolean} */ get selfMute() { return this.connection.joinConfig.selfMute; } /** * Self-deafens/undeafens the bot. * @param {boolean} selfDeaf Whether or not the bot should be self-deafened * @returns {boolean} true if the voice state was successfully updated, otherwise false */ setSelfDeaf(selfDeaf) { if (typeof selfDeaf !== "boolean") { throw new __1.DisTubeError("INVALID_TYPE", "boolean", selfDeaf, "selfDeaf"); } return this.connection.rejoin({ ...this.connection.joinConfig, selfDeaf, }); } /** * Self-mutes/unmutes the bot. * @param {boolean} selfMute Whether or not the bot should be self-muted * @returns {boolean} true if the voice state was successfully updated, otherwise false */ setSelfMute(selfMute) { if (typeof selfMute !== "boolean") { throw new __1.DisTubeError("INVALID_TYPE", "boolean", selfMute, "selfMute"); } return this.connection.rejoin({ ...this.connection.joinConfig, selfMute, }); } /** * The voice state of this connection * @type {Discord.VoiceState?} */ get voiceState() { var _a, _b, _c; return (_c = (_b = (_a = this.channel) === null || _a === void 0 ? void 0 : _a.guild) === null || _b === void 0 ? void 0 : _b.me) === null || _c === void 0 ? void 0 : _c.voice; } } exports.DisTubeVoice = DisTubeVoice; exports.default = DisTubeVoice; //# sourceMappingURL=DisTubeVoice.js.map