Make bot output embeded (discord.py) - python

So i am making a discord bot and i wrote a SAY command that outputs whatever you say,
import discord
from discord.ext import commands
#client.command()
async def say(ctx, *, message):
await ctx.message.delete() # Deletes last command
await ctx.send(f"{message}" .format(message)) # Send text from command
command .say TEXT
This will output that text as a message from the bot, instead of doing it as a normal message i need this to be a embed

You need to explicitly tell your bot to use an embed, per default it will always send a regular message. Something like the below will output an embed instead of a text message
#client.command()
async def say(ctx, *, message):
await ctx.message.delete() # Deletes last command
await ctx.send(embed=discord.Embed(description=message))
Check the documentation for more information on styling options for the embed (e.g. color, author info etc)

You should create a discord.Embed instance and pass it as embed param in the send function. And f-strings already format the string. If you add an f in front of the quotes, you won't need .format() Like that:
#client.command()
async def say(ctx, *, message):
await ctx.message.delete() # Deletes last command
myEmbed = discord.Embed(description=f"{message}")
await ctx.send(embed=myEmbed)
Embeds are not limited to descriptions, you can also add titles, fields, footers, images, thumbnails, etc.
If you want to learn about the embeds' potentials, you can look at discord.py docs about embeds.

Related

Is there a way to code a "say" command into my discord bot with python?

I have tried different options, and this one was the one that I desired the most, but I cannot seem to get it working. Could I get some help? (Sorry I am very new to coding)
This is my code:
import discord
from discord.ext import commands
client = discord.Client()
bot = commands.Bot(command_prefix='-')
#bot.command()
async def speak(ctx, *, text):
if ctx.message.author.id == ID here:
message = ctx.message
await message.delete()
await ctx.send(f"{text}")
else:
await ctx.send('I need text!')
Thanks
Your else statement makes little sense here. It is best to set up the condition differently, that you want text once and if that does not happen, then there is an else argument.
I don't know if this is relevant either, but apparently it looks like you want only one person to be able to execute this command. For the owner there would be:
#commands.is_owner()
But if you want to make it refer to another person use:
#bot.command()
#commands.is_owner() # If you want to set this condition
async def say(ctx, *, text: str = None):
if ctx.message.author is not ID_You_Want:
await ctx.send("You are not allowed to use the command.")
return # Do not proceed
if text is None: # If just say is passed with no text
await ctx.send("Please insert a text.")
else:
await ctx.send(text) # Send the text
Optional: You can also delete the command that was send with ctx.message.delete()
Your command is not executing because you defined client and bot.
Simply remove client = discord.Client() and you will be fine.

How to copy an embed in discord.py?

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])

How do I resend user input after a command (e.g. User: !send 1234 Bot: 1234) in discord.py?

I have recently started programming my own discord bot as many other people are doing...
So far what I have got is this:
#bot.command
async def on_message(message):
if message.content.startswith("t!send"):
await client.send_message(message.content)
It doesn't crash but it doesn't work either...
It seems as if you're using a tutorial for an old version of discord.py.
There are some big changes in the most recent version - rewrite. Please take some time to look for more updated tutorials, or read the documentation linked above.
Here are the cases for using both the on_message event and commands:
#bot.command()
async def send(ctx, *, sentence):
await ctx.send(sentence)
######################################
#bot.event
async def on_message(message):
args = message.content.split(" ")[1:]
if message.content.startswith("t!send"):
await message.channel.send(" ".join(args))
else:
await bot.process_commands(message) # only add this if you're also using command decorators
References:
commands.Context() - if not familiar with using command decorators
discord.on_message()
Bot.process_commands()
So first of all, on_message doesn't belong here and you also don't have to use it. (on_message() would use the decorator #bot.event) Assuming you have setup a prefix for your bot using bot = commands.Bot(command_prefix = 't!') you could do something like this:
#bot.command()
async def send(ctx, *args):
message = " ".join(args)
await ctx.send(message)
*args is everything the user types in after t!send. So for example: if the user types in t!send Hello world! args would be ["Hello", "world!"]. With .join we can join them together into a single string (message)

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:

How to get a Discord Bot to return the formatted name of a Channel?

I'm attempting to create a Discord bot using Discord.py for a server I'm in, I'm trying to get the bot to mention (blue links) other channels in the server. I thought it would have been using something like discord.TextChannel.name, discord.TextChannel.mention. But neither of those work, they only return something along the lines of "<property object at 0x03CE8B68>".
Code:
import discord
from discord.ext import commands
bot = commands.Bot(command_prefix='$')
client = discord.Client()
token = <token>
#bot.command()
async def test(ctx, arg):
await ctx.send(arg)
#bot.command()
async def mentionChan(ctx):
await ctx.send(ctx.guild.get_channel('662129928463974411').mention)
client.run(token)
#botclient.command()
async def mentionChan(ctx):
await ctx.send(ctx.guild.get_channel(CHANNEL_ID).mention)
This will mention the channel with the given id. You can get the id of a channel by right clicking a channel and selecting "Copy ID". This is only possible after you have turned on developer mode at the appearance tab in User Settings.
ctx.guild.text_channels will give you a list of all the text channels in the server if you want to use that.

Categories

Resources