0
votes

I'm using Discord Python API and i'm trying to do a bot command. However, I would like that this command could be used just once for 8 hours per user. So, I did something like this:

@bot.command()
@commands.cooldown(1, 28800, commands.BucketType.user)
@commands.has_any_role('role1', 'role2')
async def treasureChest(context):
    chosenList = random.choices(
     population=[1, 100, 200, 300, 500, 700, 1000, 5000],
     weights=[0.24, 0.249, 0.2, 0.15, 0.1, 0.05, 0.01, 0.001],
     k=1)

  earnedCoins = chosenList[0]
  if earnedCoins == 1:
    message = #some specific message
  elif earnedCoins >= 100 and earnedCoins <= 700:
    message = #other message...
  (...)

  await context.send(message)

I'm trying to set 28800 seconds as cooldown, but after a few minutes that the command is used the cooldown timer just stops and the users are able to use it again. I think the cooldown number is just too big. Is there any workaround I can do to accomplish that?

2
I cannot really reproduce the problem here, I've been running by bot since this question was asked and the cooldown worked perfectly - Łukasz Kwieciński
That's weird. Maybe multiple users using that command break the cooldown somehow when it's too big? - Yaksa
Don't think so, have you restarted the bot in the meantime? - Łukasz Kwieciński
Yes, many times. After a few minutes or hours(last time I tested 6 hours after the first use), I just could use it again. I don't understand what's going on. - Yaksa
Well if you restart the bot the cooldown will also restart - Łukasz Kwieciński

2 Answers

0
votes

Here is what I would do:

import datetime

bot.users_dict = {}
cooldown = 28800  # cooldown in seconds


@bot.command()
async def test(ctx):
    user_id = ctx.author.id
    if user_id in bot.users_dict:
        difference = (datetime.datetime.now() - bot.users_dict[user_id]).total_seconds()
        if difference < cooldown:
            await ctx.send(f"Cooldown! Wait {cooldown - difference} seconds")
            return
    bot.users_dict[user_id] = datetime.datetime.now()
    await ctx.send("Passed cooldown check")

How this code works: We define "global" dictionary that will hold the last time that the user invoked the command. If current time - the last time is smaller then the cooldown time it means that the user is on cooldown. If you have any questions feel free to ask in comments.

0
votes

Apparently, the problem was with something outside the posted code. In the same bot, I was using @client.event annotation with on_message(message) method to process greetings message in my Discord server. Somehow, this process was resetting the cooldown counter for every command using @bot.command annotation. I just removed the on_message() method and stopped using client events, and now it's working properly.