Discord.py: How do I use #commands.check on an on_message event - discord.py

I am trying to get the bot to send an emoji when someone else sends one. I have managed to get this to work, but when I use #commands.check to make sure the bot is not responding to itself, it responds anyway and the bot gets stuck in a loop of replying to itself.
def is_it_me_event(message):
if message.author.id == 1234567890:
return False
#commands.Cog.listener("on_message")
#commands.check(is_it_me_event)
async def on_message(self, message):
if str(message.content) == ":smile:":
await message.channel.send(":smile:")
I know I can do this with an if statement inside the function itself, but is there a way of doing this with the commands.check decorator or is this not compatible with functions that aren't commands?

As you suspected, you can't decorate your on_message function with a #commands.check(...) because it isn't a command. However, you can set up a predicate for these events:
def check_author_isnt_self():
def decorator(func):
async def wrapper(message):
return message.author.id != 1234567890:
# or `return message.author.id != self.bot.id` as better practice
return wrapper
return decorator
#commands.Cog.listener("on_message")
#check_author_isnt_self()
async def smile_back(self, message):
if str(message.content) == ":smile:":
await message.channel.send(":smile:")

I got it to work:
def check_author_isnt_self(func):
async def decorator(ctx, *args, **kwargs):
message = args[0]
if message.author.id != 1234567890:
await func(ctx, message)
decorator.__name__ = func.__name__
sig = inspect.signature(func)
decorator.__signature__ = sig.replace(parameters=tuple(sig.parameters.values())[1:])
return decorator
#commands.Cog.listener("on_message")
#check_author_isnt_self
async def on_message(self, message):
if str(message.content) == ":smile:":
await message.channel.send(":smile:")
This article explains how this works: https://scribe.rip/#cantsayihave/decorators-in-discord-py-e44ce3a1aae5

Related

trying to make an afk command for my bot but i am getting this error

async def afk(self, ctx, *args):
msg = ' '.join(args)
self.data.append(ctx.author.id)
self.data.append(msg)
await ctx.author.edit(nick=f'[AFK] {ctx.author.name}')
await ctx.send("afk set!")
#commands.Cog.listener()
async def on_message(self, message):
for i in range(len(self.data)):
if (f"<#{self.data[i]}>" in message.content) and (not message.author.bot):
await message.channel.send(f"<#{self.data[i]}> is away right now, they said: {self.data[i+1]}")
return None
break
#commands.Cog.listener()
async def on_typing(self, channel, user, when):
if user.id in self.data:
i = self.data.index(user.id)
self.data.remove(self.data[i+1])
self.data.remove(user.id)
nick = ctx.author.name.replace('[AFK]', '')
await ctx.author.edit(nick=nick)
await channel.send(f"{user.mention}, Welcome back!")
But it is showing ctx is not found nick = ctx.author.name.replace('[AFK]', '') i have been trying various methods to solve it, but i am not able to fix this, pls help me
You're using ctx in a func which doesnt have a ctx arg, you should instead use
nick = user.author.name.replace('[AFK]', '')
await user.author.edit(nick=nick)

How do I get bot to read mention?

If someone mentions me how do I get the bot to read that? like if someone mentions me I want the bot to say something back. How would I do that?
#client.event
me = '<#user_id>'
async def on_message(message):
member = message.author.id
if message.content == me:
await message.channel.send('my master will be back shortly')
else:
return
await client.process_commands(message)
You can use discord.Message.mentions. It returns a list of discord.Member that were mentioned in message.
#client.event
async def on_message(message):
me = message.guild.get_member(<user id>)
if me in message.mentions:
await message.channel.send('my master will be back shortly')
await client.process_commands(message)
Reference
discord.Message.mentions

How to use MessageType

so I am trying to make the bot do something when the premium_guild_subscription message comes. I have tried:
#bot.event
async def on_message(message):
MessageType = discord.MessageType
if MessageType == 'pins_add':
await message.channel.send('ITS WORKING!!!')
but its not working. The above code does nothing when the message comes. If I do message.MessageType then it says that message object has no attribute MessageType.
You need to use an instance of a class and compare that to see if it's the correct type, not comparing the class itself to a string.
#bot.event
async def on_message(message):
if message.type == discord.MessageType.pins_add:
await message.channel.send('ITS WORKING!!!')
A further example:
#bot.command()
async def test(ctx):
print(ctx.message.type == discord.MessageType.pins_add)
print(ctx.message.type == discord.MessageType.default)
Results in
!test
> False
> True
In your code, you're trying to use class. You have to call the init function from that class. So you need to access a MessageType type data from message.
According to API References, you can use message.type to access MessageType object. Then you can check if a message is pins_add type with message.type.pins_add.
#bot.event
async def on_message(message):
if message.type == discord.MessageType.pins_add:
await message.channel.send('ITS WORKING!!!')

auto mute a member if they say a specific word discord py rewrite

import discord
import re
from itertools import cycle
class Status(commands.Cog):
def __init__(self, client):
self.client = client
#commands.Cog.listener()
async def on_message(self, ctx):
if ctx.author.id == self.client.user.id:
return
if re.search("\.\.\.", ctx.content):
await ctx.send("you're... gonna get... muted... if you.. talk... like.. this...")
user = ctx.message.author
# print(str(user))
# print(str(message.content))
muted_role = discord.utils.get(ctx.author.guild.roles, name="Muted")
await self.client.add_roles(ctx.author, muted_role)
What I want is to temporarily mute a user if they use ellipses in a message they send. ctx.send doesn't work, the bot does not send a message to the channel. It says that self.client.add_roles doesn't exist.
Muted is a role that I have created that does not have any send message permissions.
Any idea why? Some help would be hugely appreciated. I'm using
AttributeError: 'Message' object has no attribute 'send' this is the error I get
[EDIT]
#commands.Cog.listener()
# #commands.command()
async def on_message(self, message):
if message.author.id == self.client.user.id:
return
if re.search("\.\.\.", message.content):
await message.channel.send("you're... gonna get... muted... if you.. talk... like.. this...")
user = message.author
muted_role = discord.utils.get(message.guild.roles, name="Muted")
await user.add_roles(muted_role, reason="you know what you did", atomic=True)
I took a look at the documentation and did this, it works, thank you for the support :)
There were many mistakes, please have a look at the documentation.
I have correct them for you -
#commands.Cog.listener()
async def on_message(self, message):
if message.author.id == self.client.user.id:
return
else:
await message.channel.send("you're... gonna get... muted... if you.. talk... like.. this...")
user = message.author
print(str(user))
print(str(message.content))
muted_role = discord.utils.get(message.guild.roles, name="Muted")
await self.user.add_roles(muted_role)
Let me know if you do still get any errors.
Last edit-
I tried this command for myself outside a cog, and it works perfectly fine :)
#client.event
async def on_message(message):
if message.author.id == client.user.id:
return
elif "test" in message.content:
await message.channel.send("you're... gonna get... muted... if you.. talk... like.. this...")
user = message.author
print(str(user))
print(str(message.content))
muted_role = discord.utils.get(message.guild.roles, name="Muted")
await user.add_roles(muted_role)
else:
return
await client.process_commands(message)

Making say command bot owner only

I am trying to make my !say command only work for the bot owner. This is what I currently have
#bot.command(pass_context = True)
async def say(ctx, *args):
mesg = ' '.join(args)
await bot.delete_message(ctx.message)
return await bot.say(mesg)
The code works but I want to make it so only I (the bot owner) can run the command.
You can also use the decorator #is_owner().
#bot.command(pass_context = True)
#commands.is_owner()
async def say(ctx):
your code...
Try doing it this way by adding an if statement
#bot.command(pass_context=True)
async def say(ctx):
if ctx.message.author.id =='bot owner id':
then execute the following code
This is how I did it - do comment if this does not work as intended.
#client.command()
#commands.is_owner()
async def say(ctx, *, message):
await ctx.send(f"{message}")
Have fun with your coding! Sorry for the late reply, I was reading old questions and seeked for unsolved issues
(remade)
The documentation for check in the 1.0 docs has the below example (slightly modified.)
def user_is_me(ctx):
return ctx.message.author.id == "Your ID"
#bot.command(pass_context = True)
#commands.check(user_is_me)
async def say(ctx, *args):
mesg = ' '.join(args)
await bot.delete_message(ctx.message)
return await bot.say(mesg)
How to find your ID

Resources