cosmicord.js
Version:
Cosmicord.js is a powerful and intuitive Lavalink wrapper designed to simplify the process of integrating Lavalink into your Node.js applications.
187 lines (153 loc) • 5.01 kB
text/typescript
import { EventEmitter } from "stream";
import { NodeEvents, CosmiNodeOptions, NodeStats } from "../interfaces";
import { CosmiPlayer, CosmiREST, CosmiSocket, Cosmicord } from "./";
import { Collection } from "discord.js";
export interface CosmiNode {
on<Key extends keyof NodeEvents>(
event: Key,
listener: (...args: NodeEvents[Key]) => void
): this;
emit<Key extends keyof NodeEvents>(
event: Key,
...args: NodeEvents[Key]
): boolean;
}
export class CosmiNode extends EventEmitter {
/** The host for the node. */
public host: string;
/** The port for the node. */
public port: number = 2333;
/** The password for the node. */
public password: string = "youshallnotpass";
/** Whether the node is secure or not. */
public secure: boolean = false;
/** The identifier for the node. */
public identifier: string = "Cosmicord";
/** The amount of retries for the node. */
public retryAmount: number = 5;
/** The amount of retries made for the node. */
private retries: number = 0;
/** The delay for the node. */
public retryDelay: number = 5000;
/** The request timeout for the node. */
public requestTimeout: number = 10000;
/** Whether the node is connected or not. */
public connected: boolean = false;
/** The stats for the node. */
public stats: NodeStats = {
players: 0,
playingPlayers: 0,
uptime: 0,
cpu: {
cores: 0,
lavalinkLoad: 0,
systemLoad: 0,
},
memory: {
allocated: 0,
free: 0,
reservable: 0,
used: 0,
},
};
/** The amount of calls made to the node. */
public calls: number = 0;
/** The socket for the node. */
public socket: CosmiSocket;
/** The version for the node. */
public version?: string;
/** The rest client for the node. */
public rest: CosmiREST;
/** The manager of the node */
public manager: Cosmicord;
/** Players of the node. */
public players: Collection<string, CosmiPlayer>;
/** The client id of the bot */
public clientId?: string;
/** Whether the node is ready or not. */
public isReady: boolean = false;
/** Creates a new node. */
constructor(manager: Cosmicord, options: CosmiNodeOptions) {
super();
this.host = options.host;
this.port = options.port || this.port;
this.password = options.password || this.password;
this.secure = options.secure || this.secure;
this.identifier = options.identifier || this.identifier;
this.retryAmount = options.retryAmount || this.retryAmount;
this.retryDelay = options.retryDelay || this.retryDelay;
this.requestTimeout = options.requestTimeout || this.requestTimeout;
this.manager = manager;
this.clientId = manager.clientId;
this.players = manager.players;
}
/** Connect to the node with websocket. */
public connectSocket(): Promise<boolean> {
return new Promise((res) => {
this.socket = new CosmiSocket(
this.manager,
this,
this.url.replace("http", "ws") + "/v3/websocket",
{
headers: {
Authorization: this.password,
"User-Id": this.clientId,
"Client-Name": "Cosmicord/v1.0.0",
},
}
);
this.socket.on("error", (err) => {
throw new Error(err.message);
});
this.on("connected", () => {
this.connected = true;
this.manager.emit("nodeConnected", this);
res(this.connected);
});
});
}
/** Get the url for the node. */
public get url(): string {
return `${this.secure ? "https" : "http"}://${this.host}:${this.port}`;
}
/** Connects to the node. */
public connect(): Promise<boolean> {
return new Promise(async (res) => {
try {
const rest = new CosmiREST(this, this.url, this.requestTimeout);
this.version = await rest.getVersion();
if (this.version.startsWith("3")) {
rest.setBaseURL(this.url + "/v3");
this.rest = rest;
res(await this.connectSocket());
} else throw new Error("Unsupported Lavalink version. (v3 required)");
} catch (e) {
this.manager.emit("debug", e.toString());
await new Promise((r) => setTimeout(r, this.retryDelay));
if (this.retryAmount === this.retries) {
throw new Error(
`Failed to connect to node ${this.identifier} after ${this.retries} retries.`
);
} else {
res(await this.reconnect());
}
}
});
}
/** Destroys the node. */
public destroy(): void {
if (this.socket) this.socket.close();
if (this.rest) delete this.rest;
this.connected = false;
this.emit("destroyed");
this.manager.emit("nodeDestroyed", this);
this.manager.nodes = this.manager.nodes.filter((n) => n.url !== this.url);
}
/** Reconnects to the node. */
public reconnect(): Promise<boolean> {
return new Promise(async (res) => {
this.destroy();
res(await this.connect());
});
}
}