on_message stops all of my bot.commands from working - client

I have a flip command that returns either heads or tails and it was working fine until I added the on_message function. I did some research on SO and read the documentation and here it says to include await bot.process_commands(message) in the on_message function but that did not solve the issue and the flip command still doesn't work. If I remove the on_message function everything works as expected.
bot.py
import discord
from discord.ext import commands
import random
# from app bot user
# click to reveal
TOKEN = 'token_here'
client = commands.Bot(command_prefix = '!')
#client.event
async def on_ready():
print('Bot ready')
#client.command()
async def flip():
flip = random.choice(['heads', 'tails'])
await client.say(flip)
#client.event
async def on_message(message):
if message.content.upper().startswith('N****'):
await client.send_message(message.channel, "Please do not use that word here.")
client.process_commands(message)
#client.event
async def on_member_join(member):
await client.change_presence(game=discord.Game(name='Hi %s' % (member)))
await client.send_message(member, "Hi %s, Welcome to Carson's Discord Server! This server is fairly NSFW at times; you've been warned! Enjoy your stay :)" % (member))
#client.event
async def on_member_remove(member):
await client.change_presence(game=discord.Game(name='Bye %s' % (member)))
client.run(TOKEN)
When I run the script, everything else works normally with no errors. It's just the commands that don't work. Any insight would be greatly appreciated.

You need to await the last line in on_message as process_commands is a coroutine.
await client.process_commands(message)
If you send !flip in discord, you should be able to receive the appropriate response (heads or tails).

Related

How to make a bot respond exactly what you say in discord.py

im trying to get my Discord bot to say exactly what i want with the command of !say excluding the !say part but im new to coding and have no idea where to start. I know the basics of making a bot say/react/delete/DM messages but thats all
Try this:
#commands.command()
async def say(self, ctx, *, arg):
await ctx.send(arg)
The full code would look something like this:
from discord.ext import commands
bot = commands.Bot(command_prefix="!", intents=discord.Intents.all())
#bot.event
async def on_ready():
print("bot is ready")
#commands.command()
async def say(self, ctx, *, arg):
await ctx.send(arg)
bot.run("YOURTOKEN")

Discord.py bot stops working after having two #client.event or 1 #client.command and 1 #client.event

The title pretty much explains it self but I'll explain it again.
So basically when I have 2 #client.event or 1 #client.command and 1 #client.event line in the code, the whole thing breaks except for the last block of code.
Like in my code here, the first #client.event works fine. The second one doesn't, but the third one does, now if I switch the second one and the third ones place then the second ones works but the third doesn't.
import discord
from discord.ext.commands import Bot
from discord.ext import commands
import asyncio
import time
import random
from discord import Game
Client = discord.client
client = commands.Bot(command_prefix = " ")
Clientdiscord = discord.Client()
#client.event
async def on_ready():
print('{0.user}'.format(client))
print('Is Online')
#client.command
async def cmds(ctx):
await ctx.send('Prefix: v!')
await client.process_commands(ctx)
#client.event
async def on_message(message):
if message.content == 'v!coin':
variable = [
'flip',
'stay',
]
await message.channel.send((random.choice)(variable))
await client.process_commands(message)
client.run("TOKEN")
If you're using the commands framework, you should add all your commands using the #client.commands decorator instead of having logic in your on_message event handler.
If you need to handle on_message events for another reason (examokeL autoresponse to non commands), you need to call await client.process_commands(message) at the end of your on_message event handler function. It should be outside any if statements but still inside the function. Only call process_commands once in your on_message, and never call it inside your commands unless you know exactly what you are doing. Your on_message function should look something like this:
#client.event
async def on_message(message):
# Do whatever here, but don't handle commands
# If you return early, any commands in the message will be skipped
await client.process_commands(message)
So instead of this:
#client.command
async def cmds(ctx):
await ctx.send('Prefix: v!')
await client.process_commands(ctx)
#client.event
async def on_message(message):
if message.content == 'v!coin':
variable = [
'flip',
'stay',
]
await message.channel.send((random.choice)(variable))
await client.process_commands(message)
You should have something like this:
#client.command()
async def cmds(ctx):
await ctx.send('Prefix: v!')
# Send a list of commands here or do whatever this command is supposed to do
# Don't call client.process_commands here
#client.command()
async def coin(ctx):
# Coinflip logic here
# I've added the original logic you had in your question
variable = [
'flip',
'stay',
]
await ctx.send((random.choice)(variable))
# no #client.event or def on_message unless you need to handle raw messages
Also, you don't need these lines of code:
Client = discord.client
client = commands.Bot(command_prefix = " ")
Clientdiscord = discord.Client()
You can just use this:
client = commands.Bot(command_prefix = "v!")
If you are using commands.Bot already, you don't need another discord.Client.
Instead of placing await client.process_commands(message) within your if statement, place it outside of it. Please review the revised code below.
#client.event
async def on_message(message):
if message.content == 'v!coin':
variable = [
'flip',
'stay',
]
await message.channel.send((random.choice)(variable))
await client.process_commands(message)
Please note that you do not need to include await client.process_commands(message) in a command, only in your on_message event.

How to have cog listener called before cog command

I have some code for a cog that looks something like this:
class Example(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.counter = 0
#commands.Cog.listener()
async def on_message(self, message):
print("Listener triggered")
self.counter += 1
#commands.group()
async def first(self, ctx):
if ctx.invoked_subcommand is None:
await ctx.send("Invalid subcommand")
#first.command()
async def second(self, ctx):
print("Command triggered")
await ctx.send(f"Current counter: {self.counter}")
When I run this code and send a message to my bot, second gets called before on_message. I have some code in second that expects on_message to be executed first, but I can't figure out a good way to make this happen. Suggestions?
check wait_for event.
and I think you are trying to make a bot count the number of valid uses of command. To do this, try:
def check(message):
#here put ur condition for message is a valide command
await client.wait_for('message', check=check)

Editing a bot's message just like when you swipe a page, discord.py

I wanted to make a command that edits the bot's old message trought another command, example:
user: !cmds
bot: *commands list*
user: !next
bot: *edits old message into a new one*
I have tried many times to make it myself, but I failed all the times, can anyone help me?
How I tried to make it:
#client.command
async def test():
embed=discord.Embed(title="Page1")
await ctx.send(embed=embed)
#client.event
async def on_command(message):
embed2=discord.Embed(title="Page2")
await client.process_commands(message)
if message.content == '$next':
await message.edit(content=embed2)
The on_command event is called whenever a command is called, you didn't register a next command, that's one, second of all on_command doesn't take message argument, it takes the Context(ctx).
An idea to make what you're asking for is having a cog with an instance variable that references to the previous message, then edit it when the next command is called.
class SomeCog(commands.Cog):
def __init__(self, client):
self.client = client
self._previous_message = None
#commands.command()
async def test(self, ctx):
message = await ctx.send("I'll edit this message when you type `$next`")
self._previous_message = message
#commands.command()
async def next(self, ctx):
if self._previous_message is None: # Exiting if the `test` command wasn't called before, i.e the message is a NoneType
return await ctx.send("You need to invoke first `$test`")
await self._previous_message.edit(content="Edited the message")
client.add_cog(SomeCog(client))
I'm guessing you could do it with global or bot vars but this is the best way to do it, in my opinion.

How to make bot respond to a certain msg?

So, I've been trying to make my bot respond to a specific keyword however when I do this the bot either doesn't respond or gives me a bunch of errors. I've tried a few methods of doing this but I didn't have much luck. If anybody can make it work would be glad here are one of the methods I tried using.
if message.content == "keyword":
await client.send_message(message.channel, "Response {0.author.mention}")
You can do this one of two ways, either with the commands extension, or within the on_message event.
Below is an example of how you can do this. With this example, when a user types "!ping" the bot will respond with "Pong". If a message contains the word "foo", then the bot will respond with "bar".
from discord.ext import commands
client = commands.Bot(command_prefix='!')
#client.event
async def on_ready():
print('client ready')
#client.command()
async def ping():
await client.say('Pong')
#client.event
async def on_message(message):
if client.user.id != message.author.id:
if 'foo' in message.content:
await client.send_message(message.channel, 'bar')
await client.process_commands(message)
client.run('TOKEN')

Resources