Im trying to make a bot that send me a message with a reaction button, when I click it, give me a role in the server. Im trying to use on_raw_reaction_add event but I cant reach a solution to make it, Im always getting errors at getting guild roles and this stuff.
In this case, guild is none, I dont know what Im doing wrong.
My code:
#client.command()
async def test(ctx):
global member
global message__id
global channel_id
channel_id = (ctx.channel.id)
member = ctx.message.author
embed = discord.Embed(title="Verify your account", color=0x03fc14)
embed.add_field(name=f"Verification!", value=('React to this message to get verified!'), inline=False)
embed.set_footer(text=ctx.author, icon_url=ctx.author.avatar_url)
mesg = await member.send(embed=embed)
await mesg.add_reaction("✅")
message__id = mesg.id
print("EXECUTED")
#client.event
async def on_raw_reaction_add(payload):
print("reacted")
print("messageid accepted")
guild = client.get_guild(payload.guild_id)
if guild is not None:
print("messageid accepted")
reactor = payload.guild.get_member(payload.member.id)
role = discord.utils.get(guild.roles, name="Member")
if payload.emoji.name == '✅':
print("emoji accepted")
await reactor.add_roles(role)
EDIT:
I changed my on_raw_reaction_add event:
#client.event
async def on_raw_reaction_add(payload):
print("reacted")
print("messageid accepted")
guild = client.get_guild(payload.guild_id)
if guild is not None:
print("guild not none ")
reactor = payload.guild.get_member(payload.member.id)
role = discord.utils.get(guild.roles, name="Verified")
if payload.emoji.name == '✅':
print("emoji accepted")
await reactor.add_roles(role)
else:
print("guild none")
And this is what happen when I try the method:
First three words are the prints of the bot reacting his own message, the "EXECUTED" is the print of test method and the last three messages. are when I react the bot message
In this case, I suggest using a wait_for rather than on_raw_reaction_add.
Example, as seen in the docs:
#client.command(aliases=["t"])
async def test(ctx):
embed = discord.Embed(title="Verify your account", color=0x03fc14)
embed.add_field(name=f"Verification!", value=('React to this message to get verified!'), inline=False)
embed.set_footer(text=ctx.author, icon_url=ctx.author.avatar_url)
# sends message to command author
mesg = await ctx.author.send(embed=embed)
await mesg.add_reaction("✅")
#check if the reactor is the user and if that reaction is the check mark
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) == '✅'
try:
#wait for the user to react according to the checks
reaction, user = await client.wait_for('reaction_add', timeout=60.0, check=check)
except asyncio.TimeoutError:
# 60 seconds without reaction
await ctx.send('Timed out')
else:
await ctx.send('✅')
docs- https://discordpy.readthedocs.io/en/stable/api.html?highlight=wait_for#discord.Client.wait_for
async def test(ctx):
global member
global message__id
global channel_id
channel_id = (ctx.channel.id)
member = ctx.message.author
embed = discord.Embed(title="Verify your account", color=0x03fc14)
embed.add_field(name=f"Verification!", value=('React to this message to get verified!'), inline=False)
embed.set_footer(text=ctx.author, icon_url=ctx.author.avatar_url)
mesg = await member.send(embed=embed)
await mesg.add_reaction("✅")
message__id = mesg.id
print("EXECUTED")
role = get(ctx.guild.roles, id=role id here)
done = False
while done == False:
reaction, user = await client.wait_for(“reaction_add”, check=check)
if user == client.user:
continue
await member.add_roles(role)
done = True
I am pretty sure something like this would work :D
When you do guild is not None, it will never fire because you are reacting in a DM channel context - where the guild is None. To access the guild information from the DM, you'll need to save it somewhere in the message (or save it yourself internally). Then, you have the guild object and you're able to add roles or do things to it.
#client.command()
async def testrole(ctx):
member = ctx.author
# ...
embed = discord.Embed(title="Verify your account", color=0x03fc14)
embed.add_field(name=f"Verification!", value=('React to this message to get verified!'), inline=False)
embed.set_footer(text=ctx.author, icon_url=ctx.author.avatar_url)
mesg = await member.send(str(ctx.guild.id), embed=embed) # we need the guild information somewhere
await mesg.add_reaction("✅")
#client.event
async def on_reaction_add(reaction, user): # there's really no need to use raw event here
if user.id == client.user.id:
return
if reaction.message.guild is None:
if reaction.emoji == '\u2705':
# we have to get the guild that we saved in the other function
# there is no other way to know the guild, since we're reacting in the DM
# that's why it was saved inside of the message that was sent to the user
guild_id = int(reaction.message.content)
guild = client.get_guild(guild_id)
member = guild.get_member(user.id)
await member.add_roles(...) # change this with your roles
** want to make reaction role which if user react message on specific channel will get role
but it doesn't work**
#client.event
async def on_reaction_add(member):
ChannelID = 932268491556405268
role = discord.utils.get(member.guild.roles, id=941124409341648957)
if member.message.channel.id != ChannelID:
return
if member.emoji == "1️⃣":
await member.add_roles(role, reason=None, atomic=True)
You can use the payload object from on_raw_reaction_add to do what you want
#client.event
async def on_raw_reaction_add(payload): # Requires Intents.reactions
channel = client.get_channel(...)
guild = client.get_guild(payload.guild_id)
role = discord.utils.get(guild.roles, id=...)
if str(payload.emoji) == "1️⃣":
await payload.member.add_roles(role, atomic=True)
await channel.send(...)
so i was making a discord bot and made a modmail system and got this error. can someone plz help and tell me where i am going wrong i searched many similar errors but didnt find the answer.
bot:
import random
import os
import sys
import asyncio
from discord.ext import commands
intents = discord.Intents.default()
intents.members = True
client = commands.Bot(command_prefix='-', intents=intents)
client.remove_command("help")
#client.event
async def on_ready():
await client.change_presence(status=discord.Status.idle, activity=discord.Game('Do -help'))
print('functioning...')
#client.event
async def on_member_join(member):
print(f'{member} has joined the server.')
await member.create_dm()
await member.dm_channel.send(f'Hi {member.mention}, welcome to my Discord server!')
#client.event
async def on_member_remove(member):
print(f'{member} has left the server.')
for filename in os.listdir("./cogs"):
if filename.endswith(".py"):
client.load_extension(f'cogs.{filename[:-3]}')
#client.command(brief="Load", help="Loading cogs")
async def load(ctx, extension):
client.load_extension(f'cogs.{extension}')
#client.command(brief="Unload", help="Unloading cogs")
async def unload(ctx, extension):
client.unload_extension(f'cogs.{extension}')
#client.command(brief="Ping", help="The time it takes for a small data set to be transmitted from your device to a server on the Internet and back to your device again.")
async def ping(ctx):
await ctx.send(f'Pong! {round(client.latency*1000)}ms')
#client.command(aliases=['test','8ball', 'future'], brief="8ball", help="A little fun game.")
async def _8ball(ctx, *,question):
responses=[ "It is certain.",
"It is decidedly so.",
"Without a doubt.",
"Yes definitely.",
"You may rely on it.",
"As I see it, yes.",
"Most likely.",
"Outlook good.",
"Yes.",
"Signs point to yes.",
"Reply hazy, try again.",
"Ask again later.",
"Better not tell you now.",
"Cannot predict now.",
"Concentrate and ask again.",
"Don't count on it.",
"My reply is no.",
"My sources say no.",
"Outlook not so good.",
"Very doubtful."]
await ctx.send(f'Question: {question}\nAnswer: {random.choice(responses)}')
#client.command(aliases=['purge','clean'], brief="Purge", help="Clears a fixed number of messahes.")
#commands.has_permissions(manage_messages=True)
async def clear(ctx, amount=5):
await ctx.channel.purge(limit=amount)
#client.command(brief="Kick", help="Kicks a person out of the guild.")
#commands.has_permissions(manage_messages=True)
async def kick(ctx, member:discord.Member, *, reason=None):
message = f"You have been kicked from {ctx.guild.name}, reason: {reason}"
await member.send(message)
await member.kick(reason=reason)
await ctx.send(f'Kicked {member.mention}')
#client.command(brief="Ban", help="Bans a person in the guild.")
#commands.has_permissions(manage_messages=True)
async def ban(ctx, member:discord.Member, *, reason=None):
message = f"You have been banned from {ctx.guild.name}, reason: {reason}"
await member.send(message)
await member.ban(reason=reason)
await ctx.send(f'Banned {member.mention}')
#client.command(brief="Unban", help="Unbans a banned person in the guild.")
#commands.has_permissions(manage_messages=True)
async def unban(ctx, *, user=None):
try:
user = await commands.converter.UserConverter().convert(ctx, user)
except:
await ctx.send("Error: user could not be found!")
return
try:
bans = tuple(ban_entry.user for ban_entry in await ctx.guild.bans())
if user in bans:
await ctx.guild.unban(user, reason="Responsible moderator: "+ str(ctx.author))
else:
await ctx.send("User not banned!")
return
except discord.Forbidden:
await ctx.send("I do not have permission to unban!")
return
except:
await ctx.send("Unbanning failed!")
return
await ctx.send(f"Successfully unbanned {user.mention}!")
class DurationConverter(commands.Converter):
async def convert(self, ctx, argument):
amount=argument[:-1]
unit=argument[-1]
if amount.isdigit() and unit in ['s','m','h','d']:
return(int(amount),unit)
raise commands.BadArgument(message="Not a valid duration")
#client.command(brief="Tempban", help="Temporarily bans a person in the guild.")
#commands.has_permissions(manage_messages=True)
async def tempban(ctx, member: commands.MemberConverter, duration: DurationConverter):
multiplier={'s':1, 'm':60, 'h':3600, 'd':86400}
amount, unit= duration
message = f"You have been banned from {ctx.guild.name}, for {amount}{unit}"
await member.send(message)
await ctx.guild.ban(member)
await ctx.send(f'{member.mention} has been banned for {amount}{unit}')
await asyncio.sleep(amount*multiplier[unit])
await ctx.guild.unban(member)
#client.command(brief="Tempmute", help="Temporarily mutes a person in the guild.")
#commands.has_permissions(manage_messages=True)
async def tempmute(ctx, member: discord.Member, duration: DurationConverter, reason=None):
multiplier = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}
amount, unit = duration
guild = ctx.guild
muteRole = discord.utils.get(guild.roles, name="Muted")
await member.add_roles(muteRole, reason=reason)
await ctx.send(f"{member.mention} has been muted in {ctx.guild} for {amount}{unit}")
await member.send(f"You have been muted in {ctx.guild} for {amount}{unit}")
await asyncio.sleep(amount*multiplier[unit])
await member.remove_roles(muteRole, reason=reason)
await ctx.send(f"{member.mention} has been unmuted in {ctx.guild} ")
await member.send(f"You have been unmuted in {ctx.guild} ")
def restart_bot():
os.execv(sys.executable, ['python'] + sys.argv)
#client.command(name= 'restart', brief="Restart", help="Restarts the bot.")
async def restart(ctx):
await ctx.send("Restarting bot...")
restart_bot()
#client.command( brief="Connects", help="Connects the bot.")
async def connect(self):
print(" bot connected")
#client.command(brief="Disconnects", help="Disconnects the bot.")
async def disconnect(self):
print("bot disconnected")
#client.command(brief="Mute", help="Mutes a person in the guild.")
#commands.has_permissions(manage_messages=True)
async def mute(ctx, member: discord.Member, *, reason=None):
guild = ctx.guild
muteRole = discord.utils.get(guild.roles, name="Muted")
if not muteRole:
await ctx.send("No Mute Role found! Creating one now...")
muteRole = await guild.create_role(name="Muted")
for channel in guild.channels:
await channel.set_permissions(muteRole, speak=False, send_messages=False, read_messages=True,
read_message_history=True)
await member.add_roles(muteRole, reason=reason)
await ctx.send(f"{member.mention} has been muted in {ctx.guild} | Reason: {reason}")
await member.send(f"You have been muted in {ctx.guild} | Reason: {reason}")
#client.command(brief="Unmute", help="Unmutes a muted person in the guild.")
#commands.has_permissions(manage_messages=True)
async def unmute(ctx, member: discord.Member, *, reason=None):
guild = ctx.guild
muteRole = discord.utils.get(guild.roles, name="Muted")
await member.remove_roles(muteRole, reason=reason)
await ctx.send(f"{member.mention} has been unmuted in {ctx.guild}")
await member.send(f"You have been unmuted in {ctx.guild}")
#client.command(brief="Slowmode", help="Enables a rate limit per message.")
#commands.has_permissions(manage_messages=True)
async def slowmode(ctx, time:int):
if (not ctx.author.guild_permissions.manage_messages):
await ctx.send('Cannot run command! Requires: ``Manage Messages``')
return
if time == 0:
await ctx.send('Slowmode is currently set to `0`')
await ctx.channel.edit(slowmode_delay = 0)
elif time > 21600:
await ctx.send('You cannot keep the slowmode higher than 6 hours!')
return
else:
await ctx.channel.edit(slowmode_delay = time)
await ctx.send(f"Slowmode has been set to `{time}` seconds!")
#client.command(brief="Prefix", help="Changes the prefix.")
async def setprefix(ctx, prefix):
client.command_prefix = prefix
await ctx.send(f"Prefix changed to ``{prefix}``")
#client.command(brief="Avatar", help="Displays a guild members pfp.")
async def avatar(ctx, member: discord.Member = None):
if member == None:
member = ctx.author
icon_url = member.avatar_url
avatarEmbed = discord.Embed(title=f"{member.name}\'s Avatar", color=0x802BAE)
avatarEmbed.set_image(url=f"{icon_url}")
avatarEmbed.timestamp = ctx.message.created_at
await ctx.send(embed=avatarEmbed)
client.run(token)
modmail:
import discord
import asyncio
from discord.ext.commands import Cog
client = discord.Client()
sent_users = []
class modmail(Cog):
def __init__(self, bot):
self.bot = bot
#Cog.listener()
async def on_message(self,message):
if message.guild: # ensure the channel is a DM
return
if message.author.bot:
return
if message.author == client.user:
return
if message.author.id in sent_users: # Ensure the intial message hasn't been sent before
return
modmail_channel = discord.utils.get(client.get_all_channels(), name="modmail")
embed = discord.Embed(color=0x00FFFF)
embed.set_author(name=f"Modmail System",
icon_url="https://cdn.discordapp.com/icons/690937143522099220/34fbd058360c3d4696848592ff1c5191.webp?size=1024")
embed.add_field(name='Report a member:', value=f"React with 1️⃣ if you want to report a member.")
embed.add_field(name='Report a Staff Member:', value=f"React with 2️⃣ if you want to report a Staff Member.")
embed.add_field(name='Warn Appeal:', value=f"React with 3️⃣ if you would like to appeal a warning.")
embed.add_field(name='Question:',
value=f"React with 4️⃣ if you have a question about our moderation system or the server rules.")
embed.set_footer(text="Modmail")
msg = await message.channel.send(embed=embed)
await msg.add_reaction("1️⃣")
await msg.add_reaction("2️⃣")
await msg.add_reaction("3️⃣")
await msg.add_reaction("4️⃣")
sent_users.append(message.author.id) # add this user to the list of sent users
try:
def check(reaction, user):
return user == message.author and str(reaction.emoji) in ["1️⃣", "2️⃣", "3️⃣", "4️⃣"]
reaction, user = await client.wait_for("reaction_add", timeout=60, check=check)
if str(reaction.emoji) == "1️⃣":
embed = discord.Embed(color=0x00FFFF)
embed.set_author(name=f"Modmail System",
icon_url="https://cdn.discordapp.com/icons/690937143522099220/34fbd058360c3d4696848592ff1c5191.webp?size=1024")
embed.add_field(name='How to Report:',
value="Send the ID of the person you are reporting and attach add a screen shot of them breaking a rule (can be ToS or a server rule).")
embed.set_footer(text="Report a member ")
await message.author.send(embed=embed)
message = await client.wait_for("message", timeout=60, check=lambda
m: m.channel == message.channel and m.author == message.author)
embed = discord.Embed(title=f"{message.content}", color=0x00FFFF)
await modmail_channel.send(embed=embed)
except asyncio.TimeoutError:
await message.channel.send("Reaction timeout!!!")
#Cog.listener()
async def on_ready(self):
print("modmail ready")
def setup(bot):
bot.add_cog(modmail(bot))
logcog:
import discord
import datetime
from datetime import datetime
from discord.ext.commands import Cog
class Example(Cog):
def __init__(self, client):
self.client = client
#Cog.listener()
async def on_ready(self):
print("log ready")
#Cog.listener()
async def on_message(self, message):
if not message.guild:
pass
else:
if not message.content and message.channel:
pass
else:
channel = discord.utils.get(message.guild.channels, name='log')
embed = discord.Embed(title="Message sent", description=message.author, color=message.author.color,
timestamp=datetime.utcnow())
embed.add_field(name="Message Sent", value=message.content, inline=True)
embed.add_field(name="Channel Sent", value=message.channel, inline=True)
await channel.send(embed=embed)
#Cog.listener()
async def on_message_edit(self, before, after):
if len(before.content)==0 and len(after.content)==0 and len(before.channel)==0:
pass
elif not before.guild:
pass
else:
channel = discord.utils.get(before.guild.channels, name='log')
embed = discord.Embed(title="Message edited", description=before.author, color=before.author.color,
timestamp=datetime.utcnow())
embed.add_field(name="Before edit", value=before.content, inline=True)
embed.add_field(name="After edit", value=after.content, inline=True)
embed.add_field(name="Channel Sent", value=before.channel, inline=True)
await channel.send(embed=embed)
#Cog.listener()
async def on_message_delete(self, message):
if not message.content and message.channel:
pass
elif not message.guild:
pass
else:
channel = discord.utils.get(message.guild.channels, name='log')
embed = discord.Embed(title="Message deleted", description=message.author, color=message.author.color,
timestamp=datetime.utcnow())
embed.add_field(name="Deleted Message", value=message.content, inline=True)
embed.add_field(name="The channel is", value=message.channel, inline=True)
await channel.send(embed=embed)
def setup(client):
client.add_cog(Example(client))
so when i run this code i get the reaction message and embed in the dm but when i click on the reaction i get no further out put and after 60s a message comes reaction timeout. I dont get any error message either.
So I finally solved the problem, which stemmed from the intents setup. In my main file I used this code:
intents = discord.Intents.default()
intents.members = True
bot = commands.Bot(command_prefix='!', intents=intents)
bot.load_extension("cogs.maincog")
bot.run(token)
You may want to do this slightly differently (like by using client), but the important part is the intents. This is apparently because the privileged intent "members" is required when testing for reactions is direct messages. I replaced the client with the Bot class, so the testing function became:
reaction, user = await self.bot.wait_for("reaction_add", timeout=60, check=check)
As far as I have tested, this should work perfectly well but let me know if you have any problems or want me to link the full code.
Edit: Look at how to enable privileged intents here.
i have a little problem with my code and i don't find any solutions,...
I write a code for my discord bot :
#client.event
async def on_message(message):
if message.content.startswith("!init"):
if message.content.split()[1] == 'règles':
id_channel = 893442599019511829
embed = discord.Embed(title = 'Création bot', description = "par Archi's modo")
embed.add_field(name="Règlement de la LSPD", value="En cliquant sur l'icône ✅ vous reconnaissez avoir blablabla,...")
mess = await client.get_channel(id_channel).send(embed=embed)
await mess.add_reaction('✅')
#client.event
async def on_raw_reaction_add(payload):
id_channel = 893442599019511829
id_message = ?????
role_a_donner = "zabloublou"
message_id = payload.message_id
member = payload.member
if message_id == id_message:
guild_id = payload.guild_id
guild = discord.utils.find(lambda g : g.id == guild_id, client.guilds)
if payload.emoji.name == '✅':
role = discord.utils.get(guild.roles, name=str(role_a_donner))
else:
role = discord.utils.get(guild.role, name=payload.emoji.name)
if role is not None:
if member is not None:
await member.add_roles(role)
channel = client.get_channel(id_channel)
await channel.send(member.mention)
And i don't know how can i get id of the message sended by the bot to use it in my function on_raw_reaction_add
Can someone help me please ?
You should consider using wait_for instead for this kind of use.Your method is mostly used for reaction roles.
Here is an example of wait_for reaction grabbed from discord.py docs for wait_for:
#client.event
async def on_message(message):
if message.content.startswith('$thumb'):
channel = message.channel
await channel.send('Send me that 👍 reaction, mate')
def check(reaction, user):
return user == message.author and str(reaction.emoji) == '👍'
try:
reaction, user = await client.wait_for('reaction_add', timeout=60.0, check=check)
except asyncio.TimeoutError:
await channel.send('👎')
else:
await channel.send('👍')
Im making a command where a user can create and delete a private voice channel. For the part where i want to add or delete a channel it wants me to add a variable. I need it to delete the voice channel the user is in. Than you in advance
Code:
client.command()
async def room(ctx, activity=None, *, member : discord.Member = None):
if activity == "STREAMING".lower():
guild = ctx.guild
user = ctx.author
await guild.create_voice_channel(f"Streaming Room - {user}")
await ctx.send("Created streaming room!")
elif activity == "RECORDING".lower():
guild = ctx.guild
user = ctx.author
channel = await guild.create_voice_channel(f"Recording Room - {user}")
everyone = ctx.message.author.guild.default_role
disallow = discord.PermissionOverwrite()
disallow.read_messages = False
disallow.send_messages = False
await channel.set_permissions(everyone, overwrite=disallow)
await ctx.send("Created recording room!")
elif activity == 'ADD'.lower():
await ctx.send(f"{member.mention} has been added to your room")
allow = discord.PermissionOverwrite()
allow.connect = True
allow.speak = True
await channel.set_permissions(member, overwrite=allow)
else:
await ctx.send('Please specify what activity you would like to be doing [streaming, recording]')
General command for the task:
#client.command()
async def delvc(ctx, member: discord.Member):
vc = member.voice.channel
if vc:
await vc.delete()
await ctx.send(f"{member.name}'s voice channel - `{vc.name}` - was deleted!")
else:
await ctx.send(f"{member.name} isn't in a voice channel at the moment.")
References:
Member.voice
discord.VoiceChannel
VoiceChannel.delete()