Skip to content
Open
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@ package-lock.json

# custom

test/config.json
test/config.json
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock=false
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "lavalink.js",
"version": "0.1.1",
"license": "MIT",
"description": "A Lavalink client for eris",
"description": "A Lavalink client for Discord.js",
"homepage": "https://github.com/briantanner/lavalink.js",
"author": {
"name": "Brian Tanner",
Expand All @@ -20,6 +20,9 @@
"dependencies": {
"ws": "^3.1.0"
},
"peerDependencies": {
"eventemitter3": "^3.0.0"
},
"devDependencies": {
"discord.js": "^11.2.1",
"docdash": "^0.4.0",
Expand Down
11 changes: 5 additions & 6 deletions src/Lavalink.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ try {
* Represents a Lavalink node
* @extends EventEmitter
* @prop {string} host The hostname for the node
* @prop {number} port The port number for the node
* @prop {Number} port The port number for the node
* @prop {string} address The full ws address for the node
* @prop {string} region The region for this node
* @prop {string} userId The client user id
* @prop {number} numShards The total number of shards the bot is running
* @prop {Number} numShards The total number of shards the bot is running
* @prop {string} password The password used to connect
* @prop {boolean} connected If it's connected to the node
* @prop {boolean} draining True if this node will no longer take new connections
* @prop {object} stats The Lavalink node stats
* @prop {Object} stats The Lavalink node stats
*/
class Lavalink extends EventEmitter {

Expand All @@ -37,6 +37,7 @@ class Lavalink extends EventEmitter {
* @param {string} options.password The password for the Lavalink node
* @param {Number} [options.timeout=5000] Optional timeout in ms used for the reconnect backoff
*/

constructor(options) {
super();

Expand Down Expand Up @@ -77,9 +78,7 @@ class Lavalink extends EventEmitter {
this.ws.on('open', this.ready.bind(this));
this.ws.on('message', this.onMessage.bind(this));
this.ws.on('close', this.disconnectHandler);
this.ws.on('error', (err) => {
this.emit('error', err);
});
this.ws.on('error', err => this.emit('error', err));
}

/**
Expand Down
15 changes: 11 additions & 4 deletions src/Player.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* Created by NoobLance & Jacz on 01.01.2018.
*/
let EventEmitter;

try {
Expand All @@ -12,13 +15,13 @@ try {
* @prop {string} id Guild id for the player
* @prop {PlayerManager} manager Reference to the player manager
* @prop {Lavalink} node Lavalink node the player is connected to
* @prop {object} client The discord.js client
* @prop {Object} client The discord.js client
* @prop {string} hostname Hostname of the lavalink node
* @prop {string} guildId Guild ID
* @prop {string} channelId Channel ID
* @prop {boolean} ready If the connection is ready
* @prop {boolean} playing If the player is playing
* @prop {object} state The lavalink player state
* @prop {Object} state The lavalink player state
* @prop {string} track The lavalink track to play
*/
class Player extends EventEmitter {
Expand Down Expand Up @@ -84,7 +87,7 @@ class Player extends EventEmitter {
* @param {*} data The payload to send
* @private
*/
async sendEvent(data) {
sendEvent(data) {
this.receivedEvents.push(data);
this.node.send(data);
process.nextTick(() => this.checkEventQueue());
Expand Down Expand Up @@ -183,7 +186,7 @@ class Player extends EventEmitter {
this.node.send({
op: 'pause',
guildId: this.guildId,
pause: pause
pause: Boolean(pause)
});
}

Expand All @@ -193,6 +196,8 @@ class Player extends EventEmitter {
* @returns {void}
*/
seek(position) {
position = parseInt(position);
if (!Number.isInteger(position)) throw 'Position must be a integer';
this.node.send({
op: 'seek',
guildId: this.guildId,
Expand All @@ -206,6 +211,8 @@ class Player extends EventEmitter {
* @returns {void}
*/
setVolume(volume) {
volume = parseInt(volume);
if (!Number.isInteger(volume)) throw 'Volume must be a integer';
this.node.send({
op: 'volume',
guildId: this.guildId,
Expand Down
80 changes: 37 additions & 43 deletions src/PlayerManager.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
/**
* Created by NoobLance & Jacz on 01.01.2018.
* DISCLAIMER: Direct port from eris-lavalink
*/
const Lavalink = require('./Lavalink');
const Player = require('./Player');

/**
* Player Manager
* @extends Map
* @prop {Player} baseObject The player class used to create new players
* @prop {object} client The discord.js client
* @prop {object} defaultRegions The default region config
* @prop {object} regions The region config being used
* @prop {Object} client The discord.js client
* @prop {Object} defaultRegions The default region config
* @prop {Object} regions The region config being used
*/
class PlayerManager extends Map {

/**
* PlayerManager constructor
* @param {Client} client Eris client
* @param {Object[]} nodes The Lavalink nodes to connect to
* @param {Map<string, Lavalink>} nodes The Lavalink nodes to connect to
* @param {Object} [options] Setup options
* @param {string} [options.defaultRegion] The default region
* @param {Number} [options.failoverRate=250] Failover rate in ms
Expand Down Expand Up @@ -84,8 +88,9 @@ class PlayerManager extends Map {
* @param {string} host The hostname of the node
*/
removeNode(host) {
const node = this.nodes.get(host);
if (!host) return;
const node = this.nodes.get(host);
if (!node) return;
node.destroy();
this.nodes.delete(host);
this.onDisconnect(node);
Expand All @@ -96,7 +101,7 @@ class PlayerManager extends Map {
* @private
*/
checkFailoverQueue() {
if (this.failoverQueue.length > 0) {
if (this.failoverQueue.length) {
const fns = this.failoverQueue.splice(0, this.failoverLimit);
for (const fn of fns) {
this.processQueue(fn);
Expand All @@ -111,7 +116,7 @@ class PlayerManager extends Map {
* @private
*/
queueFailover(fn) {
if (this.failoverQueue.length > 0) {
if (this.failoverQueue.length) {
this.failoverQueue.push(fn);
} else {
return this.processQueue(fn);
Expand All @@ -135,7 +140,7 @@ class PlayerManager extends Map {
* @private
*/
onError(node, err) {
this.client.emit(err);
this.client.emit('error', err);
}

/**
Expand All @@ -156,16 +161,11 @@ class PlayerManager extends Map {
* @private
*/
onReady() {
for (const player of [...this.values()]) {
for (const player of this.values()) {
this.queueFailover(this.switchNode.bind(this, player));
}
}

/**
* Client raw event listener
* @param {object} packet Packet received from the gateway
* @private
**/
onRaw(packet) {
switch (packet.t) {
case 'VOICE_SERVER_UPDATE':
Expand All @@ -188,11 +188,11 @@ class PlayerManager extends Map {
* @param {boolean} leave Whether to leave the channel or not on our side
*/
switchNode(player, leave) {
const { guildId, channelId, track } = player,
position = (player.state.position || 0) + (this.options.reconnectThreshold || 2000);
const { guildId, channelId, track } = player;
const position = (player.state.position || 0) + (this.options.reconnectThreshold || 2000);

const listeners = player.listeners('end'),
endListeners = [];
const listeners = player.listeners('end');
const endListeners = [];

if (listeners && listeners.length) {
for (const listener of listeners) {
Expand Down Expand Up @@ -224,16 +224,15 @@ class PlayerManager extends Map {
this.set(guildId, player);
})
.catch(err => {
player.emit('disconnect', err);
player.disconnect();
player.disconnect(err);
});
});
}

/**
* Called when a message is received from the voice node
* @param {Lavalink} node The Lavalink node
* @param {*} message The message received
* @param {Object} message The message received
* @returns {*}
* @private
*/
Expand Down Expand Up @@ -288,7 +287,7 @@ class PlayerManager extends Map {

this.client.ws.send(payload);

if (payload.op === 4 && payload.d.channel_id === null) {
if (payload.op === 4 && !payload.d.channel_id) {
this.delete(payload.d.guild_id);
}
}
Expand All @@ -303,14 +302,10 @@ class PlayerManager extends Map {
if (!player) return;

switch (message.type) {
case 'TrackEndEvent':
return player.onTrackEnd(message);
case 'TrackExceptionEvent':
return player.onTrackException(message);
case 'TrackStuckEvent':
return player.onTrackStuck(message);
default:
return player.emit('warn', `Unexpected event type: ${message.type}`);
case 'TrackEndEvent': return player.onTrackEnd(message);
case 'TrackExceptionEvent': return player.onTrackException(message);
case 'TrackStuckEvent': return player.onTrackStuck(message);
default: return player.emit('warn', `Unexpected event type: ${message.type}`);
}
}
}
Expand All @@ -326,21 +321,20 @@ class PlayerManager extends Map {
*/
async join(guildId, channelId, options, player) {
options = options || {};

player = player || this.get(guildId);
if (player && player.channelId !== channelId) {
player.switchChannel(channelId);
return Promise.resolve(player);
}
return new Promise(async (res, rej) => {
if (player && player.channelId !== channelId) {
player.switchChannel(channelId);
return res(player);
}

const region = this.getRegionFromData(options.region || 'us');
const node = await this.findIdealNode(region);
const region = this.getRegionFromData(options.region || 'us');
const node = await this.findIdealNode(region);

if (!node) {
return Promise.reject('No available voice nodes.');
}
if (!node) {
return rej('No available voice nodes.');
}

return new Promise((res, rej) => {
this.pendingGuilds[guildId] = {
channelId: channelId,
options: options || {},
Expand Down Expand Up @@ -402,7 +396,7 @@ class PlayerManager extends Map {

/**
* Called by eris when a voice server update is received
* @param {*} data The voice server update from eris
* @param {Object} data The voice server update from eris
* @private
*/
async voiceServerUpdate(data) {
Expand Down Expand Up @@ -485,7 +479,7 @@ class PlayerManager extends Map {
/**
* Get ideal region from data
* @param {string} endpoint Endpoint or region
* @returns {void}
* @returns {string}
* @private
*/
getRegionFromData(endpoint) {
Expand Down
2 changes: 0 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use strict';

const Player = require('./Player');
const PlayerManager = require('./PlayerManager');
const Lavalink = require('./Lavalink');
Expand Down
Loading