feat(services): implement periodic booster role cleanup

Add a new `boostCleanupService` to periodically scan guilds and remove
custom booster roles and database records for members who are no longer
eligible (e.g., lost boost status or left the server). This ensures
data consistency even if the bot was offline during status changes.

- Implement `startBoostCleanup` with configurable intervals
- Add `findByGuild` to `BoosterRoleStore` for batch processing
- Update `DrizzleBoosterRoleStore` to support guild-based lookups
- Add configuration for `boostCleanupIntervalMs`
This commit is contained in:
MythEclipse
2026-06-06 02:46:38 +07:00
parent 01450d976c
commit 57699d60a8
6 changed files with 142 additions and 7 deletions
+21 -1
View File
@@ -1,7 +1,11 @@
import { loadConfig } from "./config";
import { createDb } from "./db";
import { attachBotHandlers } from "./discord/bot";
import { createDiscordClient } from "./discord/client";
import { registerGuildCommandsWithToken } from "./discord/registerCommands";
import { startBoostCleanup } from "./services/boostCleanupService";
import { DiscordRoleRepository } from "./services/discordRoleRepository";
import { DrizzleBoosterRoleStore } from "./services/drizzleBoosterRoleStore";
import { logger } from "./logger";
const config = loadConfig();
@@ -13,11 +17,27 @@ await registerGuildCommandsWithToken(config.discordToken, {
logger.info("Guild commands registered", { guildId: config.discordGuildId });
const client = createDiscordClient();
attachBotHandlers(client, config);
const db = createDb(config.databaseUrl);
const store = new DrizzleBoosterRoleStore(db);
client.once("clientReady", () => {
logger.info("Discord client ready", { bot: client.user?.tag ?? "unknown bot" });
// Start periodic cleanup for boost ends missed during downtime
startBoostCleanup(
client,
store,
(guild) => new DiscordRoleRepository(guild, config.boosterRoleAnchorRoleId),
{
intervalMs: config.boostCleanupIntervalMs,
boosterEligibilityRoleId: config.boosterEligibilityRoleId,
anchorRoleId: config.boosterRoleAnchorRoleId,
},
);
logger.info("Boost cleanup started", { intervalMs: config.boostCleanupIntervalMs });
});
attachBotHandlers(client, config);
logger.info("Logging in Discord client");
await client.login(config.discordToken);