Discord python bot on_message return statement breaks commands

Question:

First, I am aware that await bot.process_commands(message) needs to be at the end of the on_message function, so I know that this isn’t the problem.

I have written a bot that is supposed to look at all messages from one channel (ignoring messages from all other channels) and look at commands in all the channels . Because of this, I do a channel check first thing in on_message() function. If it is not the appropriate channel, it returns None and stops that function. However, I’m finding that this is also causing my commands to break and no longer run.

Here is a testing bot to help recreated the basics of my error

import datetime
import discord
from discord.ext import commands


DISCORD_TOKEN='<TOKEN>'

bot = commands.Bot(command_prefix='$')

@bot.event
async def on_ready():
    print(f"Online:t{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")

@bot.command()
async def command_(ctx):

    print(f"t{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} This was seen as a command")

@bot.event
async def on_message(message):

    if message.channel.id != <CHANNEL_ID>:
        return

    print(f"t{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} This was seen as a message")    
    await bot.process_commands(message)

bot.run(DISCORD_TOKEN)

If I remove the channel check (lines 21-22), then messages get seen as messages, but commands get seen as both messages and commands, in that order. Because of the return (to break out of the function if the message did not happen in a specific channel), and because the on_message() always seems to get called first, commands just never get called, and I don’t get any output in my terminal.

Any input on what I can do to navigate this?

Asked By: Phil Robinson

||

Answers:

This code will work as you want. as I described in the comments, with the create_task function you can call an async function without await statement and because of that, the function will not be waited to end the process.

import datetime
import discord
from discord.ext import commands


DISCORD_TOKEN='<TOKEN>'

bot = commands.Bot(command_prefix='$')

@bot.event
async def on_ready():
    print(f"Online:t{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")

@bot.command()
async def command_(ctx):

    print(f"t{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} This was seen as a command")
async def check_message(message):
  if message.channel.id != <CHANNEL_ID>:
        return
  print(f"t{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} This was seen as a message")  
@bot.event
async def on_message(message):

    # You can use bot.loop.create_task() function to create a new task in the loop. 
    # The task will not be waited to end the process, so while checking the message, you can process commands at the same time
    bot.loop.create_task(check_message(message))
    await bot.process_commands(message)

bot.run(DISCORD_TOKEN)
Answered By: bilinenkisi
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.