Centralize periodic checks for mutes, tempbans, vcalerts, reminders, and scheduled posts
This should result in a significant performance improvement. The new method is also more precise than the old one, allowing the aforementioned checks to be performed with second-precision.
This commit is contained in:
parent
c84d1a0be1
commit
c7751a9da1
55 changed files with 883 additions and 366 deletions
|
@ -6,7 +6,8 @@ import { RemindCmd } from "./commands/RemindCmd";
|
|||
import { RemindersCmd } from "./commands/RemindersCmd";
|
||||
import { RemindersDeleteCmd } from "./commands/RemindersDeleteCmd";
|
||||
import { ConfigSchema, RemindersPluginType } from "./types";
|
||||
import { postDueRemindersLoop } from "./utils/postDueRemindersLoop";
|
||||
import { onGuildEvent } from "../../data/GuildEvents";
|
||||
import { postReminder } from "./functions/postReminder";
|
||||
|
||||
const defaultOptions: PluginOptions<RemindersPluginType> = {
|
||||
config: {
|
||||
|
@ -46,16 +47,16 @@ export const RemindersPlugin = zeppelinGuildPlugin<RemindersPluginType>()({
|
|||
state.reminders = GuildReminders.getGuildInstance(guild.id);
|
||||
state.tries = new Map();
|
||||
state.unloaded = false;
|
||||
|
||||
state.postRemindersTimeout = null;
|
||||
},
|
||||
|
||||
afterLoad(pluginData) {
|
||||
postDueRemindersLoop(pluginData);
|
||||
pluginData.state.unregisterGuildEventListener = onGuildEvent(pluginData.guild.id, "reminder", (reminder) =>
|
||||
postReminder(pluginData, reminder),
|
||||
);
|
||||
},
|
||||
|
||||
beforeUnload(pluginData) {
|
||||
clearTimeout(pluginData.state.postRemindersTimeout);
|
||||
pluginData.state.unregisterGuildEventListener();
|
||||
pluginData.state.unloaded = true;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@ import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
|||
import { convertDelayStringToMS, messageLink } from "../../../utils";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
import { remindersCmd } from "../types";
|
||||
import { registerUpcomingReminder } from "../../../data/loops/upcomingRemindersLoop";
|
||||
|
||||
export const RemindCmd = remindersCmd({
|
||||
trigger: ["remind", "remindme", "reminder"],
|
||||
|
@ -50,7 +51,7 @@ export const RemindCmd = remindersCmd({
|
|||
}
|
||||
|
||||
const reminderBody = args.reminder || messageLink(pluginData.guild.id, msg.channel.id, msg.id);
|
||||
await pluginData.state.reminders.add(
|
||||
const reminder = await pluginData.state.reminders.add(
|
||||
msg.author.id,
|
||||
msg.channel.id,
|
||||
reminderTime.clone().tz("Etc/UTC").format("YYYY-MM-DD HH:mm:ss"),
|
||||
|
@ -58,6 +59,8 @@ export const RemindCmd = remindersCmd({
|
|||
moment.utc().format("YYYY-MM-DD HH:mm:ss"),
|
||||
);
|
||||
|
||||
registerUpcomingReminder(reminder);
|
||||
|
||||
const msUntilReminder = reminderTime.diff(now);
|
||||
const timeUntilReminder = humanizeDuration(msUntilReminder, { largest: 2, round: true });
|
||||
const prettyReminderTime = (await timeAndDate.inMemberTz(msg.author.id, reminderTime)).format(
|
||||
|
|
|
@ -2,6 +2,7 @@ import { commandTypeHelpers as ct } from "../../../commandTypes";
|
|||
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
||||
import { sorter } from "../../../utils";
|
||||
import { remindersCmd } from "../types";
|
||||
import { clearUpcomingReminder } from "../../../data/loops/upcomingRemindersLoop";
|
||||
|
||||
export const RemindersDeleteCmd = remindersCmd({
|
||||
trigger: ["reminders delete", "reminders d"],
|
||||
|
@ -21,6 +22,7 @@ export const RemindersDeleteCmd = remindersCmd({
|
|||
}
|
||||
|
||||
const toDelete = reminders[args.num - 1];
|
||||
clearUpcomingReminder(toDelete);
|
||||
await pluginData.state.reminders.delete(toDelete.id);
|
||||
|
||||
sendSuccessMessage(pluginData, msg.channel, "Reminder deleted");
|
||||
|
|
41
backend/src/plugins/Reminders/functions/postReminder.ts
Normal file
41
backend/src/plugins/Reminders/functions/postReminder.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
import { GuildPluginData } from "knub";
|
||||
import { RemindersPluginType } from "../types";
|
||||
import { Reminder } from "../../../data/entities/Reminder";
|
||||
import { Snowflake, TextChannel } from "discord.js";
|
||||
import moment from "moment-timezone";
|
||||
import { disableLinkPreviews } from "knub/dist/helpers";
|
||||
import { DBDateFormat, SECONDS } from "../../../utils";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
|
||||
export async function postReminder(pluginData: GuildPluginData<RemindersPluginType>, reminder: Reminder) {
|
||||
const channel = pluginData.guild.channels.cache.get(reminder.channel_id as Snowflake);
|
||||
if (channel && (channel.isText() || channel.isThread())) {
|
||||
try {
|
||||
// Only show created at date if one exists
|
||||
if (moment.utc(reminder.created_at).isValid()) {
|
||||
const createdAtTS = Math.floor(moment.utc(reminder.created_at, DBDateFormat).valueOf() / 1000);
|
||||
await channel.send({
|
||||
content: disableLinkPreviews(
|
||||
`Reminder for <@!${reminder.user_id}>: ${reminder.body} \nSet <t:${createdAtTS}:R>`,
|
||||
),
|
||||
allowedMentions: {
|
||||
users: [reminder.user_id as Snowflake],
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await channel.send({
|
||||
content: disableLinkPreviews(`Reminder for <@!${reminder.user_id}>: ${reminder.body}`),
|
||||
allowedMentions: {
|
||||
users: [reminder.user_id as Snowflake],
|
||||
},
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
// If we were unable to post the reminder, we'll try again later
|
||||
console.warn(`Error when posting reminder for ${reminder.user_id} in guild ${reminder.guild_id}: ${String(err)}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await pluginData.state.reminders.delete(reminder.id);
|
||||
}
|
|
@ -14,7 +14,8 @@ export interface RemindersPluginType extends BasePluginType {
|
|||
reminders: GuildReminders;
|
||||
tries: Map<number, number>;
|
||||
|
||||
postRemindersTimeout;
|
||||
unregisterGuildEventListener: () => void;
|
||||
|
||||
unloaded: boolean;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
import { Snowflake, TextChannel } from "discord.js";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import { GuildPluginData } from "knub";
|
||||
import { disableLinkPreviews } from "knub/dist/helpers";
|
||||
import moment from "moment-timezone";
|
||||
import { SECONDS } from "../../../utils";
|
||||
import { RemindersPluginType } from "../types";
|
||||
|
||||
const REMINDER_LOOP_TIME = 10 * SECONDS;
|
||||
const MAX_TRIES = 3;
|
||||
|
||||
export async function postDueRemindersLoop(pluginData: GuildPluginData<RemindersPluginType>) {
|
||||
const pendingReminders = await pluginData.state.reminders.getDueReminders();
|
||||
for (const reminder of pendingReminders) {
|
||||
const channel = pluginData.guild.channels.cache.get(reminder.channel_id as Snowflake);
|
||||
if (channel && channel instanceof TextChannel) {
|
||||
try {
|
||||
// Only show created at date if one exists
|
||||
if (moment.utc(reminder.created_at).isValid()) {
|
||||
const target = moment.utc();
|
||||
const diff = target.diff(moment.utc(reminder.created_at, "YYYY-MM-DD HH:mm:ss"));
|
||||
const result = humanizeDuration(diff, { largest: 2, round: true });
|
||||
await channel.send({
|
||||
content: disableLinkPreviews(
|
||||
`Reminder for <@!${reminder.user_id}>: ${reminder.body} \n\`Set at ${reminder.created_at} (${result} ago)\``,
|
||||
),
|
||||
allowedMentions: {
|
||||
users: [reminder.user_id as Snowflake],
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await channel.send({
|
||||
content: disableLinkPreviews(`Reminder for <@!${reminder.user_id}>: ${reminder.body}`),
|
||||
allowedMentions: {
|
||||
users: [reminder.user_id as Snowflake],
|
||||
},
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
// Probably random Discord internal server error or missing permissions or somesuch
|
||||
// Try again next round unless we've already tried to post this a bunch of times
|
||||
const tries = pluginData.state.tries.get(reminder.id) || 0;
|
||||
if (tries < MAX_TRIES) {
|
||||
pluginData.state.tries.set(reminder.id, tries + 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await pluginData.state.reminders.delete(reminder.id);
|
||||
}
|
||||
|
||||
if (!pluginData.state.unloaded) {
|
||||
pluginData.state.postRemindersTimeout = setTimeout(() => postDueRemindersLoop(pluginData), REMINDER_LOOP_TIME);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue