AeThex-Bot-Master/aethex-bot/utils/cooldownManager.js
sirpiglr 467fd8467f Add command cooldown management to the dashboard interface
Implement new API endpoints and UI elements for managing command cooldowns, including setting, listing, and resetting them. Also, refactor cooldown cache invalidation logic to resolve circular dependency issues.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: aed2e46d-25bb-4b73-81a1-bb9e8437c261
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 10157b12-ee9f-4185-90e0-2ab9db23a6da
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3bdfff67-975a-46ad-9845-fbb6b4a4c4b5/aed2e46d-25bb-4b73-81a1-bb9e8437c261/bakeZwZ
Replit-Helium-Checkpoint-Created: true
2025-12-12 23:53:31 +00:00

145 lines
3.4 KiB
JavaScript

const DEFAULT_COOLDOWNS = {
work: 3600,
daily: 72000,
slots: 60,
coinflip: 30,
rep: 43200,
trivia: 30,
heist: 1800,
duel: 300,
gift: 60,
trade: 60
};
const userCooldowns = new Map();
const cooldownCache = new Map();
const CACHE_TTL = 5 * 60 * 1000;
async function getCommandCooldown(supabase, guildId, commandName) {
if (!supabase) {
return DEFAULT_COOLDOWNS[commandName] || 0;
}
const cacheKey = `${guildId}-${commandName}`;
const cached = cooldownCache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.value;
}
try {
const { data } = await supabase
.from('command_cooldowns')
.select('cooldown_seconds')
.eq('guild_id', guildId)
.eq('command_name', commandName)
.maybeSingle();
const cooldown = data?.cooldown_seconds ?? DEFAULT_COOLDOWNS[commandName] ?? 0;
cooldownCache.set(cacheKey, { value: cooldown, timestamp: Date.now() });
return cooldown;
} catch (error) {
console.error('Failed to fetch cooldown:', error.message);
return DEFAULT_COOLDOWNS[commandName] || 0;
}
}
function getCooldownKey(guildId, userId, commandName) {
return `${guildId}-${userId}-${commandName}`;
}
function getUserCooldown(guildId, userId, commandName) {
const key = getCooldownKey(guildId, userId, commandName);
return userCooldowns.get(key);
}
function setUserCooldown(guildId, userId, commandName) {
const key = getCooldownKey(guildId, userId, commandName);
userCooldowns.set(key, Date.now());
}
function clearUserCooldown(guildId, userId, commandName) {
const key = getCooldownKey(guildId, userId, commandName);
userCooldowns.delete(key);
}
async function checkCooldown(supabase, guildId, userId, commandName) {
const cooldownSeconds = await getCommandCooldown(supabase, guildId, commandName);
if (cooldownSeconds === 0) {
return { onCooldown: false, cooldownSeconds: 0 };
}
const cooldownMs = cooldownSeconds * 1000;
const lastUsed = getUserCooldown(guildId, userId, commandName);
if (!lastUsed) {
return { onCooldown: false, cooldownSeconds };
}
const elapsed = Date.now() - lastUsed;
const remaining = cooldownMs - elapsed;
if (remaining <= 0) {
return { onCooldown: false, cooldownSeconds };
}
return {
onCooldown: true,
remaining: remaining,
remainingSeconds: Math.ceil(remaining / 1000),
cooldownSeconds
};
}
function formatCooldownRemaining(remainingMs) {
const seconds = Math.ceil(remainingMs / 1000);
if (seconds < 60) {
return `${seconds}s`;
}
const minutes = Math.floor(seconds / 60);
const secs = seconds % 60;
if (minutes < 60) {
return secs > 0 ? `${minutes}m ${secs}s` : `${minutes}m`;
}
const hours = Math.floor(minutes / 60);
const mins = minutes % 60;
if (hours < 24) {
return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
}
const days = Math.floor(hours / 24);
const hrs = hours % 24;
return hrs > 0 ? `${days}d ${hrs}h` : `${days}d`;
}
function invalidateCooldownCache(guildId, commandName = null) {
if (commandName) {
cooldownCache.delete(`${guildId}-${commandName}`);
} else {
for (const key of cooldownCache.keys()) {
if (key.startsWith(`${guildId}-`)) {
cooldownCache.delete(key);
}
}
}
}
module.exports = {
getCommandCooldown,
getUserCooldown,
setUserCooldown,
clearUserCooldown,
checkCooldown,
formatCooldownRemaining,
invalidateCooldownCache,
DEFAULT_COOLDOWNS
};