Discord机器人!corona命令全局冷却与错误输入免冷却改造需求
Hey there! Let's tackle those two optimizations for your Discord bot's !corona command step by step. Both changes are straightforward to implement—here's how to do it:
1. Skip Cooldown on Invalid Country Input
The core idea here is to only trigger the cooldown when the API call succeeds, not when it fails (i.e., when the country isn't found). We'll move the cooldown activation logic inside the .then() block instead of running it unconditionally.
2. Switch from Per-User to Global Cooldown
Instead of tracking cooldowns per user ID, we'll use a single global variable to track when the command can be used next by anyone. This ensures all users have to wait 1 minute after someone uses the command.
Modified Full Code (with Both Fixes)
Let's assume you're using a custom cooldown system (adjust if you're using discord.js's built-in CooldownManager):
// Global cooldown variable (tracks the timestamp when the command can be used again) let coronaGlobalCooldown = 0; const COOLDOWN_DURATION = 60 * 1000; // 1 minute in milliseconds client.on('messageCreate', async (message) => { if (!message.content.startsWith('!corona')) return; // Check global cooldown first const now = Date.now(); if (now < coronaGlobalCooldown) { const timeLeft = Math.ceil((coronaGlobalCooldown - now) / 1000); return message.reply(`Please wait ${timeLeft} second(s) before using this command again.`); } const country = message.content.slice('!corona'.length).trim(); // Your API call logic here fetch(`https://your-corona-api-url.com/country/${country}`) .then(response => response.json()) .then(data => { // Process and send the corona data to the channel message.channel.send(`Corona stats for ${country}: Cases: ${data.cases}, Deaths: ${data.deaths}`); // Activate global cooldown ONLY after successful API call coronaGlobalCooldown = now + COOLDOWN_DURATION; }) .catch(() => { // No cooldown here—let the user retry immediately message.reply("I couldn't find the country you are looking for, be careful not to use Turkish letters when writing the country. You can also write country abbreviations (ex: TR, USA, AZ)"); }); });
Key Changes Explained
- Global Cooldown: We replaced per-user tracking with
coronaGlobalCooldown, a single variable that stores the timestamp when the command becomes available again. Every user checks this same variable before using the command. - Conditional Cooldown Activation: The cooldown is only set inside the
.then()block (after a successful API response). If thecatch()block runs (invalid country), we don't update the cooldown, so the user can retry right away.
If you were using discord.js's built-in CooldownManager, you'd adjust it to use a global key instead of user IDs. For example:
const cooldowns = new Discord.Collection(); // Inside the command handler: const commandName = 'corona'; const cooldownKey = 'global-corona'; // Use a fixed key instead of message.author.id if (!cooldowns.has(cooldownKey)) { cooldowns.set(cooldownKey, new Discord.Collection()); } const now = Date.now(); const timestamps = cooldowns.get(cooldownKey); const cooldownAmount = 60 * 1000; if (timestamps.has('global')) { const expirationTime = timestamps.get('global') + cooldownAmount; if (now < expirationTime) { const timeLeft = Math.ceil((expirationTime - now) / 1000); return message.reply(`Please wait ${timeLeft} second(s) before using this command again.`); } } // Then, in the .then() block: timestamps.set('global', now); setTimeout(() => timestamps.delete('global'), cooldownAmount);
Either approach will get you the behavior you want. Let me know if you need help adapting this to your exact code setup!
内容的提问来源于stack exchange,提问作者Burcu

