diff --git a/.gitignore b/.gitignore index e7c1d47..ab4da0a 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,5 @@ jspm_packages/ package-lock.json example/config.json +dist/ + diff --git a/.npmignore b/.npmignore index 09cfc1e..f5915ec 100644 --- a/.npmignore +++ b/.npmignore @@ -7,4 +7,5 @@ testing .travis.yml docs.js tslint.json -example \ No newline at end of file +example +azure-pipelines.yml \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b9d2f39..0000000 --- a/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -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 ff2057b..17868ef 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 Jacz +Copyright (c) 2018-2019 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 e88639a..443cf68 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,32 +1,52 @@ -# 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_10_x: - node_version: 10.x node_11_x: node_version: 11.x + node_10_x: + node_version: 10.x steps: -- task: NodeTool@0 - inputs: - versionSpec: $(node_version) - displayName: 'Install Node.js' - -- script: | - npm install - displayName: 'npm install' - -- script: | - npm run test - displayName: 'run tests' + - 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' \ No newline at end of file diff --git a/docs.js b/docs.js index dfd4bcf..6c7b1b4 100644 --- a/docs.js +++ b/docs.js @@ -23,7 +23,7 @@ Docma.create() }, src: [ { readme: "./README.md" }, - { lavalink: "./src/*/**/*.js" } + { lavalink: "./dist/*/**/*.js" } ], dest: "./docs", jsdoc: { plugins: ["jsdoc-dynamic"] }, diff --git a/example/app.js b/example/app.js index 1fb5f30..d410b1e 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("../src/index"); +const { PlayerManager } = require("../dist/index.js"); class MusicClient extends Client { diff --git a/package.json b/package.json index 924f2f8..e2449da 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,14 @@ { "name": "discord.js-lavalink", - "version": "2.2.2", + "version": "3.0.0", "description": "A discord.js lavalink client", - "main": "src/index.js", - "types": "typings/index.d.ts", + "main": "dist/src/index", "scripts": { - "test": "eslint src && tslint 'typings/*.ts'", - "lint": "eslint --fix src test && tslint --fix 'typings/*.ts'", + "prepublishOnly": "yarn compile", + "lint": "tslint --fix 'src/**/*.ts'", + "test:lint": "tslint 'src/**/*.ts'", + "compile": "tsc -p .", + "watch": "tsc -p . -w", "docs": "node docs.js" }, "repository": { @@ -19,6 +21,7 @@ "discord", "api", "lava", + "link", "lavalink", "lavalink.js", "discord.js" @@ -30,19 +33,19 @@ }, "homepage": "https://github.com/MrJacz/discord.js-lavalink#readme", "devDependencies": { - "@types/node": "^11.9.5", + "@types/node": "^11.11.3", "@types/ws": "^6.0.1", "discord.js": "discordjs/discord.js", "docma": "^3.2.2", - "eslint": "^5.14.1", + "eslint": "^5.15.2", "eslint-plugin-node": "^8.0.1", "eslint-plugin-promise": "^4.0.1", "jsdoc-dynamic": "^1.0.4", - "tslint": "^5.12.1", + "tslint": "^5.14.0", "typescript": "^3.3.3333" }, "dependencies": { - "ws": "^6.1.4" + "ws": "^6.2.0" }, "peerDependencies": { "discord.js": "^11.4.2" diff --git a/scripts/travis-deploy.sh b/scripts/travis-deploy.sh deleted file mode 100644 index 84d6e59..0000000 --- a/scripts/travis-deploy.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/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 deleted file mode 100644 index b08707b..0000000 --- a/src/index.js +++ /dev/null @@ -1,16 +0,0 @@ -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 new file mode 100644 index 0000000..cd01398 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,5 @@ +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.js b/src/lib/LavalinkNode.ts similarity index 79% rename from src/lib/LavalinkNode.js rename to src/lib/LavalinkNode.ts index 861e736..5a00ee0 100644 --- a/src/lib/LavalinkNode.js +++ b/src/lib/LavalinkNode.ts @@ -1,30 +1,23 @@ -const WebSocket = require("ws"); -const { EventEmitter } = require("events"); -/** - * 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 = {}) { +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) { super(); /** @@ -86,19 +79,22 @@ class LavalinkNode extends EventEmitter { * Player stats * @type {Object} */ - this.stats = {}; + this.stats = { + players: 0, + playingPlayers: 0 + }; - this.connect(); + this._connect(); } /** * Connects to the WebSocket server */ - connect() { + private _connect() { this.ws = new WebSocket(this.address, { headers: { "User-Id": this.manager.user, - "Num-Shards": this.manager.shards, + "Num-Shards": String(this.manager.shards), Authorization: this.password } }); @@ -113,7 +109,7 @@ class LavalinkNode extends EventEmitter { * Function for the onOpen WS event * @private */ - _ready() { + private _ready() { this.ready = true; /** * Emmited when the node gets ready @@ -127,7 +123,7 @@ class LavalinkNode extends EventEmitter { * @param {Object} data Object to send * @returns {boolean} */ - send(data) { + public send(data: object): boolean { if (!this.ws) return false; let payload; try { @@ -144,7 +140,7 @@ class LavalinkNode extends EventEmitter { * Destroys the WebSocket * @returns {boolean} */ - destroy() { + public destroy(): boolean { if (!this.ws) return false; this.ws.close(1000, "destroy"); this.ws = null; @@ -155,7 +151,7 @@ class LavalinkNode extends EventEmitter { * Reconnects the websocket * @private */ - _reconnect() { + private _reconnect() { this.reconnect = setTimeout(() => { this.ws.removeAllListeners(); /** @@ -163,7 +159,7 @@ class LavalinkNode extends EventEmitter { * @event LavalinkNode#reconnecting */ this.emit("reconnecting"); - this.connect(); + this._connect(); }, this.reconnectInterval); } @@ -174,8 +170,8 @@ class LavalinkNode extends EventEmitter { * @returns {void} * @private */ - _close(code, reason) { - this.connected = false; + private _close(code, reason) { + this.ready = false; if (code !== 1000 || reason !== "destroy") return this._reconnect(); this.ws = null; /** @@ -192,7 +188,7 @@ class LavalinkNode extends EventEmitter { * @returns {void} * @private */ - _message(msg) { + private _message(msg) { try { const data = JSON.parse(msg); if (data.op === "stats") this.stats = data; @@ -212,7 +208,7 @@ class LavalinkNode extends EventEmitter { * @param {Error} error error from WS * @private */ - _error(error) { + private _error(error) { /** * Emitted whenever the Node's WebSocket encounters a connection error. * @event LavalinkNode#error @@ -221,7 +217,4 @@ class LavalinkNode extends EventEmitter { this.emit("error", error); } - } - -module.exports = LavalinkNode; diff --git a/src/lib/Player.js b/src/lib/Player.ts similarity index 79% rename from src/lib/Player.js rename to src/lib/Player.ts index 6d64fd0..8ce019d 100644 --- a/src/lib/Player.js +++ b/src/lib/Player.ts @@ -1,10 +1,24 @@ -const { EventEmitter } = require("events"); +import { EventEmitter } from "events"; +import { Client } from "discord.js"; +import { PlayerManager } from "./PlayerManager"; +import { LavalinkNode } from "./LavalinkNode"; +import { Base64, PlayerOptions, VoiceServerUpdateData, LavalinkEQ } from "./Types"; /** * Player * @extends EventEmitter */ -class 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; /** * Options to pass to Player @@ -21,7 +35,7 @@ class Player extends EventEmitter { * LavaLink Player Options * @param {PlayerOptions} options Player Options */ - constructor(options) { + public constructor(options: PlayerOptions) { super(); /** * Player id (Guild ID) @@ -80,7 +94,7 @@ class Player extends EventEmitter { * @param {Object} data voiceUpdate event data * @returns {Player} */ - connect(data) { + public connect(data: { session: string; event: VoiceServerUpdateData }): Player { this.node.send({ op: "voiceUpdate", guildId: this.id, @@ -92,18 +106,18 @@ class Player extends EventEmitter { /** * Disconnects the player - * @param {string} msg Disconnect reason + * @param {string} message Disconnect reason * @returns {Player} */ - disconnect(msg) { + public disconnect(message: string): Player { this.playing = false; this.stop(); /** * Emitted when the Player disconnects * @event Player#disconnect - * @param {string} msg Disconnection reason + * @param {string} message Disconnection reason */ - this.emit("disconnect", msg); + this.emit("disconnect", message); return this; } @@ -115,7 +129,7 @@ class Player extends EventEmitter { * @param {number} [options.endTime] End time * @returns {Player} */ - play(track, options = {}) { + public play(track: Base64, options?: { startTime?: number, endTime?: number }): Player { this.track = track; this.node.send(Object.assign({ op: "play", @@ -131,7 +145,7 @@ class Player extends EventEmitter { * stops the Player * @returns {Player} */ - stop() { + public stop(): Player { this.node.send({ op: "stop", guildId: this.id @@ -146,7 +160,7 @@ class Player extends EventEmitter { * @param {boolean} [pause=true] Whether to resume or pause the player * @returns {Player} */ - pause(pause = true) { + public pause(pause: boolean = true): Player { this.node.send({ op: "pause", guildId: this.id, @@ -156,7 +170,7 @@ class Player extends EventEmitter { return this; } - resume() { + public resume(): Player { return this.pause(false); } @@ -165,7 +179,7 @@ class Player extends EventEmitter { * @param {number} volume Volume * @returns {Player} */ - volume(volume) { + public volume(volume: number): Player { this.node.send({ op: "volume", guildId: this.id, @@ -180,7 +194,7 @@ class Player extends EventEmitter { * @param {number} position The position to seek to * @returns {Player} */ - seek(position) { + public seek(position: number): Player { this.node.send({ op: "seek", guildId: this.id, @@ -193,7 +207,7 @@ class Player extends EventEmitter { * Destroys the Player * @returns {Player} */ - destroy() { + public destroy(): Player { this.node.send({ op: "destroy", guildId: this.id @@ -201,7 +215,7 @@ class Player extends EventEmitter { return this; } - setEQ(bands) { + public setEQ(bands: LavalinkEQ): Player { this.node.send({ op: "equalizer", guildId: this.id, @@ -216,7 +230,7 @@ class Player extends EventEmitter { * @param {boolean} [reactive=false] Whether to switch channel * @return {boolean} */ - switchChannel(channel, reactive = false) { + public switchChannel(channel: string, reactive: boolean = false): boolean { if (this.channel === channel) return false; this.channel = channel; if (reactive) this.updateVoiceState(channel); @@ -225,10 +239,10 @@ class Player extends EventEmitter { /** * @param {Object} message a packet - * @returns {void} + * @returns {boolean} * @private */ - event(message) { + public event(message): boolean { switch (message.type) { case "TrackEndEvent": { if (message.reason !== "REPLACED") { @@ -244,7 +258,7 @@ class Player extends EventEmitter { * @prop {Object} message The raw message */ if (this.listenerCount("error")) return this.emit("error", message); - return; + return false; } case "TrackStuckEvent": { this.stop(); @@ -267,18 +281,16 @@ class Player extends EventEmitter { * @param {boolean} [options.selfdeaf=false] selfdeaf option * @private */ - updateVoiceState(channel, { selfmute = false, selfdeaf = false } = {}) { + private updateVoiceState(channel: string, options: { selfmute?: boolean, selfdeaf?: boolean } = {}) { this.manager.sendWS({ op: 4, d: { guild_id: this.id, channel_id: channel, - self_mute: selfmute, - self_deaf: selfdeaf + self_mute: options.selfmute, + self_deaf: options.selfdeaf } }); } } - -module.exports = Player; diff --git a/src/lib/PlayerManager.js b/src/lib/PlayerManager.ts similarity index 50% rename from src/lib/PlayerManager.js rename to src/lib/PlayerManager.ts index e4f0ee0..28d58d9 100644 --- a/src/lib/PlayerManager.js +++ b/src/lib/PlayerManager.ts @@ -1,58 +1,24 @@ -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 = {}) { +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(); + if (!client) throw new Error("INVALID_CLIENT: No client provided."); - /** - * 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.client = client; this.user = client.user ? client.user.id : options.user; - /** - * 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; + this.shards = client.shard ? client.shard.count : options.shards; + this.Player = options.Player || Player; for (const node of nodes) this.createNode(node); @@ -61,12 +27,7 @@ class PlayerManager extends Collection { }); } - /** - * A function to create LavaLink nodes and set them to PlayerManager#nodes - * @param {Object} options Node options - * @returns {LavalinkNode} - */ - createNode(options) { + private createNode(options: NodeOptions): LavalinkNode { const node = new LavalinkNode(this, options); node.on("error", error => this.client.emit("error", error)); @@ -77,25 +38,14 @@ class PlayerManager extends Collection { return node; } - /** - * Removes a node by host - * @param {string} host Node host - * @returns {boolean} - */ - removeNode(host) { - const node = this.nodes.get(host); + public removeNode(host: string | LavalinkNode): boolean { + const node = host instanceof LavalinkNode ? host : this.nodes.get(host); if (!node) return false; node.removeAllListeners(); - return this.nodes.delete(host); + return this.nodes.delete(node.host); } - /** - * Used for the Node message event - * @param {Object} message Parsed message object - * @returns {*} - * @private - */ - onMessage(message) { + private onMessage(message: LavalinkWebSocketMessage): any { if (!message || !message.op) return; switch (message.op) { @@ -113,25 +63,7 @@ class PlayerManager extends Collection { } } - /** - * 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 } = {}) { + public join(data: PlayerManagerJoinData, options?: PlayerManagerJoinOptions): Player { const player = this.get(data.guild); if (player) return player; this.sendWS({ @@ -139,26 +71,14 @@ class PlayerManager extends Collection { d: { guild_id: data.guild, channel_id: data.channel, - self_mute: selfmute, - self_deaf: selfdeaf + self_mute: options.selfmute, + self_deaf: options.selfdeaf } }); - return this.spawnPlayer({ - host: data.host, - guild: data.guild, - channel: data.channel - }); + return this.spawnPlayer(data); } - /** - * Leaves voice channel and deletes Player - * @param {string} guild Guild id - * @returns {boolean} - * @example - * // Leave the current channel - * PlayerManager.leave("412180910587379712"); - */ - leave(guild) { + public leave(guild: string): boolean { this.sendWS({ op: 4, d: { @@ -181,13 +101,14 @@ class PlayerManager extends Collection { * @returns {void} * @private */ - async voiceServerUpdate(data) { + private async voiceServerUpdate(data: VoiceServerUpdateData): Promise { 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 }); @@ -201,12 +122,12 @@ class PlayerManager extends Collection { * @param {string} data.host Player host id * @returns {Player} */ - spawnPlayer(data) { + private spawnPlayer(data: PlayerManagerJoinData) { 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 = new this.Player({ + const player: Player = new this.Player({ id: data.guild, client: this.client, manager: this, @@ -225,14 +146,9 @@ class PlayerManager extends Collection { * @returns {void} * @private */ - sendWS(data) { + public sendWS(data): void { + // @ts-ignore: support both versions of discord.js 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 new file mode 100644 index 0000000..73dcf4c --- /dev/null +++ b/src/lib/Types.ts @@ -0,0 +1,67 @@ +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 new file mode 100644 index 0000000..5637725 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,31 @@ +{ + "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 73f23ce..15d7f13 100644 --- a/tslint.json +++ b/tslint.json @@ -7,9 +7,12 @@ "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, @@ -20,8 +23,8 @@ "one-line": [ false ], - "variable-name": [false], - "interface-name": [false], + "variable-name": [true, "ban-keywords", "allow-leading-underscore"], + "interface-name": [true, "always-prefix"], "no-conditional-assignment": true, "use-isnan": true, "no-trailing-whitespace": true, @@ -52,7 +55,6 @@ "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 deleted file mode 100644 index f0693d8..0000000 --- a/typings/index.d.ts +++ /dev/null @@ -1,132 +0,0 @@ -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 7b82a80..95cf6a7 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.9.5": +"@types/node@*", "@types/node@^11.11.3": version "11.11.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.3.tgz#7c6b0f8eaf16ae530795de2ad1b85d34bf2f5c58" integrity sha512-wp6IOGu1lxsfnrD+5mX6qwSwWuqsdkKKxTN4aQc4wByHAKZJf9/D4KXPQ1POUjEbnCP5LMggB0OEFNY9OTsMqg== @@ -781,7 +781,6 @@ 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" @@ -3384,7 +3383,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.12.1: +tslint@^5.14.0: version "5.14.0" resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.14.0.tgz#be62637135ac244fc9b37ed6ea5252c9eba1616e" integrity sha512-IUla/ieHVnB8Le7LdQFRGlVJid2T/gaJe5VkjzRVSRR6pA2ODYrnfR1hmxi+5+au9l50jBwpbBL34txgv4NnTQ==