Implement events and voice auto disconnect

This commit is contained in:
Ethanell 2021-11-22 15:57:31 +01:00
parent 324b321e5b
commit b761c5ca0e
6 changed files with 121 additions and 20 deletions

View file

@ -1,26 +1,17 @@
import {ApplicationCommandData, CommandInteraction} from "discord.js";
import {Module} from "./Module";
import {Logger} from "./Logger";
import {Component} from "./Component";
export abstract class Command {
module: Module;
export abstract class Command extends Component {
data: ApplicationCommandData;
logger: Logger;
protected constructor(module: Module, data: ApplicationCommandData) {
super(module, data.name);
this.module = module;
this.data = data;
this.logger = this.module.logger.createChild(this.data.name);
}
abstract execute(interaction: CommandInteraction): void;
load(): any {
};
unload(): any {
};
}

21
src/lib/Component.ts Normal file
View file

@ -0,0 +1,21 @@
import {Module} from "./Module";
import {Logger} from "./Logger";
export abstract class Component {
module: Module;
logger: Logger;
protected constructor(module: Module, name: string | null = null) {
this.module = module;
this.logger = this.module.logger.createChild(name || this.constructor.name);
}
load(): any {
};
unload(): any {
};
}

5
src/lib/Event.ts Normal file
View file

@ -0,0 +1,5 @@
import {Component} from "./Component";
export abstract class Event extends Component {
}

View file

@ -1,34 +1,82 @@
import {Command} from "./Command";
import {Modules} from "./Modules";
import {Logger} from "./Logger";
import {readdirSync} from "fs";
import {readdirSync, existsSync} from "fs";
import {Event} from "./Event";
export abstract class Module {
modules: Modules;
logger: Logger;
loadedCommands: Command[] = [];
loadedEvents: Event[] = [];
protected constructor(modules: Modules, name: string) {
this.modules = modules;
this.logger = this.modules.client.logger.createChild(name);
}
get commands() {
const folder = `${__dirname}/../modules/${this.constructor.name}/commands`;
private getComponent(name: string) {
const folder = `${__dirname}/../modules/${this.constructor.name}/${name}`;
if (existsSync(folder))
return readdirSync(folder, {withFileTypes: true})
.filter(file => file.isDirectory() || file.name.endsWith(".js"))
.map(file => (require(`${folder}/${file.name}`)[file.name.charAt(0).toUpperCase() + file.name.replace(/\.js$/, "").slice(1)+"Command"]));
.map(file => require(`${folder}/${file.name}`)[file.name.charAt(0).toUpperCase() + file.name.replace(/\.js$/, "").slice(1)+name.charAt(0).toUpperCase() + name.slice(1).replace(/s$/, "")]);
else
return [];
}
get commands() {
return this.getComponent("commands");
}
get events() {
return this.getComponent("events");
}
async load() {
const commands = this.commands.map(cmd => new cmd(this));
await Promise.all(commands.map(cmd => cmd.load()));
await this.loadCommands();
await this.loadEvents();
}
async loadCommands() {
const commands: Command[] = [];
for (const command of this.commands) {
try {
const cmd: Command = new command(this);
await cmd.load();
commands.push(cmd);
} catch (error) {
this.logger.err(`Fail to load command ${command}`);
this.logger.err(error);
}
}
this.loadedCommands = this.loadedCommands.concat(commands);
}
async loadEvents() {
const events: Event[] = [];
for (const event of this.events) {
try {
const env: Event = new event(this);
await env.load();
events.push(env);
} catch (error) {
this.logger.err(`Fail to load event ${event}`);
this.logger.err(error);
}
}
this.loadedEvents = this.loadedEvents.concat(events);
}
async unload() {
await Promise.all(this.loadedCommands.map(cmd => cmd.unload()));
this.loadedCommands = [];
await Promise.all(this.loadedEvents.map(cmd => cmd.unload()));
this.loadedEvents = [];
}
}

View file

@ -21,7 +21,7 @@ export class Modules {
if (createCommand)
await this.registerCommand(module.loadedCommands.map(c => c.data));
module.logger.info(`loaded`)
module.logger.info("loaded");
} catch (error) {
this.client.logger.err(`Fail to load module ${name}`);
this.client.logger.err(error);

View file

@ -0,0 +1,36 @@
import {Event} from "../../../lib/Event";
import {VoiceState} from "discord.js";
import {Music} from "../index";
export class VoiceStateUpdateEvent extends Event {
module: Music;
private readonly callback;
constructor(module: Music) {
super(module);
this.module = module;
this.callback = async (oldState: VoiceState, newState: VoiceState) => {
const player = this.module.players.get(oldState.guild.id);
if (!player)
return;
if (!oldState.channel || oldState.channelId != player.connexion.joinConfig.channelId || (newState.channelId == oldState.channelId))
return;
await oldState.channel.fetch(true);
if (oldState.channel.members.size == 1) {
player.disconnect();
this.module.players.delete(oldState.guild.id);
}
}
}
load() {
this.module.modules.client.on("voiceStateUpdate", this.callback);
}
unload() {
this.module.modules.client.removeListener("voiceStateUpdate", this.callback);
}
}