2021-06-18 15:41:57 +02:00
|
|
|
const { Client } = require('discord.js');
|
2021-06-19 15:06:20 +02:00
|
|
|
const fs = require('fs');
|
2021-06-18 15:41:57 +02:00
|
|
|
|
2021-06-19 15:06:20 +02:00
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
|
|
const { TextChannel, GuildMember } = require('./extensions');
|
2021-06-18 15:41:57 +02:00
|
|
|
const { Logger } = require('../logger');
|
|
|
|
const Modmail = require('./Modmail');
|
|
|
|
const Registry = require('./Registry');
|
2021-06-19 15:06:20 +02:00
|
|
|
const Resolver = require('./Resolver');
|
2021-06-18 15:41:57 +02:00
|
|
|
|
|
|
|
class ModmailClient extends Client {
|
|
|
|
|
|
|
|
constructor(options) {
|
|
|
|
|
|
|
|
super(options.clientOptions);
|
|
|
|
|
|
|
|
this._options = options;
|
|
|
|
this._ready = false;
|
|
|
|
|
2021-06-19 15:06:20 +02:00
|
|
|
this.prefix = options.prefix;
|
|
|
|
|
2021-06-18 15:41:57 +02:00
|
|
|
this.logger = new Logger(this, options.loggerOptions);
|
|
|
|
this.modmail = new Modmail(this);
|
|
|
|
this.registry = new Registry(this);
|
2021-06-19 15:06:20 +02:00
|
|
|
this.resolver = new Resolver(this);
|
2021-06-18 15:41:57 +02:00
|
|
|
|
|
|
|
this.on('ready', () => {
|
|
|
|
this.logger.info(`Client ready, logged in as ${this.user.tag}`);
|
|
|
|
});
|
|
|
|
|
2021-06-19 15:06:20 +02:00
|
|
|
this.cache = null;
|
|
|
|
|
2021-06-18 15:41:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async init() {
|
|
|
|
|
2021-06-19 15:06:20 +02:00
|
|
|
this.registry.loadCommands();
|
|
|
|
|
|
|
|
this.on('message', this.handleMessage.bind(this));
|
|
|
|
|
|
|
|
if (fs.existsSync('./persistent_cache.json')) {
|
|
|
|
this.logger.info('Loading cache');
|
|
|
|
this.cache = JSON.parse(fs.readFileSync('./persistent_cache.json', { encoding: 'utf-8' }));
|
|
|
|
} else {
|
|
|
|
this.logger.info('Cache file missing, creating...');
|
|
|
|
this.cache = {};
|
|
|
|
this.saveCache();
|
|
|
|
}
|
|
|
|
|
2021-06-18 15:41:57 +02:00
|
|
|
this.logger.info(`Logging in`);
|
|
|
|
await this.login(this._options.discordToken);
|
2021-06-19 15:06:20 +02:00
|
|
|
await this.ready();
|
|
|
|
|
|
|
|
this.mainServer = this.guilds.cache.get(this._options.mainGuild);
|
|
|
|
this.bansServer = this.guilds.cache.get(this._options.bansGuild) || null;
|
|
|
|
this.logger.info(`Starting up modmail handler`);
|
2021-06-18 15:41:57 +02:00
|
|
|
this.modmail.init();
|
|
|
|
|
2021-06-20 00:02:27 +02:00
|
|
|
process.on('exit', () => {
|
|
|
|
this.saveCache();
|
|
|
|
this.modmail.saveHistory();
|
|
|
|
// eslint-disable-next-line no-process-exit
|
|
|
|
process.exit();
|
|
|
|
});
|
2021-06-19 20:25:42 +02:00
|
|
|
process.on('SIGINT', () => {
|
|
|
|
this.saveCache.bind(this);
|
2021-06-19 21:31:51 +02:00
|
|
|
this.modmail.saveHistory();
|
2021-06-19 20:25:42 +02:00
|
|
|
// eslint-disable-next-line no-process-exit
|
|
|
|
process.exit();
|
|
|
|
});
|
2021-06-18 15:41:57 +02:00
|
|
|
|
|
|
|
this._ready = true;
|
|
|
|
|
2021-06-20 00:02:27 +02:00
|
|
|
this.cacheSaver = setInterval(this.saveCache.bind(this), 10 * 60 * 1000);
|
2021-06-19 15:06:20 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
saveCache() {
|
|
|
|
this.logger.debug('Saving cache');
|
|
|
|
delete this.cache._channels;
|
|
|
|
fs.writeFileSync('./persistent_cache.json', JSON.stringify(this.cache));
|
|
|
|
}
|
|
|
|
|
|
|
|
ready() {
|
|
|
|
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
if (this._ready) resolve();
|
|
|
|
this.once('ready', resolve);
|
|
|
|
});
|
|
|
|
|
2021-06-18 15:41:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async handleMessage(message) {
|
|
|
|
|
2021-06-19 15:06:20 +02:00
|
|
|
if (!this._ready) return;
|
|
|
|
if (message.author.bot) return;
|
|
|
|
|
|
|
|
// No command handling in dms, at least for now
|
2021-06-18 15:41:57 +02:00
|
|
|
if (!message.guild) return this.modmail.handleUser(message);
|
|
|
|
|
2021-06-19 15:06:20 +02:00
|
|
|
const { prefix } = this;
|
|
|
|
const { channel, guild, content, member } = message;
|
2021-06-19 21:35:42 +02:00
|
|
|
if (![this.mainServer.id, this.bansServer?.id || '0'].includes(guild.id)) return;
|
2021-06-19 15:06:20 +02:00
|
|
|
if (!content || !content.startsWith(prefix)) return;
|
|
|
|
|
|
|
|
const roles = member.roles.cache.map((r) => r.id);
|
|
|
|
if(!roles.some((r) => this._options.staffRoles.includes(r)) && !member.hasPermission('ADMINISTRATOR')) return;
|
|
|
|
|
|
|
|
const [rawCommand, ...args] = content.split(' ');
|
|
|
|
const commandName = rawCommand.substring(prefix.length).toLowerCase();
|
|
|
|
const command = this.registry.find(commandName);
|
|
|
|
if (!command) return;
|
|
|
|
message._caller = commandName;
|
|
|
|
|
|
|
|
if (command.showUsage && !args.length) {
|
|
|
|
|
|
|
|
let helpStr = `**${command.name}**\nUsage: ${this.prefix}${command.name} ${command.usage}`;
|
|
|
|
if (command.aliases) helpStr += `\nAliases: ${command.aliases.join(', ')}`;
|
|
|
|
return channel.send(helpStr).catch(this.logger.error.bind(this.logger));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-06-19 22:46:44 +02:00
|
|
|
this.logger.debug(`${message.author.tag} is executing command ${command.name}`);
|
2021-06-19 22:41:51 +02:00
|
|
|
const result = await command.execute(message, { args, clean: message.content.replace(`${this.prefix}${commandName}`, '').trim() }).catch((err) => {
|
2021-06-19 15:06:20 +02:00
|
|
|
this.logger.error(`Command ${command.name} errored during execution:\n${err.stack}`);
|
|
|
|
return {
|
|
|
|
error: true,
|
|
|
|
msg: `Command ${command.name} ran into an error during execution. This has been logged.`
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!result) return;
|
|
|
|
|
|
|
|
if (result.error) return channel.send(result.msg).catch(this.logger.error.bind(this.logger));
|
|
|
|
else if (result.response) return channel.send(result.response).catch(this.logger.error.bind(this.logger));
|
|
|
|
else if (typeof result === 'string') return channel.send(result).catch(this.logger.error.bind(this.logger));
|
|
|
|
|
|
|
|
}
|
2021-06-18 15:41:57 +02:00
|
|
|
|
2021-06-19 15:06:20 +02:00
|
|
|
resolveUser(input) {
|
|
|
|
return this.resolver.resolveUser(input);
|
2021-06-18 15:41:57 +02:00
|
|
|
}
|
|
|
|
|
2021-06-19 23:57:12 +02:00
|
|
|
resolveUsers(input) {
|
|
|
|
return this.resolver.resolveUsers(input);
|
|
|
|
}
|
|
|
|
|
2021-06-19 20:05:32 +02:00
|
|
|
async prompt(str, { author, channel, time }) {
|
|
|
|
|
|
|
|
if (!channel && author) channel = await author.createDM();
|
|
|
|
if (!channel) throw new Error(`Missing channel for prompt, must pass at least author.`);
|
|
|
|
await channel.send(str);
|
|
|
|
return channel.awaitMessages((m) => m.author.id === author.id, { max: 1, time: time || 30000, errors: ['time'] })
|
|
|
|
.then((collected) => {
|
|
|
|
return collected.first();
|
|
|
|
})
|
|
|
|
.catch((error) => { //eslint-disable-line no-unused-vars, handle-callback-err
|
|
|
|
return null;
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-06-18 15:41:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = ModmailClient;
|