From de8bef6520d53a1299f0478458320a7eb75c5e1d Mon Sep 17 00:00:00 2001 From: PalmDevs Date: Mon, 5 Aug 2024 00:40:36 +0700 Subject: [PATCH] fix(bots/discord): correct sticky messages logic --- bots/discord/src/context.ts | 17 +++++++--- .../messageCreate/stickyMessageReset.ts | 29 ++++++++++------ bots/discord/src/events/discord/ready.ts | 34 +++++++++++++------ 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/bots/discord/src/context.ts b/bots/discord/src/context.ts index 622ff6d..6623773 100644 --- a/bots/discord/src/context.ts +++ b/bots/discord/src/context.ts @@ -90,13 +90,20 @@ export const discord = { Record< string, { - forceSendTimerActive?: boolean - timeoutMs: number - forceSendMs?: number + /** + * Chat is active, so force send timer is also active + */ + forceTimerActive: boolean + /** + * There was a message sent, so the timer is active + */ + timerActive: boolean + timerMs: number + forceTimerMs?: number send: (forced?: boolean) => Promise currentMessage?: Message - interval?: NodeJS.Timeout - forceSendInterval?: NodeJS.Timeout + timer?: NodeJS.Timeout + forceTimer?: NodeJS.Timeout } > >, diff --git a/bots/discord/src/events/discord/messageCreate/stickyMessageReset.ts b/bots/discord/src/events/discord/messageCreate/stickyMessageReset.ts index 0183c14..e0104ac 100644 --- a/bots/discord/src/events/discord/messageCreate/stickyMessageReset.ts +++ b/bots/discord/src/events/discord/messageCreate/stickyMessageReset.ts @@ -7,24 +7,31 @@ withContext(on, 'messageCreate', async ({ discord, logger }, msg) => { const store = discord.stickyMessages[msg.guildId]?.[msg.channelId] if (!store) return - if (!store.interval) store.interval = setTimeout(store.send, store.timeoutMs) as NodeJS.Timeout + // If there isn't a timer, start it up + store.timerActive = true + if (!store.timer) store.timer = setTimeout(store.send, store.timerMs) as NodeJS.Timeout else { - store.interval.refresh() + // If there is a timer, but it isn't active, restart it + if (!store.timerActive) store.timer.refresh() + // If there is a timer and it is active, but the force timer isn't active... + else if (!store.forceTimerActive && store.forceTimerMs) { + logger.debug(`Channel ${msg.channelId} in guild ${msg.guildId} is active, starting force send timer and clearing existing timer`) - if (!store.forceSendTimerActive && store.forceSendMs) { - logger.debug(`Channel ${msg.channelId} in guild ${msg.guildId} is active, starting force send timer`) + // Clear the timer + clearTimeout(store.timer) + store.timerActive = false + store.forceTimerActive = true - store.forceSendTimerActive = true - - if (!store.forceSendInterval) - store.forceSendInterval = setTimeout( + // (Re)start the force timer + if (!store.forceTimer) + store.forceTimer = setTimeout( () => store.send(true).then(() => { - store.forceSendTimerActive = false + store.forceTimerActive = false }), - store.forceSendMs, + store.forceTimerMs, ) as NodeJS.Timeout - else store.forceSendInterval.refresh() + else store.forceTimer.refresh() } } }) diff --git a/bots/discord/src/events/discord/ready.ts b/bots/discord/src/events/discord/ready.ts index 3e21af1..f4f6dd9 100644 --- a/bots/discord/src/events/discord/ready.ts +++ b/bots/discord/src/events/discord/ready.ts @@ -14,11 +14,16 @@ export default withContext(on, 'ready', async ({ config, discord, logger }, clie if (config.stickyMessages) for (const [guildId, channels] of Object.entries(config.stickyMessages)) { const guild = await client.guilds.fetch(guildId) + // In case of configuration refresh, this will not be nullable + const oldStore = discord.stickyMessages[guildId] discord.stickyMessages[guildId] = {} for (const [channelId, { message, timeout, forceSendTimeout }] of Object.entries(channels)) { const channel = await guild.channels.fetch(channelId) - if (!channel?.isTextBased()) return + if (!channel?.isTextBased()) + return void logger.warn( + `Channel ${channelId} in guild ${guildId} is not a text channel, sticky messages will not be sent`, + ) const send = async (forced = false) => { try { @@ -33,17 +38,19 @@ export default withContext(on, 'ready', async ({ config, discord, logger }, clie await store.currentMessage?.delete().catch() store.currentMessage = msg - if (!forced) { - clearTimeout(store.forceSendInterval) + // Clear any remaining timers + clearTimeout(store.timer) + clearTimeout(store.forceTimer) + store.forceTimerActive = store.timerActive = false + + if (!forced) logger.debug( `Timeout ended for sticky message in channel ${channelId} in guild ${guildId}, channel is inactive`, ) - } else { - clearTimeout(store.interval) + else logger.debug( `Forced send timeout for sticky message in channel ${channelId} in guild ${guildId} ended, channel is too active`, ) - } logger.debug(`Sent sticky message to channel ${channelId} in guild ${guildId}`) } catch (e) { @@ -53,13 +60,20 @@ export default withContext(on, 'ready', async ({ config, discord, logger }, clie ) } } - + + // Set up the store discord.stickyMessages[guildId]![channelId] = { - forceSendMs: forceSendTimeout, - timeoutMs: timeout, + forceTimerActive: false, + timerActive: false, + forceTimerMs: forceSendTimeout, + timerMs: timeout, send, - forceSendTimerActive: false, + // If the store exists before the configuration refresh, take its current message + currentMessage: oldStore?.[channelId]?.currentMessage } + + // Send a new sticky message immediately, as well as deleting the old/outdated message, if it exists + await send() } }