Compare commits

..

No commits in common. "develop" and "2.0-pre1" have entirely different histories.

13 changed files with 65 additions and 216 deletions

View file

@ -10,7 +10,4 @@ BOT_TOKEN=
BOT_PREFIX=v! BOT_PREFIX=v!
FOLDERS_COMMANDS=commands FOLDERS_COMMANDS=commands
FOLDERS_EVENTS=events FOLDERS_EVENTS=events
COMMANDS_DISABLED=
COMMANDS_DISABLED_MESSAGE=This command is disabled.

3
.gitignore vendored
View file

@ -113,6 +113,3 @@ events/
# Linux Environment Files # Linux Environment Files
*.swp *.swp
# macOS Environment Files
.DS_Store

View file

@ -61,7 +61,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at reported to the community leaders responsible for enforcement at
ethan@vylpes.com. getgravitysoftware@gmail.com.
All complaints will be reviewed and investigated promptly and fairly. All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the All community leaders are obligated to respect the privacy and security of the

View file

@ -12,7 +12,7 @@ This project and everyone participating in it is governed by the VylBot Core Cod
> **Note:** Please don't file an issue to ask a question. You'll get faster results by using the resources below. > **Note:** Please don't file an issue to ask a question. You'll get faster results by using the resources below.
You can ask a question about the project by emailing us at `ethan@vylpes.com`. You can ask a question about the project by emailing us at `getgravitysoftware@gmail.com`.
You can ask a question about the project in the `#development` channel in the [Discord Server](https://discord.gg/UyAhAVp). You can ask a question about the project in the `#development` channel in the [Discord Server](https://discord.gg/UyAhAVp).
@ -32,7 +32,7 @@ There are a few conventions that have developed over time for this project. When
We won't accept pull requests unless these checks pass. If yours fail, simply fix what the bot says until it passes and then get a repo member to review your code. We won't accept pull requests unless these checks pass. If yours fail, simply fix what the bot says until it passes and then get a repo member to review your code.
The rules for the code is based upon [Vylpes' Config Repo](https://github.com/vylpes/Config) The rules for the code is based upon [Gravity Software's Config Repo](https://github.com/GetGravitySoft/Config)
* Variable names should use **Camel Case** * Variable names should use **Camel Case**
* Functions should put **braces on the same line** * Functions should put **braces on the same line**
@ -119,26 +119,26 @@ Enhancement suggestions are tracked as GitHub issues. After you've determined th
Unsure where to begin contributing to VylBot Core? You can start by looking through these `good first` and `help wanted` issues: Unsure where to begin contributing to VylBot Core? You can start by looking through these `good first` and `help wanted` issues:
* [Good first issue](https://github.com/vylpes/vylbot-core/labels/good%20first%20issue) - issues which should only require a few lines of code, and a test or two. * [Good first issue](https://github.com/getgravitysoft/vylbot-core/labels/good%20first%20issue) - issues which should only require a few lines of code, and a test or two.
* [Help wanted](https://github.com/vylpes/vylbot-core/labels/help%20wanted) - issues which should be a bit more involved than `good first` issues. * [Help wanted](https://github.com/getgravitysoft/vylbot-core/labels/help%20wanted) - issues which should be a bit more involved than `good first` issues.
#### Prerequisites #### Prerequisites
In order to download necessary tools, clone the repository, and install dependencies via `yarn` you need network access. In order to download necessary tools, clone the repository, and install dependencies via `npm` you need network access.
You'll need the following tools: You'll need the following tools:
* Git * Git
* NodeJS * NodeJS
Install and build all of the dependencies using `yarn` Install and build all of the dependencies using `npm`
```bash ```bash
cd vylbot-core cd VylBot Core
yarn install npm install
cp .env.template .env cp config.json.template config.json
``` ```
And then use your text editor of choice to fill in the `.env` file. And then use your text editor of choice to fill in the `config.json` file.
#### Build and Run #### Build and Run
@ -147,15 +147,15 @@ If you want to understand how VylBot Core works or want to debug an issue, you'l
First, fork the VylBot Core repository so that you can make a pull request. Then, clone your fork locally: First, fork the VylBot Core repository so that you can make a pull request. Then, clone your fork locally:
```bash ```bash
git clone https://github.com/<your-github-account>/vylbot-core.git git clone https://github.com/<your-github-account>/VylBot Core.git
``` ```
Occasionally, you will want to merge changes in the upstream repository (the official code repo) with your fork. Occasionally, you will want to merge changes in the upstream repository (the official code repo) with your fork.
```bash ```bash
cd vylbot-core cd VylBot Core
git checkout master git checkout master
git pull https://github.com/vylpes/vylbot-core.git master git pull https://github.com/getgravitysoft/VylBot Core.git master
``` ```
Manage any merge conflicts, commit them, and then push them to your fork. Manage any merge conflicts, commit them, and then push them to your fork.
@ -202,18 +202,20 @@ As well as eslint's recommended defaults.
Example Example
```ts ```js
// hello.ts function ban (member) {
import { Command, ICommandContext } from "vylbot-core"; let reason = "Example reason";
export class hello extends Command { let args = [
constructor() { "one",
super(); "two"
} ];
public override execute(context: ICommandContext) { member.ban(reason).then(() => {
context.message.reply("Hello"); // handle then here
} }).catch(err => {
// handle error here
});
} }
``` ```
@ -249,7 +251,7 @@ There are a few conventions that have developed over time for this project. When
We won't accept pull requests unless these checks pass. If yours fail, simply fix what the bot says until it passes and then get a repo member to review your code. We won't accept pull requests unless these checks pass. If yours fail, simply fix what the bot says until it passes and then get a repo member to review your code.
The rules for the code is based upon [Vylpes' Config Repo](https://github.com/vylpes/config) The rules for the code is based upon [Gravity Software's Config Repo](https://github.com/getgravitysoft/config)
* Variable names should use **Camel Case** * Variable names should use **Camel Case**
* Functions should put **braces on the same line** * Functions should put **braces on the same line**

View file

@ -14,17 +14,12 @@ BOT_PREFIX=v!
FOLDERS_COMMANDS=commands FOLDERS_COMMANDS=commands
FOLDERS_EVENTS=events FOLDERS_EVENTS=events
COMMANDS_DISABLED=
COMMANDS_DISABLED_MESSAGE=This command is disabled.
``` ```
* **BOT_TOKEN:** Your bot's token, replace {TOKEN} with your bot token. * **BOT_TOKEN:** Your bot's token, replace {TOKEN} with your bot token
* **BOT_PREFIX:** The command prefix. * **BOT_PREFIX** The command prefix
* **FOLDERS_COMMANDS:** The folder which contains your commands. * **FOLDERS_COMMANDS:** The folder which contains your commands
* **FOLDERS_EVENTS:** The folder which contains your events. * **FOLDERS_EVENTS** The folder which contains your events
* **COMMANDS_DISABLED:** List of command file names that won't run, separated by commas.
* **COMMANDS_DISABLED_MESSAGE:** The message which is replied to the user who tries to run a disabled command.
Make sure that you **DO NOT** put your .env file into VCS! Make sure that you **DO NOT** put your .env file into VCS!
@ -50,7 +45,7 @@ The code below will reply to the user with 'PONG' when they type {PREFIX}ping
import { Command, ICommandContext } from "vylbot-core"; import { Command, ICommandContext } from "vylbot-core";
export default class Ping extends Command { export class Ping extends Command {
constructor() { constructor() {
super(); super();
this._roles = [ "Moderator" ]; this._roles = [ "Moderator" ];

View file

@ -1,17 +1,16 @@
{ {
"name": "vylbot-core", "name": "vylbot-core",
"version": "2.0.1", "version": "1.0.5",
"description": "A discord client based upon discord.js", "description": "A discord client based upon discord.js",
"main": "./src/index", "main": "./src/index",
"scripts": { "scripts": {
"build": "tsc", "build": "tsc",
"test": "jest", "test": "jest --coverage",
"test:coverage": "jest --coverage",
"lint": "eslint ." "lint": "eslint ."
}, },
"author": "Vylpes", "author": "Vylpes",
"license": "MIT", "license": "MIT",
"funding": "https://ko-fi.com/vylpes", "funding": "https://ko-fi.com/gravitysoftware",
"dependencies": { "dependencies": {
"discord.js": "^12.3.1", "discord.js": "^12.3.1",
"dotenv": "^10.0.0" "dotenv": "^10.0.0"

View file

@ -22,24 +22,13 @@ export class Util {
message: "Member is not part of message", 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 folder = process.env.FOLDERS_COMMANDS;
if (existsSync(`${process.cwd()}/${folder}/`)) { if (existsSync(`${process.cwd()}/${folder}/`)) {
if (existsSync(`${process.cwd()}/${folder}/${name}.ts`)) { if (existsSync(`${process.cwd()}/${folder}/${name}.ts`)) {
const commandFile = require(`${process.cwd()}/${folder}/${name}.ts`).default; const commandFile = require(`${process.cwd()}/${folder}/${name}.ts`);
const command = new commandFile() as Command; const command = new commandFile[name]() as Command;
const requiredRoles = command._roles; const requiredRoles = command._roles;
if (!command._category) command._category = "none"; if (!command._category) command._category = "none";

View file

@ -1,7 +1,7 @@
import { Command } from "../../../src/type/command"; import { Command } from "../../../src/type/command";
export default class noCategory extends Command { export class noCategory extends Command {
constructor() { constructor() {
super(); super();
} }
} }

View file

@ -1,8 +1,8 @@
import { Command } from "../../../src/type/command"; import { Command } from "../../../src/type/command";
export default class normal extends Command { export class normal extends Command {
constructor() { constructor() {
super(); super();
this._category = "General"; this._category = "General";
} }
} }

View file

@ -1,8 +1,8 @@
import { Command } from "../../../src/type/command"; import { Command } from "../../../src/type/command";
export default class roles extends Command { export class roles extends Command {
constructor() { constructor() {
super(); super();
this._roles = [ "Moderator" ]; this._roles = [ "Moderator" ];
} }
} }

View file

@ -10,7 +10,7 @@ beforeEach(() => {
}); });
describe('OnMessage', () => { describe('OnMessage', () => {
test('Given Message Is Valid Expect Message Sent', async () => { test('Given Message Is Valid Expect Message Sent', () => {
process.env = { process.env = {
BOT_TOKEN: 'TOKEN', BOT_TOKEN: 'TOKEN',
BOT_PREFIX: '!', BOT_PREFIX: '!',
@ -30,7 +30,7 @@ describe('OnMessage', () => {
const events = new Events(); const events = new Events();
const result = await events.onMessage(message); const result = events.onMessage(message);
expect(result.valid).toBeTruthy(); expect(result.valid).toBeTruthy();
@ -41,7 +41,7 @@ describe('OnMessage', () => {
expect(result.context?.message).toBe(message); expect(result.context?.message).toBe(message);
}); });
test('Given Guild Is Null, Expect Failed Result', async () => { test('Given Guild Is Null, Expect Failed Result', () => {
process.env = { process.env = {
BOT_TOKEN: 'TOKEN', BOT_TOKEN: 'TOKEN',
BOT_PREFIX: '!', BOT_PREFIX: '!',
@ -61,13 +61,13 @@ describe('OnMessage', () => {
const events = new Events(); const events = new Events();
const result = await events.onMessage(message); const result = events.onMessage(message);
expect(result.valid).toBeFalsy(); expect(result.valid).toBeFalsy();
expect(result.message).toBe("Message was not sent in a guild, ignoring."); expect(result.message).toBe("Message was not sent in a guild, ignoring.");
}); });
test('Given Author Is A Bot, Expect Failed Result', async () => { test('Given Author Is A Bot, Expect Failed Result', () => {
process.env = { process.env = {
BOT_TOKEN: 'TOKEN', BOT_TOKEN: 'TOKEN',
BOT_PREFIX: '!', BOT_PREFIX: '!',
@ -87,13 +87,13 @@ describe('OnMessage', () => {
const events = new Events(); const events = new Events();
const result = await events.onMessage(message); const result = events.onMessage(message);
expect(result.valid).toBeFalsy(); expect(result.valid).toBeFalsy();
expect(result.message).toBe("Message was sent by a bot, ignoring."); expect(result.message).toBe("Message was sent by a bot, ignoring.");
}); });
test('Given Message Content Was Not A Command, Expect Failed Result', async () => { test('Given Message Content Was Not A Command, Expect Failed Result', () => {
process.env = { process.env = {
BOT_TOKEN: 'TOKEN', BOT_TOKEN: 'TOKEN',
BOT_PREFIX: '!', BOT_PREFIX: '!',
@ -113,13 +113,13 @@ describe('OnMessage', () => {
const events = new Events(); const events = new Events();
const result = await events.onMessage(message); const result = events.onMessage(message);
expect(result.valid).toBeFalsy(); expect(result.valid).toBeFalsy();
expect(result.message).toBe("Message was not a command, ignoring."); expect(result.message).toBe("Message was not a command, ignoring.");
}); });
test('Given Message Had No Command Name, Expect Failed Result', async () => { test('Given Message Had No Command Name, Expect Failed Result', () => {
process.env = { process.env = {
BOT_TOKEN: 'TOKEN', BOT_TOKEN: 'TOKEN',
BOT_PREFIX: '!', BOT_PREFIX: '!',
@ -139,13 +139,13 @@ describe('OnMessage', () => {
const events = new Events(); const events = new Events();
const result = await events.onMessage(message); const result = events.onMessage(message);
expect(result.valid).toBeFalsy(); expect(result.valid).toBeFalsy();
expect(result.message).toBe("Command name was not found"); expect(result.message).toBe("Command name was not found");
}); });
test('Given Command Failed To Execute, Expect Failed Result', async () => { test('Given Command Failed To Execute, Expect Failed Result', () => {
process.env = { process.env = {
BOT_TOKEN: 'TOKEN', BOT_TOKEN: 'TOKEN',
BOT_PREFIX: '!', BOT_PREFIX: '!',
@ -165,7 +165,7 @@ describe('OnMessage', () => {
const events = new Events(); const events = new Events();
const result = await events.onMessage(message); const result = events.onMessage(message);
expect(result.valid).toBeFalsy(); expect(result.valid).toBeFalsy();
expect(result.message).toBe("Command failed"); expect(result.message).toBe("Command failed");
@ -182,4 +182,4 @@ describe('OnReady', () => {
expect(console.log).toBeCalledWith("Ready"); expect(console.log).toBeCalledWith("Ready");
}); });
}); });

View file

@ -210,136 +210,6 @@ describe('LoadCommand', () => {
expect(result.valid).toBeTruthy(); 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', () => { describe('LoadEvents', () => {
@ -418,4 +288,4 @@ describe('LoadEvents', () => {
expect(result.valid).toBeFalsy(); expect(result.valid).toBeFalsy();
expect(result.message).toBe("Event folder does not exist"); expect(result.message).toBe("Event folder does not exist");
}); });
}); });

View file

@ -848,9 +848,9 @@ ansi-escapes@^4.2.1:
type-fest "^0.21.3" type-fest "^0.21.3"
ansi-regex@^5.0.0: ansi-regex@^5.0.0:
version "5.0.1" version "5.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
ansi-styles@^3.2.1: ansi-styles@^3.2.1:
version "3.2.1" version "3.2.1"
@ -2984,9 +2984,9 @@ throat@^6.0.1:
integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==
tmpl@1.0.x: tmpl@1.0.x:
version "1.0.5" version "1.0.4"
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
to-fast-properties@^2.0.0: to-fast-properties@^2.0.0:
version "2.0.0" version "2.0.0"