How to fetch and edit embeds in discord.py? - python

I want the bot to fetch embeds and scroll between them . Here is what I tried doing:
#commands.command()
async def test(self,ctx):
chan = self.bot.get_channel(746339276983238677)
message1 = await chan.fetch_message(761267709438328904)
message2 = await chan.fetch_message(761267744721076265)
message3 = await chan.fetch_message(761267778639495168)
page1= message1.embeds[0]
page2= message2.embeds[0]
page3= message3.embeds[0]
contents = [page1,page2,page3]
pages = 3
cur_page = 1
message = await ctx.send(f"Page {cur_page}/{pages}:\n{contents[cur_page-1]}")
await message.add_reaction("◀️")
await message.add_reaction("▶️")
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) in ["◀️", "▶️"]
while True:
try:
reaction, user = await self.bot.wait_for("reaction_add", timeout=60, check=check)
if str(reaction.emoji) == "▶️" and cur_page != pages:
cur_page += 1
await message.edit(content=f"Page {cur_page}/{pages}:\n{contents[cur_page-1]}")
await message.remove_reaction(reaction, user)
elif str(reaction.emoji) == "◀️" and cur_page > 1:
cur_page -= 1
await message.edit(content=f"Page {cur_page}/{pages}:\n{contents[cur_page-1]}")
await message.remove_reaction(reaction, user)
else:
await message.remove_reaction(reaction, user)
except asyncio.TimeoutError:
await message.delete()
break
It doesn't send the embeds. it sends this:
How do I fetch embeds and send them and then how to I edit them?

In order to send an embed, you're supposed to use
await ctx.send(embed=embed_variable)
attaching it to the message. You're sending the actual embed instance where it expects a string. So in your case, you should use
await ctx.send(embed=contents[cur_page-1])
Afterwards, you can edit them like you want to, using the usual embed methods & attributes (add_field, set_footer, ...).

Related

Discord.py turning a text into an embed (with pages)

I'm going to need some help with this, as I don't understand it.
I have a code which turns the page of what the bots says through reactions, the code is below:
client.command()
async def help2(ctx):
contents = ["This is page 1!", "This is page 2!", "This is page 3!", "This is page 4!"]
pages = 4
cur_page = 1
message = await ctx.send(f"Page {cur_page}/{pages}:\n{contents[cur_page-1]}")
# getting the message object for editing and reacting
await message.add_reaction("◀️")
await message.add_reaction("▶️")
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) in ["◀️", "▶️"]
# This makes sure nobody except the command sender can interact with the "menu"
while True:
try:
reaction, user = await client.wait_for("reaction_add", timeout=60, check=check)
# waiting for a reaction to be added - times out after x seconds, 60 in this
# example
if str(reaction.emoji) == "▶️" and cur_page != pages:
cur_page += 1
await message.edit(content=f"Page {cur_page}/{pages}:\n{contents[cur_page-1]}")
await message.remove_reaction(reaction, user)
elif str(reaction.emoji) == "◀️" and cur_page > 1:
cur_page -= 1
await message.edit(content=f"Page {cur_page}/{pages}:\n{contents[cur_page-1]}")
await message.remove_reaction(reaction, user)
else:
await message.remove_reaction(reaction, user)
# removes reactions if the user tries to go forward on the last page or
# backwards on the first page
except asyncio.TimeoutError:
await message.delete()
break
# ending
So this is the code, however I want to make it an embed that can be used as a help page with reactions (setfooter and author too)!
Sorry as I'm new at this!
I'm not particularly good at python either but I found this worked for me:
client = commands.Bot(command_prefix = "!", help_command = None)
#client.command()
async def help(ctx):
pages = 4
cur_page = 1
contents = ["This is page 1!", "This is page 2!", "This is page 3!", "This is page 4!"]
embed=discord.Embed(title="Help page", description=(f"Page {cur_page}/{pages}:\n{contents[cur_page-1]}"), color=0x00ffc8)
embed.set_author(name=ctx.author.display_name,icon_url=ctx.author.avatar_url)
embed.set_footer(text="footer")
message = await ctx.send(embed=embed)
# getting the message object for editing and reacting
await message.add_reaction("◀️")
await message.add_reaction("▶️")
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) in ["◀️", "▶️"]
# This makes sure nobody except the command sender can interact with the "menu"
while True:
try:
reaction, user = await client.wait_for("reaction_add", timeout=60, check=check)
# waiting for a reaction to be added - times out after x seconds, 60 in this
# example
if str(reaction.emoji) == "▶️" and cur_page != pages:
cur_page += 1
new_embed=discord.Embed(title="Help page", description=(f"Page {cur_page}/{pages}:\n{contents[cur_page-1]}"), color=0x00ffc8)
new_embed.set_author(name=ctx.author.display_name,icon_url=ctx.author.avatar_url)
new_embed.set_footer(text="footer")
await message.edit(embed=new_embed)
await message.remove_reaction(reaction, user)
elif str(reaction.emoji) == "◀️" and cur_page > 1:
cur_page -= 1
new_embed=discord.Embed(title="Help page", description=(f"Page {cur_page}/{pages}:\n{contents[cur_page-1]}"), color=0x00ffc8)
new_embed.set_author(name=ctx.author.display_name,icon_url=ctx.author.avatar_url)
new_embed.set_footer(text="footer")
await message.edit(embed=new_embed)
await message.remove_reaction(reaction, user)
else:
await message.remove_reaction(reaction, user)
# removes reactions if the user tries to go forward on the last page or
# backwards on the first page
except asyncio.TimeoutError:
await message.delete()
break
# ending

Cogs Help In Discord Py

I am trying to create a command wherein if you react on the embed, the bot sends something back. If I add this code to a cog, it won't work. If possible, can you tell me why?
#bot.command(aliases=['test','t'])
async def Test(self, ctx):
TestEmbed = discord.Embed(title="Definition", description="This is just a test embed", color=11027200)
TestEmbed.add_field(name="\u200b", value="▹❁❁▹❁◃❁❁◃",inline=False)
emojis = ['⬅️','➡️']
TestEmbedAdd = await ctx.send(embed=TestEmbed)
for emoji in emojis:
await TestEmbedAdd.add_reaction(emoji)
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) in ['⬅️', '➡️']
try:
reaction, user = await bot.wait_for('reaction_add', timeout=5, check=check)
if reaction.emoji == '➡️':
await ctx.send("Reaction 2!")
elif reaction.emoji == '⬅️':
await ctx.send("Reaction 1!")
except asyncio.TimeoutError:
await ctx.send("Time is out!")
With the help of the people in the comment section, I have found the problem with my code. I had to change bot.command into commands.command. (I've tried both bot and command, and it still works splendidly). The other crucial thing I had to add was "self" under bot.wait_for. Without the self, the command wouldn't work. Thank you so much for the help.
#commands.command(aliases=['test','t'])
async def Testing(self, ctx):
TestEmbed = discord.Embed(title="Definition", description="This is just a test embed", color=11027200)
TestEmbed.add_field(name="\u200b", value="▹❁❁▹❁◃❁❁◃",inline=False)
emojis = ['⬅️','➡️']
TestEmbedAdd = await ctx.send(embed=TestEmbed)
for emoji in emojis:
await TestEmbedAdd.add_reaction(emoji)
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) in ['⬅️', '➡️']
try:
reaction, user = await self.bot.wait_for('reaction_add', timeout=5, check=check)
if reaction.emoji == '➡️':
await ctx.send("Reaction 2!")
elif reaction.emoji == '⬅️':
await ctx.send("Reaction 1!")
except asyncio.TimeoutError:
await ctx.send("Time is out!")
you need #commands.command instead of #bot.command

I want my bot to send an embed when whenever a user reacts to the above message. Not sure how i would exactly go about doing this

#client.command()
async def ra(ctx):
embed = discord.Embed(
colour=discord.Colour.blue(),
title="RIDEALONG REQUEST",
description=str(ctx.author.mention) + " IS REQUESTING A RIDEALONG IN SERVER."
)
embed.add_field(name="For FTOs", value="Please react to this message to accept the Ride-Along.", inline=False)
embed.timestamp = datetime.utcnow()
embed.set_footer(text= "This message will automatically delete in two hours")
msg = await ctx.send(embed=embed, delete_after=7200)
await msg.add_reaction('✔️')
await msg.add_reaction('❌')
await ctx.message.delete()
enter image description here
You can use different events. Mostly we wait_for a reaction_add.
I personally use the following:
try:
reaction, user = await client.wait_for('reaction_add')
while user == client.user:
reaction, user = await client.wait_for('reaction_add')
if str(reaction.emoji) == "YourEmoji":
# Do what you want to do
except Exception: # Timeout can be added for example
return
Here we check that the bot reaction is not counting as a valid reaction but instead a user one.
The full code would be:
#client.command()
async def ra(ctx):
embed = discord.Embed(
colour=discord.Colour.blue(),
title="RIDEALONG REQUEST",
description=str(ctx.author.mention) + " IS REQUESTING A RIDEALONG IN SERVER.")
embed.add_field(name="For FTOs", value="Please react to this message to accept the Ride-Along.", inline=False)
embed.timestamp = datetime.datetime.utcnow()
embed.set_footer(text="This message will automatically delete in two hours")
msg = await ctx.send(embed=embed, delete_after=7200)
await msg.add_reaction('✔️')
await msg.add_reaction('❌')
await ctx.message.delete()
try:
reaction, user = await client.wait_for('reaction_add')
while user == client.user:
reaction, user = await client.wait_for('reaction_add')
if str(reaction.emoji) == "✔️":
# Do what you want to do
except Exception:
return

Cannot Check Reaction In Discord.py

So basically i was making a modmail system and the problem was we wanted the person who dmed the bot has to react to ✅ if he reacts then the bot has to reply him "OK"
but the code was not working so what is the problem how to fix it?
import discord
import asyncio
client = discord.Client()
#client.event
async def on_message(message):
# empty_array = []
# modmail_channel = discord.utils.get(client.get_all_channels(), name="mod-mail")
if message.author == client.user:
return
if str(message.channel.type) == "private":
embed = discord.Embed(title='Confirmation',
color=0x03d692)
embed.add_field(name="You're sending this message to **The Dynamic Legends**", value="React with :white_check_mark: to confirm." + "\nTo cancel this request, react with :x:.", inline=False)
confirmation_msg = await message.author.send(embed=embed)
await confirmation_msg.add_reaction('✅')
await confirmation_msg.add_reaction('❌')
sent_users = []
sent_users.append(message.author.name)
try:
print('Working')
def check1(reaction, user):
return user == client.user and user!='Mod Mail Humara#5439' and str(reaction.emoji) == '✅'
reaction, user = await client.wait_for("reaction_add", timeout=30.0, check=check1)
# print(reaction, user)
if str(reaction.emoji) == '✅':
message.author.send('yes)
client.run('TOKEN')
There's a logic problem in the check func
return user == client.user
It simply doesn't make sense, instead of == use != and don't put the user!='Mod Mail Humara#5439' part
Your check func fixed:
def check1(reaction, user):
return user != client.user and str(reaction.emoji) == '✅'
Also message.author.send is a coroutine, so you need to await it
await message.author.send("whatever")
Your code:
#client.event
async def on_message(message):
if message.author == client.user:
return
if isinstance(message.channel, discord.DMChannel):
embed = discord.Embed(title='Confirmation', color=0x03d692)
embed.add_field(name="You're sending this message to **The Dynamic Legends**", value="React with :white_check_mark: to confirm." + "\nTo cancel this request, react with :x:.", inline=False)
confirmation_msg = await message.author.send(embed=embed)
await confirmation_msg.add_reaction('✅')
await confirmation_msg.add_reaction('❌')
sent_users = []
sent_users.append(message.author.name)
try:
def check1(reaction, user):
return user != client.user and str(reaction.emoji) == '✅'
reaction, user = await client.wait_for("reaction_add", timeout=30.0, check=check1)
if str(reaction.emoji) == '✅':
await message.author.send('yes')
except Exception as e:
pass

(discord.py) wait_for function not checking if author reacted to message

I'm creating a "delete faction" command for my faction bot which asks the user to confirm that they want to delete their faction using reactions. My code is as follows:
embed = discord.Embed(
title=":warning: Are you sure?",
colour=discord.Colour.purple(),
description=f"Are you sure you want to delete **{name_capital}**? "
f"*Your members will lose their roles and so will you.*"
)
txt = await ctx.send(embed=embed)
await txt.add_reaction("✅")
await txt.add_reaction("❌")
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) == "✅" or "❌"
try:
reaction, user = await self.client.wait_for('reaction_add', timeout=8.0, check=check)
except asyncio.TimeoutError:
embed = discord.Embed(
title=":x: Deletion cancelled",
colour=discord.Colour.purple(),
description="Message timed out"
)
await txt.delete()
await ctx.send(embed=embed)
else:
if reaction.emoji == "❌":
await txt.delete()
elif reaction.emoji == "✅":
pass # delete faction code
The command works for the most part. But, it also works for other users who react to the message, despite me stating that not to happen in the check function.
What is wrong and how can I fix it?
Just a guess, but your check function could be malformed. Should be like this:
def check(reaction, user):
return user == ctx.author and (str(reaction.emoji) == "✅" or "❌")

Categories

Resources