Skip to content

Commit

Permalink
Feat: shortened/improved code (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
JaronZ authored Aug 30, 2021
1 parent bfd7452 commit 93cb1c8
Show file tree
Hide file tree
Showing 13 changed files with 101 additions and 142 deletions.
38 changes: 14 additions & 24 deletions src/bot.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {config} from "dotenv";
import {readdirSync} from "fs";
import {join} from "path";
import { CustomClient } from "./client";
import { PlayerEvent } from "./event";
import { SlashCommand } from "./command";
import { ClientEvent, PlayerEvent } from "./event";
import { Util } from "./util";
config();

const client = new CustomClient({
Expand All @@ -12,26 +12,16 @@ const client = new CustomClient({
]
});

for(const file of readdirSync(join(__dirname, "commands")).filter(file => file.endsWith(".js"))){
let command = require(`./commands/${file}`);
// make a new command if a class is being used
try { command = new command(); } catch (error) {}
client.commands.set(command.data.name, command);
}

for(const file of readdirSync(join(__dirname, "events/client")).filter(file => file.endsWith(".js"))){
let event = require(`./events/client/${file}`);
// make a new event if a class is being used
try { event = new event(); } catch (error) {}
client.onCustom(file, event.name, (...args) => event.run(...args), event.once);
}

for(const file of readdirSync(join(__dirname, "events/player")).filter(file => file.endsWith(".js"))){
let event: PlayerEvent = require(`./events/player/${file}`);
// make a new event if a class is being used
// @ts-ignore
try { event = new event(); } catch {}
client.player.onCustom(file, event.name, event.run);
}
Util
.getJSFiles("commands", (commands: SlashCommand[]) => {
commands.forEach(command => client.commands.set(command.data.name, command));
})
.getJSFiles("events/client", (events: ClientEvent[], files: string[]) => {
events.forEach((event, index) => event.once ?
client.once(event.name, event.run) : client.onCustom(files[index], event.name, event.run));
})
.getJSFiles("events/player", (events: PlayerEvent[], files: string[]) => {
events.forEach((event, index) => client.player.onCustom(files[index], event.name, event.run, event.once));
});

client.login(process.env.TOKEN);
16 changes: 10 additions & 6 deletions src/client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Awaited, Client, ClientEvents, ClientOptions, Collection } from "discord.js";
import { SlashCommand } from "./command";
import { ClientEvent } from "./event";
import { CustomPlayer } from "./player";

/**
Expand All @@ -16,27 +17,30 @@ class CustomClient<Ready extends boolean = boolean> extends Client<Ready> {
public readonly player: CustomPlayer;

private readonly events: Collection<string, {
name: string,
listener: (...args: any[]) => any
name: keyof ClientEvents;
listener: (...args: ClientEvents[keyof ClientEvents]) => Awaited<void>;
}> = new Collection();

constructor(options: ClientOptions){
super(options);
this.player = new CustomPlayer(this);
}

public onCustom<K extends keyof ClientEvents>(file: string, event: K, listener: (...args: ClientEvents[K]) => Awaited<void>, once: boolean = false): this {
public onCustom<K extends keyof ClientEvents>(file: string, event: K, listener: (...args: ClientEvents[K]) => Awaited<void>): this {
this.events.set(file, {
name: event,
listener
});
return once ? this.once(event, listener) : this.on(event, listener);
return this.on(event, listener);
}

public offCustom(file: string): this {
public reloadEvent(newEvent: ClientEvent, file: string): this {
if(newEvent.once) return;
const oldEvent = this.events.get(file);
this.events.delete(file);
return this.off(oldEvent.name, oldEvent.listener);
return this
.off(oldEvent.name, oldEvent.listener)
.onCustom(file, newEvent.name, newEvent.run);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ abstract class SlashCommand {
/**
* Run this command
*/
public abstract run(interaction: CommandInteraction): void | Promise<void>;
public abstract run(interaction: CommandInteraction, ...args: any[]): any;
}

export {SlashCommand};
20 changes: 9 additions & 11 deletions src/commands/disconnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,15 @@ module.exports = class extends SlashCommand {
{guild} = interaction,
{channel} = guild.me.voice;

if(!(interaction.member as GuildMember).voice.channel.equals(channel)){
return void interaction.editReply({
embeds: [
new MessageEmbed({
color: "RED",
title: "Can't disconnect",
description: "You need to be in the same voice channel to disconnect"
})
]
});
}
if(!(interaction.member as GuildMember).voice.channel.equals(channel)) return interaction.editReply({
embeds: [
new MessageEmbed({
color: "RED",
title: "Can't disconnect",
description: "You need to be in the same voice channel to disconnect"
})
]
});

client.player.deleteQueue(guild);

Expand Down
8 changes: 5 additions & 3 deletions src/commands/join.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module.exports = class extends SlashCommand {
});
}

async run(interaction: CommandInteraction){
async run(interaction: CommandInteraction, sendReply: boolean = true){
const client = interaction.client as CustomClient,
{member, guild} = interaction,
{voice} = member as GuildMember;
Expand All @@ -26,7 +26,7 @@ module.exports = class extends SlashCommand {
if (!queue.connection) await queue.connect(voice.channel);
} catch {
client.player.deleteQueue(guild);
return void interaction.editReply({
return interaction.editReply({
embeds: [
new MessageEmbed({
color: "RED",
Expand All @@ -37,7 +37,7 @@ module.exports = class extends SlashCommand {
});
}

interaction.editReply({
if(sendReply) interaction.editReply({
embeds: [
new MessageEmbed({
color: "GREEN",
Expand All @@ -46,5 +46,7 @@ module.exports = class extends SlashCommand {
})
]
});

return queue;
}
}
27 changes: 6 additions & 21 deletions src/commands/play.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { SlashCommandBuilder } from "@discordjs/builders";
import { QueryType } from "discord-player";
import { CommandInteraction, GuildMember, MessageEmbed } from "discord.js";
import { QueryType, Queue } from "discord-player";
import { CommandInteraction, MessageEmbed } from "discord.js";
import { CustomClient } from "../client";
import { SlashCommand } from "../command";

Expand All @@ -26,10 +26,9 @@ module.exports = class extends SlashCommand {
result = await client.player.search(query, {
requestedBy: interaction.user,
searchEngine: QueryType.AUTO
}),
{guild} = interaction;
});

if(!result || !result.tracks.length) return void interaction.editReply({
if(!result || !result.tracks.length) return interaction.editReply({
embeds: [
new MessageEmbed({
color: "RED",
Expand All @@ -39,22 +38,8 @@ module.exports = class extends SlashCommand {
]
});

const queue = client.player.createQueue(guild, {metadata: interaction});

try {
if (!queue.connection) await queue.connect((interaction.member as GuildMember).voice.channel);
} catch {
client.player.deleteQueue(guild);
return void interaction.editReply({
embeds: [
new MessageEmbed({
color: "RED",
title: "Can't join voice channel",
description: "Unable to join your voice channel"
})
]
});
}
const queue = await client.commands.get("join").run(interaction, false);
if(!(queue instanceof Queue)) return;

const type = result.playlist ? "playlist" : "song";

Expand Down
5 changes: 3 additions & 2 deletions src/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ config();
const commands: SlashCommand[] = readdirSync(join(__dirname, "commands"))
.filter(file => file.endsWith(".js"))
.map(file => {
let command = require(`./commands/${file}`);
let command: SlashCommand = require(`./commands/${file}`);
// make a new command if a class is being used
// @ts-ignore
try { command = new command(); } catch (error) {}
return command as SlashCommand;
return command;
}),
rest = new REST({version: "9"}).setToken(process.env.TOKEN),
guildId = process.env.GUILD,
Expand Down
45 changes: 8 additions & 37 deletions src/event.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { PlayerEvents } from "discord-player";
import { ClientEvents } from "discord.js";
import { Awaited, ClientEvents } from "discord.js";

/**
* Base class for events
*/
abstract class OTEvent {
abstract class OTEvent<Name extends string> {
/**
* The name of the event
*/
public readonly name: string;
public readonly name: Name;
/**
* If this event should only be run once
*/
Expand All @@ -20,57 +20,28 @@ abstract class OTEvent {
* @param name The name of the event
* @param once If this event should only be run once
*/
public constructor(name: string, once: boolean = false){
public constructor(name: Name, once: boolean = false){
this.name = name;
this.once = once;
}

/**
* Run this event
*/
public abstract run(...args: unknown[]): void;
public abstract run(...args: unknown[]): unknown;
}

/**
* Base class for client events
*/
abstract class ClientEvent extends OTEvent {
/**
* The name of the event
*/
declare public readonly name: keyof ClientEvents;

/**
* Make a new client event
* @param name The name of the event
* @param once If this event should only be run once
*/
public constructor(name: keyof ClientEvents, once: boolean = false){
super(name, once);
}
abstract class ClientEvent<K extends keyof ClientEvents = keyof ClientEvents> extends OTEvent<K> {
public abstract run(...args: ClientEvents[K]): Awaited<void>;
}

/**
* Base class for player events
*/
abstract class PlayerEvent<K extends keyof PlayerEvents = keyof PlayerEvents> extends OTEvent {
/**
* The name of the event
*/
declare public readonly name: K;

/**
* Make a new player event
* @param name The name of the event
* @param once If this event should only be run once
*/
public constructor(name: K, once: boolean = false){
super(name, once);
}

/**
* Run this event
*/
abstract class PlayerEvent<K extends keyof PlayerEvents = keyof PlayerEvents> extends OTEvent<K> {
public abstract run: PlayerEvents[K];
}

Expand Down
34 changes: 6 additions & 28 deletions src/events/client/ready.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,20 @@
import { ActivityOptions } from "discord.js";
import { watch } from "fs";
import { CustomClient } from "../../client";
import { SlashCommand } from "../../command";
import { CustomConsole } from "../../console";
import { ClientEvent, PlayerEvent } from "../../event";
import { Util } from "../../util";

module.exports = class extends ClientEvent {
constructor(){
super("ready", true);
}

async run(client: CustomClient<true>){
watch("dist/commands", "utf8", (eventType, file) => {
if(eventType != "change") return;
const path = `../../commands/${file}`;
delete require.cache[require.resolve(path)];
let command = require(path);
try { command = new command(); } catch (error) {}
client.commands.set(command.data.name, command);
});
watch("dist/events/client", "utf8", (eventType, file) => {
if(eventType != "change") return;
client.offCustom(file);
const path = `./${file}`;
delete require.cache[require.resolve(path)];
let event = require(path);
try { event = new event(); } catch (error) {}
client.onCustom(file, event.name, (...args) => event.run(...args));
});
watch("dist/events/player", "utf8", (eventType, file) => {
if(eventType != "change") return;
client.player.offCustom(file);
const path = `../player/${file}`;
delete require.cache[require.resolve(path)];
let event: PlayerEvent = require(path);
// @ts-ignore
try { event = new event(); } catch {}
client.player.onCustom(file, event.name, event.run);
});
Util
.watchDir("dist/commands", (command: SlashCommand) => client.commands.set(command.data.name, command))
.watchDir("dist/events/client", (event: ClientEvent, file: string) => client.reloadEvent(event, file))
.watchDir("dist/events/player", (event: PlayerEvent, file: string) => client.player.reloadEvent(event, file));

try {
CustomConsole.log("Setting default permission for guild (/) commands.");
Expand Down
3 changes: 1 addition & 2 deletions src/events/player/connectionCreate.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Queue, StreamDispatcher } from "discord-player";
import { CommandInteraction } from "discord.js";
import { CustomConsole } from "../../console";
import { PlayerEvent } from "../../event";

Expand All @@ -8,7 +7,7 @@ module.exports = class extends PlayerEvent<"connectionCreate"> {
super("connectionCreate");
}

run = (queue: Queue<CommandInteraction>, connection: StreamDispatcher) => {
run = (queue: Queue, connection: StreamDispatcher) => {
CustomConsole.log(`[${queue.guild.name}] Now connected to 🔊 ${connection.channel.name}`);
}
}
Loading

0 comments on commit 93cb1c8

Please sign in to comment.