I'm trying to make a command that deletes the message content and send it back to the user if it's not the word "role".
Code is working fine. The message gets deleted if it's not "role" and I do received a dm with the deleted message, but I don't know if I'm doing it right because I get this error "AttributeError: 'ClientUser' object has no attribute 'create_dm'".
Here's my code:
#commands.Cog.listener()
async def on_message(self, message):
dm = await message.author.create_dm()
if not message.guild:
return
if not message.channel.name == 'roles':
return
elif message.channel.name == 'roles' and message.content != 'role':
if message.author.bot:
pass
else:
await dm.send(f'{message.content}')
await message.delete()
Discord bots can't send DM's to eachother, only to Users. Your bot is trying to send a DM to itself, which it can't. You need to check with an if-statement if the message's author is a bot or not.
You're already doing this later on in your code, to see if it should send the message or not, but the create_dm() function at the top will have already failed at that point (as it can't create a dm), so it will never get there.
#commands.Cog.listener()
async def on_message(self, message):
if message.author.bot:
return # Ignore bot messages
if not message.guild:
return
if not message.channel.name == 'roles':
return
elif message.content != 'role':
await message.author.send(message.content)
await message.delete()
PS. A few more things to note here:
You can just use User.send() instead of create_dm() & dm.send().
An f-string with nothing but the content can just be the content itself (f"{word}" == word, or str(word) in case it's not a string).
You have an if checking if the channel name is not "roles", and afterwards in the elif you check if it is - if it wouldn't be "roles" then it would've gotten into the first if & returned so the second one is unnecessary.
Related
I know how to take a triggering message's content, but not the next.
#client.event
async def on_message(message):
if message.content.startswith('&trade'):
I then want my code to read take the next message's content instead of the message that triggers the event. After the &trade command, a different bot will always immediately respond with a message, so it will always be the next message with content.
Here you basically need to wait until the next message by the author
#client.event
async def on_message(message):
if message.content.startswith('$greet'):
channel = message.channel
author = message.author
await channel.send('Say hello!')
def check(m):
return m.author == author and m.channel == channel
msg = await client.wait_for('message', check=check)
await channel.send('Hello {.author}!'.format(msg))
This code basically checks the next message by the author, and returns the message's author.
For more info check out the docs: https://discordpy.readthedocs.io/en/latest/api.html#discord.Client.wait_for
Maybe try setting a variable and checking if it's set every time a user sends a message?
trade = False
#client.event
async def on_message(message):
global trade
if trade:
#Here's the message content that you wanted
trade = False
return
if message.content.startswith('&trade'):
trade = True
So I have an AntiSpam system in place, which is made in on_message event of discord.py. The code to the same is below -->
#bot.event
async def on_message(message):
await bot.wait_until_ready()
if message.author == bot.user:
return
bucket = bot.AntiSpam.get_bucket(message)
retry_after = bucket.update_rate_limit()
if retry_after:
print('Someone was being naughty')
await message.channel.purge(before=datetime.utcnow(), after=datetime.utcnow()-timedelta(seconds=5))
await message.channel.send(f'Please don\'t spam, {message.author.mention}', delete_after=5.0)
This deletes every single message sent since the last 5 seconds. How to make it so that it would only delete the message sent by that spammer? I know I have to use the check kwarg of TextChannel.purge(), but I need a way to make the check. Can I get any help regarding this?
The check would be very simple:
def check(m):
return m.author == message.author
await message.channel.purge(before=datetime.utcnow(), after=datetime.utcnow()-timedelta(seconds=5), check=check)
We're checking if the author of the message passed into the check is the same as the author of the previous message.
Right now I'm trying to ask my bot to check when I, AND ONLY I write a messageS it says words. But I don't know how to make discordpy see if i messaged or not, I assume I have to use message.author.id() method. Please help. :3
#MODULES
import discord
from discord.ext import commands
from discord.utils import get
#THE CODE
bot = commands.Bot(command_prefix = '.')
#bot.event
async def on_message(message):
if message.author == bot.user:
return
if message.author.id('MY ACTUAL USER ID'):
await bot.say('words')
bot.run('MY BOT TOKEN')
bot.say is deprecated from the old async branch. Either way, you also haven’t defined where it sends the message to. Make sure you aren’t using a string for your user id, it’s an int and can be passed without quotes.
Simply replace the 123... with yours or others id
if message.author.id('MY ACTUAL USER ID'): should be instead if message.author.id == 123456789:
#bot.event
async def on_message(message):
if message.author == bot.user:
return
if message.author.id == 123456789:
await message.channel.send('words')
I am attempting to teach myself how to use discord.py, and I am trying to make a bot that will be able to recognize which guild it received a command from, and refrence another file, so it can have individual presets per server, but my problem is that Guild.id does not seem to get the ID, and spits out <member 'id' of 'Guild' objects> in the shell, where I would expect the guild ID to be printed, and I am lost as to what could possibly be wrong.
The part I am not able to get work is only the last 'elif' prompt, but I added the rest of the code for more context, in case it is an error earlier in my code.
import discord
client = discord.Client()
#client.event
async def on_ready():
#Bootup confirmation
print("We have logged in as {0.user}".format(client))
#client.event
async def on_message(message):
#Debugging reference
print("{0.guild} - {0.author}: {0.content}".format(message))
#Check if message is from bot and return if true
if message.author == client.user:
return
#Check if message contains $test and return a response
elif message.content.startswith("$test"):
await message.channel.send("Hello!")
elif message.content.startswith("$id"):
gid = discord.Guild.id
print(gid)
guild_id = message.guild.id
I'd recommed you using commands.Bot instead
I'm programming a bot for discord and trying to delete messages but only the one of the bots since I'm doing some commands that make him spam quite a lot.
So what I've found works well to bulk delete would be
#bot.command(pass_context = True)
async def purge(ctx,msglimit : int):
deleted = await bot.purge_from(ctx.message.channel, limit=msglimit)
await bot.say("Cleared **{}** Messages".format(len(deleted)))
but the documentation shows this command
def is_me(m):
return m.author == client.user
deleted = await client.purge_from(channel, limit=100, check=is_me)
await client.send_message(channel, 'Deleted {} message(s)'.format(len(deleted)))
But i can't really guet it to work if someone has an idea
def is_me(m):
return m.author == bot.user
#bot.command(pass_context = True)
async def purge(ctx):
deleted = await bot.purge_from(ctx.message.channel, check=is_me)
await bot.say("Cleared **{}** Messages".format(len(deleted)))
This deletes a certain number of messages (100 by default).
The purge_from method takes an argument called check which is a function that takes a message and returns whether the message should be deleted.
The is_me function will return true if the message author is the bot.
Which means that calling purge will delete the bot that picked up this command. If you need the bot to delete a different user's messages, you will need to change the condition.