Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
Takiyo0 committed Jun 12, 2022
0 parents commit 7a57ac0
Show file tree
Hide file tree
Showing 12 changed files with 887 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
dist
test
package-lock.json
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"printWidth": 120,
"trailingComma": "all",
"singleQuote": true
}
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Kazagumo
#### A [Shoukaku](https://github.com/Deivu/Shoukaku) wrapper with built in queue system

#### ⚠️ Unfinished 2.0.0 update, Do not use for production ⚠️

![Kazagumo](https://i.imgur.com/jfVSvHj.png)
> Kazagumo © Azur Lane
## Features:

✓ Built-in queue system
✓ Easy to use
✓ Modular system
✓ Stable _kinda_
✓ 💖 cute shipgirl

## Documentation

> [Shoukaku](https://github.com/Deivu/Shoukaku) by [Deivu](https://github.com/Deivu); https://deivu.github.io/Shoukaku
> Kazagumo; https://takiyo0.github.io/Kazagumo
## Installation

> npm i kazagumo
## Lavalink installation

> Full tutorial step-by-step with image [here](https://github.com/Weeb-Devs/Laffey/blob/main/readme/LAVALINK_INSTALLATION.md) ©Weeb-Devs, the owner is me tbh
> System requirements [here](https://github.com/freyacodes/Lavalink#requirements)
more content will be added soon
33 changes: 33 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "kazagumo",
"version": "2.0.0",
"description": "A shoukaku wrapper with built-in queue support.",
"main": "dist/Index.js",
"types": "dist/Index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "tsc",
"format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"",
"lint": "tslint -p tsconfig.json"
},
"keywords": [],
"author": "Takiyo",
"files": [
"dist/**/*"
],
"license": "ISC",
"devDependencies": {
"@types/events": "^3.0.0",
"@types/node": "^17.0.42",
"@types/ws": "^8.5.3",
"discord.js": "^13.8.0",
"prettier": "^2.6.2",
"tslint": "^6.1.3",
"tslint-config-prettier": "^1.18.0",
"typescript": "^4.7.3"
},
"dependencies": {
"events": "^3.3.0",
"shoukaku": "github:Deivu/Shoukaku#15b4457c20862308abc39c181b0e51e1755bef28"
}
}
13 changes: 13 additions & 0 deletions src/Index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// import { NodeOption, PlayerUpdate, ShoukakuOptions, TrackExceptionEvent, WebSocketClosedEvent } from "shoukaku";
import KazagumoTrack from "./Managers/Supports/KazagumoTrack";
import { KazagumoQueue } from "./Managers/Supports/KazagumoQueue";
import KazagumoPlayer from "./Managers/KazagumoPlayer";
// import KazagumoPlayer from "./Managers/KazagumoPlayer";
// import { KazagumoOptions } from "./Modules/Interfaces";
// import { Connector } from "shoukaku/dist/src/connectors/Connector";


export * from "./Kazagumo";
export { KazagumoTrack, KazagumoQueue, KazagumoPlayer };

export const version = "2.0.0";
116 changes: 116 additions & 0 deletions src/Kazagumo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { EventEmitter } from "events";
import { KazagumoOptions, KazagumoPlugin, KazagumoError, createPlayerOptions, State, KazagumoSearchOptions, KazagumoSearchResult, SourceIDs, Events, SearchResultTypes } from "./Modules/Interfaces";
import { NodeOption, ShoukakuOptions, Shoukaku, Node, WebSocketClosedEvent, TrackExceptionEvent, PlayerUpdate } from "shoukaku";
import { Connector } from "shoukaku/dist/src/connectors/Connector";

import KazagumoPlayer from "./Managers/KazagumoPlayer";
import KazagumoTrack from "./Managers/Supports/KazagumoTrack";

export declare interface Kazagumo {
on(event: "playerStart", listener: (track: KazagumoTrack) => void): this;
on(event: "playerResolveError", listener: (track: KazagumoTrack) => void): this;
on(event: "playerDestroy", listener: (player: KazagumoPlayer) => void): this;
on(event: "playerEnd", listener: (player: KazagumoPlayer) => void): this;
on(event: "playerEmpty", listener: (player: KazagumoPlayer) => void): this;
on(event: "playerClosed", listener: (player: KazagumoPlayer, data: WebSocketClosedEvent) => void): this;
on(event: "playerException", listener: (player: KazagumoPlayer, data: TrackExceptionEvent) => void): this;
on(event: "PlayerUpdate", listener: (player: KazagumoPlayer, data: PlayerUpdate) => void): this;


on(event: "debug", listener: (data: unknown) => void): this;

}

export class Kazagumo extends EventEmitter {
public shoukaku: Shoukaku;
private kazagumoOptions: KazagumoOptions;
public readonly players: Map<string, KazagumoPlayer> = new Map();

constructor(public KazagumoOptions: KazagumoOptions, connector: Connector, nodes: NodeOption[], options: ShoukakuOptions = {}) {
super();

this.shoukaku = new Shoukaku(connector, nodes, options);
this.kazagumoOptions = KazagumoOptions;

if (this.KazagumoOptions.plugins) {
for (const plugin of this.KazagumoOptions.plugins) {
if (!(plugin instanceof KazagumoPlugin)) throw new KazagumoError(1, "Plugin must be an instance of Plugin");
plugin.load(this);
}
}

this.players = new Map<string, KazagumoPlayer>();
}

public async createPlayer(options: createPlayerOptions): Promise<KazagumoPlayer> {
const exist = this.players.get(options.guildId);
if (exist) return exist;

let node;
if (options.loadBalancer) node = this.getLeastUsedNode();
else if (options.nodeName) node = this.shoukaku.getNode(options.nodeName);
else node = this.shoukaku.getNode("auto");

if (!options.deaf) options.deaf = false;
if (!options.mute) options.mute = false;

if (!node) throw new KazagumoError(3, "No node found");

const shoukakuPlayer = await node.joinChannel({
guildId: options.guildId,
channelId: options.voiceId,
deaf: options.deaf,
mute: options.mute,
shardId: options.shardId && !isNaN(options.shardId) ? options.shardId : 0
});

const kazagumoPlayer = new KazagumoPlayer(this, shoukakuPlayer, { guildId: options.guildId, voiceId: options.voiceId, textId: options.textId, deaf: options.deaf });
this.players.set(options.guildId, kazagumoPlayer);
return kazagumoPlayer;
}

public getPlayer(guildId: string): KazagumoPlayer | undefined {
return this.players.get(guildId);
}

public destroyPlayer(guildId: string): void {
const player = this.getPlayer(guildId);
if (!player) return;
player.destroy();
this.players.delete(guildId);
}

public getLeastUsedNode(): Node {
const nodes: Node[] = [...this.shoukaku.nodes.values()];

const onlineNodes = nodes.filter(node => node.state === State.CONNECTED);
if (!onlineNodes.length) throw new KazagumoError(2, "No nodes are online");

const leastUsedNode = onlineNodes.reduce((a, b) => a.players.size < b.players.size ? a : b);
return leastUsedNode;
}

public async search(query: string, options?: KazagumoSearchOptions): Promise<KazagumoSearchResult> {
const node = this.getLeastUsedNode();
if (!node) throw new KazagumoError(3, "No node is available");

const source = SourceIDs[options?.engine || this.kazagumoOptions.defaultSearchEngine || "youtube"];

const result = await node.rest.resolve(!/^https?:\/\//.test(query) ? `${source}search:${query}` : query).catch(_ => null);
if (!result) return this.buildSearch(undefined, [], "SEARCH");
this.emit(Events.Debug, `Searched ${query}; Track results: ${result.tracks.length}`);

let loadType = "TRACK" as SearchResultTypes;
if (result.playlistInfo.name) loadType = "PLAYLIST";

return this.buildSearch(result.playlistInfo.name ?? undefined, result.tracks.map(track => new KazagumoTrack(track, options?.requester)), loadType);
}

private buildSearch(playlistName?: string, tracks: KazagumoTrack[] = [], type?: SearchResultTypes): KazagumoSearchResult {
return {
playlistName,
tracks,
type: type ?? "TRACK"
};
}
}
Loading

0 comments on commit 7a57ac0

Please sign in to comment.