I know you can't mention inside the actual embed, but how do i mention outside of the embed? like as content (message)? Rn, i am using a python script to send a webhook like this:
Code:
message = prepare_webhooks.discord()
embed = message.embed()
embed.title = f"Done"
embed.add_field("username", item.username)
embed.add_field("mention", "<#&799799447483187210>")
embed.image.url = item.avatar
message.embeds.append(embed)
message = json.loads(json.dumps(
message, default=lambda o: o.__dict__))
x = requests.post(webhook_link, json=message)
Any word on this thx
You actually can use mention in an embed: in field's value and in the embed's description.
Here's a basic command example:
#bot.command()
async def mention(ctx, member=None):
member = member or ctx.author
embed = Embed(description=member.mention)
ctx.send(embed=embed)
If you still want to mention out of the embed, just pass the mention before passing your embed:
#In a command
ctx.send(member.mention, embed=embed)
#In a on_message event
message.channel.send(member.mention, embed=embed)
Reference : discord.abc.Messageable.send
Related
While coding my discord python bot, I was making 2 bot commands. One sends a webhook embed to a specified channel as a placeholder for the embed. The other command edits the embed that I just created as the embed placeholder. My code looks like this. When I run this, range2 is a required argument that is missing and get_embedID is defined as Price1.
#bot.command()
async def addEmbed(ctx):
channel = bot.get_channel(1234567890)
embed = discord.Embed(title='Placeholder')
message = await channel.send(embed=embed)
get_embedID = message.id
return get_embedID
#bot.command()
async def editEmbed(get_embedID, ctx, range1, range2):
message = await ctx.channel.fetch_message(get_embedID)
embed = message.embeds[0]
embed.title(title=f'Open for current prices:')
embed.add_field(description=f'{range1} to {range2}')
new_embed = discord.Embed.from_dict(embed.to_dict())
await get_embedID.edit(embed=new_embed)`
When testing out my code in discord, I first run !addEmbed, and we have an embed placeholder successfully send, and my get_embedID variable has the message id for the embed I just sent.
Then, I run !editEmbed 123 456
I want the !editEmbed command to edit my embed I made in !addEmbed with the embed title and description I have in my editEmbed function with range1 being 123, and range2 being 456.
When I run this, range2 is a required argument that is missing and get_embedID is defined as range1.
I don't know how to make sure my get_embedID argument comes down to the editEmbed function in my code.
The first reason you code didn't work is because ctx was after get_embedID. Since ctx is automatically passed in when the command's callback is called, it needs to be before the other parameters.
Also embed.title is an attribute (of type str) and cannot be called.
In the answer code bellow I changed to modifying the embed itself and fixed it to change the values of the attributes: title & description
Here I have also moved embed_id to a global variable and the addEmbed command then sets it.
Then when editEmbed is called it will use the embed_id set in addEmbed
embed_id = None
#bot.command()
async def addEmbed( ctx):
global embed_id
channel = bot.get_channel(1036408156923887746)
embed = discord.Embed(title="Placeholder")
message = await channel.send(embed=embed)
embed_id = message.id
#bot.command()
async def editEmbed(ctx, range1, range2):
global embed_id
message = await ctx.channel.fetch_message(embed_id) # get the me
embeds = message.embeds # get embeds on message
embed = embeds[0] # first embed
embed.title = f"Open for current prices:" # modify the embeds title
embed.description = f"{range1} to {range2}" # modify the embeds desc
await message.edit(embeds=embeds) # edit the message with the new embed
I'm making a discord bot with Python and I want to send an embed when the use use the command ]kill .So when I tag someone and use the command the output is not the member name.
I need to make it the tagged user's name.
This is my code.
killgifs = ['https://c.tenor.com/1dtHuFICZF4AAAAC/kill-smack.gif' , 'https://c.tenor.com/gQAWuiZnbZ4AAAAC/pokemon-anime.gif' , 'https://c.tenor.com/PJbU0yjG3BUAAAAd/anime-girl.gif' , 'https://c.tenor.com/Re9dglY0sCwAAAAC/anime-wasted.gif']
#bot.command(name='kill')
async def kill (ctx,person) :
author = ctx.author
embed = discord.Embed (color=discord.Color.red())
embed.set_author(name=f'{author} kills {person}')
embed.set_image(url = (random.choice(killgifs)))
await ctx.send(embed=embed)
You can work with discord.Member here since you can't mention a person in an embed title/author field. Simply change your code to the following:
killgifs = ['https://c.tenor.com/1dtHuFICZF4AAAAC/kill-smack.gif',
'https://c.tenor.com/gQAWuiZnbZ4AAAAC/pokemon-anime.gif',
'https://c.tenor.com/PJbU0yjG3BUAAAAd/anime-girl.gif',
'https://c.tenor.com/Re9dglY0sCwAAAAC/anime-wasted.gif']
#bot.command(name='kill')
async def kill(ctx, person: discord.Member): # Make the person a discord.Member
author = ctx.author
embed = discord.Embed(color=discord.Color.red())
embed.set_author(name=f'{author} kills {person.display_name}') # Display the name
embed.set_image(url=(random.choice(killgifs)))
await ctx.send(embed=embed)
I want the bot fetch a message(embed) and send it to channel where command is invoked.
Following code works fine for normal text message:
#bot.command()
async def fetch(ctx):
channel = bot.get_channel(736984092368830468)
msg = await channel.fetch_message(752779298439430164)
await ctx.send(msg.content)
For sending embeds I tried:
#bot.command()
async def fetch(ctx):
channel = bot.get_channel(736984092368830468)
msg = await channel.fetch_message(752779298439430164)
await ctx.send(msg.embeds.copy())
It sends this instead of sending embed:
How do I make the bot copy and send embed?
The problem is that you are trying to send a list of discord.Embed objects as a string in your await ctx.send(msg.embeds.copy())
The ctx.send() method has a parameter called embed to send embeds in a message.
await ctx.send(embed=msg.embeds[0])
Should do the trick. This way you are sending an actual discord.Embed object, instead of a list of discord.Embeds
You should not need the .copy() method in
await ctx.send(embed=msg.embeds[0].copy())
although you can use it
The only downside of using the index operator [0] is that you can only access one embed contained in your message. The discord API does not provide a way to send multiple embeds in a single message. (see this question).
A workaround could be iterating over every embed in the msg.embeds list and send a message for every embed.
for embed in msg.embeds:
await ctx.send(embed=embed)
This unfortunately results in multiple messages being sent by the bot, but you don't really notice.
You have to select the first embed like this and use [copy] if you want to change into it before sending again.(https://discordpy.readthedocs.io/en/latest/api.html?highlight=embed#discord.Embed.copy)
#bot.command()
async def fetch(ctx):
channel = bot.get_channel(736984092368830468)
msg = await channel.fetch_message(752779298439430164)
await ctx.send(embed=msg.embeds[0])
I've created a code that sends the gif of a hug on command and specifies who it's to, however, I also want to make it optional to mention a member.
the current code is:
#client.command()
async def hug(ctx, member):
username = ctx.message.author.display_name
embed = discord.Embed(title = (f'{username} has sent a hug to {member}!'), description = ('warm, fuzzy and comforting <3'), color = 0x83B5E3)
image = random.choice([(url1), (url2),....(url10)])
embed.set_image(url=image)
await ctx.channel.send(embed=embed)
I want to change it so that if the author uses the command and doesn't mention the member, the command still works, and sends one of the gifs instead. Do I have to create an if statement?
Additionally, if it is possible, how do I change it so that the member's display name is used just like how the author's display name is used?
I've tried doing something like this, but it doesn't work:
#client.command()
async def hug(ctx, member):
username = ctx.message.author.display_name
name = member.display_name
embed = discord.Embed(title = (f'{username} has sent a hug to {name}!'), description = ('warm, fuzzy and comforting <3'), color = 0x83B5E3)
image = random.choice([(url1), (url2),...(url10)])
embed.set_image(url=image)
await ctx.channel.send(embed=embed)
Thank you in advance for any help
You can define your member argument to None by default. If you invoke your command without mentionning anyone, member will have None as value and the if member statement won't be triggered.
Also, by defining member as a Member object in the function's arguments, you'll be able to access the mentionned member's informations.
Here's how you use it :
#client.command()
async def hug(ctx, member: discord.Member = None):
if member:
embed = discord.Embed(title=f'{ctx.author} has sent a hug to {member}!',
description='warm, fuzzy and comforting <3',
color=0x83B5E3)
else:
embed = discord.Embed(color=0x83B5E3)
image = random.choice([(url1), (url2),....(url10)])
embed.set_image(url=image)
await ctx.channel.send(embed=embed)
I have been getting into coding my very own discord bot using Discord.py in Thonny, using python version 3.7.6. I want to have an embed when a certain command is typed (!submit) to have the users name as the title and the content of the message as the description. I am fine having !submit ' ' in my embed but if there is any way of taking that out and only having the content of the message minus the !submit i would highly appreciate it. Right now with my code i am getting two errors, one is that the client.user.name is the name of the bot (submit bot) and not the author (old code), and i am getting this message 'Command raised an exception: TypeError: Object of type Member is not JSON serializable' with my new code(below), if anyone could offer insight please reply with the appropriate fixes!
client = commands.Bot(command_prefix = '!')
channel = client.get_channel(707110628254285835)
#client.event
async def on_ready():
print ("bot online")
#client.command()
async def submit(message):
embed = discord.Embed(
title = message.message.author,
description = message.message.content,
colour = discord.Colour.dark_purple()
)
channel = client.get_channel(707110628254285835)
await channel.send(embed=embed)
client.run('TOKEN')
client = commands.Bot(command_prefix = '!')
#got rid of the old channel variable here
#client.event
async def on_ready():
print ("bot online")
#client.command()
async def submit(ctx, *, message): #the `*` makes it so that the message can include spaces
embed = discord.Embed(
title = ctx.author, #author is an instance of the context class
description = message, #No need to get the content of a message object
colour = discord.Colour.dark_purple()
)
channel = client.get_channel(707110628254285835)
await channel.send(embed=embed)
client.run('TOKEN')
Problems:
1. channel is defined twice,
2. function commands in discord.py take an implicit context argument, usually called ctx.
Overall, it looks like you aren't understand the underlying OOP concepts that discord.py has to offer. It might be helpful to refresh your memory with an online class or article.
You're pretty close...
The following items should help:
Working with commands you generally define the context of the command as "ctx", which is the first and sometime only argument. "message" is generally used on message events like async def on_message(message):.
To break out the message from the command itself you add arguments to the function definition.
To get the name of the user you need to cast to a string to avoid the TypeError.
To send the message back in the same channel as the !submit was entered, you can use await ctx.send(embed=embed)
Try:
#client.command()
async def submit(ctx, *, extra=None):
embed = discord.Embed(
title=str(ctx.author.display_name),
description=extra,
colour=discord.Colour.dark_purple()
)
await ctx.send(embed=embed)
Result: