From c8f86ae762f1f9550fd368be403c1209d5b41262 Mon Sep 17 00:00:00 2001 From: Drew Short Date: Sun, 29 Dec 2019 12:41:39 -0600 Subject: [PATCH] Adding shutdown hook * Migrated some code into Bot class * Added shutdown hook with async pattern to send shutdown message * Added utility module * Added buildInfo version on startup and in startup message --- bot/bot.js | 99 +++++++++++++++++++++++++++++++++++++++++--------- bot/utility.js | 18 +++++++++ index.js | 6 ++- 3 files changed, 104 insertions(+), 19 deletions(-) create mode 100644 bot/utility.js diff --git a/bot/bot.js b/bot/bot.js index 6a38a1b..42d7c28 100644 --- a/bot/bot.js +++ b/bot/bot.js @@ -1,9 +1,59 @@ +let fs = require('fs'); let sdk = require("matrix-js-sdk"); let message = require("./message.js"); +let utility = require("./utility.js"); class Bot { - constructor(config) { - this.config = config + constructor(config, buildInfo) { + this.config = config; + this.buildInfo = buildInfo; + this.connected = false; + } + + sendStatusStartup() { + let promises = [Promise.resolve(true)] + if (this.connected) { + this.config.statusRooms.forEach(roomId => { + console.log("Notifying %s", roomId, "of startup"); + promises.push(this.client.sendMessage( + roomId, message.createBasic("Started with version: " + this.buildInfo) + ).then(function () { + console.log("Notified %s", roomId, "of startup"); + })); + }); + } else { + console.log("Attempting to send startup message while disconnected"); + } + return Promise.all(promises); + } + + sendStatusShutdown() { + let promises = [Promise.resolve(true)] + if (this.connected) { + this.config.statusRooms.forEach(roomId => { + console.log("Notifying %s", roomId, "of Shutdown"); + promises.push(this.client.sendMessage( + roomId, message.createBasic("Shutting down") + ).then(function () { + console.log("Notified %s", roomId, "of shutdown"); + })); + }); + } else { + console.log("Attempting to send shutdown message while disconnected"); + } + return Promise.all(promises); + } +} + +function getBuildInfo(buildInfoPath) { + try { + return fs.readFileSync(buildInfoPath, "utf8"); + } catch (err) { + if (err.code === 'ENOENT') { + return "UNKNOWN_" + utility.toISODateString(new Date()); + } else { + console.log("Unexpected Error! " + err); + } } } @@ -11,7 +61,10 @@ function create(configFile) { let config = require(configFile); console.log("Running with config:"); console.log(config); - return new Bot(config); + let buildInfo = getBuildInfo("../build.info") + console.log("Running version:"); + console.log(buildInfo); + return new Bot(config, buildInfo); } function init(bot) { @@ -22,39 +75,49 @@ function init(bot) { userId: bot.config.userId }); - function sendClientStatusUpdate() { - bot.config.statusRooms.forEach(roomId => { - console.log("Notifying %s", roomId); - bot.client.sendMessage(roomId, message.createBasic("Started!")).done(function () { - console.log("Notified %s", roomId); - }) - }); - } - - // Prep the bot - bot.client.on("sync", function (state, previousState, data) { + bot.client.on("sync", async function (state, previousState, data) { switch (state) { case "PREPARED": - sendClientStatusUpdate(); + bot.connected = true; + await bot.sendStatusStartup(); break; } }); - // auto join rooms that an admin user has invited the bot to bot.client.on("RoomMember.membership", function (event, member) { if (member.membership === "invite" && bot.config.admin.indexOf(ember.userId) >= 0) { - bot.client.joinRoom(member.roomId).done(function () { + bot.client.joinRoom(member.roomId).done(function () { console.log("Auto-joined %s", member.roomId); }); } }); + /* Capture Exit Conditions */ + + ["SIGINT", "SIGTERM"].forEach((signature) => { + process.on(signature, async () => { + await bot.sendStatusShutdown() + .then(function () { + console.log("Gracefully stopping Matrix SDK Client") + bot.client.stopClient(); + }); + process.exit(0); + }); + }); + + process.on('exit', async function () { + console.log("Shutting Down"); + }); + return bot; } function run(bot) { - bot.client.startClient() + // console.log("Initializing Crypto"); + // await bot.client.initCrypto(); + console.log("Starting Matrix SDK Client"); + bot.client.startClient(); } exports.create = create; diff --git a/bot/utility.js b/bot/utility.js new file mode 100644 index 0000000..318467c --- /dev/null +++ b/bot/utility.js @@ -0,0 +1,18 @@ +function toISODateString(d) { + function pad(n) { return n < 10 ? '0' + n : n } + return d.getUTCFullYear() + '-' + + pad(d.getUTCMonth() + 1) + '-' + + pad(d.getUTCDate()) + 'T' + + pad(d.getUTCHours()) + ':' + + pad(d.getUTCMinutes()) + ':' + + pad(d.getUTCSeconds()) + 'Z' +} + +function sleep(ms){ + return new Promise(resolve=>{ + setTimeout(resolve,ms) + }) +} + +exports.toISODateString = toISODateString; +exports.sleep = sleep; \ No newline at end of file diff --git a/index.js b/index.js index 98f636c..51fb774 100644 --- a/index.js +++ b/index.js @@ -1,2 +1,6 @@ let bot = require('./bot/bot.js'); -bot.run(bot.init(bot.create("../data/config.json"))); +bot.run( + bot.init( + bot.create("../data/config.json") + ) +);