feat: Add /cleanup admin command and enhance lootdrop cleanup service to optionally include claimed items.

This commit is contained in:
syntaxbullet
2026-01-06 19:27:41 +01:00
parent 2e6bdec38c
commit b989e807dc
2 changed files with 60 additions and 7 deletions

View File

@@ -0,0 +1,45 @@
import { createCommand } from "@lib/utils";
import { SlashCommandBuilder, PermissionFlagsBits } from "discord.js";
import { lootdropService } from "@/modules/economy/lootdrop.service";
import { createBaseEmbed } from "@lib/embeds";
export const cleanup = createCommand({
data: new SlashCommandBuilder()
.setName("cleanup")
.setDescription("Manually trigger cleanup tasks")
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
.addStringOption(option =>
option.setName("type")
.setDescription("The type of cleanup to perform")
.setRequired(true)
.addChoices(
{ name: 'Lootdrops', value: 'lootdrops' }
)
)
.addBooleanOption(option =>
option.setName("include_claimed")
.setDescription("Whether to cleanup claimed lootdrops as well (only for lootdrops type)")
.setRequired(false)
),
execute: async (interaction) => {
await interaction.deferReply({ ephemeral: true });
const type = interaction.options.getString("type", true);
const includeClaimed = interaction.options.getBoolean("include_claimed") || false;
try {
let count = 0;
if (type === 'lootdrops') {
count = await lootdropService.cleanupExpiredLootdrops(includeClaimed);
}
const embed = createBaseEmbed("Cleanup Complete")
.setDescription(`Successfully executed cleanup for **${type}**.\nDeleted **${count}** records. ${includeClaimed ? "\n(Included claimed items)" : ""}`);
await interaction.editReply({ embeds: [embed] });
} catch (error) {
console.error("Cleanup failed:", error);
await interaction.editReply({ content: "❌ An error occurred while performing cleanup." });
}
}
});

View File

@@ -27,7 +27,7 @@ class LootdropService {
// Cleanup interval for activity tracking and expired lootdrops
setInterval(() => {
this.cleanupActivity();
this.cleanupExpiredLootdrops();
this.cleanupExpiredLootdrops(true);
}, 60000);
}
@@ -45,16 +45,24 @@ class LootdropService {
}
}
private async cleanupExpiredLootdrops() {
public async cleanupExpiredLootdrops(includeClaimed: boolean = false): Promise<number> {
try {
const now = new Date();
await DrizzleClient.delete(lootdrops)
.where(and(
isNull(lootdrops.claimedBy),
lt(lootdrops.expiresAt, now)
));
const whereClause = includeClaimed
? lt(lootdrops.expiresAt, now)
: and(isNull(lootdrops.claimedBy), lt(lootdrops.expiresAt, now));
const result = await DrizzleClient.delete(lootdrops)
.where(whereClause)
.returning();
if (result.length > 0) {
console.log(`[LootdropService] Cleaned up ${result.length} expired lootdrops.`);
}
return result.length;
} catch (error) {
console.error("Failed to cleanup lootdrops:", error);
return 0;
}
}