mirror of
https://github.com/chenasraf/venom.git
synced 2026-05-18 01:29:07 +00:00
* feat: improved command handler
This commit is contained in:
24
README.md
24
README.md
@@ -1,3 +1,23 @@
|
||||
# Team Codemonkey Discord Bot
|
||||
# Venom Discord Bot
|
||||
|
||||
This is the Discord bot for Team Codemonkey
|
||||
This is the Discord bot for Creation Asylum.
|
||||
|
||||
## Development
|
||||
|
||||
- Requires [NodeJS](https://nodejs.org/), recommend at least the latest LTS version.
|
||||
- Run `yarn` or `npm install` to install dependencies
|
||||
|
||||
### Environment Variables
|
||||
|
||||
At a minimum you need to provide the Discord bots Token, which can be found on the Bot tab of a Discord application. See table below for possible values.
|
||||
|
||||
| key | description | example |
|
||||
|-------------------|-------------|---------|
|
||||
| BOT_TRIGGER | Prefix of message to let bot know you are speaking to it
|
||||
| DISCORD_BOT_TOKEN | Discord bots Token
|
||||
| ENVIRONMENT | What environment the bot is running in | `production`, `development` or `test` |
|
||||
| LOG_LEVEL | What level of logs should be displayed in console | `error`, `warn`, `info`, `verbose`, `debug` or `silly` |
|
||||
|
||||
### Bot commands
|
||||
|
||||
To add a command you create a Typescript file in `src/bot/commands/[filename].ts` and ensure it implements the \src/bot/commands/ICommand.ts` interface. You can see the other files in this directory for implementation examples. Also ensure you export this file in `src/bot/commands/index.ts`.
|
||||
|
||||
10
package.json
10
package.json
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "teamcodemonkey-bot",
|
||||
"name": "venom",
|
||||
"version": "0.0.1",
|
||||
"description": "A bot for the Team Codemonkey Discord",
|
||||
"description": "A bot for the Creation Asylum Discord",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/jondeaves/tcm-bot",
|
||||
"bugs": "https://github.com/jondeaves/jondeaves/issues",
|
||||
"repository": "https://github.com/jondeaves/venom",
|
||||
"bugs": "https://github.com/jondeaves/venom/issues",
|
||||
"author": "Jon Deaves <hello@jondeaves.me> https://jondeaves.me",
|
||||
"contributors": [
|
||||
"Jon Deaves <hello@jondeaves.me> https://jondeaves.me"
|
||||
@@ -35,4 +35,4 @@
|
||||
"tslint-react": "~5.0.0",
|
||||
"typescript": "~3.9.7"
|
||||
}
|
||||
}
|
||||
}
|
||||
4
src/.env.template
Normal file
4
src/.env.template
Normal file
@@ -0,0 +1,4 @@
|
||||
BOT_TRIGGER=!
|
||||
DISCORD_BOT_TOKEN=[replace with own token]
|
||||
ENVIRONMENT=production
|
||||
LOG_LEVEL=error
|
||||
34
src/app.ts
34
src/app.ts
@@ -1,10 +1,13 @@
|
||||
import { exit } from 'process';
|
||||
import Discord from 'discord.js';
|
||||
|
||||
import container from './inversity.config';
|
||||
|
||||
import ConfigService from './core/services/config.service';
|
||||
import LoggerService from './core/services/logger.service';
|
||||
import { exit } from 'process';
|
||||
|
||||
import ICommand from './bot/commands/ICommand';
|
||||
import rawCommands from './bot/commands';
|
||||
|
||||
export default class App {
|
||||
private _configService: ConfigService = container.resolve<ConfigService>(ConfigService);
|
||||
@@ -14,11 +17,40 @@ export default class App {
|
||||
|
||||
public async init(): Promise<void> {
|
||||
this._discordClient = new Discord.Client();
|
||||
const commandList = new Discord.Collection<string, ICommand>();
|
||||
|
||||
rawCommands.forEach(rawCommand => {
|
||||
commandList.set(rawCommand.name, rawCommand);
|
||||
});
|
||||
|
||||
// Triggers once after connecting to server
|
||||
this._discordClient.once('ready', () => {
|
||||
this._loggerService.log('info', "The Bot is connected to Discord server");
|
||||
});
|
||||
|
||||
// Triggers on every message the bot can see
|
||||
this._discordClient.on('message', async message => {
|
||||
const prefix = this._configService.get('BOT_TRIGGER');
|
||||
|
||||
// If the message either doesn't start with the prefix or was sent by a bot, exit early.
|
||||
if (!message.content.startsWith(prefix) || message.author.bot) return;
|
||||
|
||||
const args = message.content.slice(prefix.length).trim().split(/ +/);
|
||||
const commandName = args.shift().toLowerCase();
|
||||
const command = commandList.get(commandName) || commandList.find(cmd => cmd.aliases && cmd.aliases.includes(commandName));
|
||||
|
||||
if (!command) {
|
||||
return message.reply('Monkey no understand that command yet!');
|
||||
};
|
||||
|
||||
try {
|
||||
await command.execute(message, args, prefix, commandList);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
message.reply('there was an error trying to execute that command!');
|
||||
}
|
||||
});
|
||||
|
||||
this._discordClient.login(this._configService.get('DISCORD_BOT_TOKEN'))
|
||||
.catch((reason) => {
|
||||
this._loggerService.log('error', `Cannot initialise Discord client. Check the token: ${this._configService.get('DISCORD_BOT_TOKEN')}`);
|
||||
|
||||
8
src/bot/commands/ICommand.ts
Normal file
8
src/bot/commands/ICommand.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import Discord, { Collection } from 'discord.js';
|
||||
|
||||
export default interface ICommand {
|
||||
name: string;
|
||||
aliases?: string[];
|
||||
description: string;
|
||||
execute: (message: Discord.Message, args: string[], prefix?: string, commands?: Collection<string, ICommand>) => Promise<void>,
|
||||
}
|
||||
47
src/bot/commands/help.ts
Normal file
47
src/bot/commands/help.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import Discord, { Collection } from 'discord.js';
|
||||
|
||||
import ICommand from './ICommand';
|
||||
|
||||
const command: ICommand = {
|
||||
name: 'help',
|
||||
aliases: ['commands'],
|
||||
description: 'Lists available commands!',
|
||||
async execute(message: Discord.Message, args: string[], prefix: string, commands: Collection<string, ICommand>) {
|
||||
const data = [];
|
||||
|
||||
if (!args.length) {
|
||||
// Get for all commands
|
||||
data.push('Here\'s a list of all my commands:\n');
|
||||
data.push(commands.map(command => command.name).join(', '));
|
||||
data.push(`\nYou can send \`${prefix}help [command name]\` to get info on a specific command!`);
|
||||
} else {
|
||||
// Get description of single command
|
||||
const name = args[0].toLowerCase();
|
||||
const command = commands.get(name) || commands.find(c => c.aliases && c.aliases.includes(name));
|
||||
|
||||
if (!command) {
|
||||
message.reply('that\'s not a valid command!');
|
||||
} else {
|
||||
data.push(`**Name:** ${command.name}`);
|
||||
|
||||
if (command.aliases) data.push(`**Aliases:** ${command.aliases.join(', ')}`);
|
||||
if (command.description) data.push(`**Description:** ${command.description}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
try {
|
||||
await message.author.send(data, { split: true });
|
||||
if (message.channel.type === 'dm')
|
||||
return;
|
||||
message.reply('I\'ve sent you a DM with all my commands!');
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`Could not send help DM to ${message.author.tag}.\n`, error);
|
||||
message.reply('it seems like I can\'t DM you! Do you have DMs disabled?');
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default command;
|
||||
9
src/bot/commands/index.ts
Normal file
9
src/bot/commands/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import help from './help';
|
||||
import ping from './ping';
|
||||
import see from './see';
|
||||
|
||||
export default [
|
||||
help,
|
||||
ping,
|
||||
see
|
||||
]
|
||||
14
src/bot/commands/ping.ts
Normal file
14
src/bot/commands/ping.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import Discord from 'discord.js';
|
||||
|
||||
import ICommand from './ICommand';
|
||||
|
||||
const command: ICommand = {
|
||||
name: 'ping',
|
||||
aliases: ['hello'],
|
||||
description: 'Ping!',
|
||||
async execute(message: Discord.Message, args: string[]) {
|
||||
message.reply('Pong.');
|
||||
},
|
||||
};
|
||||
|
||||
export default command;
|
||||
13
src/bot/commands/see.ts
Normal file
13
src/bot/commands/see.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import Discord from 'discord.js';
|
||||
|
||||
import ICommand from './ICommand';
|
||||
|
||||
const command: ICommand = {
|
||||
name: 'see',
|
||||
description: 'See!',
|
||||
async execute(message: Discord.Message, args: string[]) {
|
||||
message.reply(`Server: ${message.guild.name}\nYour username: ${message.author.username}\nYour ID: ${message.author.id}`);
|
||||
},
|
||||
};
|
||||
|
||||
export default command;
|
||||
@@ -31,6 +31,7 @@ export default class ConfigService {
|
||||
|
||||
private setup(): void {
|
||||
this.config = {
|
||||
BOT_TRIGGER: process.env.BOT_TRIGGER || '!',
|
||||
DISCORD_BOT_TOKEN: process.env.DISCORD_BOT_TOKEN,
|
||||
ENVIRONMENT: (process.env.NODE_ENV as Environment) || 'development',
|
||||
LOG_LEVEL: (process.env.LOG_LEVEL as LogLevel) || 'info',
|
||||
|
||||
@@ -2,6 +2,7 @@ import LogLevel from "./LogLevel";
|
||||
import Environment from "./Environment";
|
||||
|
||||
export default interface Config {
|
||||
BOT_TRIGGER: string;
|
||||
DISCORD_BOT_TOKEN: string;
|
||||
ENVIRONMENT: Environment;
|
||||
LOG_LEVEL: LogLevel;
|
||||
|
||||
Reference in New Issue
Block a user