Add support for scheduled !suspend
parent
bee147c19d
commit
688ab7ceea
|
@ -0,0 +1,15 @@
|
|||
exports.up = async function(knex, Promise) {
|
||||
await knex.schema.table('threads', table => {
|
||||
table.dateTime('scheduled_suspend_at').index().nullable().defaultTo(null).after('channel_id');
|
||||
table.string('scheduled_suspend_id', 20).nullable().defaultTo(null).after('channel_id');
|
||||
table.string('scheduled_suspend_name', 128).nullable().defaultTo(null).after('channel_id');
|
||||
});
|
||||
};
|
||||
|
||||
exports.down = async function(knex, Promise) {
|
||||
await knex.schema.table('threads', table => {
|
||||
table.dropColumn('scheduled_suspend_at');
|
||||
table.dropColumn('scheduled_suspend_id');
|
||||
table.dropColumn('scheduled_suspend_name');
|
||||
});
|
||||
};
|
|
@ -356,6 +356,7 @@ class Thread {
|
|||
/**
|
||||
* @param {String} time
|
||||
* @param {Eris~User} user
|
||||
* @param {Number} silent
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async scheduleClose(time, user, silent) {
|
||||
|
@ -390,7 +391,10 @@ class Thread {
|
|||
await knex('threads')
|
||||
.where('id', this.id)
|
||||
.update({
|
||||
status: THREAD_STATUS.SUSPENDED
|
||||
status: THREAD_STATUS.SUSPENDED,
|
||||
scheduled_suspend_at: null,
|
||||
scheduled_suspend_id: null,
|
||||
scheduled_suspend_name: null
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -405,6 +409,34 @@ class Thread {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} time
|
||||
* @param {Eris~User} user
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async scheduleSuspend(time, user) {
|
||||
await knex('threads')
|
||||
.where('id', this.id)
|
||||
.update({
|
||||
scheduled_suspend_at: time,
|
||||
scheduled_suspend_id: user.id,
|
||||
scheduled_suspend_name: user.username
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async cancelScheduledSuspend() {
|
||||
await knex('threads')
|
||||
.where('id', this.id)
|
||||
.update({
|
||||
scheduled_suspend_at: null,
|
||||
scheduled_suspend_id: null,
|
||||
scheduled_suspend_name: null
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} userId
|
||||
* @returns {Promise<void>}
|
||||
|
|
|
@ -273,6 +273,18 @@ async function getThreadsThatShouldBeClosed() {
|
|||
return threads.map(thread => new Thread(thread));
|
||||
}
|
||||
|
||||
async function getThreadsThatShouldBeSuspended() {
|
||||
const now = moment.utc().format('YYYY-MM-DD HH:mm:ss');
|
||||
const threads = await knex('threads')
|
||||
.where('status', THREAD_STATUS.OPEN)
|
||||
.whereNotNull('scheduled_suspend_at')
|
||||
.where('scheduled_suspend_at', '<=', now)
|
||||
.whereNotNull('scheduled_suspend_at')
|
||||
.select();
|
||||
|
||||
return threads.map(thread => new Thread(thread));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
findById,
|
||||
findOpenThreadByUserId,
|
||||
|
@ -283,5 +295,6 @@ module.exports = {
|
|||
getClosedThreadsByUserId,
|
||||
findOrCreateThreadForUser,
|
||||
getThreadsThatShouldBeClosed,
|
||||
getThreadsThatShouldBeSuspended,
|
||||
createThreadInDB
|
||||
};
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
const humanizeDuration = require('humanize-duration');
|
||||
const moment = require('moment');
|
||||
const Eris = require('eris');
|
||||
const config = require('../config');
|
||||
|
@ -8,8 +7,6 @@ const blocked = require('../data/blocked');
|
|||
const {messageQueue} = require('../queue');
|
||||
|
||||
module.exports = bot => {
|
||||
const humanizeDelay = (delay, opts = {}) => humanizeDuration(delay, Object.assign({conjunction: ' and '}, opts));
|
||||
|
||||
// Check for threads that are scheduled to be closed and close them
|
||||
async function applyScheduledCloses() {
|
||||
const threadsToBeClosed = await threads.getThreadsThatShouldBeClosed();
|
||||
|
@ -90,7 +87,6 @@ module.exports = bot => {
|
|||
// Timed close
|
||||
const delayStringArg = args.find(arg => utils.delayStringRegex.test(arg));
|
||||
if (delayStringArg) {
|
||||
// Set a timed close
|
||||
const delay = utils.convertDelayStringToMS(delayStringArg);
|
||||
if (delay === 0 || delay === null) {
|
||||
thread.postSystemMessage(`Invalid delay specified. Format: "1h30m"`);
|
||||
|
@ -102,9 +98,9 @@ module.exports = bot => {
|
|||
|
||||
let response;
|
||||
if (silentClose) {
|
||||
response = `Thread is now scheduled to be closed silently in ${humanizeDelay(delay)}. Use \`${config.prefix}close cancel\` to cancel.`;
|
||||
response = `Thread is now scheduled to be closed silently in ${utils.humanizeDelay(delay)}. Use \`${config.prefix}close cancel\` to cancel.`;
|
||||
} else {
|
||||
response = `Thread is now scheduled to be closed in ${humanizeDelay(delay)}. Use \`${config.prefix}close cancel\` to cancel.`;
|
||||
response = `Thread is now scheduled to be closed in ${utils.humanizeDelay(delay)}. Use \`${config.prefix}close cancel\` to cancel.`;
|
||||
}
|
||||
|
||||
thread.postSystemMessage(response);
|
||||
|
|
|
@ -1,11 +1,70 @@
|
|||
const moment = require('moment');
|
||||
const threadUtils = require('../threadUtils');
|
||||
const threads = require("../data/threads");
|
||||
const utils = require('../utils');
|
||||
const config = require('../config');
|
||||
|
||||
const {THREAD_STATUS} = require('../data/constants');
|
||||
|
||||
module.exports = bot => {
|
||||
const addInboxServerCommand = (...args) => threadUtils.addInboxServerCommand(bot, ...args);
|
||||
|
||||
// Check for threads that are scheduled to be suspended and suspend them
|
||||
async function applyScheduledSuspensions() {
|
||||
const threadsToBeSuspended = await threads.getThreadsThatShouldBeSuspended();
|
||||
for (const thread of threadsToBeSuspended) {
|
||||
if (thread.status === THREAD_STATUS.OPEN) {
|
||||
await thread.suspend();
|
||||
await thread.postSystemMessage(`**Thread suspended** as scheduled by ${thread.scheduled_suspend_name}. This thread will act as closed until unsuspended with \`!unsuspend\``);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function scheduledSuspendLoop() {
|
||||
try {
|
||||
await applyScheduledSuspensions();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
setTimeout(scheduledSuspendLoop, 2000);
|
||||
}
|
||||
|
||||
scheduledSuspendLoop();
|
||||
|
||||
addInboxServerCommand('suspend', async (msg, args, thread) => {
|
||||
if (! thread) return;
|
||||
|
||||
if (args.length) {
|
||||
// Cancel timed suspend
|
||||
if (args.includes('cancel') || args.includes('c')) {
|
||||
// Cancel timed suspend
|
||||
if (thread.scheduled_suspend_at) {
|
||||
await thread.cancelScheduledSuspend();
|
||||
thread.postSystemMessage(`Cancelled scheduled suspension`);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Timed suspend
|
||||
const delayStringArg = args.find(arg => utils.delayStringRegex.test(arg));
|
||||
if (delayStringArg) {
|
||||
const delay = utils.convertDelayStringToMS(delayStringArg);
|
||||
if (delay === 0 || delay === null) {
|
||||
thread.postSystemMessage(`Invalid delay specified. Format: "1h30m"`);
|
||||
return;
|
||||
}
|
||||
|
||||
const suspendAt = moment.utc().add(delay, 'ms');
|
||||
await thread.scheduleSuspend(suspendAt.format('YYYY-MM-DD HH:mm:ss'), msg.author);
|
||||
|
||||
thread.postSystemMessage(`Thread will be suspended in ${utils.humanizeDelay(delay)}. Use \`${config.prefix}suspend cancel\` to cancel.`);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await thread.suspend();
|
||||
thread.postSystemMessage(`**Thread suspended!** This thread will act as closed until unsuspended with \`!unsuspend\``);
|
||||
});
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const Eris = require('eris');
|
||||
const bot = require('./bot');
|
||||
const moment = require('moment');
|
||||
const humanizeDuration = require('humanize-duration');
|
||||
const publicIp = require('public-ip');
|
||||
const attachments = require('./data/attachments');
|
||||
const config = require('./config');
|
||||
|
@ -293,6 +294,8 @@ function isSnowflake(str) {
|
|||
return snowflakeRegex.test(str);
|
||||
}
|
||||
|
||||
const humanizeDelay = (delay, opts = {}) => humanizeDuration(delay, Object.assign({conjunction: ' and '}, opts));
|
||||
|
||||
module.exports = {
|
||||
BotError,
|
||||
|
||||
|
@ -324,4 +327,6 @@ module.exports = {
|
|||
setDataModelProps,
|
||||
|
||||
isSnowflake,
|
||||
|
||||
humanizeDelay,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue