import { Snowflake, TextChannel, User } from "discord.js"; import { GuildPluginData } from "knub"; import moment from "moment-timezone"; import { channelToTemplateSafeChannel, userToTemplateSafeUser } from "../../../utils/templateSafeObjects"; import { LogType } from "../../../data/LogType"; import { logger } from "../../../logger"; import { DBDateFormat, SECONDS, verboseChannelMention, verboseUserMention } from "../../../utils"; import { PostPluginType } from "../types"; import { postMessage } from "./postMessage"; import { LogsPlugin } from "../../Logs/LogsPlugin"; const SCHEDULED_POST_CHECK_INTERVAL = 5 * SECONDS; export async function scheduledPostLoop(pluginData: GuildPluginData) { const duePosts = await pluginData.state.scheduledPosts.getDueScheduledPosts(); for (const post of duePosts) { const channel = pluginData.guild.channels.cache.get(post.channel_id as Snowflake); if (channel instanceof TextChannel) { const [username, discriminator] = post.author_name.split("#"); const author: User = (await pluginData.client.users.fetch(post.author_id as Snowflake)) || { id: post.author_id, username, discriminator, }; try { const postedMessage = await postMessage( pluginData, channel, post.content, post.attachments, post.enable_mentions, ); pluginData.getPlugin(LogsPlugin).logPostedScheduledMessage({ author, channel, messageId: postedMessage.id, }); } catch { pluginData.getPlugin(LogsPlugin).logBotAlert({ body: `Failed to post scheduled message by ${verboseUserMention(author)} to ${verboseChannelMention( channel, )}`, }); logger.warn( `Failed to post scheduled message to #${channel.name} (${channel.id}) on ${pluginData.guild.name} (${pluginData.guild.id})`, ); } } let shouldClear = true; if (post.repeat_interval) { const nextPostAt = moment.utc().add(post.repeat_interval, "ms"); if (post.repeat_until) { const repeatUntil = moment.utc(post.repeat_until, DBDateFormat); if (nextPostAt.isSameOrBefore(repeatUntil)) { await pluginData.state.scheduledPosts.update(post.id, { post_at: nextPostAt.format(DBDateFormat), }); shouldClear = false; } } else if (post.repeat_times) { if (post.repeat_times > 1) { await pluginData.state.scheduledPosts.update(post.id, { post_at: nextPostAt.format(DBDateFormat), repeat_times: post.repeat_times - 1, }); shouldClear = false; } } } if (shouldClear) { await pluginData.state.scheduledPosts.delete(post.id); } } pluginData.state.scheduledPostLoopTimeout = setTimeout( () => scheduledPostLoop(pluginData), SCHEDULED_POST_CHECK_INTERVAL, ); }