1

I am very new to coding and want to just add a command timer to the code i got off the internet. I don't know how to do this and all the other codes I find are too much for me to know. I just want to be able to add around a 10 second cooldown timer to each command.

import discord

import asyncio

from discord.ext import commands

import datetime as DT

import discord.utils

class MyClient (discord.Client):

    async def on_ready(self):

        print('Logged in as')
        print(self.user.name)
        print(self.user.id)
        print('------')

    async def on_message(self, message):
        # we do not want the bot to reply to itself
        if message.author.id == self.user.id:
            return

        if message.content.startswith('!discord'): # I want to add a timer
            channel = client.get_user(message.author.id)
            await channel.send(''.format(message))

    async def on_member_join(self, member):
        guild = member.guild
        if guild.system_channel is not None:
            to_send = 'Welcome {0.mention} to {1.name}!'.format(member, guild)
            await guild.system_channel.send(to_send)

client = MyClient()

client.run('')
RKRK
  • 1,354
  • 5
  • 14
  • 17
Karisma_DC
  • 13
  • 2
  • I think you have a mistake in `await channel.send(''.format(message))`. The `format()` function needs curly braces as input, in order to provide parameters. You need to change it to `'{}'.format(message)` otherwise you'll just get an empty string(`''`) as output. – emilanov Aug 12 '19 at 09:11
  • 1
    The command works fine, its a link to my discord, I just removed it so no one can see it. – Karisma_DC Aug 12 '19 at 09:31

2 Answers2

1

The time.sleep() function, which another user suggested is a blocking call. Which means it will block the entire thread from being ran. I am not sure exactly how the Discord framework works, but I imagine thread blocking might be a problem.

A better solution I think would be to use asyncio, especially since you've already imported it. It will allow the program to do other stuff, while waiting the 10 seconds. Another Stackoverflow thread if you're interested

if message.content.startswith('!discord'):
            channel = client.get_user(message.author.id)
            await asyncio.sleep(10)
            await channel.send(''.format(message))

Edit

You can save the last time the function was called, and check with an IF-statement if 10 seconds have passed since the last call.

class MyClient (discord.Client):

    last_called = None

    async def on_ready(self):
        # other stuff

    async def on_message(self, message):
        # check if 10 seconds have passed since the last call
        if MyClient.last_called and DT.datetime.now() < MyClient.last_called + DT.timedelta(seconds=10):
            return

        # we do not want the bot to reply to itself
        if message.author.id == self.user.id:
            return

        if message.content.startswith('!discord'):
            channel = client.get_user(message.author.id)
            await channel.send(''.format(message))
            MyClient.last_called = DT.datetime.now()  # save the last call time
Community
  • 1
  • 1
emilanov
  • 352
  • 2
  • 12
  • I was wondering if there was a way to make the command not work for 10 seconds. This way allows the command to send every 10 seconds but not cancel it out. People can still spam it and it will basically send every 10 seconds. Would it be better to add the command to target the specific user? – Karisma_DC Aug 12 '19 at 09:19
  • Hmm, can you move the `asyncio.sleep()` call one line lower, so that it's after `channel.send()`? Or you can just ident it back, so that it's outside the IF-statement and it will sleep even if the message doesn't start with `!discord`. Also I am curious to see how the programm will behave if a user sends a message while the function is waiting. – emilanov Aug 12 '19 at 09:26
  • the function waits the 10 seconds and automatically sends the same command after the 10 seconds are up. – Karisma_DC Aug 12 '19 at 09:26
  • I have edited my answer, this should probably do what you want it to. – emilanov Aug 12 '19 at 09:41
  • You want the variable to be under the class definition. Otherwise, you define it in the `on_ready()` function, and thus cannot access it from another function. Check my edit again. Plus, now you have two `on_message` functions and you want only one of those. – emilanov Aug 12 '19 at 10:05
  • https://prnt.sc/orjtsa Like so? if so, it doesnt work in keeping the me from spamming the command. – Karisma_DC Aug 12 '19 at 10:10
  • Again. You have defined `async def on_message(self, message):` twice in your code. Remove the second definition. You want the IF-statement containing the `last_call` check to be together with the author check and the `message.content.startswith()` check. – emilanov Aug 12 '19 at 10:16
  • https://prnt.sc/ork3jb Like this? I have made it look like yours. If it is this, I am getting an error that says https://prnt.sc/ork4h5 Also I am very new to this website and also new to coding. you have to give me a bit before I can fully understand it. – Karisma_DC Aug 12 '19 at 10:31
  • This one's on me. You need to replace all references except the declaration to `last_called` with `MyClient.last_called` because it's a static variable. Otherwise the interpreter defines a local `last_called` variable for the function. See the edit again. – emilanov Aug 12 '19 at 10:44
  • https://prnt.sc/orkeme Like so? If so, its the same as if there were no code preventing me from spamming. – Karisma_DC Aug 12 '19 at 10:51
  • My time check logic sucked. Should be `if MyClient.last_called and DT.datetime.now() < MyClient.last_called + DT.timedelta(seconds=10):` – emilanov Aug 12 '19 at 10:59
  • 1
    Thank you so much. Now it is working perfectly. It also doesn't backlog the command to msg after the 10 seconds are up. – Karisma_DC Aug 12 '19 at 11:02
  • Glad to help. Some tips for stackoverflow. You could choose my answer as the correct one if it helped you. Also, next time when you ask a question, put as much info as possible. For example the problem that people can spam the discord bot would've been extremely helpful. – emilanov Aug 12 '19 at 11:45
0

If you add this to the imports at the top of the file:

from time import sleep

then you can use the sleep() function to pause the script for a set number of seconds when execution reaches that line. So for instance, adding this:

sleep(10)

somewhere inside the functions would sleep for 10 seconds whenever the script reaches that line.

saintamh
  • 158
  • 1
  • 4