Allow silent scheduled closes. Make close time format stricter (no whitespace).

master
Dragory 2019-03-06 21:15:09 +02:00
parent cd3da4c4ec
commit 188f7543ee
4 changed files with 60 additions and 20 deletions

View File

@ -0,0 +1,11 @@
exports.up = async function(knex, Promise) {
await knex.schema.table('threads', table => {
table.integer('scheduled_close_silent').nullable();
});
};
exports.down = async function(knex, Promise) {
await knex.schema.table('threads', table => {
table.dropColumn('scheduled_close_silent');
});
};

View File

@ -19,6 +19,7 @@ const {THREAD_MESSAGE_TYPE, THREAD_STATUS} = require('./constants');
* @property {String} scheduled_close_at * @property {String} scheduled_close_at
* @property {String} scheduled_close_id * @property {String} scheduled_close_id
* @property {String} scheduled_close_name * @property {String} scheduled_close_name
* @property {Number} scheduled_close_silent
* @property {String} alert_id * @property {String} alert_id
* @property {String} created_at * @property {String} created_at
*/ */
@ -326,10 +327,15 @@ class Thread {
/** /**
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async close(noSystemMessage = false) { async close(suppressSystemMessage = false, silent = false) {
if (! noSystemMessage) { if (! suppressSystemMessage) {
console.log(`Closing thread ${this.id}`); console.log(`Closing thread ${this.id}`);
await this.postSystemMessage('Closing thread...');
if (silent) {
await this.postSystemMessage('Closing thread silently...');
} else {
await this.postSystemMessage('Closing thread...');
}
} }
// Update DB status // Update DB status
@ -352,13 +358,14 @@ class Thread {
* @param {Eris~User} user * @param {Eris~User} user
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async scheduleClose(time, user) { async scheduleClose(time, user, silent) {
await knex('threads') await knex('threads')
.where('id', this.id) .where('id', this.id)
.update({ .update({
scheduled_close_at: time, scheduled_close_at: time,
scheduled_close_id: user.id, scheduled_close_id: user.id,
scheduled_close_name: user.username scheduled_close_name: user.username,
scheduled_close_silent: silent
}); });
} }
@ -371,7 +378,8 @@ class Thread {
.update({ .update({
scheduled_close_at: null, scheduled_close_at: null,
scheduled_close_id: null, scheduled_close_id: null,
scheduled_close_name: null scheduled_close_name: null,
scheduled_close_silent: null
}); });
} }

View File

@ -14,8 +14,11 @@ module.exports = bot => {
async function applyScheduledCloses() { async function applyScheduledCloses() {
const threadsToBeClosed = await threads.getThreadsThatShouldBeClosed(); const threadsToBeClosed = await threads.getThreadsThatShouldBeClosed();
for (const thread of threadsToBeClosed) { for (const thread of threadsToBeClosed) {
if(config.closeMessage) await thread.postToUser(config.closeMessage).catch(() => {}); if (config.closeMessage && ! thread.scheduled_close_silent) {
await thread.close(); await thread.postToUser(config.closeMessage).catch(() => {});
}
await thread.close(false, thread.scheduled_close_silent);
const logUrl = await thread.getLogUrl(); const logUrl = await thread.getLogUrl();
utils.postLog(utils.trimAll(` utils.postLog(utils.trimAll(`
@ -41,7 +44,8 @@ module.exports = bot => {
bot.registerCommand('close', async (msg, args) => { bot.registerCommand('close', async (msg, args) => {
let thread, closedBy; let thread, closedBy;
let sendCloseMessage = !! config.closeMessage; let hasCloseMessage = !! config.closeMessage;
let silentClose = false;
if (msg.channel instanceof Eris.PrivateChannel) { if (msg.channel instanceof Eris.PrivateChannel) {
// User is closing the thread by themselves (if enabled) // User is closing the thread by themselves (if enabled)
@ -67,7 +71,6 @@ module.exports = bot => {
thread = await threads.findOpenThreadByChannelId(msg.channel.id); thread = await threads.findOpenThreadByChannelId(msg.channel.id);
if (! thread) return; if (! thread) return;
// Timed close
if (args.length) { if (args.length) {
if (args.includes('cancel') || args.includes('c')) { if (args.includes('cancel') || args.includes('c')) {
// Cancel timed close // Cancel timed close
@ -77,30 +80,46 @@ module.exports = bot => {
} }
return; return;
} else if (args.includes('silent') || args.includes('s')) { }
sendCloseMessage = false;
} else { // Silent close (= no close message)
if (args.includes('silent') || args.includes('s')) {
silentClose = true;
}
// Timed close
const delayStringArg = args.find(arg => utils.delayStringRegex.test(arg));
if (delayStringArg) {
// Set a timed close // Set a timed close
const delay = utils.convertDelayStringToMS(args.join(' ')); const delay = utils.convertDelayStringToMS(delayStringArg);
if (delay === 0 || delay === null) { if (delay === 0 || delay === null) {
thread.postSystemMessage(`Invalid delay specified. Format: "1h30m"`); thread.postSystemMessage(`Invalid delay specified. Format: "1h30m"`);
return; return;
} }
const closeAt = moment.utc().add(delay, 'ms'); const closeAt = moment.utc().add(delay, 'ms');
await thread.scheduleClose(closeAt.format('YYYY-MM-DD HH:mm:ss'), msg.author); await thread.scheduleClose(closeAt.format('YYYY-MM-DD HH:mm:ss'), msg.author, silentClose ? 1 : 0);
thread.postSystemMessage(`Thread is now scheduled to be closed in ${humanizeDelay(delay)}. Use \`${config.prefix}close cancel\` to cancel.`);
let response;
if (silentClose) {
response = `Thread is now scheduled to be closed silently in ${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.`;
}
thread.postSystemMessage(response);
return; return;
} }
} }
// Regular close // Regular close
await thread.close(); await thread.close(false, silentClose);
closedBy = msg.author.username; closedBy = msg.author.username;
} }
if (sendCloseMessage) { // Send close message (unless suppressed with a silent close)
if (hasCloseMessage && ! silentClose) {
await thread.postToUser(config.closeMessage).catch(() => {}); await thread.postToUser(config.closeMessage).catch(() => {});
} }

View File

@ -220,19 +220,20 @@ function trimAll(str) {
.join('\n'); .join('\n');
} }
const delayStringRegex = /^([0-9]+)(?:([dhms])[a-z]*)?/i;
/** /**
* Turns a "delay string" such as "1h30m" to milliseconds * Turns a "delay string" such as "1h30m" to milliseconds
* @param {String} str * @param {String} str
* @returns {Number} * @returns {Number}
*/ */
function convertDelayStringToMS(str) { function convertDelayStringToMS(str) {
const regex = /^([0-9]+)\s*([dhms])?[a-z]*\s*/;
let match; let match;
let ms = 0; let ms = 0;
str = str.trim(); str = str.trim();
while (str !== '' && (match = str.match(regex)) !== null) { while (str !== '' && (match = str.match(delayStringRegex)) !== null) {
if (match[2] === 'd') ms += match[1] * 1000 * 60 * 60 * 24; if (match[2] === 'd') ms += match[1] * 1000 * 60 * 60 * 24;
else if (match[2] === 'h') ms += match[1] * 1000 * 60 * 60; else if (match[2] === 'h') ms += match[1] * 1000 * 60 * 60;
else if (match[2] === 's') ms += match[1] * 1000; else if (match[2] === 's') ms += match[1] * 1000;
@ -312,6 +313,7 @@ module.exports = {
disableLinkPreviews, disableLinkPreviews,
getSelfUrl, getSelfUrl,
getMainRole, getMainRole,
delayStringRegex,
convertDelayStringToMS, convertDelayStringToMS,
getInboxMention, getInboxMention,
postSystemMessageWithFallback, postSystemMessageWithFallback,