Create embed based of users message - python

I'm quite new to discord.py so I'm posting this here. How do I make a command so that when the user says !embed (message here) #channelhere it turns the users message into an embed and then posts it into the specified channel? An explanation would be nice to so I can try to understand it.

Based on the 2 answers I see, you can send an embed to a specific channel whatever you want by converting the channel into the channel id.
Here's the code :
#client.command()
async def echoembed(ctx, channel : discord.TextChannel, *, Text : str): # full command (!echoembed #channelhere Title here | Description here)
Title, Description = Text.split(' | ') # You need to split the arguments using |, change to other symbols whatever you want
channel_id = channel.id # this will convert the channel name into the channel id
channel_send = client.get_channel(channel_id) # we will get the channel using the channel id
embed = discord.Embed(title = Title, description = Description, color = 0x2F3136)
embed.timestamp = datetime.datetime.utcnow() # this will tell the time today
embed.set_footer(text = "\u200b", icon_url = ctx.author.avatar_url) # the \u200b is an empty character
await channel_send.send(embed = embed) # and finally, we can send the embed
If you're fairly new to discord.py, I suggest you need to read the docs before going into complicated stuff.
The docs will be linked Here
Thank me later :D

Sample code I have:
Eg: I enter !embed hello / wow
#bot.command() #used before a command
async def embed(ctx, *, content: str): #when the person uses !embed it will do what is under. Ctx is needed to store the channel of the message, author of message and other properties. content is the argument, or what you put after the !embed (in this case hello / wow)- we state that it is a string(str) or plain text if that is more clear
title, description= content.split('/') #the title and description of the embed are separated by "/" In this cas, title is "hello",description is "wow"
embed = discord.Embed(title=title, description=description, color=0x00ff40) #making the embed (MUST HAVE TITLE AND DESCRIPTION)
await ctx.send(embed=embed) #sending the embed in THE SAME CHANNEL YOU SENT THE COMMAND IN (as shown via ctx)
await ctx.message.delete() #deleting the original message by you to clean the channel up(as shown by ctx.message)
In terms of specific channel that might be a bit more complicated: however this should work perfectly

Basiclly you have to create a variable called channel that contains the channel ID, for example: channel = bot.get_channel(636399538650742795). Then you create a command that takes an argument, this argument is the message to be embeded, you store the argument in a variable, make a variable called embed, this variable will be embed = discord.Embed(value=argument), wich we will send with await channel.send(embed=embed). The actual code looks like this:
#bot.command()
async def embed(ctx, argument: str):
channel = bot.get_channel(636399538650742795)
embed = discord.Embed()
embed.add_field(name="Message", value=argument)
await channel.send(embed=embed)
To get the channel ID, just right click the channel you want to get the ID of and click Copy ID. And considering that you're very new to discord.py, I am using #bot.command() because I am defining it with bot = commands.Bot(command_prefix="$")

Related

Search discord channels for prefered posting channels

I'm trying to search through text channels for preferred channels to post in. Here's my code that works now.
#bot.event
async def on_guild_join(Guild):
channel_names = ['cool-channel', 'awesome-server', 'chatters-be-chatting']
for ch in channel_names:
try:
channel_id = discord.utils.get(Guild.text_channels, name=ch).id
channel = bot.get_channel(channel_id)
#embed stuff
await channel.send(embed=embed)
break
except:
pass
The main problem I have is if someone uses emojis or Unicode in the name, it'll pass right over it. I guess I'm trying to figure out how to search key works in channel names regardless of whatever else is in the name.
I'm not sure if I understood you correctly, but if you want to match channel names with keywords you give and then post a message in those channels, a code like this below would do.
I made it a #bot.command to test it easily, but I'm sure you can rewrite it to a #bot.event without a problem.
#bot.command()
async def test(ctx):
keywords = ['cool', 'awesome', 'chatters'] # there you can put your keywords to match with channel names
text_channel_list = [] # empty list for channel names in the guild
matches = [] # empty list for channels matching keywords
for channel in ctx.message.guild.text_channels:
text_channel_list.append(str(channel)) # adds every channel in the guild to the text_channel_list
for keyword in keywords:
for text_channel in text_channel_list:
if keyword in text_channel: # looks if keyword is in any channel name
matches.append(text_channel) # if there's a match, it adds the matched channel name to matches list
for match in matches:
channel_id = discord.utils.get(ctx.message.guild.text_channels, name=match).id
channel = bot.get_channel(channel_id)
await channel.send('test') # prints a test message in every channel from the matches list

Discordpy add an add_field to existing embed on command

I'm trying to have a single embed that is going to be used as a list of some sort. I would like for an add_field to be added when a command is pushed to the bot. For example, I want to add to this current embed a new line with embed.add_field(name, value) that is given by a user when activated. How would I go about this? I've tried using message ID and message content but I don't think this is the best method. Thanks in advance.
#bot.command()
async def mangaEmbed(ctx):
embed = discord.Embed(
title = "Completed Self Prints",
#description ="test",
color = discord.Color.blue()
)
#embed.set_footer(text="Footer")
#embed.set_image(url="https://media.discordapp.net/attachments/138231921925816320/902586759773306900/unknown.png?width=810&height=375")
#embed.set_thumbnail(url="https://media.discordapp.net/attachments/138231921925816320/902586759773306900/unknown.png?width=810&height=375")
#embed.set_author(name= "Kyle G", icon_url="https://media.discordapp.net/attachments/138231921925816320/902586759773306900/unknown.png?width=810&height=375")
embed.add_field(name="Kokou no Hito by NggKGG", value="Volumes 1-17", inline=False)
embed.add_field(name="DrangonBall Z\nby NggKGG", value="Kokoue no 222o", inline=False)
embed.add_field(name="Homoculus", value="Volumes 1-24\nManmangaboy", inline=False)
await ctx.send(embed=embed)
The new problem is not being able to pass the discord.Message using the message id
#bot.command()
async def editembed(ctx, vols, *, title):
#just assuming you only want to get the first embed in the message
message = discord.Message(903060490035556383)
print(message)
embed = message.embeds[0]
embed.add_field(name=title, value=vols, inline=False)
await message.edit(embed=embed)
If I understood your question correctly, you want to edit an already sent embed from a different command right?
message has the attribute embeds, which will return a list of embeds the message has. You can use that to get the embed you want and edit it in a separate command.
Something like this should work:
#bot.command()
async def editembed(ctx, message: discord.Message):
#just assuming you only want to get the first embed in the message
embed = message.embeds[0]
embed.add_field(name="test", value="test")
await message.edit(embed=embed)
https://discordpy.readthedocs.io/en/master/api.html?highlight=message#discord.Message.embeds
Edit:
Regarding your second question:
You would have to get your message from somewhere, if it is always the same embed that you want to edit you can just define it inside your command using fetch_message. There are 2 ways to do this, either you would have to also get the channel the message you wanna edit is in, or just use ctx but then you can only use this command in the same channel as the embed that you want to edit.
Option 1 (recommended):
#bot.command()
async def editembed(ctx):
channel = bot.get_channel(1234567890)
message = await channel.fetch_message(1234567890)
Option 2:
#bot.command()
async def editembed(ctx):
message = await ctx.fetch_message(1234567890)
Please keep in mind that embeds can only have 25 fields in them though.

Is there a way to see if a member is being mentioned in the embed?

I am using discord.py and I am trying to get the member object from the command, and when a button is pressed, it edits the message and display's user mod log data. I got it working but in a sort of odd way, it pings the person in the message, and then the event checks to see if there was a ping in (interaction) I am wondering if there is a way to look inside the embed for a mention like instead of interaction.message.mentions is there something like that for embeds instead of message? Thanks in advance!
#client.command()
async def modlogs(ctx, member: discord.Member):
main=discord.Embed(title=" ", description=f"{ctx.author.mention} please use the buttons below to navigate {member.mention}'s modlogs.", color=0x76dba8)
main.set_author(name=f"{member}", icon_url = member.avatar_url)
ram_member = member
await ctx.send(f"{member.mention}",
embed = main,
components=[[
Button(style=ButtonStyle.blue, label="Warnings", custom_id= "blue"),Button(style=ButtonStyle.blue, label="Kicks", custom_id= "red"),Button(style=ButtonStyle.blue, label="Bans", custom_id= "green")
]],
)
#client.event
async def on_button_click(interaction):
print(interaction.message)
if interaction.message.mentions:
if (interaction.message.mentions.__len__() > 0):
for member in interaction.message.mentions:
if collection2.count_documents({"_id": member.id}) == 0:
embed1=discord.Embed(description=f"{member.mention} has no warnings!", color=0xff0000)
embed1.set_author(name="Error")
else:
Get a Message
Msg = await Bot.get_message(channel, id)
Get an Embed
Look at the first answer to [this question][1].
Emb = discord.Embed.from_data(Msg.embeds[0])
Get the fields
Look at the answer to [this question][2].
for field in Emb.fields:
print(field.name)
print(field.value)
Get the description
Look at the first answer to [this question][3].
Des = Emb.description
Search for the mention
>>> Member.mention in Des
True
Searching a mention
A mention begins with ```#!``` and ends with ```>```.
So you might use this fact to search a mention into a string (Embed.description returns a string-type object).
Like this:
Men = Des[Des.find("<#!"):Des.find(">")]
UserID = int(Men[3:])
Member = ctx.fetch_user(UserID)
Links
Discord.py get message embed
How to align fields in discord.py embedded messages
discord.py Check content of embed title
How do I mention a user using user's id in discord.py?
In conclusion
I guess it will work.

Discord.py: How to add another multi-word parameter in a command function?

I am trying to create a announcement function which would send the necessary embed into the channel I specified. I have added the text that has to be sent but now I want it to include images as well.
I can't send links of images inside the embed as they won't work.
I want to send another parameter that will include the image link and send it separately into the chat. I have tried it but it was only for one single image. But when we wanted to enter one more it wouldn't work. I am trying to understand on how to do it.
The following is my code for the command I am working on.
#nd.command()
async def announce(ctx, channel, *, message):
townannouncerole = discord.utils.get(ctx.guild.roles, id=834684222441521193)
townannouncementchannel = nd.get_channel(834675349409234974)
if str(channel.lower()) == 'town':
if townannouncerole in ctx.author.roles:
townannouncementembed = discord.Embed(title="Town Announcement", description=message, color=discord.Colour.random())
townannouncementembed.set_author(name=ctx.author)
townannouncementembed.set_footer(text=datetime.datetime.now())
await townannouncementchannel.send(embed=townannouncementembed)
else:
await ctx.channel.send(f"Hi {ctx.author.mention}, you lack necessary permissions for this command!")
This is the code I used to send a single image and it worked fine.
#nd.command()
async def announce(ctx, channel, images, *, message):
townannouncerole = discord.utils.get(ctx.guild.roles, id=834684222441521193)
townannouncementchannel = nd.get_channel(834675349409234974)
if str(channel.lower()) == 'town':
if townannouncerole in ctx.author.roles:
townannouncementembed = discord.Embed(title="Town Announcement", description=message, color=discord.Colour.random())
townannouncementembed.set_author(name=ctx.author)
townannouncementembed.set_footer(text=datetime.datetime.now())
await townannouncementchannel.send(embed=townannouncementembed)
await townannouncementchannel.send(images)
else:
await ctx.channel.send(f"Hi {ctx.author.mention}, you lack necessary permissions for this command!")
Now the issue is I am not able to understand on How can I send multiple links into the chat by adding another multi-word parameter like the message one that will include every text after it. It is not necessary that you keep the parameters in the order. You can shuffle it in any way you want, to explain and solve.
Thank You! :)
You can't add another multiword parameter into a discord bot command, but what you can do is wait for another response, let me explain:
You can do like this:
#nd.command(name = "sending_links", aliases = ["send_link", "links_send"])
async def sending_links(ctx, channel):
channel = channel or ctx.channel
ctx.send("what links do you want to send? if you want to send many just seperate with \",
\" ex. www.image1.com, www.image2.com")
response = await nd.wait_for("message", timeout=60)
response = response.content.split(", ")
for link in response:
embed = discord.Embed(title = "title", description = "description")
embed.set_image(url = link)
channel.send(embed = embed)
I can't send links of images inside the embed as they won't work.
Yes you can send an image into an embed if you do embed.set_image(url = image_url)
discord.py does not allow to use keyword arguments. So you need to make a argument parser.
Example: !announce --message 'your message' --image 'url'
So you can to it with splitting content from "--" and user arguments as you want.

discordpy suggestion command

My code:
#client.command()
async def suggest(ctx, suggestion):
embed = discord.Embed(
title = "New suggestion.",
description = f"{suggestion}",
color = 0,
timestamp = ctx.message.created_at
)
embed.set_footer(text='Requested by {} | ID-{}' .format(ctx.message.author, ctx.message.author.id))
await ctx.guild.owner.send(embed=embed)
await ctx.send("Suggestion sent to server owner.")
Problem with this command is that bot does not read the whole message, it reads only first word of it.
For example I send this message: =suggest this is suggestion And bot sends embed to a owner only with the first word in this case it will send embed with only this and not whole sentence. If it is possible, how?
You can pass the keyword-only argument
async def suggest(ctx, *, suggestion):
Take a look at the introduction

Categories