Discord Bot raises AttributeError "no attribute 'say'" [duplicate] - python

For some reason send_message isn't working properly on my Discord bot and I can't find anyway to fix it.
import asyncio
import discord
client = discord.Client()
#client.async_event
async def on_message(message):
author = message.author
if message.content.startswith('!test'):
print('on_message !test')
await test(author, message)
async def test(author, message):
print('in test function')
await client.send_message(message.channel, 'Hi %s, i heard you.' % author)
client.run("key")
on_message !test
in test function
Ignoring exception in on_message
Traceback (most recent call last):
File "C:\Users\indit\AppData\Roaming\Python\Python36\site-packages\discord\client.py", line 223, in _run_event
yield from coro(*args, **kwargs)
File "bot.py", line 15, in on_message
await test(author, message)
File "bot.py", line 21, in test
await client.send_message(message.channel, 'Hi %s, i heard you.' % author)
AttributeError: 'Client' object has no attribute 'send_message'

You are probably running the rewrite version of discord.py, since the discord.Client object does not a have a send_message method.
To fix your problem you can just have it as:
async def test(author, message):
await message.channel.send('I heard you! {0.name}'.format(author))
but for what i see you doing I reccomend using the commands extension
This makes creating a bot and commands for the bot much simpler, for example here is some code that does exactly the same as yours
from discord.ext import commands
bot = commands.Bot(command_prefix='!')
#bot.command()
async def test(ctx):
await ctx.send('I heard you! {0}'.format(ctx.author))
bot.run('token')

As per discord.py documentation, migration to v1.0 brought a lot of major changes in the API, including the fact that a lot of functionality was moved out of discord.Client and put into their respective model.
E.g. in your specific case:
Client.send_message(abc.Messageable) --> abc.Messageable.send()
So your code would be restyled from this:
await client.send_message(message.channel, 'I heard you! {0}'.format(message.author))
to this:
await message.channel.send('I heard you! {0}'.format(message.author))
This makes the code much more consistent and more accurate in depicting the actual discord entities, i.e. it's intuitive that a discord Message is sent to a Channel (subclass of abc.Messageable) and not to the Client itself.
There is a quite large list of migrations in this sense; you can find them all here
under the Models are Stateful section.

The discord.py can't be used for the send_message() function anymore, I think. But this doesn't mean we can not send messages. Another way of sending messages into the channel do exist.
You can use:
await message.channel.send("")
for this purpose.
So let's apply this into your code now.
import asyncio
import discord
client = discord.Client()
#client.async_event
async def on_message(message):
author = message.author
if message.content.startswith('!test'):
print('on_message !test')
await test(author, message)
async def test(author, message):
print('in test function')
await message.channel.send(F'Hi {author}, I heard you.')
client.run("key")
Now this would fix your issue and you'll be able to use your bot to send messages easily.
Thank You! :D

Related

AttributeError: 'Member' object has no attribute 'avatar_url'

I am trying to make a Discord bot and one of the features is a welcoming from my bot using on_member_join. This is the event:
#bot.event
async def on_member_join(member, self):
embed = discord.Embed(colour=discord.Colour(0x95efcc), description=f"Welcome to Rebellions server! You are the{len(list(member.guild.members))}th member!")
embed.set_thumbnail(url=f"{member.avatar_url}")
embed.set_author(name=f"{member.name}", icon_url=f"{member.avatar_url}")
embed.set_footer(text=f"{member.guild}", icon_url=f"{member.guild.icon_url}")
embed.timestamp = datetime.datetime.utcnow()
await welcome_channel.send(embed=embed)
Although when the bot is working and running and someone joins my server I get this error:
[2022-11-07 19:38:10] [ERROR ] discord.client: Ignoring exception in on_member_join
Traceback (most recent call last):
File "C:\Users\stene\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\client.py", line 409, in _run_event
await coro(*args, **kwargs)
File "C:\Users\stene\OneDrive\Documents\GitHub\bot\main.py", line 25, in on_member_join
embed.set_thumbnail(url=f"{member.avatar_url}")
^^^^^^^^^^^^^^^^^
AttributeError: 'Member' object has no attribute 'avatar_url'
I am running the latest version of discord.py and python.
Thanks!
welcome cog:
import discord
from discord.ext import commands
import asyncio
import datetime
class WelcomeCog(commands.Cog, name="Welcome"):
def __init__(self, bot):
self.bot = bot
#commands.Cog.listener()
async def on_member_join(self, member):
embed = discord.Embed(colour=discord.Colour(0x95efcc), description=f"Welcome to Rebellions server! You are the{len(list(member.guild.members))}th member!")
embed.set_thumbnail(url=member.avatar.url)
embed.set_author(name=member.name, icon_url=member.avatar.url)
embed.set_footer(text=member.guild)
embed.timestamp = datetime.datetime.utcnow()
channel = self.bot.get_channel(1038893507961692290)
await channel.send(embed=embed)
async def setup(bot):
await bot.add_cog(WelcomeCog(bot))
print("Welcome cog has been loaded successfully!")
In discord.py 2.0 the attribute Member.avatar_url got removed and replaced by Member.avatar. To access the URL, you should use member.avatar.url.
Check out the migration guide for similar instances. Using pip freeze you can check which version of discord.py you have installed, but I assume it's 2.x, and probably you followed a tutorial or copied a code example that used discord.py 1.x.
Following your code you have several errors, which can be corrected in the following code:
First: async def on_member_join(member, self): is an incorrect code.
self always comes before any other argument if this event is in a cog file, but still it isn't a required argument so completely remove it. The correct code for this line is async def on_member_join(member):
Second: Make sure you're using the correct event listener.
#client.event or #bot.event if this is in your Main file, and #commands.Cog.listener() if this is in your cog file.
Third: Please change (member, self): to (member:discord.Member)
Good luck! :D

AttributeError: 'ClientUser' object has no attribute 'guild_permissions' on Discord.py

I am trying to make a "!invite" command to generate an invite link to the server and send it to the user's DM.
The command works, but I am getting the following error on console:
Ignoring exception in on_message
Traceback (most recent call last):
File "C:\Users\001\Envs\Pix\lib\site-packages\discord\client.py", line 343, in _run_event
await coro(*args, **kwargs)
File "C:\Users\001\PycharmProjects\Testing bot\cogs\invite.py", line 27, in on_message
if ctx.author.guild_permissions.administrator:
AttributeError: 'ClientUser' object has no attribute 'guild_permissions'
Nevertheless, I get the link: My DM screenshot.
How can I fix this error?
Code:
from discord.ext import commands
from var.canais import inviteChannel
class Invite(commands.Cog):
def __init__(self, client):
self.client = client
#commands.command(
name='invite',
pass_context=True
)
async def invite(self, ctx):
invitelink = await ctx.channel.create_invite(
max_uses=1,
unique=True
)
if inviteChannel:
await ctx.message.delete()
await ctx.author.send(f'Invite link: {invitelink}')
#commands.Cog.listener()
async def on_message(self, ctx):
if inviteChannel:
if ctx.author.guild_permissions.administrator:
return
else:
if not ctx.content.startswith('!invite'):
await ctx.delete()
def setup(client):
client.add_cog(Invite(client))
This error is occurring because the on_message event is also called when the bot sends a message, and in your case the bot is sending the message in a dm, therefore it should be a User object (Member objects are guild only), and user objects don't have permissions since they are not inside a server. It's a ClientUser object instead of User which is a special class like User that is unique to the bot. this is a separate class compared to User because this has some special methods that only the bot can use like one for editing the bot's name and more
to fix this just ignore if the message is sent from a bot so the code would be
#commands.Cog.listener()
async def on_message(self, ctx):
if message.author.bot:
return
if inviteChannel:
if ctx.author.guild_permissions.administrator:
return
if not ctx.content.startswith('!invite'):
await ctx.delete()
Here I added if message.author.bot: return so that it stops the function execution if the author is a bot. and I also removed the unnecessary else statement
As the error says:
The line
if ctx.author.guild_permissions.administrator:
throw an AttributeError error because 'ctx.author' (of type ClientUser) does not have guild_permissions attribute.
The error massage also entail that the error was ignored, and so the code proceed without stoping.
I found this
answer that might help you overcome this issue
good luck!

Attribute Error: 'Client' object has no attribute 'command'

from discord.ext import commands
client = commands.Bot(command_prefix='{')
#client.command()
async def ping(ctx):
await ctx.send("Pong!")
I'm extremely new to Python and I'm currently learning how to program a discord bot with discord.py rewrite. I followed this code from a YouTuber named Lucas. This is his exact code. His seems to work but for some reason, my PyCharm still says that client has no attribute command. May someone teach me how to fix it?
This is the error
Traceback (most recent call last):
File "C:/Users/danie/PycharmProjects/Discord Tutorial/bot.py", line 93, in <module>
#client.command()
AttributeError: 'Client' object has no attribute 'command'
With my knowledge, if you wish to continue using the client part of discord.py, then you should try the on_message part of it, An example:
async def on_message(message):
if message.content.startswith('{ping'):
await message.channel.send('pong')
But if you want a reletivly easier alternative, (At least it makes more sense to me) You could try #bot.command Example:
import discord
from discord.ext import commands
TOKEN = ''
bot = commands.Bot(command_prefix='{')
#bot.command()
async def ping(ctx):
await ctx.send('pong')
One great thing about #bot.command is its easier to get input.
If you want to get what the user says after they do the command, then you could do.
#bot.command()
async def ping(ctx, *, variableName):
await ctx.send(f'You said {variableName}')
And if you want an error message if they mess up you could do
#bot.command()
async def ping(ctx, *, variableName):
await ctx.send(f'You said {variableName}')
#ping.error
async def ping_error(ctx, error):
ctx.send("Please enter something after the command")
And in my experience, it is much easier to find help on stackoverflow if you are using #bot.command as most other people use it as well. However, back to you wanting to use #client.command I do not know about that. However, if you want to switch over to #bot.command then I'm sure you can look up what you want to do on either google or stackoverflow and look until you find one for #bot.command Which shouldn't be that long.

How to get your Discord bot to say something specific, then delete the previous message

Im new to working with discord.py, basically im simply trying to make my discord bot say something then delete the previous text, so for example I want to type "/say hello" then I want the bot to grab that, remove the prefix and just print "hello", Ive already googled and searched and found another guide but there was no follow up answers and when I tried the solutions they errored, below is the code im using
import discord
from discord.ext import commands
bot = discord.Client()
prefix = "/"
#bot.event
async def on_ready():
print("Online")
#bot.event
async def on_message(message):
args = message.content.split(" ")[1:]
if message.content.startswith(prefix + "say"):
await bot.delete_message(message)
await bot.send_message(message.channel, " ".join(args))
bot.run("token")
and this is the error the console prints out
C:\Users\unknownuser\anaconda3\envs\discordbot\pythonw.exe C:/Users/unknownuser/PycharmProjects/discordbot/bot.py
Online
Ignoring exception in on_message
Traceback (most recent call last):
File "C:\Users\unknownuser\anaconda3\envs\discordbot\lib\site-packages\discord\client.py", line 313, in _run_event
await coro(*args, **kwargs)
File "C:/Users/unknownuser/PycharmProjects/discordbot/bot.py", line 15, in on_message
await bot.delete_message(message)
AttributeError: 'Client' object has no attribute 'delete_message'
As I start learning the documentation and logic behind it I should start figuring it out for myself but this one has me stumped, Help would be appreciated
Looks like you're using a tutorial for an old version of discord.py.
There are some major changes in the most recent - rewrite - version.
Example for your code
# using the command decorator
#bot.command()
async def say(ctx, *, sentence):
await ctx.message.delete()
await ctx.send(sentence)
#############################################
# using the on_message event
#bot.event
async def on_message(message):
args = message.content.split(" ")[1:]
if message.content.startswith(prefix + "say"):
await message.delete()
await message.channel.send(" ".join(args))
else:
await bot.process_commands(message) # allows decorated commands to work
References:
Message.delete()
Bot.process_commands()
Messageable.send()

AttributeError: 'Client' object has no attribute 'send_message' (Discord Bot)

For some reason send_message isn't working properly on my Discord bot and I can't find anyway to fix it.
import asyncio
import discord
client = discord.Client()
#client.async_event
async def on_message(message):
author = message.author
if message.content.startswith('!test'):
print('on_message !test')
await test(author, message)
async def test(author, message):
print('in test function')
await client.send_message(message.channel, 'Hi %s, i heard you.' % author)
client.run("key")
on_message !test
in test function
Ignoring exception in on_message
Traceback (most recent call last):
File "C:\Users\indit\AppData\Roaming\Python\Python36\site-packages\discord\client.py", line 223, in _run_event
yield from coro(*args, **kwargs)
File "bot.py", line 15, in on_message
await test(author, message)
File "bot.py", line 21, in test
await client.send_message(message.channel, 'Hi %s, i heard you.' % author)
AttributeError: 'Client' object has no attribute 'send_message'
You are probably running the rewrite version of discord.py, since the discord.Client object does not a have a send_message method.
To fix your problem you can just have it as:
async def test(author, message):
await message.channel.send('I heard you! {0.name}'.format(author))
but for what i see you doing I reccomend using the commands extension
This makes creating a bot and commands for the bot much simpler, for example here is some code that does exactly the same as yours
from discord.ext import commands
bot = commands.Bot(command_prefix='!')
#bot.command()
async def test(ctx):
await ctx.send('I heard you! {0}'.format(ctx.author))
bot.run('token')
As per discord.py documentation, migration to v1.0 brought a lot of major changes in the API, including the fact that a lot of functionality was moved out of discord.Client and put into their respective model.
E.g. in your specific case:
Client.send_message(abc.Messageable) --> abc.Messageable.send()
So your code would be restyled from this:
await client.send_message(message.channel, 'I heard you! {0}'.format(message.author))
to this:
await message.channel.send('I heard you! {0}'.format(message.author))
This makes the code much more consistent and more accurate in depicting the actual discord entities, i.e. it's intuitive that a discord Message is sent to a Channel (subclass of abc.Messageable) and not to the Client itself.
There is a quite large list of migrations in this sense; you can find them all here
under the Models are Stateful section.
The discord.py can't be used for the send_message() function anymore, I think. But this doesn't mean we can not send messages. Another way of sending messages into the channel do exist.
You can use:
await message.channel.send("")
for this purpose.
So let's apply this into your code now.
import asyncio
import discord
client = discord.Client()
#client.async_event
async def on_message(message):
author = message.author
if message.content.startswith('!test'):
print('on_message !test')
await test(author, message)
async def test(author, message):
print('in test function')
await message.channel.send(F'Hi {author}, I heard you.')
client.run("key")
Now this would fix your issue and you'll be able to use your bot to send messages easily.
Thank You! :D

Categories