UNPKG

discord-dj

Version:

Discord DJ Bot. Let you play music in your server. Inspired by PlugDJ

1 lines 5.58 kB
"use strict"; var Discordie = require('discordie'); var Utils = require('./Utils.js'); class InternalDJ { constructor(bot, voiceConnection, wrapper, handler, keys) { this.bot = bot; this.wrapper = wrapper; this.handler = handler; /* TODO: use it in the future */ this.voiceConnection = voiceConnection; this.playable = null; this.musicQueue = []; this.stream = null; this.decoder = null; this.encoder = null; this.multithreaded = false; this.bitrate = 64; this.stopping = false; this.keys = keys; this.disconnectedEvent = function(info) { if(info.voiceConnection == this.voiceConnection) this.destroy(); }.bind(this); this.bot.Dispatcher.on(Discordie.Events.VOICE_DISCONNECTED, this.disconnectedEvent); } destroy() { this.bot.Dispatcher.removeListener(Discordie.Events.VOICE_DISCONNECTED, this.disconnectedEvent); } decodeStream(stream, format, sampleRate, channels) { if(typeof format == 'undefined') format = null; var options = { sampleRate: sampleRate, channels: channels }; var decoders = Utils.getDecoders(); for(var i = 0; i < decoders.length; i++) { var decoder = decoders[i]; if(decoder.canDecode(format)) { this.decoder = decoder; return decoder.createDecoder(stream, options); } } return Promise.reject('No decoder found'); } playStream(stream, sampleRate, channels, bitDepth) { var options = { frameDuration: 60, sampleRate: sampleRate, channels: channels, float: false, multiThreadedVoice: this.multithreaded, bitrate: this.bitrate }; var readSize = sampleRate / 1000 * options.frameDuration * bitDepth / 8 * channels; var playable = this.playable; stream.once('readable', function() { if(this.playable != playable) return; this.encoder = this.voiceConnection.getEncoder(options); if(this.encoder == null) return; this.encoder.onNeedBuffer = function() { if(this.stopping) return; if(this.playable != playable) return this.stop(); if(this.decoder == null) return; if(stream == null) return; var chunk = stream.read(readSize); if(!chunk) return setTimeout(this.encoder.onNeedBuffer, options.frameDuration); var sampleCount = readSize / channels / (bitDepth / 8); this.encoder.enqueue(chunk, sampleCount); }.bind(this); this.encoder.onNeedBuffer(); }.bind(this)); } play(playable) { this.stop(); playable.init(this); this.playable = playable; var sampleRate = 48000; var bitDepth = 16; var channels = 2; playable.createStream().then(function(stream) { if(this.playable != playable) return; this.stream = stream; this.decodeStream(this.stream, playable.getFormat(), sampleRate, channels).then(function(decodedStream) { decodedStream.once('end', function() { if(this.stopping) return; if(this.playable != playable) return; this.playable = null; this.stream = null; this.skip(); }.bind(this)); decodedStream.once('readable', function() { if(this.playable != playable) return; this.wrapper.emit('play'); }.bind(this)); this.playStream(decodedStream, sampleRate, channels, bitDepth); }.bind(this), function(err) { console.log("Music skipped by a decoder error: " + err); }); }.bind(this), function(error) { console.log("Music skipped by an error: " + error); this.skip(); }.bind(this)); } stop() { if(this.stopping) return; this.stopping = true; try { if(this.decoder != null) { this.decoder.destroyDecoder(); this.decoder = null; } if(this.encoder != null) { this.encoder.kill(); this.encoder = null; } if(this.stream != null) { if(this.stream.end) this.stream.end(); if(this.stream.destroy) this.stream.destroy(); this.stream = null; } } catch(e) { console.log("An error ocurred while stopping the current music: " + e); } this.stopping = false; } skip() { this.stop(); if(this.playable != null) { this.playable.removeAllListeners('data-changed'); this.playable = null; } this.wrapper.emit('skip'); if(this.playable == null && this.musicQueue.length > 0) { this.play(this.musicQueue.shift()); } } addToQueue(playable) { playable.on('data-changed', function() { this.wrapper.emit('data-changed'); }.bind(this)); playable.loadData(); if(this.playable == null) { this.play(playable); } else { this.musicQueue.push(playable); } } } module.exports = InternalDJ;