v3.0 #145
42 changed files with 3368 additions and 147 deletions
|
@ -13,8 +13,6 @@ BOT_AUTHOR=Vylpes
|
||||||
BOT_DATE=28 Nov 2021
|
BOT_DATE=28 Nov 2021
|
||||||
BOT_OWNERID=147392775707426816
|
BOT_OWNERID=147392775707426816
|
||||||
|
|
||||||
CORE_VER=2.0.2
|
|
||||||
|
|
||||||
FOLDERS_COMMANDS=src/commands
|
FOLDERS_COMMANDS=src/commands
|
||||||
FOLDERS_EVENTS=src/events
|
FOLDERS_EVENTS=src/events
|
||||||
|
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
{
|
|
||||||
"token": "",
|
|
||||||
"prefix": "v!",
|
|
||||||
"commands": [
|
|
||||||
"commands"
|
|
||||||
],
|
|
||||||
"events": [
|
|
||||||
"events"
|
|
||||||
],
|
|
||||||
"about": {
|
|
||||||
"description": "Discord Bot for Vylpes' Den",
|
|
||||||
"version": "2.2",
|
|
||||||
"core-ver": "1.0.4",
|
|
||||||
"author": "Vylpes",
|
|
||||||
"date": "23/11/2021"
|
|
||||||
},
|
|
||||||
"ban": {
|
|
||||||
"modrole": "Moderator",
|
|
||||||
"logchannel": "mod-logs"
|
|
||||||
},
|
|
||||||
"clear": {
|
|
||||||
"modrole": "Moderator",
|
|
||||||
"logchannel": "mod-logs"
|
|
||||||
},
|
|
||||||
"eval": {
|
|
||||||
"ownerid": "147392775707426816"
|
|
||||||
},
|
|
||||||
"kick": {
|
|
||||||
"modrole": "Moderator",
|
|
||||||
"logchannel": "mod-logs"
|
|
||||||
},
|
|
||||||
"mute": {
|
|
||||||
"modrole": "Moderator",
|
|
||||||
"logchannel": "mod-logs",
|
|
||||||
"muterole": "Muted"
|
|
||||||
},
|
|
||||||
"partner": {
|
|
||||||
"adminrole": "Admin",
|
|
||||||
"partnersfile": "data/partner/partner.json"
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"adminrole": "Admin",
|
|
||||||
"rulesfile": "data/rules/rules.json"
|
|
||||||
},
|
|
||||||
"unmute": {
|
|
||||||
"modrole": "Moderator",
|
|
||||||
"logchannel": "mod-logs",
|
|
||||||
"muterole": "Muted"
|
|
||||||
},
|
|
||||||
"warn": {
|
|
||||||
"modrole": "Moderator",
|
|
||||||
"logchannel": "mod-logs"
|
|
||||||
},
|
|
||||||
"role": {
|
|
||||||
"assignable": [
|
|
||||||
"Notify",
|
|
||||||
"VotePings",
|
|
||||||
"ProjectUpdates"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
5
jest.config.js
Normal file
5
jest.config.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
/** @type {import('@ts-jest/dist/types').InitialOptionsTsJest} */
|
||||||
|
module.exports = {
|
||||||
|
preset: 'ts-jest',
|
||||||
|
testEnvironment: 'node',
|
||||||
|
};
|
|
@ -6,7 +6,8 @@
|
||||||
"typings": "./dist",
|
"typings": "./dist",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"start": "ts-node ./src/vylbot"
|
"start": "ts-node ./src/vylbot",
|
||||||
|
"test": "jest"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -17,10 +18,14 @@
|
||||||
"bugs": "https://github.com/Vylpes/vylbot-app/issues",
|
"bugs": "https://github.com/Vylpes/vylbot-app/issues",
|
||||||
"homepage": "https://github.com/Vylpes/vylbot-app",
|
"homepage": "https://github.com/Vylpes/vylbot-app",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/jest": "^27.0.3",
|
||||||
|
"discord.js": "12.5.3",
|
||||||
"dotenv": "^10.0.0",
|
"dotenv": "^10.0.0",
|
||||||
"emoji-regex": "^9.2.0",
|
"emoji-regex": "^9.2.0",
|
||||||
|
"jest": "^27.4.5",
|
||||||
|
"jest-mock-extended": "^2.0.4",
|
||||||
"random-bunny": "^2.0.0",
|
"random-bunny": "^2.0.0",
|
||||||
"vylbot-core": "^2.0.3"
|
"ts-jest": "^27.1.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^16.11.10",
|
"@types/node": "^16.11.10",
|
||||||
|
|
37
src/Register.ts
Normal file
37
src/Register.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import { CoreClient } from "./client/client";
|
||||||
|
import About from "./commands/about";
|
||||||
|
import Ban from "./commands/ban";
|
||||||
|
import Clear from "./commands/clear";
|
||||||
|
import Evaluate from "./commands/eval";
|
||||||
|
import Help from "./commands/help";
|
||||||
|
import Kick from "./commands/kick";
|
||||||
|
import Mute from "./commands/mute";
|
||||||
|
import Poll from "./commands/poll";
|
||||||
|
import Role from "./commands/role";
|
||||||
|
import Rules from "./commands/rules";
|
||||||
|
import Unmute from "./commands/unmute";
|
||||||
|
import Warn from "./commands/warn";
|
||||||
|
import MemberEvents from "./events/MemberEvents";
|
||||||
|
import MessageEvents from "./events/MessageEvents";
|
||||||
|
|
||||||
|
export default class Register {
|
||||||
|
public static RegisterCommands(client: CoreClient) {
|
||||||
|
client.RegisterCommand("about", new About());
|
||||||
|
client.RegisterCommand("ban", new Ban());
|
||||||
|
client.RegisterCommand("clear", new Clear());
|
||||||
|
client.RegisterCommand("eval", new Evaluate());
|
||||||
|
client.RegisterCommand("help", new Help());
|
||||||
|
client.RegisterCommand("kick", new Kick());
|
||||||
|
client.RegisterCommand("mute", new Mute());
|
||||||
|
client.RegisterCommand("poll", new Poll());
|
||||||
|
client.RegisterCommand("role", new Role());
|
||||||
|
client.RegisterCommand("rules", new Rules());
|
||||||
|
client.RegisterCommand("unmute", new Unmute());
|
||||||
|
client.RegisterCommand("warn", new Warn());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RegisterEvents(client: CoreClient) {
|
||||||
|
client.RegisterEvent(new MemberEvents());
|
||||||
|
client.RegisterEvent(new MessageEvents());
|
||||||
|
}
|
||||||
|
}
|
59
src/client/client.ts
Normal file
59
src/client/client.ts
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
import { Client } from "discord.js";
|
||||||
|
import * as dotenv from "dotenv";
|
||||||
|
import ICommandItem from "../contracts/ICommandItem";
|
||||||
|
import IEventItem from "../contracts/IEventItem";
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
import { Event } from "../type/event";
|
||||||
|
|
||||||
|
import { Events } from "./events";
|
||||||
|
import { Util } from "./util";
|
||||||
|
|
||||||
|
export class CoreClient extends Client {
|
||||||
|
private _commandItems: ICommandItem[];
|
||||||
|
private _eventItems: IEventItem[];
|
||||||
|
|
||||||
|
private _events: Events;
|
||||||
|
private _util: Util;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
dotenv.config();
|
||||||
|
|
||||||
|
this._commandItems = [];
|
||||||
|
this._eventItems = [];
|
||||||
|
|
||||||
|
this._events = new Events();
|
||||||
|
this._util = new Util();
|
||||||
|
}
|
||||||
|
|
||||||
|
public start() {
|
||||||
|
if (!process.env.BOT_TOKEN) throw "BOT_TOKEN is not defined in .env";
|
||||||
|
if (!process.env.BOT_PREFIX) throw "BOT_PREFIX is not defined in .env";
|
||||||
|
if (!process.env.FOLDERS_COMMANDS) throw "FOLDERS_COMMANDS is not defined in .env";
|
||||||
|
if (!process.env.FOLDERS_EVENTS) throw "FOLDERS_EVENTS is not defined in .env";
|
||||||
|
|
||||||
|
super.on("message", (message) => this._events.onMessage(message, this._commandItems));
|
||||||
|
super.on("ready", this._events.onReady);
|
||||||
|
|
||||||
|
super.login(process.env.BOT_TOKEN);
|
||||||
|
|
||||||
|
this._util.loadEvents(this, this._eventItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegisterCommand(name: string, command: Command) {
|
||||||
|
const item: ICommandItem = {
|
||||||
|
Name: name,
|
||||||
|
Command: command,
|
||||||
|
};
|
||||||
|
|
||||||
|
this._commandItems.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegisterEvent(event: Event) {
|
||||||
|
const item: IEventItem = {
|
||||||
|
Event: event,
|
||||||
|
};
|
||||||
|
|
||||||
|
this._eventItems.push(item);
|
||||||
|
}
|
||||||
|
}
|
76
src/client/events.ts
Normal file
76
src/client/events.ts
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
import { Message } from "discord.js";
|
||||||
|
import { IBaseResponse } from "../contracts/IBaseResponse";
|
||||||
|
import ICommandItem from "../contracts/ICommandItem";
|
||||||
|
import { Util } from "./util";
|
||||||
|
|
||||||
|
export interface IEventResponse extends IBaseResponse {
|
||||||
|
context?: {
|
||||||
|
prefix: string;
|
||||||
|
name: string;
|
||||||
|
args: string[];
|
||||||
|
message: Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Events {
|
||||||
|
private _util: Util;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._util = new Util();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit when a message is sent
|
||||||
|
// Used to check for commands
|
||||||
|
public onMessage(message: Message, commands: ICommandItem[]): IEventResponse {
|
||||||
|
if (!message.guild) return {
|
||||||
|
valid: false,
|
||||||
|
message: "Message was not sent in a guild, ignoring.",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (message.author.bot) return {
|
||||||
|
valid: false,
|
||||||
|
message: "Message was sent by a bot, ignoring.",
|
||||||
|
};
|
||||||
|
|
||||||
|
const prefix = process.env.BOT_PREFIX as string;
|
||||||
|
|
||||||
|
if (message.content.substring(0, prefix.length).toLowerCase() == prefix.toLowerCase()) {
|
||||||
|
const args = message.content.substring(prefix.length).split(" ");
|
||||||
|
const name = args.shift();
|
||||||
|
|
||||||
|
if (!name) return {
|
||||||
|
valid: false,
|
||||||
|
message: "Command name was not found",
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = this._util.loadCommand(name, args, message, commands);
|
||||||
|
|
||||||
|
if (!res.valid) {
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: res.message,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: true,
|
||||||
|
context: {
|
||||||
|
prefix: prefix,
|
||||||
|
name: name,
|
||||||
|
args: args,
|
||||||
|
message: message,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: "Message was not a command, ignoring.",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit when bot is logged in and ready to use
|
||||||
|
public onReady() {
|
||||||
|
console.log("Ready");
|
||||||
|
}
|
||||||
|
}
|
102
src/client/util.ts
Normal file
102
src/client/util.ts
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
// Required Components
|
||||||
|
import { Client, Message } from "discord.js";
|
||||||
|
import { readdirSync, existsSync } from "fs";
|
||||||
|
import { IBaseResponse } from "../contracts/IBaseResponse";
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
import { Event } from "../type/event";
|
||||||
|
import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
|
import ICommandItem from "../contracts/ICommandItem";
|
||||||
|
import IEventItem from "../contracts/IEventItem";
|
||||||
|
|
||||||
|
export interface IUtilResponse extends IBaseResponse {
|
||||||
|
context?: {
|
||||||
|
name: string;
|
||||||
|
args: string[];
|
||||||
|
message: Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Util Class
|
||||||
|
export class Util {
|
||||||
|
public loadCommand(name: string, args: string[], message: Message, commands: ICommandItem[]): IUtilResponse {
|
||||||
|
if (!message.member) return {
|
||||||
|
valid: false,
|
||||||
|
message: "Member is not part of message",
|
||||||
|
};
|
||||||
|
|
||||||
|
const disabledCommands = process.env.COMMANDS_DISABLED?.split(',');
|
||||||
|
|
||||||
|
if (disabledCommands?.find(x => x == name)) {
|
||||||
|
message.reply(process.env.COMMANDS_DISABLED_MESSAGE || "This command is disabled.");
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: "Command is disabled",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const folder = process.env.FOLDERS_COMMANDS;
|
||||||
|
|
||||||
|
const item = commands.find(x => x.Name == name);
|
||||||
|
|
||||||
|
if (!item) {
|
||||||
|
message.reply('Command not found');
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: "Command not found"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const requiredRoles = item.Command._roles;
|
||||||
|
|
||||||
|
for (const i in requiredRoles) {
|
||||||
|
if (!message.member.roles.cache.find(role => role.name == requiredRoles[i])) {
|
||||||
|
message.reply(`You require the \`${requiredRoles[i]}\` role to run this command`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: `You require the \`${requiredRoles[i]}\` role to run this command`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const context: ICommandContext = {
|
||||||
|
name: name,
|
||||||
|
args: args,
|
||||||
|
message: message
|
||||||
|
};
|
||||||
|
|
||||||
|
item.Command.execute(context);
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: true,
|
||||||
|
context: context
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the events
|
||||||
|
loadEvents(client: Client, events: IEventItem[]): IUtilResponse {
|
||||||
|
const folder = process.env.FOLDERS_EVENTS;
|
||||||
|
|
||||||
|
events.forEach((e) => {
|
||||||
|
client.on('channelCreate', e.Event.channelCreate);
|
||||||
|
client.on('channelDelete', e.Event.channelDelete);
|
||||||
|
client.on('channelUpdate', e.Event.channelUpdate);
|
||||||
|
client.on('guildBanAdd', e.Event.guildBanAdd);
|
||||||
|
client.on('guildBanRemove', e.Event.guildBanRemove);
|
||||||
|
client.on('guildCreate', e.Event.guildCreate);
|
||||||
|
client.on('guildMemberAdd', e.Event.guildMemberAdd);
|
||||||
|
client.on('guildMemberRemove', e.Event.guildMemberRemove);
|
||||||
|
client.on('guildMemberUpdate', e.Event.guildMemberUpdate);
|
||||||
|
client.on('message', e.Event.message);
|
||||||
|
client.on('messageDelete', e.Event.messageDelete);
|
||||||
|
client.on('messageUpdate', e.Event.messageUpdate);
|
||||||
|
client.on('ready', e.Event.ready);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import { Command, ICommandContext } from "vylbot-core";
|
import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
import PublicEmbed from "../helpers/PublicEmbed";
|
import PublicEmbed from "../helpers/embeds/PublicEmbed";
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
|
||||||
export default class About extends Command {
|
export default class About extends Command {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -10,7 +11,6 @@ export default class About extends Command {
|
||||||
public override execute(context: ICommandContext) {
|
public override execute(context: ICommandContext) {
|
||||||
const embed = new PublicEmbed(context, "About", "")
|
const embed = new PublicEmbed(context, "About", "")
|
||||||
.addField("Version", process.env.BOT_VER)
|
.addField("Version", process.env.BOT_VER)
|
||||||
.addField("VylBot Core", process.env.CORE_VER)
|
|
||||||
.addField("Author", process.env.BOT_AUTHOR)
|
.addField("Author", process.env.BOT_AUTHOR)
|
||||||
.addField("Date", process.env.BOT_DATE);
|
.addField("Date", process.env.BOT_DATE);
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import { Command, ICommandContext } from "vylbot-core";
|
import ErrorEmbed from "../helpers/embeds/ErrorEmbed";
|
||||||
import ErrorEmbed from "../helpers/ErrorEmbed";
|
|
||||||
import ErrorMessages from "../constants/ErrorMessages";
|
import ErrorMessages from "../constants/ErrorMessages";
|
||||||
import LogEmbed from "../helpers/LogEmbed";
|
import LogEmbed from "../helpers/embeds/LogEmbed";
|
||||||
import PublicEmbed from "../helpers/PublicEmbed";
|
import PublicEmbed from "../helpers/embeds/PublicEmbed";
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
|
|
||||||
export default class Bane extends Command {
|
export default class Ban extends Command {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { Command, ICommandContext } from "vylbot-core";
|
import ErrorEmbed from "../helpers/embeds/ErrorEmbed";
|
||||||
import ErrorEmbed from "../helpers/ErrorEmbed";
|
|
||||||
import { TextChannel } from "discord.js";
|
import { TextChannel } from "discord.js";
|
||||||
import PublicEmbed from "../helpers/PublicEmbed";
|
import PublicEmbed from "../helpers/embeds/PublicEmbed";
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
|
|
||||||
export default class Clear extends Command {
|
export default class Clear extends Command {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Command, ICommandContext } from "vylbot-core";
|
import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
import ErrorEmbed from "../helpers/ErrorEmbed";
|
import ErrorEmbed from "../helpers/embeds/ErrorEmbed";
|
||||||
import PublicEmbed from "../helpers/PublicEmbed";
|
import PublicEmbed from "../helpers/embeds/PublicEmbed";
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
|
||||||
export default class Evaluate extends Command {
|
export default class Evaluate extends Command {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { existsSync, readdirSync } from "fs";
|
import { existsSync, readdirSync } from "fs";
|
||||||
import { Command, ICommandContext } from "vylbot-core";
|
import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
import ErrorEmbed from "../helpers/ErrorEmbed";
|
import ErrorEmbed from "../helpers/embeds/ErrorEmbed";
|
||||||
import PublicEmbed from "../helpers/PublicEmbed";
|
import PublicEmbed from "../helpers/embeds/PublicEmbed";
|
||||||
import StringTools from "../helpers/StringTools";
|
import StringTools from "../helpers/StringTools";
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
|
||||||
interface ICommandData {
|
interface ICommandData {
|
||||||
Exists: boolean;
|
Exists: boolean;
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { Command, ICommandContext } from "vylbot-core";
|
|
||||||
import ErrorMessages from "../constants/ErrorMessages";
|
import ErrorMessages from "../constants/ErrorMessages";
|
||||||
import ErrorEmbed from "../helpers/ErrorEmbed";
|
import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
import LogEmbed from "../helpers/LogEmbed";
|
import ErrorEmbed from "../helpers/embeds/ErrorEmbed";
|
||||||
import PublicEmbed from "../helpers/PublicEmbed";
|
import LogEmbed from "../helpers/embeds/LogEmbed";
|
||||||
|
import PublicEmbed from "../helpers/embeds/PublicEmbed";
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
|
||||||
export default class Kick extends Command {
|
export default class Kick extends Command {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { Command, ICommandContext } from "vylbot-core";
|
|
||||||
import ErrorMessages from "../constants/ErrorMessages";
|
import ErrorMessages from "../constants/ErrorMessages";
|
||||||
import ErrorEmbed from "../helpers/ErrorEmbed";
|
import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
import LogEmbed from "../helpers/LogEmbed";
|
import ErrorEmbed from "../helpers/embeds/ErrorEmbed";
|
||||||
import PublicEmbed from "../helpers/PublicEmbed";
|
import LogEmbed from "../helpers/embeds/LogEmbed";
|
||||||
|
import PublicEmbed from "../helpers/embeds/PublicEmbed";
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
|
||||||
export default class Mute extends Command {
|
export default class Mute extends Command {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Command, ICommandContext } from "vylbot-core";
|
import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
import ErrorEmbed from "../helpers/ErrorEmbed";
|
import ErrorEmbed from "../helpers/embeds/ErrorEmbed";
|
||||||
import PublicEmbed from "../helpers/PublicEmbed";
|
import PublicEmbed from "../helpers/embeds/PublicEmbed";
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
|
||||||
export default class Poll extends Command {
|
export default class Poll extends Command {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { Command, ICommandContext } from "vylbot-core";
|
import ErrorEmbed from "../helpers/embeds/ErrorEmbed";
|
||||||
import ErrorEmbed from "../helpers/ErrorEmbed";
|
import PublicEmbed from "../helpers/embeds/PublicEmbed";
|
||||||
import PublicEmbed from "../helpers/PublicEmbed";
|
|
||||||
import { Role as DiscordRole } from "discord.js";
|
import { Role as DiscordRole } from "discord.js";
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
|
|
||||||
export default class Role extends Command {
|
export default class Role extends Command {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { existsSync, readFileSync } from "fs";
|
import { existsSync, readFileSync } from "fs";
|
||||||
import { Command, ICommandContext } from "vylbot-core";
|
import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
import ErrorEmbed from "../helpers/ErrorEmbed";
|
import ErrorEmbed from "../helpers/embeds/ErrorEmbed";
|
||||||
import PublicEmbed from "../helpers/PublicEmbed";
|
import PublicEmbed from "../helpers/embeds/PublicEmbed";
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
|
||||||
interface IRules {
|
interface IRules {
|
||||||
title?: string;
|
title?: string;
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { Command, ICommandContext } from "vylbot-core";
|
|
||||||
import ErrorMessages from "../constants/ErrorMessages";
|
import ErrorMessages from "../constants/ErrorMessages";
|
||||||
import ErrorEmbed from "../helpers/ErrorEmbed";
|
import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
import LogEmbed from "../helpers/LogEmbed";
|
import ErrorEmbed from "../helpers/embeds/ErrorEmbed";
|
||||||
import PublicEmbed from "../helpers/PublicEmbed";
|
import LogEmbed from "../helpers/embeds/LogEmbed";
|
||||||
|
import PublicEmbed from "../helpers/embeds/PublicEmbed";
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
|
||||||
export default class Unmute extends Command {
|
export default class Unmute extends Command {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { Command, ICommandContext } from "vylbot-core";
|
import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
import ErrorEmbed from "../helpers/ErrorEmbed";
|
import ErrorEmbed from "../helpers/embeds/ErrorEmbed";
|
||||||
import LogEmbed from "../helpers/LogEmbed";
|
import LogEmbed from "../helpers/embeds/LogEmbed";
|
||||||
import PublicEmbed from "../helpers/PublicEmbed";
|
import PublicEmbed from "../helpers/embeds/PublicEmbed";
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
|
||||||
export default class Warn extends Command {
|
export default class Warn extends Command {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
4
src/contracts/IBaseResponse.ts
Normal file
4
src/contracts/IBaseResponse.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export interface IBaseResponse {
|
||||||
|
valid: boolean;
|
||||||
|
message?: string;
|
||||||
|
}
|
7
src/contracts/ICommandContext.ts
Normal file
7
src/contracts/ICommandContext.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { Message } from "discord.js";
|
||||||
|
|
||||||
|
export interface ICommandContext {
|
||||||
|
name: string;
|
||||||
|
args: string[];
|
||||||
|
message: Message;
|
||||||
|
}
|
6
src/contracts/ICommandItem.ts
Normal file
6
src/contracts/ICommandItem.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
|
||||||
|
export default interface ICommandItem {
|
||||||
|
Name: string,
|
||||||
|
Command: Command,
|
||||||
|
}
|
6
src/contracts/IEventItem.ts
Normal file
6
src/contracts/IEventItem.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
import { Event } from "../type/event";
|
||||||
|
|
||||||
|
export default interface IEventItem {
|
||||||
|
Event: Event,
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { Event } from "vylbot-core";
|
import { Event } from "../type/event";
|
||||||
import { GuildMember } from "discord.js";
|
import { GuildMember } from "discord.js";
|
||||||
import EventEmbed from "../helpers/EventEmbed";
|
import EventEmbed from "../helpers/embeds/EventEmbed";
|
||||||
import GuildMemberUpdate from "./MemberEvents/GuildMemberUpdate";
|
import GuildMemberUpdate from "./MemberEvents/GuildMemberUpdate";
|
||||||
|
|
||||||
export default class MemberEvents extends Event {
|
export default class MemberEvents extends Event {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { GuildMember } from "discord.js";
|
import { GuildMember } from "discord.js";
|
||||||
import EventEmbed from "../../helpers/EventEmbed";
|
import EventEmbed from "../../helpers/embeds/EventEmbed";
|
||||||
|
|
||||||
export default class GuildMemberUpdate {
|
export default class GuildMemberUpdate {
|
||||||
private _oldMember: GuildMember;
|
private _oldMember: GuildMember;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Event } from "vylbot-core";
|
import { Event } from "../type/event";
|
||||||
import { Message } from "discord.js";
|
import { Message } from "discord.js";
|
||||||
import EventEmbed from "../helpers/EventEmbed";
|
import EventEmbed from "../helpers/embeds/EventEmbed";
|
||||||
|
|
||||||
export default class MessageEvents extends Event {
|
export default class MessageEvents extends Event {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { MessageEmbed } from "discord.js";
|
import { MessageEmbed } from "discord.js";
|
||||||
import { ICommandContext } from "vylbot-core";
|
import { ICommandContext } from "../../contracts/ICommandContext";
|
||||||
|
|
||||||
export default class ErrorEmbed extends MessageEmbed {
|
export default class ErrorEmbed extends MessageEmbed {
|
||||||
private _context: ICommandContext;
|
private _context: ICommandContext;
|
|
@ -1,6 +1,4 @@
|
||||||
import { MessageEmbed, TextChannel, User, Guild } from "discord.js";
|
import { MessageEmbed, TextChannel, User, Guild } from "discord.js";
|
||||||
import ErrorMessages from "../constants/ErrorMessages";
|
|
||||||
import ErrorEmbed from "./ErrorEmbed";
|
|
||||||
|
|
||||||
export default class EventEmbed extends MessageEmbed {
|
export default class EventEmbed extends MessageEmbed {
|
||||||
private _guild: Guild;
|
private _guild: Guild;
|
|
@ -1,6 +1,6 @@
|
||||||
import { MessageEmbed, TextChannel, User } from "discord.js";
|
import { MessageEmbed, TextChannel, User } from "discord.js";
|
||||||
import { ICommandContext } from "vylbot-core";
|
import ErrorMessages from "../../constants/ErrorMessages";
|
||||||
import ErrorMessages from "../constants/ErrorMessages";
|
import { ICommandContext } from "../../contracts/ICommandContext";
|
||||||
import ErrorEmbed from "./ErrorEmbed";
|
import ErrorEmbed from "./ErrorEmbed";
|
||||||
|
|
||||||
export default class LogEmbed extends MessageEmbed {
|
export default class LogEmbed extends MessageEmbed {
|
|
@ -1,5 +1,5 @@
|
||||||
import { MessageEmbed } from "discord.js";
|
import { MessageEmbed } from "discord.js";
|
||||||
import { ICommandContext } from "vylbot-core";
|
import { ICommandContext } from "../../contracts/ICommandContext";
|
||||||
|
|
||||||
export default class PublicEmbed extends MessageEmbed {
|
export default class PublicEmbed extends MessageEmbed {
|
||||||
private _context: ICommandContext;
|
private _context: ICommandContext;
|
15
src/type/command.ts
Normal file
15
src/type/command.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
|
|
||||||
|
export class Command {
|
||||||
|
public _roles: string[];
|
||||||
|
|
||||||
|
public _category?: string;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._roles = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public execute(context: ICommandContext) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
55
src/type/event.ts
Normal file
55
src/type/event.ts
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
import { Channel, Guild, User, GuildMember, Message, PartialDMChannel, PartialGuildMember, PartialMessage } from "discord.js";
|
||||||
|
|
||||||
|
export class Event {
|
||||||
|
public channelCreate(channel: Channel) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public channelDelete(channel: Channel | PartialDMChannel) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public channelUpdate(oldChannel: Channel, newChannel: Channel) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public guildBanAdd(guild: Guild, user: User) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public guildBanRemove(guild: Guild, user: User) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public guildCreate(guild: Guild) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public guildMemberAdd(member: GuildMember) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public guildMemberRemove(member: GuildMember | PartialGuildMember) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public guildMemberUpdate(oldMember: GuildMember | PartialGuildMember, newMember: GuildMember) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public message(message: Message) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public messageDelete(message: Message | PartialMessage) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public messageUpdate(oldMessage: Message | PartialMessage, newMessage: Message | PartialMessage) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ready() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import { CoreClient } from "vylbot-core";
|
import { CoreClient } from "./client/client";
|
||||||
import * as dotenv from "dotenv";
|
import * as dotenv from "dotenv";
|
||||||
|
import Register from "./Register";
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
|
@ -22,4 +23,8 @@ requiredConfigs.forEach(config => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const client = new CoreClient();
|
const client = new CoreClient();
|
||||||
|
|
||||||
|
Register.RegisterCommands(client);
|
||||||
|
Register.RegisterEvents(client);
|
||||||
|
|
||||||
client.start();
|
client.start();
|
7
tests/__mocks/commands/noCategory.ts
Normal file
7
tests/__mocks/commands/noCategory.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { Command } from "../../../src/type/command";
|
||||||
|
|
||||||
|
export default class noCategory extends Command {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
8
tests/__mocks/commands/normal.ts
Normal file
8
tests/__mocks/commands/normal.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { Command } from "../../../src/type/command";
|
||||||
|
|
||||||
|
export default class normal extends Command {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._category = "General";
|
||||||
|
}
|
||||||
|
}
|
8
tests/__mocks/commands/roles.ts
Normal file
8
tests/__mocks/commands/roles.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { Command } from "../../../src/type/command";
|
||||||
|
|
||||||
|
export default class roles extends Command {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._roles = [ "Moderator" ];
|
||||||
|
}
|
||||||
|
}
|
5
tests/__mocks/events/normal.ts
Normal file
5
tests/__mocks/events/normal.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { Event } from "../../../src/type/event";
|
||||||
|
|
||||||
|
export class normal extends Event {
|
||||||
|
public override channelCreate() {}
|
||||||
|
}
|
139
tests/client/client.test.ts
Normal file
139
tests/client/client.test.ts
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
import { CoreClient } from "../../src/client/client";
|
||||||
|
|
||||||
|
import { Client } from "discord.js";
|
||||||
|
import * as dotenv from "dotenv";
|
||||||
|
import { Events } from "../../src/client/events";
|
||||||
|
import { Util } from "../../src/client/util";
|
||||||
|
|
||||||
|
jest.mock("discord.js");
|
||||||
|
jest.mock("dotenv");
|
||||||
|
jest.mock("../../src/client/events");
|
||||||
|
jest.mock("../../src/client/util");
|
||||||
|
|
||||||
|
describe('Constructor', () => {
|
||||||
|
test('Constructor_ExpectSuccessfulInitialisation', () => {
|
||||||
|
const coreClient = new CoreClient();
|
||||||
|
|
||||||
|
expect(coreClient).toBeInstanceOf(Client);
|
||||||
|
expect(dotenv.config).toBeCalledTimes(1);
|
||||||
|
expect(Events).toBeCalledTimes(1);
|
||||||
|
expect(Util).toBeCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Start', () => {
|
||||||
|
test('Given Env Is Valid, Expect Successful Start', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
const coreClient = new CoreClient();
|
||||||
|
|
||||||
|
expect(() => coreClient.start()).not.toThrow();
|
||||||
|
expect(coreClient.on).toBeCalledWith("message", expect.any(Function));
|
||||||
|
expect(coreClient.on).toBeCalledWith("ready", expect.any(Function));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given BOT_TOKEN Is Null, Expect Failure', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
const coreClient = new CoreClient();
|
||||||
|
|
||||||
|
expect(() => coreClient.start()).toThrow("BOT_TOKEN is not defined in .env");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given BOT_TOKEN Is Empty, Expect Failure', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: '',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
const coreClient = new CoreClient();
|
||||||
|
|
||||||
|
expect(() => coreClient.start()).toThrow("BOT_TOKEN is not defined in .env");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given BOT_PREFIX Is Null, Expect Failure', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
const coreClient = new CoreClient();
|
||||||
|
|
||||||
|
expect(() => coreClient.start()).toThrow("BOT_PREFIX is not defined in .env");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given BOT_PREFIX Is Empty, Expect Failure', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
const coreClient = new CoreClient();
|
||||||
|
|
||||||
|
expect(() => coreClient.start()).toThrow("BOT_PREFIX is not defined in .env");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given FOLDERS_COMMANDS Is Null, Expect Failure', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
const coreClient = new CoreClient();
|
||||||
|
|
||||||
|
expect(() => coreClient.start()).toThrow("FOLDERS_COMMANDS is not defined in .env");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given FOLDERS_COMMANDS Is Empty, Expect Failure', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: '',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
const coreClient = new CoreClient();
|
||||||
|
|
||||||
|
expect(() => coreClient.start()).toThrow("FOLDERS_COMMANDS is not defined in .env");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given FOLDERS_EVENTS Is Null, Expect Failure', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
}
|
||||||
|
|
||||||
|
const coreClient = new CoreClient();
|
||||||
|
|
||||||
|
expect(() => coreClient.start()).toThrow("FOLDERS_EVENTS is not defined in .env");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given FOLDERS_EVENTS Is Empty, Expect Failure', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: '',
|
||||||
|
}
|
||||||
|
|
||||||
|
const coreClient = new CoreClient();
|
||||||
|
|
||||||
|
expect(() => coreClient.start()).toThrow("FOLDERS_EVENTS is not defined in .env");
|
||||||
|
});
|
||||||
|
});
|
185
tests/client/events.test.ts
Normal file
185
tests/client/events.test.ts
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
import { Events } from "../../src/client/events";
|
||||||
|
|
||||||
|
import { Message, Client, TextChannel, Guild, SnowflakeUtil, DMChannel } from "discord.js";
|
||||||
|
import { Util } from "../../src/client/util";
|
||||||
|
|
||||||
|
jest.mock("../../src/client/util");
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Util.prototype.loadCommand = jest.fn();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('OnMessage', () => {
|
||||||
|
test('Given Message Is Valid Expect Message Sent', async () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
};
|
||||||
|
|
||||||
|
Util.prototype.loadCommand = jest.fn().mockReturnValue({ valid: true });
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
guild: {},
|
||||||
|
author: {
|
||||||
|
bot: false,
|
||||||
|
},
|
||||||
|
content: "!test first",
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const events = new Events();
|
||||||
|
|
||||||
|
const result = await events.onMessage(message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeTruthy();
|
||||||
|
|
||||||
|
expect(result.context?.prefix).toBe('!');
|
||||||
|
expect(result.context?.name).toBe('test');
|
||||||
|
expect(result.context?.args.length).toBe(1);
|
||||||
|
expect(result.context?.args[0]).toBe('first');
|
||||||
|
expect(result.context?.message).toBe(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given Guild Is Null, Expect Failed Result', async () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
Util.prototype.loadCommand = jest.fn().mockReturnValue({ valid: true });
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
guild: null,
|
||||||
|
author: {
|
||||||
|
bot: false,
|
||||||
|
},
|
||||||
|
content: "!test first",
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const events = new Events();
|
||||||
|
|
||||||
|
const result = await events.onMessage(message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeFalsy();
|
||||||
|
expect(result.message).toBe("Message was not sent in a guild, ignoring.");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given Author Is A Bot, Expect Failed Result', async () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
Util.prototype.loadCommand = jest.fn().mockReturnValue({ valid: true });
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
guild: {},
|
||||||
|
author: {
|
||||||
|
bot: true,
|
||||||
|
},
|
||||||
|
content: "!test first",
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const events = new Events();
|
||||||
|
|
||||||
|
const result = await events.onMessage(message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeFalsy();
|
||||||
|
expect(result.message).toBe("Message was sent by a bot, ignoring.");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given Message Content Was Not A Command, Expect Failed Result', async () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
Util.prototype.loadCommand = jest.fn().mockReturnValue({ valid: true });
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
guild: {},
|
||||||
|
author: {
|
||||||
|
bot: false,
|
||||||
|
},
|
||||||
|
content: "This is a standard message",
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const events = new Events();
|
||||||
|
|
||||||
|
const result = await events.onMessage(message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeFalsy();
|
||||||
|
expect(result.message).toBe("Message was not a command, ignoring.");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given Message Had No Command Name, Expect Failed Result', async () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
Util.prototype.loadCommand = jest.fn().mockReturnValue({ valid: true });
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
guild: {},
|
||||||
|
author: {
|
||||||
|
bot: false,
|
||||||
|
},
|
||||||
|
content: "!",
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const events = new Events();
|
||||||
|
|
||||||
|
const result = await events.onMessage(message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeFalsy();
|
||||||
|
expect(result.message).toBe("Command name was not found");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given Command Failed To Execute, Expect Failed Result', async () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
Util.prototype.loadCommand = jest.fn().mockReturnValue({ valid: false, message: "Command failed" });
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
guild: {},
|
||||||
|
author: {
|
||||||
|
bot: false,
|
||||||
|
},
|
||||||
|
content: "!test first",
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const events = new Events();
|
||||||
|
|
||||||
|
const result = await events.onMessage(message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeFalsy();
|
||||||
|
expect(result.message).toBe("Command failed");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('OnReady', () => {
|
||||||
|
test('Expect Console Log', () => {
|
||||||
|
console.log = jest.fn();
|
||||||
|
|
||||||
|
const events = new Events();
|
||||||
|
|
||||||
|
events.onReady();
|
||||||
|
|
||||||
|
expect(console.log).toBeCalledWith("Ready");
|
||||||
|
});
|
||||||
|
});
|
421
tests/client/util.test.ts
Normal file
421
tests/client/util.test.ts
Normal file
|
@ -0,0 +1,421 @@
|
||||||
|
import { Util } from "../../src/client/util";
|
||||||
|
|
||||||
|
import { Client, Guild, Message, Role, SnowflakeUtil, TextChannel, User } from "discord.js";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
|
jest.mock("fs");
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fs.existsSync = jest.fn();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('LoadCommand', () => {
|
||||||
|
test('Given Successful Exection, Expect Successful Result', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
process.cwd = jest.fn().mockReturnValue("../../tests/__mocks");
|
||||||
|
fs.existsSync = jest.fn().mockReturnValue(true);
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
member: {
|
||||||
|
roles: {
|
||||||
|
cache: {
|
||||||
|
find: jest.fn().mockReturnValue(true),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const util = new Util();
|
||||||
|
|
||||||
|
const result = util.loadCommand("normal", [ "first" ], message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given Member Is Null, Expect Failed Result', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
process.cwd = jest.fn().mockReturnValue("../../tests/__mocks");
|
||||||
|
fs.existsSync = jest.fn().mockReturnValue(true);
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
member: null
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const util = new Util();
|
||||||
|
|
||||||
|
const result = util.loadCommand("normal", [ "first" ], message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeFalsy();
|
||||||
|
expect(result.message).toBe("Member is not part of message");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given Folder Does Not Exist, Expect Failed Result', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
process.cwd = jest.fn().mockReturnValue("../../tests/__mocks");
|
||||||
|
fs.existsSync = jest.fn().mockReturnValue(false);
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
member: {
|
||||||
|
roles: {
|
||||||
|
cache: {
|
||||||
|
find: jest.fn().mockReturnValue(true),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const util = new Util();
|
||||||
|
|
||||||
|
const result = util.loadCommand("normal", [ "first" ], message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeFalsy();
|
||||||
|
expect(result.message).toBe("Command folder does not exist");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given File Does Not Exist, Expect Failed Result', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
process.cwd = jest.fn().mockReturnValue("../../tests/__mocks");
|
||||||
|
fs.existsSync = jest.fn().mockReturnValueOnce(true)
|
||||||
|
.mockReturnValue(false);
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
member: {
|
||||||
|
roles: {
|
||||||
|
cache: {
|
||||||
|
find: jest.fn().mockReturnValue(true),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const util = new Util();
|
||||||
|
|
||||||
|
const result = util.loadCommand("normal", [ "first" ], message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeFalsy();
|
||||||
|
expect(result.message).toBe("File does not exist");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given User Does Have Role, Expect Successful Result', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
process.cwd = jest.fn().mockReturnValue("../../tests/__mocks");
|
||||||
|
fs.existsSync = jest.fn().mockReturnValue(true);
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
member: {
|
||||||
|
roles: {
|
||||||
|
cache: {
|
||||||
|
find: jest.fn().mockReturnValue(true),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const util = new Util();
|
||||||
|
|
||||||
|
const result = util.loadCommand("roles", [ "first" ], message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given User Does Not Have Role, Expect Failed Result', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
process.cwd = jest.fn().mockReturnValue("../../tests/__mocks");
|
||||||
|
fs.existsSync = jest.fn().mockReturnValue(true);
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
member: {
|
||||||
|
roles: {
|
||||||
|
cache: {
|
||||||
|
find: jest.fn().mockReturnValue(false),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const util = new Util();
|
||||||
|
|
||||||
|
const result = util.loadCommand("roles", [ "first" ], message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeFalsy();
|
||||||
|
expect(result.message).toBe("You require the `Moderator` role to run this command");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given Command Category Is Null, Expect Successful Result', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
process.cwd = jest.fn().mockReturnValue("../../tests/__mocks");
|
||||||
|
fs.existsSync = jest.fn().mockReturnValue(true);
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
member: {
|
||||||
|
roles: {
|
||||||
|
cache: {
|
||||||
|
find: jest.fn().mockReturnValue(true),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const util = new Util();
|
||||||
|
|
||||||
|
const result = util.loadCommand("noCategory", [ "first" ], message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given command is set to disabled, Expect command to not fire', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
COMMANDS_DISABLED: 'normal',
|
||||||
|
COMMANDS_DISABLED_MESSAGE: 'disabled',
|
||||||
|
}
|
||||||
|
|
||||||
|
process.cwd = jest.fn().mockReturnValue("../../tests/__mocks");
|
||||||
|
fs.existsSync = jest.fn().mockReturnValue(true);
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
member: {
|
||||||
|
roles: {
|
||||||
|
cache: {
|
||||||
|
find: jest.fn().mockReturnValue(true),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const messageReply = jest.spyOn(message, 'reply');
|
||||||
|
|
||||||
|
const util = new Util();
|
||||||
|
|
||||||
|
const result = util.loadCommand("normal", [ "first" ], message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeFalsy();
|
||||||
|
expect(result.message).toBe("Command is disabled");
|
||||||
|
expect(messageReply).toBeCalledWith("disabled");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given command COMMANDS_DISABLED_MESSAGE is empty, Expect default message sent', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
COMMANDS_DISABLED: 'normal',
|
||||||
|
}
|
||||||
|
|
||||||
|
process.cwd = jest.fn().mockReturnValue("../../tests/__mocks");
|
||||||
|
fs.existsSync = jest.fn().mockReturnValue(true);
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
member: {
|
||||||
|
roles: {
|
||||||
|
cache: {
|
||||||
|
find: jest.fn().mockReturnValue(true),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const messageReply = jest.spyOn(message, 'reply');
|
||||||
|
|
||||||
|
const util = new Util();
|
||||||
|
|
||||||
|
const result = util.loadCommand("normal", [ "first" ], message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeFalsy();
|
||||||
|
expect(result.message).toBe("Command is disabled");
|
||||||
|
expect(messageReply).toBeCalledWith("This command is disabled.");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given a different command is disabled, Expect command to still fire', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
COMMANDS_DISABLED: 'anything',
|
||||||
|
}
|
||||||
|
|
||||||
|
process.cwd = jest.fn().mockReturnValue("../../tests/__mocks");
|
||||||
|
fs.existsSync = jest.fn().mockReturnValue(true);
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
member: {
|
||||||
|
roles: {
|
||||||
|
cache: {
|
||||||
|
find: jest.fn().mockReturnValue(true),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const util = new Util();
|
||||||
|
|
||||||
|
const result = util.loadCommand("normal", [ "first" ], message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given a different command is disabled with this one, Expect command to not fire', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
COMMANDS_DISABLED: 'normal,anything,',
|
||||||
|
}
|
||||||
|
|
||||||
|
process.cwd = jest.fn().mockReturnValue("../../tests/__mocks");
|
||||||
|
fs.existsSync = jest.fn().mockReturnValue(true);
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
member: {
|
||||||
|
roles: {
|
||||||
|
cache: {
|
||||||
|
find: jest.fn().mockReturnValue(true),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
} as unknown as Message;
|
||||||
|
|
||||||
|
const util = new Util();
|
||||||
|
|
||||||
|
const result = util.loadCommand("normal", [ "first" ], message);
|
||||||
|
|
||||||
|
expect(result.valid).toBeFalsy();
|
||||||
|
expect(result.message).toBe("Command is disabled");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('LoadEvents', () => {
|
||||||
|
test('Given Events Are Loaded, Expect Successful Result', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
process.cwd = jest.fn().mockReturnValue("../../tests/__mocks");
|
||||||
|
fs.existsSync = jest.fn().mockReturnValue(true);
|
||||||
|
fs.readdirSync = jest.fn().mockReturnValue(["normal.ts"]);
|
||||||
|
|
||||||
|
const client = {
|
||||||
|
on: jest.fn(),
|
||||||
|
} as unknown as Client;
|
||||||
|
|
||||||
|
const util = new Util();
|
||||||
|
|
||||||
|
const result = util.loadEvents(client);
|
||||||
|
|
||||||
|
const clientOn = jest.spyOn(client, 'on');
|
||||||
|
|
||||||
|
expect(result.valid).toBeTruthy();
|
||||||
|
expect(clientOn).toBeCalledTimes(13);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given No Events Found, Expect Successful Result', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
process.cwd = jest.fn().mockReturnValue("../../tests/__mocks");
|
||||||
|
fs.existsSync = jest.fn().mockReturnValue(true);
|
||||||
|
fs.readdirSync = jest.fn().mockReturnValue(["normal"]);
|
||||||
|
|
||||||
|
const client = {
|
||||||
|
on: jest.fn(),
|
||||||
|
} as unknown as Client;
|
||||||
|
|
||||||
|
const util = new Util();
|
||||||
|
|
||||||
|
const result = util.loadEvents(client);
|
||||||
|
|
||||||
|
const clientOn = jest.spyOn(client, 'on');
|
||||||
|
|
||||||
|
expect(result.valid).toBeTruthy();
|
||||||
|
expect(clientOn).toBeCalledTimes(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Given Event Folder Does Not Exist, Expect Failed Result', () => {
|
||||||
|
process.env = {
|
||||||
|
BOT_TOKEN: 'TOKEN',
|
||||||
|
BOT_PREFIX: '!',
|
||||||
|
FOLDERS_COMMANDS: 'commands',
|
||||||
|
FOLDERS_EVENTS: 'events',
|
||||||
|
}
|
||||||
|
|
||||||
|
process.cwd = jest.fn().mockReturnValue("../../tests/__mocks");
|
||||||
|
fs.existsSync = jest.fn().mockReturnValue(false);
|
||||||
|
fs.readdirSync = jest.fn().mockReturnValue(["normal.ts"]);
|
||||||
|
|
||||||
|
const client = {
|
||||||
|
on: jest.fn(),
|
||||||
|
} as unknown as Client;
|
||||||
|
|
||||||
|
const util = new Util();
|
||||||
|
|
||||||
|
const result = util.loadEvents(client);
|
||||||
|
|
||||||
|
expect(result.valid).toBeFalsy();
|
||||||
|
expect(result.message).toBe("Event folder does not exist");
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue