From 69486b55951dc0d0bb083c744d5df3b7f0e885b0 Mon Sep 17 00:00:00 2001 From: "Ean Milligan (Bastion)" Date: Fri, 28 Apr 2023 15:53:17 -0400 Subject: [PATCH] Update ready.ts, start work on notification system --- deps.ts | 2 - src/buttons/live-event/updateEvent.ts | 2 +- src/db.ts | 5 +- src/events/ready.ts | 72 +++++++++++++++++++-------- src/notificationSystem.ts | 2 + src/types/commandTypes.ts | 10 ++++ 6 files changed, 69 insertions(+), 24 deletions(-) create mode 100644 src/notificationSystem.ts diff --git a/deps.ts b/deps.ts index eab28a7..f1a0c59 100644 --- a/deps.ts +++ b/deps.ts @@ -16,8 +16,6 @@ export { ButtonStyles, ChannelTypes, createBot, - editBotMember, - editBotStatus, getBotIdFromToken, Intents, InteractionResponseTypes, diff --git a/src/buttons/live-event/updateEvent.ts b/src/buttons/live-event/updateEvent.ts index ef23102..6f432b5 100644 --- a/src/buttons/live-event/updateEvent.ts +++ b/src/buttons/live-event/updateEvent.ts @@ -33,7 +33,7 @@ const execute = async (bot: Bot, interaction: Interaction) => { }); bot.helpers.editMessage(evtChannelId, evtMessageId, { embeds: [interaction.message.embeds[0]] }).then(() => { - dbClient.execute(queries.updateEvent, [eventTime, evtChannelId, evtMessageId]).then(() => { + dbClient.execute(queries.updateEventTime, [eventTime, evtChannelId, evtMessageId]).then(() => { // Acknowledge user so discord doesn't get annoyed bot.helpers.sendInteractionResponse(interaction.id, interaction.token, { type: InteractionResponseTypes.ChannelMessageWithSource, diff --git a/src/db.ts b/src/db.ts index a9926d3..f68d9b6 100644 --- a/src/db.ts +++ b/src/db.ts @@ -13,8 +13,11 @@ export const dbClient = await new Client().connect({ export const queries = { callIncCnt: (cmdName: string) => `CALL INC_CNT("${cmdName}");`, + selectEvents: (notifiedFlag: number, lockedFlag: number) => `SELECT * FROM active_events WHERE notifiedFlag = ${notifiedFlag} AND lockedFlag = ${lockedFlag} AND eventTime < ?`, + selectFailedEvents: 'SELECT * FROM active_events WHERE (notifiedFlag = -1 OR lockedFlag = -1) AND eventTime < ?', insertEvent: 'INSERT INTO active_events(messageId,channelId,guildId,ownerId,eventTime) values(?,?,?,?,?)', - updateEvent: 'UPDATE active_events SET eventTime = ? WHERE channelId = ? AND messageId = ?', + updateEventTime: 'UPDATE active_events SET eventTime = ? WHERE channelId = ? AND messageId = ?', + updateEventFlags: (notifiedFlag: number, lockedFlag: number) => `UPDATE active_events SET notifiedFlag = ${notifiedFlag} AND lockedFlag = ${lockedFlag} WHERE channelId = ? AND messageId = ?`, deleteEvent: 'DELETE FROM active_events WHERE channelId = ? AND messageId = ?', }; diff --git a/src/events/ready.ts b/src/events/ready.ts index 38daa0d..054c339 100644 --- a/src/events/ready.ts +++ b/src/events/ready.ts @@ -1,50 +1,82 @@ import config from '../../config.ts'; import { LOCALMODE } from '../../flags.ts'; -import { ActivityTypes, Bot, BotWithCache, editBotMember, editBotStatus, log, LT } from '../../deps.ts'; +import { ActivityTypes, Bot, BotWithCache, log, LT } from '../../deps.ts'; import { getRandomStatus, successColor } from '../commandUtils.ts'; +import { ActiveEvent } from '../types/commandTypes.ts'; import utils from '../utils.ts'; +import { dbClient, queries } from '../db.ts'; + +const tenMinutes = 10 * 60 * 1000; + +// Storing intervalIds in case bot soft reboots to prevent multiple of these intervals from stacking +let notificationIntervalId: number; +let botStatusIntervalId: number; export const ready = (rawBot: Bot) => { const bot = rawBot as BotWithCache; log(LT.INFO, `${config.name} Logged in!`); - editBotStatus(bot, { + bot.helpers.editBotStatus({ activities: [{ name: 'Booting up . . .', type: ActivityTypes.Game, createdAt: new Date().getTime(), }], status: 'online', - }); + }).catch((e) => log(LT.ERROR, `Failed to update status (booting): ${utils.jsonStringifyBig(e)}`)); // Interval to rotate the status text every 30 seconds to show off more commands - setInterval(async () => { + if (botStatusIntervalId) clearInterval(botStatusIntervalId); + botStatusIntervalId = setInterval(async () => { log(LT.LOG, 'Changing bot status'); - try { - // Wrapped in try-catch due to hard crash possible - editBotStatus(bot, { - activities: [{ - name: getRandomStatus(bot.guilds.size + bot.dispatchedGuildIds.size), - type: ActivityTypes.Game, - createdAt: new Date().getTime(), - }], - status: 'online', - }); - } catch (e) { - log(LT.ERROR, `Failed to update status: ${utils.jsonStringifyBig(e)}`); - } + bot.helpers.editBotStatus({ + activities: [{ + name: getRandomStatus(bot.guilds.size + bot.dispatchedGuildIds.size), + type: ActivityTypes.Game, + createdAt: new Date().getTime(), + }], + status: 'online', + }).catch((e) => log(LT.ERROR, `Failed to update status (in interval): ${utils.jsonStringifyBig(e)}`)); }, 30000); + // Interval to handle event notifications and cleanup every minute + if (notificationIntervalId) clearInterval(notificationIntervalId); + notificationIntervalId = setInterval(() => { + const now = new Date().getTime(); + + // Notify Members of Events + dbClient.execute(queries.selectEvents(0, 0), [new Date(now + tenMinutes)]).then((events) => events.rows?.forEach((event) => console.log(event as ActiveEvent))).catch((e) => + utils.commonLoggers.dbError('ready.ts@notifyMembers', 'SELECT events from', e) + ); + + // // Notify Alternates of Events (if NOT full) and lock the event message + // dbClient.execute(queries.selectEvents(1, 0), [new Date(now)]).then((events) => console.log(events.rows as ActiveEvent[])).catch((e) => + // utils.commonLoggers.dbError('ready.ts@notifyAlternates', 'SELECT events from', e) + // ); + + // // Delete the event + // dbClient.execute(queries.selectEvents(1, 1), [new Date(now - tenMinutes)]).then((events) => console.log(events.rows as ActiveEvent[])).catch((e) => + // utils.commonLoggers.dbError('ready.ts@deleteEvent', 'SELECT events from', e) + // ); + + // // Handle events that failed at some point + // dbClient.execute(queries.selectFailedEvents, [new Date(now + tenMinutes)]).then((events) => console.log(events.rows as ActiveEvent[])).catch((e) => + // utils.commonLoggers.dbError('ready.ts@deleteEvent', 'SELECT events from', e) + // ); + }, 60000); + // setTimeout added to make sure the startup message does not error out setTimeout(() => { - LOCALMODE && editBotMember(bot, config.devServer, { nick: `LOCAL - ${config.name}` }); - editBotStatus(bot, { + LOCALMODE && bot.helpers.editBotMember(config.devServer, { nick: `LOCAL - ${config.name}` }); + + bot.helpers.editBotStatus({ activities: [{ name: 'Booting Complete', type: ActivityTypes.Game, createdAt: new Date().getTime(), }], status: 'online', - }); + }).catch((e) => log(LT.ERROR, `Failed to update status (boot complete): ${utils.jsonStringifyBig(e)}`)); + bot.helpers.sendMessage(config.logChannel, { embeds: [{ title: `${config.name} is now Online`, diff --git a/src/notificationSystem.ts b/src/notificationSystem.ts new file mode 100644 index 0000000..bf994be --- /dev/null +++ b/src/notificationSystem.ts @@ -0,0 +1,2 @@ +// define functions that take db data and do actions on it +// in ready, call db select to create a to do list and send it here in dbclient.execute().then(FUNC FROM THIS FILE).catch() diff --git a/src/types/commandTypes.ts b/src/types/commandTypes.ts index b0117de..db518a5 100644 --- a/src/types/commandTypes.ts +++ b/src/types/commandTypes.ts @@ -43,3 +43,13 @@ export type UrlIds = { channelId: bigint; messageId: bigint; }; + +export type ActiveEvent = { + messageId: bigint; + channelId: bigint; + guildId: bigint; + ownerId: bigint; + eventTime: Date; + notifiedFlag: number; + lockedFlag: number; +};