feat: Add /cleanup admin command and enhance lootdrop cleanup service to optionally include claimed items.
This commit is contained in:
45
src/commands/admin/cleanup.ts
Normal file
45
src/commands/admin/cleanup.ts
Normal 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." });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -27,7 +27,7 @@ class LootdropService {
|
|||||||
// Cleanup interval for activity tracking and expired lootdrops
|
// Cleanup interval for activity tracking and expired lootdrops
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
this.cleanupActivity();
|
this.cleanupActivity();
|
||||||
this.cleanupExpiredLootdrops();
|
this.cleanupExpiredLootdrops(true);
|
||||||
}, 60000);
|
}, 60000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,16 +45,24 @@ class LootdropService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async cleanupExpiredLootdrops() {
|
public async cleanupExpiredLootdrops(includeClaimed: boolean = false): Promise<number> {
|
||||||
try {
|
try {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
await DrizzleClient.delete(lootdrops)
|
const whereClause = includeClaimed
|
||||||
.where(and(
|
? lt(lootdrops.expiresAt, now)
|
||||||
isNull(lootdrops.claimedBy),
|
: and(isNull(lootdrops.claimedBy), lt(lootdrops.expiresAt, now));
|
||||||
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) {
|
} catch (error) {
|
||||||
console.error("Failed to cleanup lootdrops:", error);
|
console.error("Failed to cleanup lootdrops:", error);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user