108 lines
3.4 KiB
TypeScript
108 lines
3.4 KiB
TypeScript
import * as path from 'path';
|
|
import * as fs from 'fs';
|
|
import * as Discord from "discord.js";
|
|
import {Message, Snowflake} from "discord.js";
|
|
import {Command, CommandCollection} from "./Command";
|
|
import {prefix, token, userDict} from "./config.json";
|
|
|
|
export class CustomClient extends Discord.Client {
|
|
commandCollection = new CommandCollection();
|
|
cooldowns : { [name : string] : Discord.Collection<Snowflake, number> } = {};
|
|
prefix = prefix;
|
|
|
|
async importCommand(commandPath : string, message? : Message) : Promise<boolean> {
|
|
try {
|
|
this.commandCollection.add((await import(commandPath)).default);
|
|
}catch(error) {
|
|
const errorMessage = "Error while importing command " + commandPath;
|
|
console.error(errorMessage);
|
|
console.error(error);
|
|
|
|
if (message)
|
|
await message.reply(errorMessage);
|
|
else {
|
|
const user = await this.users.fetch(userDict.misabiko);
|
|
await user.send(errorMessage);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
handleMessage(message : Message) {
|
|
//If message doesn't have prefix or is bot-made, ignore
|
|
if (!message.content.startsWith(prefix) || message.author.bot) return;
|
|
|
|
const args = message.content.slice(prefix.length).split(/ +/);
|
|
const commandName = args.shift().toLowerCase();
|
|
|
|
const command = client.commandCollection.get(commandName);
|
|
if (!command) return;
|
|
|
|
if (command.args && !args.length) {
|
|
let reply = `You didn't provide any arguments, ${message.author}.`;
|
|
|
|
if (command.usage)
|
|
reply += `\nUsage: \`${prefix}${command.name} ${command.usage}\``;
|
|
|
|
return message.channel.send(reply);
|
|
}
|
|
|
|
if (command.guildOnly && message.channel.type !== 'text')
|
|
return message.reply(`You can only call the ${command} commmand on a server.`);
|
|
|
|
if (!command.checkPermission(message.author.id))
|
|
return message.reply(`You don't have the permission for that command, ask <@${userDict.misabiko}> for help.`);
|
|
|
|
if (!this.cooldowns[command.name])
|
|
this.cooldowns[command.name] = new Discord.Collection();
|
|
|
|
const timeLeft = this.getTimeLeft(command, message.author.id);
|
|
if (timeLeft)
|
|
return message.reply(`Please wait ${timeLeft.toFixed(1)} more second(s) before reusing the \`${command.name}\` command.`);
|
|
|
|
try {
|
|
command.execute(message, args, client);
|
|
}catch (error) {
|
|
console.error(error);
|
|
message.reply("There was an error trying to execute the command.");
|
|
}
|
|
}
|
|
|
|
getTimeLeft(command : Command, authorId : string) {
|
|
const now = Date.now();
|
|
const timestamps : Discord.Collection<Snowflake, number> = this.cooldowns[command.name];
|
|
const cooldownAmount = command.cooldown * 1000;
|
|
|
|
if (!timestamps.has(authorId)) {
|
|
timestamps.set(authorId, now);
|
|
setTimeout(() => timestamps.delete(authorId), cooldownAmount);
|
|
}else {
|
|
const expirationTime = timestamps.get(authorId) + cooldownAmount;
|
|
|
|
if (now < expirationTime)
|
|
return (expirationTime - now) / 1000;
|
|
|
|
timestamps.set(authorId, now);
|
|
setTimeout(() => timestamps.delete(authorId), cooldownAmount);
|
|
}
|
|
}
|
|
|
|
getCommand(message : string) {
|
|
return message.substring(this.prefix.length);
|
|
}
|
|
}
|
|
|
|
const client = new CustomClient();
|
|
const commandFiles = fs.readdirSync(path.join(__dirname, "commands")).filter((file : string) => file.endsWith(".js"));
|
|
|
|
for (const file of commandFiles)
|
|
client.importCommand(path.join(__dirname, "commands", file)).then();
|
|
|
|
client.on("message", message => client.handleMessage(message as Message));
|
|
|
|
client.on("ready", () => console.log("Ready!"));
|
|
|
|
client.login(token).then(() => console.log("ConjureBot logged in!")); |