2
votes

I tried today to make a python discord.py based bot for a bit of fun, and following some random tutorials and copying code it worked great, and I added a few new commands once I'd gotten the hang of it, but apparently randomly most of the commands stopped working, and for some reason now only the bottom most command actually functions in discord, any ideas why this could be? Code:

import discord
from discord.ext import commands

description = 'Tutorial Bot'
bot_prefix = '!'

client = commands.Bot(description=description, command_prefix=bot_prefix)

list_of_strings = ['hello', 'hi']

@client.event
async def on_ready():
    print('Connected')

@client.event
async def on_message(message):
    if message.content.startswith('!what'):
        await client.send_message(message.channel, 'Huh?')

@client.event
async def on_message(message):
    if message.content in list_of_strings:
        await client.send_message(message.channel, 'Hey there')

client.run('*set to code before attempting*')

I had set the client.run to the newest code, but whenever I use the bottom list of strings command it works fine, but the !what section doesn't work. I tried reversing them and the same problem persisted, with only the bottom most one working regardless of which order they're in. Is there something obvious I'm probably missing here?

2
I haven't used any of this before, but presumably the second overwrites the first... - Artemis

2 Answers

3
votes

I'm no expert at Python but part of your issue might be the two function declarations being fully defined the same way. I would imagine the second function is redefining the first.

@client.event
async def on_message(message):
    //Function 1 code
@client.event
async def on_message(message):
    //Function 2 code

Instead of using two move the conditional of the second into the first like so:

@client.event
async def on_message(message):
    if message.content.startswith('!what'):
        await client.send_message(message.channel, 'Huh?')

    elif message.content in list_of_strings:
        await client.send_message(message.channel, 'Hey there')
2
votes

When you use the Client.event decorator, that's actually assigning the client.on_message attribute to be the coroutine you wrote. client.on_message can't be two things at the same time, so the older one is discarded.

You have the right idea though: you should be splitting your commands into discrete units instead of keeping them in a single monolithic coroutine. For this, you actually use the Bot.command() decorator.

import discord
from discord.ext import commands

description = 'Tutorial Bot'
bot_prefix = '!'

client = commands.Bot(description=description, command_prefix=bot_prefix)

list_of_strings = ['hello', 'hi']

@client.event
async def on_ready():
    print('Connected')

@client.command(pass_context=True)
async def what(ctx):
    await client.say('Huh?')

@client.event
async def on_message(message):
    if message.author == client.user:
        return  # We don't want our bot to respond to itself
    if message.content in list_of_strings:
        await client.send_message(message.channel, 'Hey there')
    await client.process_commands(message)  # Hand off to the command logic

client.run('*set to code before attempting*')