0
votes

I am making a Discord Bot that does various things, including reacting to the person who mentions the bot and reacting to things certain users say in a certain channel. My code (shortened for clarity) is:

BOT = os.getenv('DISCORD_BOT_MENTION') 
CHANNEL = os.getenv('DISCORD_CHANNEL')
USER1 = os.getenv('DISCORD_USER1_ID')
USER2 = os.getenv('DISCORD_USER2_ID')

@bot.event 
async def on_message(message):  
    content = message.content # Did bot get mentioned?
    channel = message.channel # Where was the bot mentioned
    channel_ID = message.channel.id #
    user = message.author.name # Who mentioned the bot
    user_ID = message.author.id

    if user == client.user:
        return

    elif BOT in content:
        brankos_responses = [
            "Hello",
            "Hi",
        ]
        weights_responses = [
            15,
            10,
        ]
        response = random.choices(brankos_responses, weights_responses, k = 1)
        await asyncio.sleep(0.7) # Wait 0.7s before answering
        await channel.send(response[0])
    
    elif channel_ID == int(CHANNEL):
        if user_ID == int(USER_ID_1): 
            brankos_responses = [
                "Test Message 1 for User 1 in Channel",
                "Test Message 2 for User 1 in Channel",
            ]
            response = random.choice(brankos_responses)
            await channel.send(response)

        if user_ID == int(USER_id_2):
            brankos_responses = [
                "Test Message 1 for User 2 In Channel",
                "Test Message 2 for User 2 in Channel",
            ]
            response = random.choice(brankos_responses)
            await channel.send(response)

    else: 
        return

    await bot.process_commands(message)

However I found that if you spam @ the bot or if the Users 1 and 2 talk in Channel, it will keep giving replies, and I would like to limit that. In discord.py commands that's easy with @commands.cooldown(1, 3600, commands.BucketType.user) for example, however what I have is not a command, so it can't be used here.

I thought that I could just have the bot sleep (with await asyncio), when it notices a message in the CHANNEL from one of the users, and then when the person has not said anything for 5 seconds that it would run the code and send 1 reply, however that just results in all the responses piling up and all being send after a few seconds.

So my question is: How can I limit the amount of replies the bot gives?

Right now I am trying this:

        user_list = [
            int(USER1_ID),
            int(USER2_ID),
            int(USER3_ID),
            int(USER4_ID),
        ]

        messages = 0 # Define the count
        
        if user_ID in user_list:
            messages += 1 # Add one to count
            print(messages)

            if messages > 5: # If messages is more than 5, execute code
                response = random.choice(brankos_responses)
                await channel.send(response)
                messages = 0 # Reset count

But because it runs again, it resets to messages = 1 again, and if I put messages = 0 outside the function it does not work.

1
There's a pretty common design pattern that you can use. Set a time of when the next action is allowed. When trying to the action, check if the current time is before that set time. If so, cancel the action. Otherwise, do the action and reset the next allowed time to a time shortly in the futureHymns For Disco
That sounds logical, but I do not know how to even start to attempt this idea :\Buster

1 Answers

1
votes

If your intention is purely to have a cooldown on the bot timewise, then you could do something such as:

class StackOverflow(commands.Cog):
    def __init__(self, client):
        self.client = client
        self.last_timeStamp = datetime.datetime.utcfromtimestamp(0)

    @commands.Cog.listener()
    async def on_message(self, message):
        time_difference = (datetime.datetime.utcnow() - self.last_timeStamp).total_seconds()
        if time_difference < 120:
            # Don't do anything and return
            return

        else:
            #Do things
            self.last_timeStamp = datetime.datetime.utcnow()

This was done in a Cog, so you might have to make alterations if you want to use it outside a Cog. If you wanted to just count the number of messages, then just have a int variable, increment it every message and change the if statement.