From 4fde3cef4cd3edf20a7f07bbeb1d673dedf7a254 Mon Sep 17 00:00:00 2001 From: Jacz Date: Mon, 18 Mar 2019 17:47:33 +1100 Subject: [PATCH] Revert "The start of a new module! (#50)" (#51) This reverts commit 32fabc7528121563b89ae597dcb0dd0ad9420604. --- .gitignore | 2 - .npmignore | 3 +- .travis.yml | 14 ++ LICENSE | 2 +- azure-pipelines.yml | 64 +++----- docs.js | 2 +- example/app.js | 2 +- package.json | 21 ++- scripts/travis-deploy.sh | 29 ++++ src/index.js | 16 ++ src/index.ts | 5 - src/lib/{LavalinkNode.ts => LavalinkNode.js} | 77 +++++---- src/lib/{Player.ts => Player.js} | 62 +++----- .../{PlayerManager.ts => PlayerManager.js} | 150 ++++++++++++++---- src/lib/Types.ts | 67 -------- tsconfig.json | 31 ---- tslint.json | 12 +- typings/index.d.ts | 132 +++++++++++++++ yarn.lock | 5 +- 19 files changed, 418 insertions(+), 278 deletions(-) create mode 100644 .travis.yml create mode 100644 scripts/travis-deploy.sh create mode 100644 src/index.js delete mode 100644 src/index.ts rename src/lib/{LavalinkNode.ts => LavalinkNode.js} (79%) rename src/lib/{Player.ts => Player.js} (79%) rename src/lib/{PlayerManager.ts => PlayerManager.js} (50%) delete mode 100644 src/lib/Types.ts delete mode 100644 tsconfig.json create mode 100644 typings/index.d.ts diff --git a/.gitignore b/.gitignore index ab4da0a..e7c1d47 100644 --- a/.gitignore +++ b/.gitignore @@ -58,5 +58,3 @@ jspm_packages/ package-lock.json example/config.json -dist/ - diff --git a/.npmignore b/.npmignore index f5915ec..09cfc1e 100644 --- a/.npmignore +++ b/.npmignore @@ -7,5 +7,4 @@ testing .travis.yml docs.js tslint.json -example -azure-pipelines.yml \ No newline at end of file +example \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b9d2f39 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +language: node_js +node_js: + - "10" + - "11" +install: npm install +jobs: + include: + - stage: test + script: npm test + - stage: deploy + script: bash ./scripts/travis-deploy.sh +cache: + directories: + - node_modules diff --git a/LICENSE b/LICENSE index 17868ef..ff2057b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018-2019 Jacz +Copyright (c) 2018 Jacz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 443cf68..e88639a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,52 +1,32 @@ +# Node.js +# Build a general Node.js project with npm. +# Add steps that analyze code, save build artifacts, deploy, and more: +# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript + +trigger: +- master + pool: vmImage: 'ubuntu-16.04' strategy: matrix: - node_11_x: - node_version: 11.x node_10_x: node_version: 10.x + node_11_x: + node_version: 11.x steps: - - task: NodeTool@0 - inputs: - versionSpec: $(node_version) - displayName: 'Install Node.js' - - script: yarn - displayName: 'Install Dependencies' - - script: yarn run test:lint - displayName: 'Run test lint' - condition: succeededOrFailed() - - bash: | - set -e - - if [ "$TRAVIS_BRANCH" != "master" -o -n "$TRAVIS_TAG" -o "$TRAVIS_PULL_REQUEST" != "false" ]; then - echo -e "Not building for a non master branch push - building without deploying." - npm run docs - exit 0 - fi - - echo -e "Building for a master branch push - building and deploying." - - REPO=$(git config remote.origin.url) - SHA=$(git rev-parse --verify HEAD) - - TARGET_BRANCH="gh-pages" - git clone $REPO out -b $TARGET_BRANCH - - yarn run docs - - rsync -vau docs/ out/ - - cd out - git add --all . - git config user.name "Azure Pipelines" - git config user.email "${COMMIT_EMAIL}" - git commit -m "Docs build: ${SHA}" || true - git push "https://${GH_TOKEN}@github.com/MrJacz/discord.js-lavalink.git" $TARGET_BRANCH - env: - COMMIT_EMAIL: $(commitEmail) - GH_TOKEN: $(githubToken) - displayName: 'Build docs' +- task: NodeTool@0 + inputs: + versionSpec: $(node_version) + displayName: 'Install Node.js' + +- script: | + npm install + displayName: 'npm install' + +- script: | + npm run test + displayName: 'run tests' \ No newline at end of file diff --git a/docs.js b/docs.js index 6c7b1b4..dfd4bcf 100644 --- a/docs.js +++ b/docs.js @@ -23,7 +23,7 @@ Docma.create() }, src: [ { readme: "./README.md" }, - { lavalink: "./dist/*/**/*.js" } + { lavalink: "./src/*/**/*.js" } ], dest: "./docs", jsdoc: { plugins: ["jsdoc-dynamic"] }, diff --git a/example/app.js b/example/app.js index d410b1e..1fb5f30 100644 --- a/example/app.js +++ b/example/app.js @@ -2,7 +2,7 @@ const config = require("./config.json"); const fetch = require("node-fetch"); const { URLSearchParams } = require("url"); const { Client } = require("discord.js"); -const { PlayerManager } = require("../dist/index.js"); +const { PlayerManager } = require("../src/index"); class MusicClient extends Client { diff --git a/package.json b/package.json index e2449da..924f2f8 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,12 @@ { "name": "discord.js-lavalink", - "version": "3.0.0", + "version": "2.2.2", "description": "A discord.js lavalink client", - "main": "dist/src/index", + "main": "src/index.js", + "types": "typings/index.d.ts", "scripts": { - "prepublishOnly": "yarn compile", - "lint": "tslint --fix 'src/**/*.ts'", - "test:lint": "tslint 'src/**/*.ts'", - "compile": "tsc -p .", - "watch": "tsc -p . -w", + "test": "eslint src && tslint 'typings/*.ts'", + "lint": "eslint --fix src test && tslint --fix 'typings/*.ts'", "docs": "node docs.js" }, "repository": { @@ -21,7 +19,6 @@ "discord", "api", "lava", - "link", "lavalink", "lavalink.js", "discord.js" @@ -33,19 +30,19 @@ }, "homepage": "https://github.com/MrJacz/discord.js-lavalink#readme", "devDependencies": { - "@types/node": "^11.11.3", + "@types/node": "^11.9.5", "@types/ws": "^6.0.1", "discord.js": "discordjs/discord.js", "docma": "^3.2.2", - "eslint": "^5.15.2", + "eslint": "^5.14.1", "eslint-plugin-node": "^8.0.1", "eslint-plugin-promise": "^4.0.1", "jsdoc-dynamic": "^1.0.4", - "tslint": "^5.14.0", + "tslint": "^5.12.1", "typescript": "^3.3.3333" }, "dependencies": { - "ws": "^6.2.0" + "ws": "^6.1.4" }, "peerDependencies": { "discord.js": "^11.4.2" diff --git a/scripts/travis-deploy.sh b/scripts/travis-deploy.sh new file mode 100644 index 0000000..84d6e59 --- /dev/null +++ b/scripts/travis-deploy.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# Based on https://github.com/hydrabolt/discord.js-site/blob/master/deploy/deploy.sh + +set -e + +if [ "$TRAVIS_BRANCH" != "master" -o -n "$TRAVIS_TAG" -o "$TRAVIS_PULL_REQUEST" != "false" ]; then + echo -e "Not building for a non master branch push - building without deploying." + npm run docs + exit 0 +fi + +echo -e "Building for a master branch push - building and deploying." + +REPO=$(git config remote.origin.url) +SHA=$(git rev-parse --verify HEAD) + +TARGET_BRANCH="gh-pages" +git clone $REPO dist -b $TARGET_BRANCH + +npm run docs + +rsync -vau docs/ dist/ + +cd dist +git add --all . +git config user.name "Travis CI" +git config user.email "${COMMIT_EMAIL}" +git commit -m "Docs build: ${SHA}" || true +git push "https://${GH_TOKEN}@github.com/MrJacz/discord.js-lavalink.git" $TARGET_BRANCH \ No newline at end of file diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..b08707b --- /dev/null +++ b/src/index.js @@ -0,0 +1,16 @@ +module.exports = { + Node: require("./lib/LavalinkNode"), + Player: require("./lib/Player"), + PlayerManager: require("./lib/PlayerManager"), + version: require("../package.json").version +}; + +/** + * @external Client + * @see {@link https://discord.js.org/#/docs/main/master/class/Client} + */ + +/** + * @external Collection + * @see {@link https://discord.js.org/#/docs/main/master/class/Collection} + */ diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index cd01398..0000000 --- a/src/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { LavalinkNode } from "./lib/LavalinkNode"; -import { Player } from "./lib/Player"; -import { PlayerManager } from "./lib/PlayerManager"; - -export { LavalinkNode, Player, PlayerManager }; diff --git a/src/lib/LavalinkNode.ts b/src/lib/LavalinkNode.js similarity index 79% rename from src/lib/LavalinkNode.ts rename to src/lib/LavalinkNode.js index 5a00ee0..861e736 100644 --- a/src/lib/LavalinkNode.ts +++ b/src/lib/LavalinkNode.js @@ -1,23 +1,30 @@ +const WebSocket = require("ws"); +const { EventEmitter } = require("events"); -import * as WebSocket from "ws"; -import { EventEmitter } from "events"; -import { PlayerManager } from "./PlayerManager"; -import { NodeStats, NodeOptions } from "./Types"; - -export class LavalinkNode extends EventEmitter { - public manager: PlayerManager; - public host: string; - public port?: number | string; - public address: string; - public region?: string; - public password?: string; - public ready: boolean; - public ws?: WebSocket; - public reconnect?: NodeJS.Timer; - public reconnectInterval?: number; - public stats: NodeStats; - - public constructor(manager: PlayerManager, options: NodeOptions) { +/** + * Lavalink Websocket + * @extends {EventEmitter} + */ +class LavalinkNode extends EventEmitter { + + /** + * LavalinkNode Options + * @typedef {Object} LavalinkNodeOptions + * @memberof LavalinkNode + * @property {string} host Lavalink host + * @property {number|string} [port=2333] Lavalink port + * @property {string} [address] Lavalink address + * @property {string} [region] Lavalink region + * @property {string} [password="youshallnotpass"] Lavalink password + * @property {number} [reconnectInterval=5000] Reconnectinterval + */ + + /** + * LavaLink options + * @param {PlayerManager} manager The PlayerManager that created the Node + * @param {LavalinkNodeOptions} options LavaLink options + */ + constructor(manager, options = {}) { super(); /** @@ -79,22 +86,19 @@ export class LavalinkNode extends EventEmitter { * Player stats * @type {Object} */ - this.stats = { - players: 0, - playingPlayers: 0 - }; + this.stats = {}; - this._connect(); + this.connect(); } /** * Connects to the WebSocket server */ - private _connect() { + connect() { this.ws = new WebSocket(this.address, { headers: { "User-Id": this.manager.user, - "Num-Shards": String(this.manager.shards), + "Num-Shards": this.manager.shards, Authorization: this.password } }); @@ -109,7 +113,7 @@ export class LavalinkNode extends EventEmitter { * Function for the onOpen WS event * @private */ - private _ready() { + _ready() { this.ready = true; /** * Emmited when the node gets ready @@ -123,7 +127,7 @@ export class LavalinkNode extends EventEmitter { * @param {Object} data Object to send * @returns {boolean} */ - public send(data: object): boolean { + send(data) { if (!this.ws) return false; let payload; try { @@ -140,7 +144,7 @@ export class LavalinkNode extends EventEmitter { * Destroys the WebSocket * @returns {boolean} */ - public destroy(): boolean { + destroy() { if (!this.ws) return false; this.ws.close(1000, "destroy"); this.ws = null; @@ -151,7 +155,7 @@ export class LavalinkNode extends EventEmitter { * Reconnects the websocket * @private */ - private _reconnect() { + _reconnect() { this.reconnect = setTimeout(() => { this.ws.removeAllListeners(); /** @@ -159,7 +163,7 @@ export class LavalinkNode extends EventEmitter { * @event LavalinkNode#reconnecting */ this.emit("reconnecting"); - this._connect(); + this.connect(); }, this.reconnectInterval); } @@ -170,8 +174,8 @@ export class LavalinkNode extends EventEmitter { * @returns {void} * @private */ - private _close(code, reason) { - this.ready = false; + _close(code, reason) { + this.connected = false; if (code !== 1000 || reason !== "destroy") return this._reconnect(); this.ws = null; /** @@ -188,7 +192,7 @@ export class LavalinkNode extends EventEmitter { * @returns {void} * @private */ - private _message(msg) { + _message(msg) { try { const data = JSON.parse(msg); if (data.op === "stats") this.stats = data; @@ -208,7 +212,7 @@ export class LavalinkNode extends EventEmitter { * @param {Error} error error from WS * @private */ - private _error(error) { + _error(error) { /** * Emitted whenever the Node's WebSocket encounters a connection error. * @event LavalinkNode#error @@ -217,4 +221,7 @@ export class LavalinkNode extends EventEmitter { this.emit("error", error); } + } + +module.exports = LavalinkNode; diff --git a/src/lib/Player.ts b/src/lib/Player.js similarity index 79% rename from src/lib/Player.ts rename to src/lib/Player.js index 8ce019d..6d64fd0 100644 --- a/src/lib/Player.ts +++ b/src/lib/Player.js @@ -1,24 +1,10 @@ -import { EventEmitter } from "events"; -import { Client } from "discord.js"; -import { PlayerManager } from "./PlayerManager"; -import { LavalinkNode } from "./LavalinkNode"; -import { Base64, PlayerOptions, VoiceServerUpdateData, LavalinkEQ } from "./Types"; +const { EventEmitter } = require("events"); /** * Player * @extends EventEmitter */ -export class Player extends EventEmitter { - public id: string; - public client: Client; - public manager: PlayerManager; - public node: LavalinkNode; - public channel: string; - public playing: boolean; - public paused: boolean; - public state: any; - public track?: Base64; - public timestamp?: number; +class Player extends EventEmitter { /** * Options to pass to Player @@ -35,7 +21,7 @@ export class Player extends EventEmitter { * LavaLink Player Options * @param {PlayerOptions} options Player Options */ - public constructor(options: PlayerOptions) { + constructor(options) { super(); /** * Player id (Guild ID) @@ -94,7 +80,7 @@ export class Player extends EventEmitter { * @param {Object} data voiceUpdate event data * @returns {Player} */ - public connect(data: { session: string; event: VoiceServerUpdateData }): Player { + connect(data) { this.node.send({ op: "voiceUpdate", guildId: this.id, @@ -106,18 +92,18 @@ export class Player extends EventEmitter { /** * Disconnects the player - * @param {string} message Disconnect reason + * @param {string} msg Disconnect reason * @returns {Player} */ - public disconnect(message: string): Player { + disconnect(msg) { this.playing = false; this.stop(); /** * Emitted when the Player disconnects * @event Player#disconnect - * @param {string} message Disconnection reason + * @param {string} msg Disconnection reason */ - this.emit("disconnect", message); + this.emit("disconnect", msg); return this; } @@ -129,7 +115,7 @@ export class Player extends EventEmitter { * @param {number} [options.endTime] End time * @returns {Player} */ - public play(track: Base64, options?: { startTime?: number, endTime?: number }): Player { + play(track, options = {}) { this.track = track; this.node.send(Object.assign({ op: "play", @@ -145,7 +131,7 @@ export class Player extends EventEmitter { * stops the Player * @returns {Player} */ - public stop(): Player { + stop() { this.node.send({ op: "stop", guildId: this.id @@ -160,7 +146,7 @@ export class Player extends EventEmitter { * @param {boolean} [pause=true] Whether to resume or pause the player * @returns {Player} */ - public pause(pause: boolean = true): Player { + pause(pause = true) { this.node.send({ op: "pause", guildId: this.id, @@ -170,7 +156,7 @@ export class Player extends EventEmitter { return this; } - public resume(): Player { + resume() { return this.pause(false); } @@ -179,7 +165,7 @@ export class Player extends EventEmitter { * @param {number} volume Volume * @returns {Player} */ - public volume(volume: number): Player { + volume(volume) { this.node.send({ op: "volume", guildId: this.id, @@ -194,7 +180,7 @@ export class Player extends EventEmitter { * @param {number} position The position to seek to * @returns {Player} */ - public seek(position: number): Player { + seek(position) { this.node.send({ op: "seek", guildId: this.id, @@ -207,7 +193,7 @@ export class Player extends EventEmitter { * Destroys the Player * @returns {Player} */ - public destroy(): Player { + destroy() { this.node.send({ op: "destroy", guildId: this.id @@ -215,7 +201,7 @@ export class Player extends EventEmitter { return this; } - public setEQ(bands: LavalinkEQ): Player { + setEQ(bands) { this.node.send({ op: "equalizer", guildId: this.id, @@ -230,7 +216,7 @@ export class Player extends EventEmitter { * @param {boolean} [reactive=false] Whether to switch channel * @return {boolean} */ - public switchChannel(channel: string, reactive: boolean = false): boolean { + switchChannel(channel, reactive = false) { if (this.channel === channel) return false; this.channel = channel; if (reactive) this.updateVoiceState(channel); @@ -239,10 +225,10 @@ export class Player extends EventEmitter { /** * @param {Object} message a packet - * @returns {boolean} + * @returns {void} * @private */ - public event(message): boolean { + event(message) { switch (message.type) { case "TrackEndEvent": { if (message.reason !== "REPLACED") { @@ -258,7 +244,7 @@ export class Player extends EventEmitter { * @prop {Object} message The raw message */ if (this.listenerCount("error")) return this.emit("error", message); - return false; + return; } case "TrackStuckEvent": { this.stop(); @@ -281,16 +267,18 @@ export class Player extends EventEmitter { * @param {boolean} [options.selfdeaf=false] selfdeaf option * @private */ - private updateVoiceState(channel: string, options: { selfmute?: boolean, selfdeaf?: boolean } = {}) { + updateVoiceState(channel, { selfmute = false, selfdeaf = false } = {}) { this.manager.sendWS({ op: 4, d: { guild_id: this.id, channel_id: channel, - self_mute: options.selfmute, - self_deaf: options.selfdeaf + self_mute: selfmute, + self_deaf: selfdeaf } }); } } + +module.exports = Player; diff --git a/src/lib/PlayerManager.ts b/src/lib/PlayerManager.js similarity index 50% rename from src/lib/PlayerManager.ts rename to src/lib/PlayerManager.js index 28d58d9..e4f0ee0 100644 --- a/src/lib/PlayerManager.ts +++ b/src/lib/PlayerManager.js @@ -1,24 +1,58 @@ -import { Client, Collection } from "discord.js"; -import { Player } from "./Player"; -import { LavalinkNode } from "./LavalinkNode"; -import { PlayerManagerOptions, PlayerManagerNodes, NodeOptions, LavalinkWebSocketMessage, PlayerManagerJoinData, PlayerManagerJoinOptions, VoiceServerUpdateData } from "./Types"; - -export class PlayerManager extends Collection { - private client: Client; - public nodes = new Collection(); - public user: string; - public shards: number; - private Player: any; // tslint:disable-line: variable-name - - public constructor(client: Client, nodes: PlayerManagerNodes[], options: PlayerManagerOptions) { - super(); +const { Collection } = require("discord.js"); +const Player = require("./Player"); +const LavalinkNode = require("./LavalinkNode"); + +/** + * Player Manager class + * @extends {external:Collection} + */ +class PlayerManager extends Collection { + + /** + * PlayerManager options + * @typedef {Object} PlayerManagerOptions + * @memberof PlayerManager + * @property {string} user Client user id + * @property {number} shards Total number of shards your bot is operating on + * @property {Player} [player] Custom player class + */ + /** + * Constructs the PlayerManager + * @param {external:Client} client Discord.js Client + * @param {Object[]} nodes Array of Lavalink Nodes + * @param {PlayerManagerOptions} options PlayerManager Options + */ + constructor(client, nodes = [], options = {}) { + super(); if (!client) throw new Error("INVALID_CLIENT: No client provided."); - this.client = client; + /** + * The client of the PlayerManager + * @type {external:Client} + * @private + */ + Object.defineProperty(this, "client", { value: client }); + /** + * Collection of LavaLink Nodes + * @type {external:Collection} + */ + this.nodes = new Collection(); + /** + * This client's id + * @type {string} + */ this.user = client.user ? client.user.id : options.user; - this.shards = client.shard ? client.shard.count : options.shards; - this.Player = options.Player || Player; + /** + * Total number of shards your bot is operating on + * @type {number} + */ + this.shards = options.shards || 1; + /** + * The Player class + * @type {Player} + */ + this.Player = options.player || Player; for (const node of nodes) this.createNode(node); @@ -27,7 +61,12 @@ export class PlayerManager extends Collection { }); } - private createNode(options: NodeOptions): LavalinkNode { + /** + * A function to create LavaLink nodes and set them to PlayerManager#nodes + * @param {Object} options Node options + * @returns {LavalinkNode} + */ + createNode(options) { const node = new LavalinkNode(this, options); node.on("error", error => this.client.emit("error", error)); @@ -38,14 +77,25 @@ export class PlayerManager extends Collection { return node; } - public removeNode(host: string | LavalinkNode): boolean { - const node = host instanceof LavalinkNode ? host : this.nodes.get(host); + /** + * Removes a node by host + * @param {string} host Node host + * @returns {boolean} + */ + removeNode(host) { + const node = this.nodes.get(host); if (!node) return false; node.removeAllListeners(); - return this.nodes.delete(node.host); + return this.nodes.delete(host); } - private onMessage(message: LavalinkWebSocketMessage): any { + /** + * Used for the Node message event + * @param {Object} message Parsed message object + * @returns {*} + * @private + */ + onMessage(message) { if (!message || !message.op) return; switch (message.op) { @@ -63,7 +113,25 @@ export class PlayerManager extends Collection { } } - public join(data: PlayerManagerJoinData, options?: PlayerManagerJoinOptions): Player { + /** + * Joins the voice channel and spawns a new player + * @param {Object} data Object with guild, channel, host infomation + * @param {string} data.guild Guild id + * @param {string} data.channel Channel id + * @param {string} data.host host + * @param {Object} [options] Options + * @param {boolean} [options.selfmute=false] Selfmute + * @param {boolean} [options.selfdeaf=false] Selfdeaf + * @returns {Player} + * @example + * // Join voice channel + * PlayerManager.join({ + * guild: "412180910587379712", + * channel: "412180910587379716", + * host: "localhost" + * }); + */ + join(data, { selfmute = false, selfdeaf = false } = {}) { const player = this.get(data.guild); if (player) return player; this.sendWS({ @@ -71,14 +139,26 @@ export class PlayerManager extends Collection { d: { guild_id: data.guild, channel_id: data.channel, - self_mute: options.selfmute, - self_deaf: options.selfdeaf + self_mute: selfmute, + self_deaf: selfdeaf } }); - return this.spawnPlayer(data); + return this.spawnPlayer({ + host: data.host, + guild: data.guild, + channel: data.channel + }); } - public leave(guild: string): boolean { + /** + * Leaves voice channel and deletes Player + * @param {string} guild Guild id + * @returns {boolean} + * @example + * // Leave the current channel + * PlayerManager.leave("412180910587379712"); + */ + leave(guild) { this.sendWS({ op: 4, d: { @@ -101,14 +181,13 @@ export class PlayerManager extends Collection { * @returns {void} * @private */ - private async voiceServerUpdate(data: VoiceServerUpdateData): Promise { + async voiceServerUpdate(data) { const guild = this.client.guilds.get(data.guild_id); if (!guild) return; const player = this.get(data.guild_id); if (!player) return; if (!guild.me) await guild.members.fetch(this.client.user.id).catch(() => null); player.connect({ - // @ts-ignore: support both versions of discord.js session: guild.me.voice ? guild.me.voice.sessionID : guild.me.voiceSessionID, event: data }); @@ -122,12 +201,12 @@ export class PlayerManager extends Collection { * @param {string} data.host Player host id * @returns {Player} */ - private spawnPlayer(data: PlayerManagerJoinData) { + spawnPlayer(data) { const exists = this.get(data.guild); if (exists) return exists; const node = this.nodes.get(data.host); if (!node) throw new Error(`INVALID_HOST: No available node with ${data.host}`); - const player: Player = new this.Player({ + const player = new this.Player({ id: data.guild, client: this.client, manager: this, @@ -146,9 +225,14 @@ export class PlayerManager extends Collection { * @returns {void} * @private */ - public sendWS(data): void { - // @ts-ignore: support both versions of discord.js + sendWS(data) { return typeof this.client.ws.send === "function" ? this.client.ws.send(data) : this.client.guilds.get(data.d.guild_id).shard.send(data); } + static get [Symbol.species]() { + return PlayerManager; + } + } + +module.exports = PlayerManager; diff --git a/src/lib/Types.ts b/src/lib/Types.ts deleted file mode 100644 index 73dcf4c..0000000 --- a/src/lib/Types.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { Client } from "discord.js"; -import { PlayerManager } from "./PlayerManager"; -import { LavalinkNode } from "./LavalinkNode"; -import { Player } from "./Player"; - -export type PlayerManagerOptions = { - user: string; - shards: number; - Player?: Player; -}; - -export type PlayerManagerNodes = { - host: string; - port?: number | string; - password?: string; -}; - -export type PlayerManagerJoinData = { - guild: string; - channel: string; - host: string; -}; - -export type PlayerManagerJoinOptions = { - selfmute?: boolean, - selfdeaf?: boolean -}; - -export type PlayerOptions = { - id: string; - client: Client; - manager: PlayerManager; - node: LavalinkNode; - channel: string; -}; - -export type NodeOptions = { - host: string; - port?: number | string; - address?: string; - region?: string; - password?: string; - reconnectInterval?: number; -}; - -export type NodeStats = { - players: number; - playingPlayers: number; -}; - -export type LavalinkWebSocketMessage = { - [key: string]: any; - op: "playerUpdate" | "stats" | "event"; -}; - -export type VoiceServerUpdateData = { - token: string; - guild_id: string; - endpoint: string; -}; - -export type LavalinkEQ = { - band: number; - gain: number; -}[]; - -export type Base64 = string; diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 5637725..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "compilerOptions": { - "alwaysStrict": true, - "declaration": true, - "esModuleInterop": false, - "experimentalDecorators": true, - "forceConsistentCasingInFileNames": true, - "lib": ["esnext"], - "module": "commonjs", - "moduleResolution": "node", - "newLine": "LF", - "noImplicitReturns": true, - "noImplicitThis": true, - "noUnusedParameters": true, - "outDir": "./dist", - "pretty": true, - "removeComments": true, - "resolveJsonModule": true, - "sourceMap": true, - "strictBindCallApply": true, - "target": "esnext", - "types": ["discord.js"] - }, - "exclude": [ - "node_modules", - "example", - ], - "include": [ - "./src/**/*" - ] -} \ No newline at end of file diff --git a/tslint.json b/tslint.json index 15d7f13..73f23ce 100644 --- a/tslint.json +++ b/tslint.json @@ -7,12 +7,9 @@ "comment-format": [ true, "check-space" ], - "indent": [ - true, "spaces", 4 - ], + "indent": [true, "spaces", 4], "curly": false, "class-name": true, - "semicolon": [true, "always"], "triple-equals": true, "eofline": true, "no-bitwise": false, @@ -23,8 +20,8 @@ "one-line": [ false ], - "variable-name": [true, "ban-keywords", "allow-leading-underscore"], - "interface-name": [true, "always-prefix"], + "variable-name": [false], + "interface-name": [false], "no-conditional-assignment": true, "use-isnan": true, "no-trailing-whitespace": true, @@ -55,6 +52,7 @@ "property-declaration": "onespace", "variable-declaration": "onespace" } - ] + ], + "semicolon": [true, "always"] } } \ No newline at end of file diff --git a/typings/index.d.ts b/typings/index.d.ts new file mode 100644 index 0000000..f0693d8 --- /dev/null +++ b/typings/index.d.ts @@ -0,0 +1,132 @@ +declare module "discord.js-lavalink" { + import { EventEmitter } from "events"; + import * as WebSocket from "ws"; + import { + Client as DiscordClient, + Collection + } from "discord.js"; + + export const version: string; + + export class PlayerManager extends Collection { + public constructor(client: DiscordClient, nodes: object[], options: PlayerManagerOptions); + + public client: DiscordClient; + public nodes: Collection; + + public createNode(options: object): LavalinkNode; + public removeNode(host: string): boolean; + private onMessage(message: object): any; + public join(data: { guild: string, channel: string, host: string, }, options?: { selfmute?: boolean, selfdeaf?: boolean }): Promise; + public leave(guild: string): boolean; + private voiceServerUpdate(data: object): void; + public spawnPlayer(data: { guild: string, channel: string, host: string }): Player; + private sendWS(data: { op: number, d: object }): any; + } + + export class Player extends EventEmitter { + public constructor(options: PlayerOptions); + + public id: string; + public client: DiscordClient; + public manager: PlayerManager; + public node: LavalinkNode; + public channel: string; + public playing: boolean; + public paused: boolean; + public state: object; + public track?: Base64; + public timestamp?: number; + + public on(event: string, listener: Function): this; + public on(event: "disconnect", listener: (msg: string) => void): this; + public on(event: "error", listener: (error: Error) => void): this; + public on(event: "end", listener: (message: object) => void): this; + + public once(event: string, listener: Function): this; + public once(event: "disconnect", listener: (msg: string) => void): this; + public once(event: "error", listener: (error: Error) => void): this; + public once(event: "end", listener: (message: object) => void): this; + + public connect(data: object): this; + public disconnect(msg?: string): this; + public play(track: Base64, options?: { startTime?: number, endTime?: number }): this; + public stop(): this; + public pause(pause?: boolean): this; + public resume(): this; + public volume(volume: number): this; + public seek(position: number): this; + public destroy(): this; + public switchChannel(channel: string, reactive?: boolean): boolean; + private event(message: object): any; + private updateVoiceState(channel: string, options?: { selfmute?: boolean, selfdeaf?: boolean }): void; + } + + class LavalinkNode extends EventEmitter { + public constructor(manager: PlayerManager, options: NodeOptions); + + public manager: PlayerManager; + public host: string; + public port?: number | string; + public address?: string; + public region?: string; + public password?: string; + public ready: boolean; + public ws?: WebSocket; + public reconnect?: NodeJS.Timer; + public reconnectInterval?: number; + public stats: NodeStats; + + public on(event: string, listener: Function): this; + public on(event: "ready" | "reconnecting", listener: () => void): this; + public on(event: "disconnect", listener: (reason: string) => void): this; + public on(event: "message", listener: (data: any) => void): this; + public on(event: "error", listener: (error: Error) => void): this; + + public once(event: string, listener: Function): this; + public once(event: "ready" | "reconnecting", listener: () => void): this; + public once(event: "disconnect", listener: (reason: string) => void): this; + public once(event: "message", listener: (data: any) => void): this; + public once(event: "error", listener: (error: Error) => void): this; + + public connect(): void; + public send(data: object): boolean; + public destroy(): boolean; + private _reconnect(): void; + private _ready(): void; + private _close(code: number, reason?: string): void; + private _message(msg: object): any; + private _error(error: Error): void; + } + + export { LavalinkNode as Node }; + + export type PlayerManagerOptions = { + user: string; + shards: number; + }; + + export type PlayerOptions = { + id: string; + client: DiscordClient; + manager: PlayerManager; + node: LavalinkNode; + channel: string; + }; + + export type NodeOptions = { + host: string; + port?: number | string; + address?: string; + region?: string; + password?: string; + reconnectInterval?: number; + }; + + export type NodeStats = { + players: number; + playingPlayers: number; + }; + + export type Base64 = string; +} diff --git a/yarn.lock b/yarn.lock index 95cf6a7..7b82a80 100644 --- a/yarn.lock +++ b/yarn.lock @@ -35,7 +35,7 @@ resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== -"@types/node@*", "@types/node@^11.11.3": +"@types/node@*", "@types/node@^11.9.5": version "11.11.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.3.tgz#7c6b0f8eaf16ae530795de2ad1b85d34bf2f5c58" integrity sha512-wp6IOGu1lxsfnrD+5mX6qwSwWuqsdkKKxTN4aQc4wByHAKZJf9/D4KXPQ1POUjEbnCP5LMggB0OEFNY9OTsMqg== @@ -781,6 +781,7 @@ diff@^3.2.0: discord.js@discordjs/discord.js: version "12.0.0-dev" + uid df1889ab4902416de2bf6b3c144d55e35dbf116f resolved "https://codeload.github.com/discordjs/discord.js/tar.gz/df1889ab4902416de2bf6b3c144d55e35dbf116f" dependencies: form-data "^2.3.3" @@ -3383,7 +3384,7 @@ tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== -tslint@^5.14.0: +tslint@^5.12.1: version "5.14.0" resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.14.0.tgz#be62637135ac244fc9b37ed6ea5252c9eba1616e" integrity sha512-IUla/ieHVnB8Le7LdQFRGlVJid2T/gaJe5VkjzRVSRR6pA2ODYrnfR1hmxi+5+au9l50jBwpbBL34txgv4NnTQ==