diff --git a/src/data/Snippet.js b/src/data/Snippet.js index 28a6987..5a8982e 100644 --- a/src/data/Snippet.js +++ b/src/data/Snippet.js @@ -1,3 +1,5 @@ +const utils = require("../utils"); + /** * @property {String} trigger * @property {String} body @@ -7,7 +9,7 @@ */ class Snippet { constructor(props) { - Object.assign(this, props); + utils.setDataModelProps(this, props); } } diff --git a/src/data/Thread.js b/src/data/Thread.js index 490207b..3c13145 100644 --- a/src/data/Thread.js +++ b/src/data/Thread.js @@ -23,7 +23,7 @@ const {THREAD_MESSAGE_TYPE, THREAD_STATUS} = require('./constants'); */ class Thread { constructor(props) { - Object.assign(this, props); + utils.setDataModelProps(this, props); } /** @@ -92,7 +92,7 @@ class Thread { }); // The string type check is due to a knex bug, see https://github.com/tgriesser/knex/issues/1276 - if (this.scheduled_close_at && typeof this.scheduled_close_at === 'string') { + if (this.scheduled_close_at) { await this.cancelScheduledClose(); await this.postSystemMessage(`Cancelling scheduled closing of this thread due to new reply`); } @@ -145,7 +145,7 @@ class Thread { }); // The string type check is due to a knex bug, see https://github.com/tgriesser/knex/issues/1276 - if (this.scheduled_close_at && typeof this.scheduled_close_at === 'string') { + if (this.scheduled_close_at) { await this.cancelScheduledClose(); await this.postSystemMessage({ content: `<@!${this.scheduled_close_id}> Thread that was scheduled to be closed got a new reply. Cancelling.`, diff --git a/src/data/ThreadMessage.js b/src/data/ThreadMessage.js index 06004f4..2704287 100644 --- a/src/data/ThreadMessage.js +++ b/src/data/ThreadMessage.js @@ -1,3 +1,5 @@ +const utils = require("../utils"); + /** * @property {Number} id * @property {String} thread_id @@ -11,7 +13,7 @@ */ class ThreadMessage { constructor(props) { - Object.assign(this, props); + utils.setDataModelProps(this, props); } } diff --git a/src/main.js b/src/main.js index 099e196..157d09e 100644 --- a/src/main.js +++ b/src/main.js @@ -257,7 +257,7 @@ addInboxServerCommand('close', async (msg, args, thread) => { if (args[0] === 'cancel') { // Cancel timed close // The string type check is due to a knex bug, see https://github.com/tgriesser/knex/issues/1276 - if (thread.scheduled_close_at && typeof thread.scheduled_close_at === 'string') { + if (thread.scheduled_close_at) { await thread.cancelScheduledClose(); thread.postSystemMessage(`Cancelled scheduled closing`); } diff --git a/src/utils.js b/src/utils.js index 6510f49..474247d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -231,6 +231,29 @@ function postSystemMessageWithFallback(channel, thread, text) { } } +/** + * A normalized way to set props in data models, fixing some inconsistencies between different DB drivers in knex + * @param {Object} target + * @param {Object} props + */ +function setDataModelProps(target, props) { + for (const prop in props) { + if (! props.hasOwnProperty(prop)) continue; + // DATETIME fields are always returned as Date objects in MySQL/MariaDB + if (props[prop] instanceof Date) { + // ...even when NULL, in which case the date's set to unix epoch + if (props[prop].getUTCFullYear() === 1970) { + target[prop] = null; + } else { + // Set the value as a string in the same format it's returned in SQLite + target[prop] = moment.utc(props[prop]).format('YYYY-MM-DD HH:mm:ss'); + } + } else { + target[prop] = props[prop]; + } + } +} + module.exports = { BotError, @@ -257,4 +280,6 @@ module.exports = { chunk, trimAll, + + setDataModelProps, };