player-engine
Version:
Play your Musics in Your Discord Music Bot | Discord.js V13 Only
263 lines (262 loc) • 12.2 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const discord_js_1 = require("discord.js");
const voice_1 = require("@discordjs/voice");
const Queue_1 = __importDefault(require("./Queue"));
const Engines = __importStar(require("music-engines"));
const PlayerError_1 = __importDefault(require("../utils/PlayerError"));
const Enums_1 = require("../utils/Enums");
const PlayerTrack_1 = __importDefault(require("../Structers/PlayerTrack"));
const events_1 = require("events");
const { SoundCloud, Spotify, YouTube, Deezer, wrappers } = Engines;
const { youtube, soundcloud, spotify, deezer } = wrappers;
const { YouTubeTrack } = youtube;
const { SoundCloudTrack } = soundcloud;
const { SpotifyTrack } = spotify;
const { DeezerTrack } = deezer;
class Player extends events_1.EventEmitter {
constructor(guild, opts) {
super({
captureRejections: true
});
this.engine = new YouTube();
this.repeat = "none";
this.guild = guild;
this.settings = opts;
this.setEngine(this.settings.engine);
this.tracks = new Queue_1.default();
}
watchDestroyed(emit = true) {
if (this.isDestroyed && emit)
this.emit(Enums_1.PlayerEvents.ERROR, new PlayerError_1.default(Enums_1.Errors.NOT_EXIST, `This Player is destroyed and doesn't exist.`));
return this.isDestroyed;
}
destroy(dc = true) {
if (this.watchDestroyed())
return;
if (this.vcSubscription instanceof voice_1.PlayerSubscription)
this.vcSubscription.unsubscribe();
this.vcSubscription = null;
if (dc)
this.vcConnection.disconnect();
this.vcConnection.destroy();
}
setEngine(engine) {
if (this.watchDestroyed())
return;
if (!(engine in Engines))
throw new PlayerError_1.default(Enums_1.Errors.NOT_SUPPORTED, `${engine} is not supported by Music-Engines package.`);
this.settings.engine = engine;
this.engine = new Engines[engine];
return this;
}
setBitrate(a) {
var _a;
if (this.watchDestroyed())
return;
if (a === "auto")
a = (_a = this.channel.bitrate) !== null && _a !== void 0 ? _a : 64000;
this.tracks.setMusicBitrates(a);
}
setVolume(a) {
if (this.watchDestroyed())
return;
if (a > Infinity || a < 0 || isNaN(a))
return false;
this.tracks.setMusicBitrates(a);
return true;
}
setRepeatMode(mode) {
if (this.watchDestroyed())
return;
const modes = ["one", "all", "none"];
if (!modes.includes(mode))
return false;
this.repeat = mode;
return true;
}
isChannelEmpty(channel) {
if (this.watchDestroyed())
return;
if (!this.channel && !channel)
throw new PlayerError_1.default(Enums_1.Errors.NOT_EXIST, 'There is no VoiceConnection for a channel established Yet.');
if (!channel)
channel = this.channel;
return channel.members.filter(x => !x.user.bot).size === 0;
}
search(query, options = { engine: this.settings.engine, single: true }) {
return __awaiter(this, void 0, void 0, function* () {
if (this.watchDestroyed())
return;
const engine = (options.engine && options.engine in Engines) ? new Engines[options.engine] : this.engine;
const searchRes = yield engine.use(query);
if (Array.isArray(searchRes)) {
if (options.single)
if (searchRes[0] instanceof YouTubeTrack || searchRes[0] instanceof SpotifyTrack || searchRes[0] instanceof SoundCloudTrack || searchRes[0] instanceof DeezerTrack)
return new PlayerTrack_1.default(searchRes[0]);
else if (options.limit)
searchRes.length = options.limit;
return searchRes.map(x => new PlayerTrack_1.default(x));
}
else
return new PlayerTrack_1.default(searchRes);
});
}
connection(channel) {
if (this.watchDestroyed())
return;
if (this.vcConnection)
return this.vcConnection;
else if ((0, voice_1.getVoiceConnection)(this.guild.id)) {
this.vcConnection = (0, voice_1.getVoiceConnection)(this.guild.id);
this.isConnected = true;
return this.vcConnection;
}
else if (channel instanceof discord_js_1.VoiceChannel || channel instanceof discord_js_1.StageChannel) {
this.vcConnection = (0, voice_1.joinVoiceChannel)({
adapterCreator: channel.guild.voiceAdapterCreator,
guildId: this.guild.id,
channelId: channel.id,
selfDeaf: ('selfDeaf' in this.settings) ? this.settings.selfDeaf : true,
selfMute: ('selfMute' in this.settings) ? this.settings.selfMute : false
});
this.isConnected = true;
// Handle Voice Connection Events
this.vcConnection.on("error", (e) => { this.emit(Enums_1.PlayerEvents.ERROR, e); });
this.vcConnection.on(voice_1.VoiceConnectionStatus.Ready, (o, n) => {
this.emit(Enums_1.PlayerEvents.CONNECT, o, n);
this.isConnected = true;
});
// Handle Server Reconnects
this.vcConnection.on(voice_1.VoiceConnectionStatus.Disconnected, (o, n) => __awaiter(this, void 0, void 0, function* () {
try {
yield Promise.race([
(0, voice_1.entersState)(this.vcConnection, voice_1.VoiceConnectionStatus.Signalling, 5000),
(0, voice_1.entersState)(this.vcConnection, voice_1.VoiceConnectionStatus.Connecting, 5000),
]);
}
catch (error) {
this.emit(Enums_1.PlayerEvents.DISCONNECT, error);
}
}));
return this.vcConnection;
}
else if (channel)
throw new PlayerError_1.default(Enums_1.Errors.INVALID_INPUT, `Channel is not a VoiceChannel or StageChannel.`);
else
throw new PlayerError_1.default(Enums_1.Errors.NOT_EXIST, `There is no VoiceConnection established neither recived a valid input in the method.`);
}
pause(interpolateSilence = true) {
if (this.watchDestroyed())
return;
if (!this.vcConnection || !this.audioPlayer)
throw new PlayerError_1.default(Enums_1.Errors.NOT_EXIST, 'There is no Voice Connection or Audio Player established Yet.');
return this.audioPlayer.pause(interpolateSilence);
}
resume() {
if (this.watchDestroyed())
return;
if (!this.vcConnection || !this.audioPlayer)
throw new PlayerError_1.default(Enums_1.Errors.NOT_EXIST, 'There is no Voice Connection or Audio Player established Yet.');
return this.audioPlayer.unpause();
}
stop(unsubscribe = false, forceStop = true) {
if (this.watchDestroyed())
return;
if (!this.vcConnection || !this.audioPlayer || !this.vcSubscription)
throw new PlayerError_1.default(Enums_1.Errors.NOT_EXIST, 'There is no VoiceConnection, AudioPlayer or VoiceSubscription established Yet.');
if (unsubscribe && this.vcSubscription) {
if (this.vcSubscription instanceof voice_1.PlayerSubscription)
this.vcSubscription.unsubscribe();
this.vcSubscription = null;
}
return this.audioPlayer.stop(forceStop);
}
play(tracks, interaction) {
return __awaiter(this, void 0, void 0, function* () {
if (this.watchDestroyed())
return;
if (!this.vcConnection || !this.isConnected)
throw new PlayerError_1.default(Enums_1.Errors.NOT_EXIST, 'There is no Voice Connection established Yet.');
if (!this.audioPlayer)
this.audioPlayer = (0, voice_1.createAudioPlayer)({
behaviors: {
noSubscriber: (this.settings.leaveOnEnd) ? voice_1.NoSubscriberBehavior.Stop : voice_1.NoSubscriberBehavior.Pause
}
});
if (this.tracks.initialized)
yield tracks.map((x) => __awaiter(this, void 0, void 0, function* () { return yield x.init(); }));
this.tracks.addTracks(tracks);
if (!this.tracks.initialized)
yield this.tracks.init();
if (!this.isPlaying) {
this.audioPlayer.play(this.tracks.current().createResource());
if (!this.vcSubscription)
this.vcSubscription = this.vcConnection.subscribe(this.audioPlayer);
this.emit(Enums_1.PlayerEvents.TRACK, this.tracks.current());
this.isPlaying = true;
}
// Handle Next Tracks
this.audioPlayer.on(voice_1.AudioPlayerStatus.Idle, (o, n) => {
// Handle Repeat Mode
if (this.repeat == "all")
this.tracks.repeat();
else if (this.repeat == "one")
this.tracks.repeatOne();
if (!this.tracks.nextTracks().length) {
this.emit(Enums_1.PlayerEvents.END, this.tracks.current());
if (this.settings.leaveOnEnd) {
if (this.vcSubscription instanceof voice_1.PlayerSubscription)
this.vcSubscription.unsubscribe();
this.vcConnection.disconnect();
this.vcConnection.destroy();
}
}
else {
this.tracks.next();
this.audioPlayer.play(this.tracks.current().createResource());
this.emit(Enums_1.PlayerEvents.TRACK, this.tracks.current());
}
});
this.audioPlayer.on("error", (e) => {
this.emit(Enums_1.PlayerEvents.ERROR, e);
});
});
}
}
exports.default = Player;