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
145 lines
3.4 KiB
JavaScript
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
|
|
};
|