Discord Python Argument missing when it's defined - python

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

Related

discord py create_guild did not return

I'm trying to use discord py 2.0.0 to create a guild and give me the invite URL.
However, when he executes to
guild = await self.bot.create_guild(name="My server")
he will not execute the following codes
async def create(self, interaction: discord.Interaction):
await interaction.response.send_message("a")
guild = await self.bot.create_guild(name="My server")
await interaction.response.send_message("b")
inv = await guild.text_channels[0].create_invite()
await interaction.response.send_message(inv.url)
Then when I additionally execute the program below, he lists that server.
Sorry my English is not well.
I want some way can create a guild and it's invite url in a command.
I managed to get this working this morning. The issue is that the guild object returned from bot.create_guild won't necessarily have the channels cached - you gotta fetch them. And then, the first "channel" in the list of channels is a category - so we want to filter them for actual text channels.
Code is slightly different to yours as I was quick prototyping; you can adapt for your needs accordingly.
#client.slash_command()
async def create(interaction: discord.Interaction):
new_guild = await client.create_guild(name="A test Guild") # type: discord.Guild
actual_guild = await client.fetch_guild(new_guild.id)
channels = await actual_guild.fetch_channels()
channel = [c for c in channels if type(c) == discord.TextChannel][0] # type: discord.TextChannel
invite = await channel.create_invite()
print(invite.url)
await interaction.response.send_message(f"Invite: {invite.url}")
Working fine as below.

How can I send the member name when a user tag someone

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)

Discord Mentions in Embed

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

How do I make mentioning a member optional within a command?

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)

Discord.py trying to get the message author in my 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:

Categories

Resources