2018-03-13 01:45:31 -04:00
|
|
|
const moment = require('moment');
|
|
|
|
const Eris = require('eris');
|
|
|
|
const config = require('../config');
|
2018-09-20 16:31:14 -04:00
|
|
|
const utils = require('../utils');
|
|
|
|
const threads = require('../data/threads');
|
|
|
|
const blocked = require('../data/blocked');
|
|
|
|
const {messageQueue} = require('../queue');
|
2018-03-13 01:45:31 -04:00
|
|
|
|
2019-06-16 15:27:30 -04:00
|
|
|
module.exports = (bot, knex, config, commands) => {
|
2018-03-13 01:45:31 -04:00
|
|
|
// Check for threads that are scheduled to be closed and close them
|
|
|
|
async function applyScheduledCloses() {
|
|
|
|
const threadsToBeClosed = await threads.getThreadsThatShouldBeClosed();
|
|
|
|
for (const thread of threadsToBeClosed) {
|
2019-03-06 14:15:09 -05:00
|
|
|
if (config.closeMessage && ! thread.scheduled_close_silent) {
|
|
|
|
await thread.postToUser(config.closeMessage).catch(() => {});
|
|
|
|
}
|
|
|
|
|
|
|
|
await thread.close(false, thread.scheduled_close_silent);
|
2018-03-13 01:45:31 -04:00
|
|
|
|
|
|
|
const logUrl = await thread.getLogUrl();
|
|
|
|
utils.postLog(utils.trimAll(`
|
|
|
|
Modmail thread with ${thread.user_name} (${thread.user_id}) was closed as scheduled by ${thread.scheduled_close_name}
|
|
|
|
Logs: ${logUrl}
|
|
|
|
`));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function scheduledCloseLoop() {
|
|
|
|
try {
|
|
|
|
await applyScheduledCloses();
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
setTimeout(scheduledCloseLoop, 2000);
|
|
|
|
}
|
|
|
|
|
|
|
|
scheduledCloseLoop();
|
|
|
|
|
|
|
|
// Close a thread. Closing a thread saves a log of the channel's contents and then deletes the channel.
|
2019-06-16 15:27:30 -04:00
|
|
|
commands.addGlobalCommand('close', '[opts...]', async (msg, args) => {
|
2018-09-20 16:31:14 -04:00
|
|
|
let thread, closedBy;
|
|
|
|
|
2019-03-06 14:15:09 -05:00
|
|
|
let hasCloseMessage = !! config.closeMessage;
|
|
|
|
let silentClose = false;
|
2019-02-23 16:32:18 -05:00
|
|
|
|
2018-09-20 16:31:14 -04:00
|
|
|
if (msg.channel instanceof Eris.PrivateChannel) {
|
|
|
|
// User is closing the thread by themselves (if enabled)
|
|
|
|
if (! config.allowUserClose) return;
|
|
|
|
if (await blocked.isBlocked(msg.author.id)) return;
|
|
|
|
|
|
|
|
thread = await threads.findOpenThreadByUserId(msg.author.id);
|
|
|
|
if (! thread) return;
|
|
|
|
|
|
|
|
// We need to add this operation to the message queue so we don't get a race condition
|
|
|
|
// between showing the close command in the thread and closing the thread
|
|
|
|
await messageQueue.add(async () => {
|
|
|
|
thread.postSystemMessage('Thread closed by user, closing...');
|
|
|
|
await thread.close(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
closedBy = 'the user';
|
|
|
|
} else {
|
|
|
|
// A staff member is closing the thread
|
|
|
|
if (! utils.messageIsOnInboxServer(msg)) return;
|
|
|
|
if (! utils.isStaff(msg.member)) return;
|
|
|
|
|
|
|
|
thread = await threads.findOpenThreadByChannelId(msg.channel.id);
|
|
|
|
if (! thread) return;
|
|
|
|
|
2019-06-16 15:27:30 -04:00
|
|
|
if (args.opts && args.opts.length) {
|
|
|
|
if (args.opts.includes('cancel') || args.opts.includes('c')) {
|
2018-09-20 16:31:14 -04:00
|
|
|
// Cancel timed close
|
|
|
|
if (thread.scheduled_close_at) {
|
|
|
|
await thread.cancelScheduledClose();
|
|
|
|
thread.postSystemMessage(`Cancelled scheduled closing`);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2019-03-06 14:15:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Silent close (= no close message)
|
2019-06-16 15:27:30 -04:00
|
|
|
if (args.opts.includes('silent') || args.opts.includes('s')) {
|
2019-03-06 14:15:09 -05:00
|
|
|
silentClose = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Timed close
|
2019-06-16 15:27:30 -04:00
|
|
|
const delayStringArg = args.opts.find(arg => utils.delayStringRegex.test(arg));
|
2019-03-06 14:15:09 -05:00
|
|
|
if (delayStringArg) {
|
|
|
|
const delay = utils.convertDelayStringToMS(delayStringArg);
|
2019-02-23 16:32:18 -05:00
|
|
|
if (delay === 0 || delay === null) {
|
|
|
|
thread.postSystemMessage(`Invalid delay specified. Format: "1h30m"`);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const closeAt = moment.utc().add(delay, 'ms');
|
2019-03-06 14:15:09 -05:00
|
|
|
await thread.scheduleClose(closeAt.format('YYYY-MM-DD HH:mm:ss'), msg.author, silentClose ? 1 : 0);
|
|
|
|
|
|
|
|
let response;
|
|
|
|
if (silentClose) {
|
2019-03-06 14:37:36 -05:00
|
|
|
response = `Thread is now scheduled to be closed silently in ${utils.humanizeDelay(delay)}. Use \`${config.prefix}close cancel\` to cancel.`;
|
2019-03-06 14:15:09 -05:00
|
|
|
} else {
|
2019-03-06 14:37:36 -05:00
|
|
|
response = `Thread is now scheduled to be closed in ${utils.humanizeDelay(delay)}. Use \`${config.prefix}close cancel\` to cancel.`;
|
2019-03-06 14:15:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
thread.postSystemMessage(response);
|
2018-03-13 01:45:31 -04:00
|
|
|
|
2018-09-20 16:31:14 -04:00
|
|
|
return;
|
2018-03-13 01:45:31 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-20 16:31:14 -04:00
|
|
|
// Regular close
|
2019-03-06 14:15:09 -05:00
|
|
|
await thread.close(false, silentClose);
|
2018-09-20 16:31:14 -04:00
|
|
|
closedBy = msg.author.username;
|
2018-03-13 01:45:31 -04:00
|
|
|
}
|
|
|
|
|
2019-03-06 14:15:09 -05:00
|
|
|
// Send close message (unless suppressed with a silent close)
|
|
|
|
if (hasCloseMessage && ! silentClose) {
|
2018-09-20 16:31:14 -04:00
|
|
|
await thread.postToUser(config.closeMessage).catch(() => {});
|
|
|
|
}
|
2018-03-13 01:45:31 -04:00
|
|
|
|
|
|
|
const logUrl = await thread.getLogUrl();
|
|
|
|
utils.postLog(utils.trimAll(`
|
2018-09-20 16:31:14 -04:00
|
|
|
Modmail thread with ${thread.user_name} (${thread.user_id}) was closed by ${closedBy}
|
2018-03-13 01:45:31 -04:00
|
|
|
Logs: ${logUrl}
|
|
|
|
`));
|
|
|
|
});
|
|
|
|
|
|
|
|
// Auto-close threads if their channel is deleted
|
|
|
|
bot.on('channelDelete', async (channel) => {
|
|
|
|
if (! (channel instanceof Eris.TextChannel)) return;
|
|
|
|
if (channel.guild.id !== utils.getInboxGuild().id) return;
|
2018-09-20 16:31:14 -04:00
|
|
|
|
2018-03-13 01:45:31 -04:00
|
|
|
const thread = await threads.findOpenThreadByChannelId(channel.id);
|
|
|
|
if (! thread) return;
|
|
|
|
|
|
|
|
console.log(`[INFO] Auto-closing thread with ${thread.user_name} because the channel was deleted`);
|
2018-09-20 16:31:14 -04:00
|
|
|
if (config.closeMessage) await thread.postToUser(config.closeMessage).catch(() => {});
|
2018-03-13 01:45:31 -04:00
|
|
|
await thread.close(true);
|
|
|
|
|
|
|
|
const logUrl = await thread.getLogUrl();
|
|
|
|
utils.postLog(utils.trimAll(`
|
|
|
|
Modmail thread with ${thread.user_name} (${thread.user_id}) was closed automatically because the channel was deleted
|
|
|
|
Logs: ${logUrl}
|
|
|
|
`));
|
|
|
|
});
|
|
|
|
};
|