// encapsulate a channel where we do playback class ShredPlaybackChannel { constructor(guildID, vcID, vtID=null, autoJoin=false, active=true) { this._guildID = guildID; this._vcID = vcID; this._vtID = vtID; this._uri = ShredPlaybackChannel.defaultURI; this._auto = autoJoin; this._active = active; } get guildID() { return this._guildID; } get vcID() { return this._vcID; } get vtID() { return this._vtID; } get uri() { return this._uri; } get autoJoin() { return this.autoJoin === true; } get active() { return this._active === true; } stopPlayback(part=false) { if(this.voiceConnection) { // stop if we are already playing (allows start to reset) console.log("Stopping player.."); this.voiceConnection.stopPlaying(); if( part !== false ) { this.voiceConnection.leave(); } } else { console.log("Unable to stop playback: no voice connection."); } } restartPlaybackDelayed( // miliseconds of delay before resuming playback delay=ShredPlaybackChannel.defaultRestartPlaybackDelayMS ) { setTimeout( function() { this.onVoiceConnection() }, delay ); } startPlayback() { if(this.voiceConnection) { // stop if we are already playing (allows start to reset) if(this.voiceConnection.playing) { this.stopPlayback(); } // invokes FFMPEG this.voiceConnection.play( ShredPlaybackChannel.defaultURI, ShredPlaybackChannel.defaultStreamOptions ); // if that didn't throw the stream is now active this._active = true; // auto-reconnect unless stream if stream was active this.voiceConnection.once("end", function () { if(this.active) { this._active = false; this.restartPlaybackDelayed(); } }); } else { console.log("Unable to start playback: no voice connection."); } } onVoiceConnection(voiceConnection=null) { if(voiceConnection) { // save new voiceConnection when provided this.voiceConnection = voiceConnection; } if(this.active) { this.startPlayback(); } } endVoiceConnection() { this._active = false; if(this.voiceConnection) { this.stopPlaying(); this.voiceConnection = null; } else { console.log(`Cannot end voice connection, no connection to channel ID ${this.vcID}`); } } startVoiceConnection(bot) { const me = this; bot.joinVoiceChannel( me.vcID ).catch((err) => { console.log( 'ERROR: failed to join channel ' + `${this.vcID} on guild ${this.guildID}: ` + err); console.debug( me ); }).then(function (vc) { me.onVoiceConnection(vc); if( me.vtID ) { bot.createMessage( me.vtID, `Now playing **${me.uri}**`) } }); } static JoinAndPlay( bot, guildID, voiceChannelID, voiceTextChannelID=null, autoJoin=false, active=true ) { try { const ch = new ShredPlaybackChannel( guildID, voiceChannelID, voiceTextChannelID, autoJoin, active ); ch.startVoiceConnection(bot); return ch; } catch (err) { console.log( 'ERROR: failed to join channel ' +`${voiceChannelID} on guild ${guildID}: ` + err ); } } static get defaultURI() { return "https://shred.ing/live.ogg"; } static get defaultStreamOptions() { return { voiceDataTimeout: -1 }; } static get defaultRestartPlaybackDelayMS() { return 1500; } } module.exports = ShredPlaybackChannel;