Sync271
Sync271

Reputation: 33

How do I get the discord bot to trigger commands on it's own message using discord.py?

Let's just say the user enters an invalid command, the bot suggests a command with (y/n)? If y, then the bot should trigger the suggested command. I feel this can be achieved in 2 ways:

  1. If the bot can trigger commands on its own message
  2. If I can call the command from the other cogs

I can't seem to get either of em working.

Here is an example to help you guys help me better:

Let's just say this below code is from a cog called Joke.py:

@commands.command()
async def joke(self,ctx):
await ctx.send("A Joke")

And then there another cog "CommandsCorrection.py" that corrects wrong commands used by the user that are saved on data.json file:

@commands.Cog.listener()
async def on_message(self, message):
    channel = message.channel
    prefix = get_prefix(self,message)
    if message.author.id == bot.id:
        return
    elif message.content.startswith(prefix):
            withoutprefix = message.content.replace(prefix,"")
            if withoutprefix in data:
                return
            else:
                try:
                    rightCommand= get_close_matches(withoutprefix, data.keys())[0]
                    await message.channel.send(f"Did you mean {prefix}%s instead? Enter Y if yes, or N if no:" %rightCommand)
                    def check(m):
                        return m.content == "Y" or "N" and m.channel == channel
                    msg = await self.client.wait_for('message', check=check, timeout = 10.0)
                    msg.content = msg.content.lower()
                    if msg.content == "y":
                        await channel.send(f'{prefix}{rightCommand}')
                    elif msg.content == "n":
                        await channel.send('You said no.')
                except asyncio.TimeoutError:
                    await channel.send('Timed Out')
                except IndexError as error:
                    await channel.send("Command Not Found. Try !help for the list of commands and use '!' as prefix.")

in the above code await message.channel.send(f"Did you mean {prefix}%s instead? Enter Y if yes, or N if no:" %rightCommand) suggests the right command and await channel.send(f'{prefix}{rightCommand}') sends the right command.

So,for example:

user : !jok
bot  : Did you mean !joke instead? Enter Y if yes, or N if no:
user : y
bot  : !joke **I want to trigger the command when it sends this message by reading its own message or my just calling that command/function

How should I go about this?

Upvotes: 2

Views: 6066

Answers (2)

Sync271
Sync271

Reputation: 33

@Patrick Haugh suggested this idea, he was on to something but wasn't really working but I got a way to get it working. If you use the following method for a cog, you'll be able to read bot commands as well:

import discord
from discord.ext import commands

async def command_logic(self, ctx):
    await ctx.send("Running command")

class Example(commands.Cog):

    def __init__(self, client):
        self.client = client


    @commands.command()
    async def my_command(self, ctx):
        await command_logic(self,ctx)

    @commands.Cog.listener()
    async def on_message(self, message):
        if message.content == '!command':
            ctx = await self.client.get_context(message)
            await command_logic(self,ctx)

def setup(client):
    client.add_cog(Example(client))

Upvotes: 1

Patrick Haugh
Patrick Haugh

Reputation: 61014

One solution would be to separate the logic of your commands from the command callbacks and put it in it's own coroutines. Then you can call these coroutines freely from any of the command callbacks.

So you would turn code like this:

@bot.command()
async def my_command(ctx):
    await ctx.send("Running command")

@bot.command()
async def other_command(ctx, arg):
    if arg == "command":
        await ctx.send("Running command")

Into something like this:

async def command_logic(ctx):
    await ctx.send("Running command")

@bot.command()
async def my_command(ctx):
    await command_logic(ctx)

@bot.command()
async def other_command(ctx, arg):
    if arg == "command":
        await command_logic(ctx)

Upvotes: 1

Related Questions