modmail/structure/Client.js

170 lines
6.0 KiB
JavaScript
Raw Normal View History

2021-12-03 13:05:21 +01:00
const { inspect } = require('util');
2021-06-18 15:41:57 +02:00
const { Client } = require('discord.js');
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');
const Cache = require('./JsonCache');
2021-06-18 15:41:57 +02:00
class ModmailClient extends Client {
2021-10-22 09:35:04 +02:00
constructor (options) {
2021-06-18 15:41:57 +02:00
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.registry = new Registry(this);
2021-06-19 15:06:20 +02:00
this.resolver = new Resolver(this);
this.cache = new Cache(this);
this.modmail = new Modmail(this);
2021-06-18 15:41:57 +02:00
this.on('ready', () => {
this.logger.info(`Client ready, logged in as ${this.user.tag}`);
});
}
2021-10-22 09:35:04 +02:00
async init () {
2021-06-18 15:41:57 +02:00
2021-06-19 15:06:20 +02:00
this.registry.loadCommands();
this.on('message', this.handleMessage.bind(this));
this.cache.load();
2021-06-19 15:06:20 +02:00
2021-06-18 15:41:57 +02:00
this.logger.info(`Logging in`);
2021-06-20 16:43:05 +02:00
const promise = this.ready();
2021-06-18 15:41:57 +02:00
await this.login(this._options.discordToken);
2021-06-20 16:43:05 +02:00
await promise;
2021-06-19 15:06:20 +02:00
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-07-19 21:30:31 +02:00
await this.modmail.init();
2021-06-18 15:41:57 +02:00
2021-06-20 00:02:27 +02:00
process.on('exit', () => {
2021-06-20 00:21:27 +02:00
this.logger.warn('process exiting');
2021-10-22 09:35:04 +02:00
this.cache.savePersistentCache();
this.cache.saveModmailHistory(this.modmail);
2021-06-20 00:02:27 +02:00
});
2021-06-19 20:25:42 +02:00
process.on('SIGINT', () => {
2021-06-20 00:21:27 +02:00
this.logger.warn('received sigint');
2021-10-22 09:35:04 +02:00
// this.cache.save();
// this.cache.saveModmailHistory(this.modmail);
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
2021-11-29 11:25:38 +01:00
process.on('unhandledRejection', (reason, prom) => {
2022-01-12 17:46:06 +01:00
this.logger.error(`Unhandled promise rejection at: ${inspect(prom)}\nReason: ${reason}`);
2021-11-29 11:25:38 +01:00
});
2021-06-18 15:41:57 +02:00
this._ready = true;
await this.modmail.reminderChannel.send(`Modmail bot booted and ready.`);
2021-06-18 15:41:57 +02:00
2021-06-19 15:06:20 +02:00
}
2021-10-22 09:35:04 +02:00
ready () {
2021-06-19 15:06:20 +02:00
return new Promise((resolve) => {
if (this._ready) resolve();
this.once('ready', resolve);
});
2021-06-18 15:41:57 +02:00
}
2021-10-22 09:35:04 +02:00
async handleMessage (message) {
2021-06-18 15:41:57 +02:00
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-20 00:21:27 +02:00
if (!message.guild) try {
return this.modmail.handleUser(message);
} catch (err) {
this.logger.error(`Error during user handle:\n${err.stack}`);
return;
}
2021-06-18 15:41:57 +02:00
2021-06-19 15:06:20 +02:00
const { prefix } = this;
const { channel, guild, content, member } = message;
2021-10-22 09:35:04 +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);
2021-10-22 09:35:04 +02:00
if (!roles.some((r) => this._options.staffRoles.includes(r)) && !member.hasPermission('ADMINISTRATOR')) return;
2021-06-19 15:06:20 +02:00
2021-10-22 09:35:04 +02:00
const [ rawCommand, ...args ] = content.split(' ');
const commandName = rawCommand.substring(prefix.length);
2021-06-19 15:06:20 +02:00
const command = this.registry.find(commandName);
if (!command) return;
2021-12-22 10:30:50 +01:00
message._caller = commandName.toLowerCase();
2021-06-19 15:06:20 +02:00
if (command.showUsage && !args.length) {
let helpStr = `**${command.name}**\nUsage: ${this.prefix}${command.name} ${command.usage}`;
if (command.aliases) helpStr += `\nAliases: ${command.aliases.join(', ')}`;
2021-12-02 18:20:30 +01:00
return channel.send(helpStr).catch(err => this.logger.error(`Client.handleMessage errored at channel.send:\n${err.stack}`));
2021-06-19 15:06:20 +02:00
}
2021-06-19 22:46:44 +02:00
this.logger.debug(`${message.author.tag} is executing command ${command.name}`);
2021-11-29 11:25:38 +01:00
const clean = message.content.replace(`${this.prefix}${commandName}`, '').trim();
2021-11-29 14:38:37 +01:00
const result = await command.execute(message, { args: [ ...args ], clean }).catch((err) => {
this.logger.error(`Command ${command.name} errored during execution:\nARGS: [ "${args.join('", "')}" ]\n${err.stack}`);
2021-06-19 15:06:20 +02:00
return {
error: true,
msg: `Command ${command.name} ran into an error during execution. This has been logged.`
};
});
if (!result) return;
2021-12-03 13:05:21 +01:00
if (result.error) return channel.send(result.msg).catch(err => this.logger.error(`Client.load errored at channel.send:\n${err.stack}\n${inspect(result)}`));
else if (result.response) return channel.send(result.response).catch(err => this.logger.error(`Client.load errored at channel.send:\n${err.stack}\n${inspect(result)}`));
else if (typeof result === 'string') return channel.send(result).catch(err => this.logger.error(`Client.load errored at channel.send:\n${err.stack}\n${inspect(result)}`));
2021-06-19 15:06:20 +02:00
}
2021-06-18 15:41:57 +02:00
2021-10-22 09:35:04 +02:00
resolveUser (...args) {
return this.resolver.resolveUser(...args);
}
2021-10-22 09:35:04 +02:00
resolveUsers (...args) {
return this.resolver.resolveUsers(...args);
}
2021-10-22 09:35:04 +02:00
resolveChannels (...args) {
return this.resolver.resolveChannels(...args);
2021-06-18 15:41:57 +02:00
}
2021-10-22 09:35:04 +02:00
resolveChannel (...args) {
return this.resolver.resolveChannel(...args);
2021-06-19 23:57:12 +02:00
}
2021-10-22 09:35:04 +02:00
async prompt (str, { author, channel, time }) {
2021-06-19 20:05:32 +02:00
if (!channel && author) channel = await author.createDM();
if (!channel) throw new Error(`Missing channel for prompt, must pass at least author.`);
2021-12-02 18:20:30 +01:00
await channel.send(str).catch(err => this.logger.error(`Client.prompt errored at channel.send:\n${err.stack}`));
2021-10-22 09:35:04 +02:00
return channel.awaitMessages((m) => m.author.id === author.id, { max: 1, time: time || 30000, errors: [ 'time' ] })
2021-06-19 20:05:32 +02:00
.then((collected) => {
return collected.first();
})
2021-10-22 09:35:04 +02:00
.catch((error) => { // eslint-disable-line no-unused-vars, handle-callback-err
2021-06-19 20:05:32 +02:00
return null;
});
}
2021-06-18 15:41:57 +02:00
}
module.exports = ModmailClient;