Skip to content

Commit

Permalink
feat: make kirishima extendable
Browse files Browse the repository at this point in the history
  • Loading branch information
KagChi committed Mar 22, 2022
1 parent d41357d commit 34093f4
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 78 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"main": "dist/index.js",
"module": "dist/index.mjs",
"description": "Kirishima is extendable, fast, flexible, asynchronous lavalink client",
"version": "0.5.0",
"version": "0.6.0",
"license": "GPL-3.0",
"repository": {
"url": "https://github.com/kirishima-ship/core"
Expand Down
71 changes: 71 additions & 0 deletions src/Base/BaseKirishima.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
import Collection from '@discordjs/collection';
import EventEmitter from 'node:events';
import { KirishimaPlayer, KirishimaPlayerOptions } from '..';
import { KirishimaNode } from '../Structures/KirishimaNode';
import { Structure } from '../Structures/Structure';
import { KirishimaOptions, LoadTrackResponse } from '../typings';

export class BaseKirishima extends EventEmitter {
public nodes: Collection<string, KirishimaNode> = new Collection();
public players?: Collection<string, KirishimaPlayer>;
public constructor(public options: KirishimaOptions) {
super();

if (typeof options.send !== 'function') throw Error('Send function must be present and must be a function.');

if (
typeof options.spawnPlayer !== 'function' ||
(typeof options.spawnPlayer === undefined && (typeof options.fetchPlayer !== 'function' || typeof options.fetchPlayer === undefined))
) {
this.players = new Collection();
options.spawnPlayer = this.defaultSpawnPlayerHandler.bind(this);
}

if (
typeof options.fetchPlayer !== 'function' ||
(typeof options.fetchPlayer === undefined && (typeof options.spawnPlayer !== 'function' || typeof options.spawnPlayer === undefined))
) {
options.fetchPlayer = this.defaultFetchPlayerHandler.bind(this);
}

if (!options.nodes.length) throw new Error('Nodes option must not a empty array');
}

public resolveNode(identifierOrGroup?: string) {
const resolveIdenfitierNode = this.nodes.filter((x) => x.connected).find((x) => x.options.identifier === identifierOrGroup);
if (resolveIdenfitierNode) return resolveIdenfitierNode;
const resolveGroupedNode = this.nodes.filter((x) => x.connected).find((x) => x.options.group?.includes(identifierOrGroup!)!);
if (resolveGroupedNode) return resolveGroupedNode;
return this.resolveBestNode().first();
}

public resolveBestNode() {
return this.nodes
.filter((x) => x.connected)
.sort((x, y) => {
const XLoad = x.stats?.cpu ? (x.stats.cpu.systemLoad / x.stats.cpu.cores) * 100 : 0;
const YLoad = y.stats?.cpu ? (y.stats.cpu.systemLoad / y.stats.cpu.cores) * 100 : 0;
return XLoad - YLoad;
});
}

public async resolveTracks(options: string | { source?: string | undefined; query: string }, node?: KirishimaNode): Promise<LoadTrackResponse> {
node ??= this.resolveNode();
const resolveTracks = await node!.rest.loadTracks(options);
if (resolveTracks?.tracks.length) resolveTracks.tracks = resolveTracks.tracks.map((x) => new (Structure.get('KirishimaTrack'))(x));
return resolveTracks as unknown as LoadTrackResponse;
}

private defaultSpawnPlayerHandler(guildId: string, options: KirishimaPlayerOptions, node: KirishimaNode) {
const player = this.players!.has(guildId);
if (player) return this.players!.get(guildId)!;
const kirishimaPlayer = new (Structure.get('KirishimaPlayer'))(options, this, node);
this.players!.set(guildId, kirishimaPlayer);
return kirishimaPlayer;
}

private defaultFetchPlayerHandler(guildId: string) {
return this.players!.get(guildId);
}
}
5 changes: 3 additions & 2 deletions src/Structures/BasePlayer.ts → src/Base/BasePlayer.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { GatewayVoiceServerUpdateDispatch, GatewayVoiceStateUpdateDispatch } from 'discord-api-types/gateway/v9';
import { WebsocketOpEnum } from 'lavalink-api-types';
import { KirishimaPlayerOptions, Kirishima, KirishimaNode, createVoiceChannelJoinPayload } from '..';
import { KirishimaPlayerOptions, KirishimaNode, createVoiceChannelJoinPayload } from '..';
import { BaseKirishima } from './BaseKirishima';

export class BasePlayer {
public voiceServer: GatewayVoiceServerUpdateDispatch['d'] | undefined;
public voiceState: GatewayVoiceStateUpdateDispatch['d'] | undefined;

public constructor(public options: KirishimaPlayerOptions, public kirishima: Kirishima, public node: KirishimaNode) {}
public constructor(public options: KirishimaPlayerOptions, public kirishima: BaseKirishima, public node: KirishimaNode) {}

public async connect() {
await this.kirishima.options.send(this.options, createVoiceChannelJoinPayload(this.options));
Expand Down
70 changes: 2 additions & 68 deletions src/Structures/Kirishima.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,11 @@
/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
import { EventEmitter } from 'node:events';
import type { KirishimaNodeOptions, KirishimaOptions, KirishimaPlayerOptions, LoadTrackResponse } from '../typings';
import type { KirishimaNodeOptions, KirishimaPlayerOptions } from '../typings';
import crypto from 'node:crypto';

import { KirishimaNode } from './KirishimaNode';
import { GatewayVoiceServerUpdateDispatch, GatewayVoiceStateUpdateDispatch } from 'discord-api-types/gateway/v9';
import Collection from '@discordjs/collection';
import { KirishimaPlayer } from './KirishimaPlayer';
import { Structure } from './Structure';

export class Kirishima extends EventEmitter {
public nodes: Collection<string, KirishimaNode> = new Collection();
public players?: Collection<string, KirishimaPlayer>;
public constructor(public options: KirishimaOptions) {
super();

if (typeof options.send !== 'function') throw Error('Send function must be present and must be a function.');

if (
typeof options.spawnPlayer !== 'function' ||
(typeof options.spawnPlayer === undefined && (typeof options.fetchPlayer !== 'function' || typeof options.fetchPlayer === undefined))
) {
this.players = new Collection();
options.spawnPlayer = this.defaultSpawnPlayerHandler.bind(this);
}

if (
typeof options.fetchPlayer !== 'function' ||
(typeof options.fetchPlayer === undefined && (typeof options.spawnPlayer !== 'function' || typeof options.spawnPlayer === undefined))
) {
options.fetchPlayer = this.defaultFetchPlayerHandler.bind(this);
}

if (!options.nodes.length) throw new Error('Nodes option must not a empty array');
}

export class Kirishima extends Structure.get('BaseKirishima') {
public async initialize(clientId?: string) {
if (!clientId && !this.options.clientId) throw new Error('Invalid clientId provided');
if (clientId && !this.options.clientId) this.options.clientId = clientId;
Expand Down Expand Up @@ -72,31 +43,6 @@ export class Kirishima extends EventEmitter {
return this;
}

public resolveNode(identifierOrGroup?: string) {
const resolveGroupedNode = this.nodes.filter((x) => x.connected).find((x) => x.options.group?.includes(identifierOrGroup!)!);
if (resolveGroupedNode) return resolveGroupedNode;
const resolveIdenfitierNode = this.nodes.filter((x) => x.connected).find((x) => x.options.identifier === identifierOrGroup);
if (resolveIdenfitierNode) return resolveIdenfitierNode;
return this.resolveBestNode().first();
}

public resolveBestNode() {
return this.nodes
.filter((x) => x.connected)
.sort((x, y) => {
const XLoad = x.stats?.cpu ? (x.stats.cpu.systemLoad / x.stats.cpu.cores) * 100 : 0;
const YLoad = y.stats?.cpu ? (y.stats.cpu.systemLoad / y.stats.cpu.cores) * 100 : 0;
return XLoad - YLoad;
});
}

public async resolveTracks(options: string | { source?: string | undefined; query: string }, node?: KirishimaNode): Promise<LoadTrackResponse> {
node ??= this.resolveNode();
const resolveTracks = await node!.rest.loadTracks(options);
if (resolveTracks?.tracks.length) resolveTracks.tracks = resolveTracks.tracks.map((x) => new (Structure.get('KirishimaTrack'))(x));
return resolveTracks as unknown as LoadTrackResponse;
}

public spawnPlayer(options: KirishimaPlayerOptions, node?: KirishimaNode) {
return this.options.spawnPlayer!(options.guildId, options, node ?? this.resolveNode()!);
}
Expand All @@ -121,16 +67,4 @@ export class Kirishima extends EventEmitter {
await this.handleVoiceServerUpdate(packet as GatewayVoiceServerUpdateDispatch);
}
}

private defaultSpawnPlayerHandler(guildId: string, options: KirishimaPlayerOptions, node: KirishimaNode) {
const player = this.players!.has(guildId);
if (player) return this.players!.get(guildId)!;
const kirishimaPlayer = new (Structure.get('KirishimaPlayer'))(options, this, node);
this.players!.set(guildId, kirishimaPlayer);
return kirishimaPlayer;
}

private defaultFetchPlayerHandler(guildId: string) {
return this.players!.get(guildId);
}
}
2 changes: 1 addition & 1 deletion src/Structures/KirishimaNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { KirishimaNodeOptions } from '../typings';
import type { Kirishima } from './Kirishima';
import { GatewayVoiceServerUpdateDispatch, GatewayVoiceStateUpdateDispatch } from 'discord-api-types/gateway/v9';
import { LavalinkStatsPayload, WebsocketOpEnum } from 'lavalink-api-types';
import { BasePlayer } from './BasePlayer';
import { BasePlayer } from '../Base/BasePlayer';

export class KirishimaNode {
public ws!: Gateway;
Expand Down
4 changes: 2 additions & 2 deletions src/Structures/KirishimaPlayer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Kirishima } from './Kirishima';
import type { KirishimaPlayerOptions } from '../typings/index';
import { isTrack, KirishimaNode } from '../index';

Expand All @@ -17,13 +16,14 @@ import {
import { KirishimaTrack } from './Track/KirishimaTrack';
import { KirishimaFilter, KirishimaFilterOptions } from './KirishimaFilter';
import { Structure } from './Structure';
import { BaseKirishima } from '../Base/BaseKirishima';

export class KirishimaPlayer extends Structure.get('BasePlayer') {
public filters = new (Structure.get('KirishimaFilter'))();
public paused = false;
public playing = false;

public constructor(public options: KirishimaPlayerOptions, public kirishima: Kirishima, public node: KirishimaNode) {
public constructor(public options: KirishimaPlayerOptions, public kirishima: BaseKirishima, public node: KirishimaNode) {
super(options, kirishima, node);
}

Expand Down
6 changes: 4 additions & 2 deletions src/Structures/Structure.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
/* eslint-disable @typescript-eslint/no-extraneous-class */
import type { Extendable } from '../typings';
import { BasePlayer } from './BasePlayer';
import { BasePlayer } from '../Base/BasePlayer';
import { KirishimaFilter } from './KirishimaFilter';

import { KirishimaNode } from './KirishimaNode';
import { KirishimaPlayer } from './KirishimaPlayer';
import { KirishimaPartialTrack } from './Track/KirishimaPartialTrack';
import { KirishimaTrack } from './Track/KirishimaTrack';
import { BaseKirishima } from '../Base/BaseKirishima';

const structures = {
KirishimaNode,
KirishimaPlayer,
KirishimaPartialTrack,
KirishimaTrack,
KirishimaFilter,
BasePlayer
BasePlayer,
BaseKirishima
};

export abstract class Structure {
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ export * from './Structures/Track/KirishimaPartialTrack';
export * from './Structures/Track/KirishimaTrack';
export * from './Structures/KirishimaFilter';
export * from './Structures/KirishimaPlugin';
export * from './Structures/BasePlayer';
export * from './Base/BasePlayer';
export * from './typings/index';
export * from './Util';
4 changes: 3 additions & 1 deletion src/typings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import type { KirishimaTrack } from '../Structures/Track/KirishimaTrack';
import type { KirishimaPartialTrack } from '../Structures/Track/KirishimaPartialTrack';
import { KirishimaFilter } from '../Structures/KirishimaFilter';
import { KirishimaPlugin } from '../Structures/KirishimaPlugin';
import { BasePlayer } from '../Structures/BasePlayer';
import { BasePlayer } from '../Base/BasePlayer';
import { LoadTrackResponse as OLoadTrackResponse } from 'lavalink-api-types';
import { BaseKirishima } from '../Base/BaseKirishima';

export interface KirishimaOptions {
clientId?: string;
Expand Down Expand Up @@ -69,6 +70,7 @@ export interface Extendable {
KirishimaPartialTrack: typeof KirishimaPartialTrack;
KirishimaFilter: typeof KirishimaFilter;
BasePlayer: typeof BasePlayer;
BaseKirishima: typeof BaseKirishima;
}

export interface LoadTrackResponse extends OLoadTrackResponse {
Expand Down

0 comments on commit 34093f4

Please sign in to comment.