Jay Heartland
Jay Heartland

Reputation: 53

Listening for messages in Discord.py while retaining commands

What I'm aiming to do is have my bot always listen for specific messages in discord.py. In the example, the message it should be listening for is $greet which it should respond to with "Say hello" read aloud in Text To Speech.

This works fine, however it disables regular commands I have setup like !play and !help. Is there anyway to get around this limitation?

Example code:

@my_bot.event
async def on_message(message, timeout=10,):
    if message.content.startswith('$greet'):
        await my_bot.send_message(message.channel, 'Say hello', tts=True)
        msg = await my_bot.wait_for_message(author=message.author, content='hello')
        await my_bot.send_message(message.channel, 'Hello.')

Expected output:

User: !play
Bot: Now playing...
User: $greet
Bot: Say hello

Actual output:

User: !play
User: $greet
Bot: Say hello

Upvotes: 4

Views: 10651

Answers (2)

Blimmo
Blimmo

Reputation: 363

While using the commands part of the discord.py module you rely on the instance of Bot calling your commands for any of them to happen. This is done by the bot's coroutine method process_commands in a complicated way which I'm not going to interpret.

From the source:

# command processing

@asyncio.coroutine
def process_commands(self, message):
    ...

This is turn is called by the on_message event.

@asyncio.coroutine
def on_message(self, message):
    yield from self.process_commands(message)

When you override the on_message event to implement your custom behaviour, you are replacing this default behaviour, so you'll need to call process_commands yourself after your special processing.

From the docstring for the process_commands coroutine:

By default, this coroutine is called inside the :func:on_message event. If you choose to override the :func:on_message event, then you should invoke this coroutine as well.

You can do this using putting this:

await bot.process_commands(message)

at the end of your on_message event

I did something like this:

if message.channel.is_private:
    # Handle commands
    await bot.process_commands(message)
    await bot.delete_message(message)

to only allow commands in private messages and delete the command message after.

Upvotes: 4

Wright
Wright

Reputation: 3424

You can put them in separate files. Or you can just have them use the same prefix '!'

Upvotes: 1

Related Questions