discord.py embed message doesn't update - discord.py

sorry for my english^^
I'm doing a discord bot in python (i'm a beginner in python) and i'm doing it step by step. I had some GREAT help here and I want again a little help if possible :)
I don't know how to do it correctly, but i try to edit the embed with the #user who click on the emoji. If someone click on the "tank smiley", it edit the embed on the field "tank", and i want that the 5 fields (1 tank, 1 heal, 3 dps) can be fill.
Tell me if it's possible, and if i'm trying right with discord.edit ?
Thanks :)
# bot.py
import os
from discord.ext import commands
from discord.ext.commands import Bot
import discord
from discord import Embed, Emoji
from dotenv import load_dotenv
import random
import asyncio
load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
GUILD = os.getenv('DISCORD_GUILD')
# On définit le préfixe
bot = commands.Bot(command_prefix='!')
# On print les infos après le lancement du bot et
# on affiche un message d'activité pour le bot.
#bot.event
async def on_ready():
for guild in bot.guilds:
if guild.name == GUILD:
break
print(
f'{bot.user} is connected to the following guild:\n'
f'{guild.name}(id: {guild.id})'
)
await bot.change_presence(activity = discord.Activity(
type = discord.ActivityType.watching,
name = 'Sylàn être mauvais'))
# Commande mm+ dans un embed
#bot.command()
async def mm(ctx, arg, arg2, arg3, help="permet de créer une invit mm+ avec !mm clé niveau heure. Exemple: !mm Boralus +14 21h00"):
embed = discord.Embed(title="Inscription pour {} en {} vers {}" .format(arg, arg2, arg3), description="Composition du groupe") #,color=Hex code
embed.add_field(name="Tank", value="<:tank:761252435720667157>tank\n", inline = False)
embed.add_field(name="Heal", value="<:heal:761252937548169246>heal\n", inline = False)
embed.add_field(name="Dps1", value="<:dps:761252937066217512>dps1\n", inline = False)
embed.add_field(name="Dps2", value="<:dps:761252937066217512>dps2\n", inline = False)
embed.add_field(name="Dps3", value="<:dps:761252937066217512>dps3\n", inline = False)
sent = await ctx.send(embed=embed)
emojis=['<:tank:761252435720667157>', '<:heal:761252937548169246>', '<:dps:761252937066217512>']
for emoji in emojis:
await sent.add_reaction(emoji)
#bot.event
async def on_raw_reaction_add(payload):
channel = bot.get_channel(payload.channel_id)
message = await channel.fetch_message(payload.message_id)
if message.author != payload.member:
return
reaction = discord.utils.get(message.reactions, emoji=payload.emoji.name)
embed = message.embeds[0]
tank = bot.get_emoji(761252435720667157)
heal = bot.get_emoji(761252937548169246)
dps = bot.get_emoji(761252937066217512)
if reaction == 'tank':
embed.set_field_at(1, name='Tank', value='Modified value')
elif reaction == 'heal':
embed.set_field_at(2, name='Heal', value='Modified value')
elif reaction == 'dps':
embed.set_field_at(3, name='Dps', value='Modified value')
await message.edit(embed=embed)
#Message d'erreur si mauvaise utilisation
#mm.error
async def mm_error(ctx, error):
if isinstance(error, commands.MissingRequiredArgument):
await ctx.send("Merci d'utiliser le bot avec !mm clé niveau heure. Exemple: !mm Boralus +14 21h00")
# EOF
bot.run(TOKEN)

You're on the right track with the Message.edit() method.
Since you're just asking for some code, here's a simple example of what you want to do:
#bot.command()
async def send_embed(self, ctx):
embed = (Embed(name='A nice embed')
.add_field(name='Field 1', value='Value 1')
.add_field(name='Field 2', value='Value 2'))
emojis = ['1️⃣', '2️⃣']
message = await ctx.send(embed=embed)
for emoji in emojis:
await message.add_reaction(emoji)
#bot.event
async def on_raw_reaction_add(self, payload):
if payload.member.bot:
return
channel = bot.get_channel(payload.channel_id)
message = await channel.fetch_message(payload.message_id)
embed, emojis = message.embeds[0], ['1️⃣', '2️⃣']
index = emojis.index(payload.emoji.name)
embed.set_field_at(index, name=embed.fields[index].name, value=payload.member.mention, inline=False)
await message.edit(embed=embed)
The advantage with on_raw_reaction_add is that you don't need that while loop anymore, however, it would be triggered if you add a reaction to any message so you'd need to store the message id and compare it. You decide what you prefer :)
References :
on_raw_reaction_add()
Embed.set_field_at()
Message.edit()
discord.utils.get()

Related

How to pass a command funcion over an event one on discordpy?

I made a bot that changes nicknames of members when they type !nick + their nickname and id of a game. The problem is, some people are unaware of how to use the commands to do that, so they get stuck in my registrarion text-chat. Here is the code:
#client.event
async def on_message(message):
channel = message.channel
if message.content.startswith('!nick'):
pass
else:
await channel.send("Algo deu errado aqui. Não esqueça de escrever !nick antes de digitar seu nome e ID do servidor.")
#client.command(pass_context=True)
async def nick(ctx, nickname, sobrenick, ident=''):
autor = ctx.message.author
channel = client.get_channel(channel_id)
if ctx.message.content.startswith('!nick'):
if ident == '':
await autor.edit(nick=nickname + " | " + sobrenick)
await ctx.send(f'Seu nick foi alterado para: {nickname} | {sobrenick}, se confirma digite !entrar pra continuar, se não redigite o nick')
else:
await autor.edit(nick=nickname + " " + sobrenick + " | " + ident)
await ctx.send(f'Seu nick foi alterado para: {nickname} {sobrenick} | {ident}, se confirma digite !entrar pra continuar, se não redigite o nick')
As you guys can see, to solve that I've tried to make an event before the command that triggers whenever a person types something that doesnt start with '!nick', and then made the bot sent a message explaining that they need to use !nick before their actual info to make it work.
I don't know if its because of the 'pass' after the if, or if its because event classes rules above command ones, but I'm a little bit new to python and what I was expecting with that was to the bot just send a message on the channel telling the member to use the right command until he does it right.
But the else condition on the event class just doesnt work. I've tried to include the same else condition on the command class too, following the "if ctx.message.content.startswith('!nick'):", and it doesnt work also...
If you override the default on_message event, you need to add client.process_commands to allow the bot to process the registered commands.
#client.event
async def on_message(message):
...
await client.process_commands(message)
Or you can use client.listen instead of client.event
#client.listen("on_message")
async def my_on_message(message):
...
Here is the FAQ from discord.py about this issue.

Cooldown on on_message event discord.py

I'm trying to make a suggestion system with discord.py. A user DMs the bot a message and the bot sends that message in a specific channel. The code works, I wanted to understand if it is possible to add a cooldown in sending DMs to the bot and how to do it.
#client.event
async def on_message(message):
if not message.author.bot:
if isinstance(message.channel, DMChannel):
if len(message.content) > 700:
await message.channel.send("Suggerimento troppo lungo")
else:
embedMod= discord.Embed(title="Suggerimento:", description=message.content, colour=0xfc5a50, timestamp=datetime.utcnow())
embedMod.set_footer(icon_url="https://s3.us-west-2.amazonaws.com/cdn.lnk.bio/profilepics/-1230732_20210524863.jpg")
embedMod.set_author(name=f'{message.author}', icon_url=f'{message.author.avatar_url}')
mod = client.get_channel(900085945414582312)
await mod.send(embed=embedMod)
await message.channel.send('Suggerimento registrato con successo, grazie mille.')
Update, is correct?
#client.event # Suggerimenti
async def on_message(message):
bucket = cd_mapping.get_bucket(message)
retry_after = bucket.update_rate_limit()
if retry_after:
await message.channel.send("Scimmia")
else:
if not message.author.bot:
if isinstance(message.channel, DMChannel):
if len(message.content) > 700:
await message.channel.send("Suggerimento troppo lungo")
else:
embedMod= discord.Embed(title="Suggerimento:", description=message.content, colour=0xfc5a50, timestamp=datetime.utcnow())
embedMod.set_footer(icon_url="https://s3.us-west-2.amazonaws.com/cdn.lnk.bio/profilepics/-1230732_20210524863.jpg")
embedMod.set_author(name=f'{message.author}', icon_url=f'{message.author.avatar_url}')
mod = client.get_channel(900085945414582312)
await mod.send(embed=embedMod)
await message.channel.send('Suggerimento registrato con successo, grazie mille.')
else:
await client.process_commands(message)
You can do it with discord.py cooldowns:
from discord.ext import commands
cd_mapping = commands.CooldownMapping.from_cooldown(1, 60, commands.BucketType.user)
#client.event
async def on_message(message):
bucket = cd_mapping.get_bucket(message)
retry_after = bucket.update_rate_limit()
if retry_after:
# rate limited
else:
# not rate limited

How to make bot reply to a mention discord.py

I'm making a discord bot and a problem that has come up for me is that the bot won't reply to the user, here is the code
#Code Imports
import discord
import random
from discord import message
from discord import channel
from discord.embeds import Embed
from discord.ext import commands
from discord.ext.commands.bot import Bot
from discord.message import Message
from apikeys import *
from discord import guild
from discord import emoji
from discord import *
from discord import ContentFilter
from discord import channel
from discord import client
#intents
intents=discord.Intents.default()
intents.members=True
#prefix
client=commands.Bot(command_prefix='!',intents=intents)
#Start
#client.event
async def on_ready():
for emoji in client.emojis:
print("Name:", emoji.name + ",", "ID:", emoji.id)
print('Bot is Online {0.user}'.format(client))
print("--------------------------------------------------------------------------------------------------------------------------------------------------------")
client.remove_command('help')
#Commands
#client.command()
async def work(ctx):
await ctx.send('use !war to get up the war menu')
emojigood = '\N{THUMBS UP SIGN}'
emojibad="\N{THUMBS DOWN SIGN}"
#client.command()
async def help(ctx):
embed=discord.Embed(title='Help', description='!war is currently under testing please do not complain about it', color=0x00000)
await ctx.send(embed=embed)
#client.command()
async def war(ctx):
embed = discord.Embed(title='War', description='You are starting a war, do you want to continue?', color=0x00000)
msg = await ctx.send(embed=embed)
await msg.add_reaction(emojigood)
await msg.add_reaction(emojibad)
def check(r, user):
return (r.emoji == emojigood or r.emoji == emojibad) and r.message == msg
#Checks whether the message is the same, and the emoji is one of the accepted ones, and returns either True or False
r, user = await client.wait_for('reaction_add',timeout=10 ,check=check)
#this is equivalent to a event listener within your command, it will stop there until a reaction that meets the requirements has been found
#(This won't block other commands and functions)
if r.emoji == emojigood:
embed = discord.Embed(title='War', description='Please now choose a country', color=0x00000)
await ctx.send(embed=embed)
prefix = "!" #insert your prefix
async def on_message(message):
if message.author == client.user:
return
if message.content == f'{prefix}war': #dont need to use this string, just illustrating the point
await message.channel.send("What country do you want to start a war with?")
def check(msg):
return msg.author == message.author and len(msg.role_mentions) > 0
msg = await client.wait_for('message', check=check)
role = msg.role_mentions[0]
channel = client.get_channel(849230881994047508)
await channel.send(f"{role.mention} {message.author} has declared war on you.")
client.run(token)
What's meant to happen:
Bot: Which role would you like to start a war with
User:#something
Bot:Send information to UN, 'War on #something'
I don't know how to make it see the role mention
You have a couple of issues, the way to make the code you're using function decently is to replace message.content with message.clean_content, however, 1. That will react to any message starting with # or a mention, which is probably not what you want, and 2. any message not beginning with the mention wouldn't work.
You say in your description that you're looking for role mentions, which is a different attribute, and you're looking to send a message, and wait for a response, so here's a piece of sample code that would solve those issues, assuming I'm interpreting your question correctly:
def check(msg):
return msg.author == message.author and len(msg.role_mentions) > 0
msg = await client.wait_for('message', check=check)
role = msg.role_mentions[0]
channel = client.get_channel(ID of the channel)
await channel.send(f"{role.mention} {message.author} has declared war on you."
If I misinterpreted any of what you wanted or you're not sure how some of it works, shoot me a comment and I'll do my best to explain!
Docs reference for slightly more complex objects used:
role_mentions,
wait_for(),

how do i resolve this [ discord.py ]

how are you doing today i sure hope your doing great im sorry for the spam on other account i apologize. ok so my problem is that i switched from client to bot basically bot = commands.Bot i tried renaming all the commmands to bot.event or bot.command can someone pls help me pls i would appreciate it thank you here is the code :)
#bot.command()
async def ping(ctx):
await ctx.send(f'Pong!\n`{round(client.latency*1000)}ms`')
#bot.command(aliases=['8ball'])
async def _8ball(ctx, *, question):
responses = [ "It is certain.",
"As I see it, yes",
"Ask again later.",
"Better not tell you now.",
"Cannot predict now.",
"Concentrate and ask again.",
"Don't count it",
"It is certain.",
"It is decidedly so.",
"Most likely.",
"My reply is no."
"My sources say no.",
"Outlook not so good.",
"Outlook good.",
"Reply hazy, try again.",
"Signs point to yes.",
"Very doubtful.",
"Without a doubt.",
"Yes.",
"Yes – definitely.",
"You may rely on it." ]
await ctx.send(f'Question: {question}\nAnswer: {random.choice(responses)}')
#commands.has_permissions(ban_members=True)
#bot.command()
async def kick(ctx, user: discord.Member, *, reason="No reason provided"):
await user.ban(reason=reason)
kick = discord.Embed(title=f":boom: Kicked {user.name}!", description=f"Reason: {reason}\nBy: {ctx.author.mention}")
await ctx.message.delete()
await ctx.channel.send(embed=kick)
await user.send(embed=kick)
#commands.has_permissions(ban_members=True)
#bot.command()
async def ban(ctx, user: discord.Member, *, reason="No reason provided"):
await user.ban(reason=reason)
ban = discord.Embed(title=f":boom: Banned {user.name}!", description=f"Reason: {reason}\nBy: {ctx.author.mention}")
await ctx.message.delete()
await ctx.channel.send(embed=ban)
await user.send(embed=ban)
#bot.command()
async def unban(ctx, *, member):
banned_users = await ctx.guild.bans()
member_name, member_discriminator = member.split('#')
for ban_entry in banned_users:
user = ban_entry.user
if (user.name, user.discriminator) == (member_name, member_discriminator):
await ctx.guild.unban(user)
await ctx.channel.send(f"Unbanned: {user.mention}")
#bot.command(pass_context = True)
async def mute(ctx, user_id, userName: discord.User):
if ctx.message.author.server_permissions.administrator:
user = ctx.message.author
role = discord.utils.get(user.server.roles, name="Muted")
#bot.command()
async def serverinfo(ctx):
name = str(ctx.guild.name)
description = str(ctx.guild.description)
owner = str(ctx.guild.owner)
id = str(ctx.guild.id)
region = str(ctx.guild.region)
memberCount = str(ctx.guild.member_count)
icon = str(ctx.guild.icon_url)
embed = discord.Embed(
title=name + " Server Information",
description=description,
color=discord.Color.blue()
)
embed.set_thumbnail(url=icon)
embed.add_field(name="Owner", value=owner, inline=True)
embed.add_field(name="Server ID", value=id, inline=True)
embed.add_field(name="Region", value=region, inline=True)
embed.add_field(name="Member Count", value=memberCount, inline=True)
await ctx.send(embed=embed)
await client.add_roles(user, role)
#bot.command()
async def setdelay(ctx, seconds: int):
await ctx.channel.edit(slowmode_delay=seconds)
await ctx.send(f"Set the slowmode delay in this channel to {seconds} seconds!")
#bot.command()
async def afk(ctx, mins):
current_nick = ctx.author.nick
await ctx.send(f"{ctx.author.mention} has gone afk for {mins} minutes.")
await ctx.author.edit(nick=f"{ctx.author.name} [AFK]")
counter = 0
while counter <= int(mins):
counter += 1
await asyncio.sleep(60)
if counter == int(mins):
await ctx.author.edit(nick=current_nick)
await ctx.send(f"{ctx.author.mention} is no longer AFK")
break
def setup(bot):
bot.add_cog(Afk(bot))
def user_is_me(ctx):
return ctx.message.author.id == "Your ID"
def convert(time):
pos = ["s","m","h","d"]
time_dict = {"s" : 1, "m" : 60, "h" : 3600, "d": 3600*24}
unit = time[-1]
if unit not in pos:
return -1
try:
val = int(time[:-1])
except:
return -2
return val * time_dict[unit]
#bot.command()
#commands.has_permissions(kick_members=True)
async def giveaway(ctx):
await ctx.send("Let's start with this giveaway! Answer these questions within 15 seconds!")
questions = ["Which channel should it be hosted in?", "What should be the duration of the giveaway? (s|m|h|d)", "What is the prize of the giveaway?"]
answers = []
def check(m):
return m.author == ctx.author and m.channel == ctx.channel
for i in questions:
await ctx.send(i)
try:
msg = await bot.wait_for('messsage', timeout=15.0, check=check)
except asyncio.TimeoutError:
await ctx.send('You didn\'t answer in time, please be quicker next time!')
return
else:
answers.append(msg.content)
try:
c_id = int(answers[0][2:-1])
except:
await ctx.send(f"You didn't mention a channel properly. Do it like this {ctx.channel.mention} next time.")
return
channel = bot.get_channel(c_id)
time = convert(answers[1])
if time == -1:
await ctx.send(f"You didn't answer with a proper unit. Use (s|m|h|d) next time!")
return
elif time == -2:
await ctx.send(f"The time just be an integer. Please enter an integer next time.")
return
prize = answers[2]
await ctx.send(f"The giveaway will be in {channel.mention} and will last {answers[1]} seconds!")
embed = discord.embed(title = "Giveaway!", description = f"{prize}", color = ctx.author.color)
embed.add_field(name = "Hosted by:", value = ctx.author.mention)
embed.set_footer(text = f"Ends {answers[1]} from now!")
my_msg = await channel.send(embed = embed)
await my_msg.add_reaction("🎉")
await asyncio.sleep(time)
new_msg = await channel.fetch_message(my_msg.id)
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(bot.user))
winner = random.choice(users)
await channel.send(f"Congratulations! {winner.mention} won the prize: {prize}!")
#bot.command()
#commands.has_permissions(kick_members=True)
async def reroll(ctx, channel : discord.TextChannel, id_ : int):
try:
new_msg = await channel.fetch_message(id_)
except:
await ctx.send("The ID that was entered was incorrect, make sure you have entered the correct giveaway message ID.")
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(bot.user))
winner = random.choice(users)
await channel.send(f"Congratulations the new winner is: {winner.mention} for the giveaway rerolled!")
if you want me to answer anything to help you solve it feel free to comment thank you so much have a great day!
It seems like you copied most of the code from the internet and bashed it together to create a bot or a cog (based on your question I would guess a bot).
Assuming this is a snippet of your main bot file and not a cog there are a couple of things that could be different:
Put your utility functions in one place (peferably after your import statatements). It's good practise overall and makes more readeable code.
Unless you have a cog class in the same file as your bot instance (which is bad practise) you shouldn't need this:
def setup(bot):
bot.add_cog(Afk(bot))
If there is a cog class named Afk you should move it into a separate file (putting the cog class into the main bot file defeats the purpose of the cog)
In your mute command you have pass_context = True. This is from the old version of discord.py and is no longer needed.
I can't tell you much more since there's no point in trying to debug your code since you didn't give us any errors or stacktrace to work with.
It is very exhausting, so you can just leave client in every command, just write this client = commands.Bot(command_prefix = 'your prefix') it is the same bot, but it just has a different name.
If you meant that, because i didn't really understand what you need

My giveaway cog command isn't working for some reason

So I made a giveaway command in a cog, and for some weird reason it's not working. I'm not getting any errors or anything. Since it's "interactive", the first two questions work fine but once it asks for the prize, it just freezes and doesn't do anything after that. My friend is also working on a different bot and gave me his code which worked perfectly on his end, but not on mine. Here is my code:
import discord
from discord.ext import commands
from discord.ext.commands import BucketType, cooldown, CommandOnCooldown
import random
import json
import datetime
import asyncio
class Giveaway(commands.Cog):
"""Giveaway commands. You must have manage message permissions to use these"""
def __init__(self, bot):
self.bot = bot
# Helper functions
def convert(self, time):
pos = ["s", "m", "h", "d"]
time_dict = {"s": 1, "m": 60, "h": 3600, "d": 2600*24}
unit = time[-1]
if unit not in pos:
return -1
try:
val = int(time[:-1])
except:
return -2
return val * time_dict[unit]
# Bot Events
# Bot Commands
#commands.command()
#commands.has_permissions(kick_members=True)
async def giveaway(self, ctx, host: discord.Member):
await ctx.send("Let's start with this giveaway! Answer these questions within 15 seconds!")
questions = ["Which channel should it be hosted in?",
"What should be the duration of the giveaway? (s|m|h|d)",
"What is the prize of the giveaway?"]
answers = [f"{ctx.channel.mention}"]
def check(m):
return m.author == ctx.author and m.channel == ctx.channel
for i in questions:
await ctx.send(i)
try:
msg = await self.bot.wait_for('message', timeout=15.0, check=check)
except asyncio.TimeoutError:
await ctx.send('You didn\'t answer in time, please be quicker next time!')
return
else:
answers.append(msg.content)
try:
c_id = int(answers[0][2:-1])
except:
await ctx.send(f"You didn't mention a channel properly smh")
return
channel = self.bot.get_channel(c_id)
time = convert(answers[2])
prize = answers[3]
await ctx.send(f"The giveaway for {prize} will be in {channel.mention} and will last {answers[2]}!! Hosted by {host.mention}")
embed = discord.Embed(title="Giveaway!", description=f"{prize}", color=discord.Colour.dark_purple())
embed.add_field(name="Hosted by:", value=f"{host}")
embed.set_footer(text=f"Ends {answers[2]} from now!")
my_msg = await channel.send(embed=embed)
await my_msg.add_reaction("🎉")
await asyncio.sleep(time)
new_msg = await channel.fetch_message(my_msg.id)
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(self.bot.user))
winner = random.choice(users)
await channel.send(f"Congratulations! {winner.mention} won the prize: {prize} from {host.mention}!!")
def setup(bot):
bot.add_cog(Giveaway(bot))
Please let me know what I should do to fix it!!

Resources