I have this embed with rules to my discord server and the embed also has a reaction, the reaction is a check mark(✅). If you react to that embed with that check mark you will get a "Verify" role and your reaction will be deleted.
So it always gonna be one reaction and if u react you get "Verify" role and your reaction get deleted.
But that is the problem, I don't get my role when I react and my reaction doesn't get deleted either. I don't have any errors don't know how to fix this.
This is my code
#bot.command(name='rules', pass_ctx=True)
async def rules(ctx):
rules_embed = discord.Embed(title='DISCORD RULES', color=0xf30000)
rules_embed.add_field(name="**1. No spamming** ", value="Don't send a lot of small/big messages right after "
"each other. Do not disrupt chat by spamming.",
inline=False)
rules_embed.add_field(name="**2. No NSFW material** ", value="This is a community server and not meant to "
"share this kind of material.", inline=False)
rules_embed.add_field(name="**3. No bullying or threats** ", value="Threats to other users of DDoS(Distributed "
"Denial of Service), Death, DoX/Doxx, abuse, "
"and other "
"malicious threats are absolutely not okay.",
inline=False)
rules_embed.add_field(name="**4. Don't beg for ranks** ", value="Don't beg for staff or other ranks", inline=False)
rules_embed.add_field(name="**5. No racism** ", value="Racism is absolutely not okay in this discord server",
inline=False)
rules_embed.add_field(name="**6. Have fun** ", value="Just have fun and be nice", inline=False)
send_rules = await ctx.message.channel.send(embed=rules_embed)
reactions = ['✅']
for i in reactions:
await send_rules.add_reaction(i)
#bot.event
async def on_raw_reaction_add(payload):
channel = bot.get_channel(payload.channel_id)
message = await channel.fetch_message(payload.message_id)
guild = bot.get_guild(payload.guild_id)
reaction = discord.utils.get(message.reactions, emoji=payload.emoji.name)
# only work if it is the client
if payload.member.id == bot.user.id:
return
if payload.message_id == 784182764009947177 and reaction.emoji == '✅':
roles = discord.utils.get(guild.roles, name='Verify')
await payload.member.add_roles(roles)
await reaction.remove(payload.member)
Thanks for the help!
You had several mistakes in the code, I have fixed them and commented a few of them. Please check the following CODE.
#bot.event
async def on_raw_reaction_add(payload):
#You forgot to await the bot.get_channel
channel = await bot.get_channel(payload.channel_id)
message = await channel.fetch_message(payload.message_id)
guild = bot.get_guild(payload.guild_id)
#Put the following Line
member = guild.get_member(payload.user_id)
reaction = discord.utils.get(message.reactions, emoji=payload.emoji.name)
# only work if it is the client
if payload.user_id == bot.user.id:
return
if payload.message_id == 784182764009947177 and reaction.emoji == '✅':
roles = discord.utils.get(guild.roles, name='Verify')
await member.add_roles(roles)
await reaction.remove(payload.member)
Related
I am creating a discord bot, and with this bot I want to create a verify command. I started working on it, and everything works to the point of giving the reaction (Sending message with the "yes and "no" reactions), when I run the code, it doesn't throw any errors. If you do help me, I would please also like an explanation of why my code doesn't work and why your's does if you can, so I can learn.
Thank you! -JJ
Code:
#client.command()
async def verify(ctx):
verifier = ctx.author
jj = await client.fetch_user(270397954773352469)
validReactions = ['✅', '🚫']
role = discord.utils.get(ctx.guild.roles, name="Verified")
await ctx.send(f'{verifier}... Awaiting Verification, you will recieve a dm when you are verified')
dm = await jj.send(f'{verifier.mention} is trying to be verified, do you know him/her?')
await dm.add_reaction("✅")
await dm.add_reaction("🚫")
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) in validReactions
reaction, user = await client.wait_for('reaction_add', timeout=float('inf') , check=check) #float('inf') for no timeout on when I can add the reaction for yes or no
if str(reaction.emoji) == "✅":
await verifier.send("You have been verified")
await client.add_roles(verifier, role)
elif str(reaction.emoji) == "🚫":
await verifier.send("You have not been verified, please try again if you think this was a mistake, or contact the owner")
You send a message to person called jj and user == ctx.author in check function is always True. (Because ctx.author can not see that message). So, try to replace
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) in validReactions
with
def check(reaction, user):
return user == jj and str(reaction.emoji) in validReactions
I have a verification process on my server that takes the inputs of the new member (First name and section and whatever) then sends it to a channel in a server where admins click on an emote to accept/deny the person. The problem is, once 2+ people open tickets, it basically becomes unusable.
To make me sane while writing it, I'll make a scenario.
x, y join the server.
Both send verification requests.
Admin accepts request for x.
Instead of x being approved, x and y gets approved.
This is really bugging me as I might as well do it without the wait_for() checks.
Code:
#commands.Cog.listener()
async def on_member_join(self, member: discord.Member):
channel = member.guild.get_channel(734637251681583164)
verichannel = member.guild.get_channel(849593765097373696)
embed = discord.Embed(
title=f"Welcome {member.name}, keep in mind that this is NOT an [woah privacy] server!",
description=f"This is not a family-friendly server, so please leave if you're not comfortable with it. \n Make sure to read <#734639183737389060> & <#750190162000216215> before proceeding! \n To get access to our server, please verify at <#848430448223977512>.",
color=0x2ecc71
)
embed.set_thumbnail(url=member.avatar_url)
await channel.send(member.mention, embed=embed)
# DM verification
def check(m):
return m.guild == None and m.author == member
awaitingverification = discord.Embed(title="Verification Request", description=f"User: {member.mention}", color = 0x01c618)
embed= discord.Embed(title="What is this?",
description="This is a verification program for the unofficial [woah privacy] server. We do this to ensure the safety and privacy of our members. We are going to ask information that will be sent to our admins for further processing.",
color=0x00d118)
embed.set_author(name="[woah privacy] Verification program")
embed.add_field(name="1st Question: What is your first name?", value="Example: Jordan",
inline=False)
await member.send(embed=embed)
try:
first_name = await self.bot.wait_for('message',timeout=30, check=check)
except asyncio.TimeoutError:
await member.send("Timed out. Re-Join.")
return
awaitingverification.add_field(name="First Name", value=first_name.content, inline=True)
embed = discord.Embed(title="Verification: 2nd step",
description="This is the second step of the verification process.", color=0x00d118)
embed.set_author(name="[woah privacy] Verification program")
embed.add_field(name="2nd Question: What is your section? If you are not enrolled, reply 'Visitor'.", value="Example: LS208", inline=False)
await member.send(embed=embed)
try:
section = await self.bot.wait_for('message',timeout=30, check=check)
except asyncio.TimeoutError:
await member.send("Timed out. Re-Join.")
return
awaitingverification.add_field(name="Section", value=section.content, inline=True)
embed = discord.Embed(title="Verification: 3rd step",
description="This is the third step of the verification process.", color=0x00d118)
embed.set_author(name="[woah privacy] Verification program")
embed.add_field(name="3rd Question: Do you agree with all our rules? Reply with 'Yes' if you do.",
value="Below is a skimmed version of our full rules, so be sure to read them after.",
inline=False)
embed.add_field(name="This is not an official [woah privacy] server.", value="If there is one, then... we dont care.",
inline=False)
embed.add_field(name="Names in the server are your real first names.", value="If not: kicked out the door.",
inline=False)
embed.add_field(name="This is not a family friendly server.",
value="It's a mess here sometimes but thats what's good about it.", inline=False)
embed.add_field(name="Don't be an asshole.", value="We wont hesitate to swing that ban hammer.", inline=False)
embed.add_field(name="No loopholes.", value="Because.. Well... It's bad.", inline=False)
embed.add_field(name="Read the Discord ToS (Terms of Service)", value="TL:DR: Must be 13+ to use discord.",
inline=False)
await member.send(embed=embed)
try:
rulestatus = await self.bot.wait_for('message',timeout=30, check=check)
except asyncio.TimeoutError:
await member.send("Timed out. Re-Join.")
return
awaitingverification.add_field(name="Rules", value=rulestatus.content, inline=True)
awaitingverification.set_footer(text="🟩: Student, 🟨: Visitor, 🟥: Deny and Kick")
await member.send("Thank you. Your application will be processed in due time.")
verification = await verichannel.send(embed=awaitingverification)
await verification.add_reaction("🟩")
await verification.add_reaction("🟨")
await verification.add_reaction("🟥")
def check(reaction, user):
return str(reaction.emoji) in ["🟩", "🟨", "🟥"] and user != self.bot.user
reaction, user = await self.bot.wait_for("reaction_add", check=check)
if str(reaction.emoji) == "🟩":
embed = discord.Embed(title="Verification Request", description=f"User: {member.mention}")
embed.add_field(name="Status:", value=f"Approved by {user}: Student", inline=False)
await verification.edit(embed=embed)
await verification.clear_reactions()
role1 = discord.utils.get(member.guild.roles, name="Students")
await member.add_roles(role1)
if discord.utils.get(member.guild.roles, name=f"Section: {section.content}"):
sectionrole = discord.utils.get(member.guild.roles, name=f"Section: {section.content}")
await member.add_roles(sectionrole)
else:
await member.guild.create_role(name=f"Section: {section.content}")
sectionrole = discord.utils.get(member.guild.roles, name=f"Section: {section.content}")
await member.add_roles(sectionrole)
await member.send("Your Verification Request has been granted as Student. Have a good time and check the rules!")
return
elif str(reaction.emoji) == "🟨":
embed = discord.Embed(title="Verification Request", description=f"User: {member.mention}")
embed.add_field(name="Status:", value=f"Approved by {user}: Visitor", inline=False)
await verification.edit(embed=embed)
await verification.clear_reactions()
role2 = discord.utils.get(member.guild.roles, name="Visitors")
await member.add_roles(role2)
await member.send("Your Verification Request has been granted as Visitor. Have a good time and check the rules!")
return
elif str(reaction.emoji) == "🟥":
embed = discord.Embed(title="Verification Request", description=f"User: {member.mention}")
embed.add_field(name="Status:", value=f"Denied by {user}", inline=False)
await verification.edit(embed=embed)
await verification.clear_reactions()
await member.send("Your Verification Request has been denied.")
await member.kick()
return
p.s sorry, I didn't skim any of the code, I wanted to share it as is because maybe it's my spaghetti's fault.
To solve this, check if it's the same message in check:
verification = await verichannel.send(embed=awaitingverification)
await verification.add_reaction("🟩")
await verification.add_reaction("🟨")
await verification.add_reaction("🟥")
def check(reaction, user):
return str(reaction.emoji) in ["🟩", "🟨", "🟥"] and user != self.bot.user and reaction.message == verification
reaction, user = await self.bot.wait_for("reaction_add", check=check)
References:
reaction.message
I have a function to store all the users that have responded in a string and output them.
Now I have the problem that if User1 gives a reaction and deletes it again, then User1 is still in the list.
# hatch <type> <time>
now = datetime.now()
add_time = now + timedelta(minutes=int(args[2]))
cur = add_time.strftime('%H:%M')
embed = discord.Embed(title='Raid meldung von ' + str(message.author.display_name), color=discord.Color.green())
embed.add_field(name='Raid Typ: ', value=args[1], inline=True)
embed.add_field(name="Schluepft um: ", value=cur + "", inline=True)
embed.add_field(name='Interesse: ', value='Keine Zusagen', inline=False)
channel = bot.get_channel(818662081531740163)
mess = await channel.send(embed=embed)
re_time = int(float(args[2])) * 60
emoji_list = ['✅', '❌']
for i in emoji_list:
await mess.add_reaction(i)
while True:
users = ""
try:
reaction, user= await bot.wait_for("reaction_add", timeout=re_time)
if str(reaction) == '✅':
mess = await channel.fetch_message(mess.id)
reaction_list = mess.reactions
react = get(mess.reactions, emoji='✅')
for reactions in reaction_list:
if str(reactions) == "✅":
if react and react.count <= 2:
user_list = [user async for user in reactions.users() if user != bot.user]
for user in user_list:
users = users + user.mention + "\n"
else:
users = users + user.mention + "\n"
embed1 = discord.Embed(title='Raid meldung von ' + str(message.author.display_name), color=discord.Color.green())
embed1.add_field(name='Raid Typ: ', value=args[1], inline=True)
embed1.add_field(name="Schluepft um: ", value=cur + "", inline=True)
embed1.add_field(name='Interesse: ', value=users, inline=False)
await mess.edit(embed = embed1)
except asyncio.TimeoutError:
break
await asyncio.sleep(re_time)
embed_end = discord.Embed(title='Raid meldung von ' + str(message.author.display_name), color=discord.Color.red())
embed_end.add_field(name='Raid Typ: ', value=args[1], inline=True)
embed_end.add_field(name="Schluepft um: ", value="Beendet", inline=True)
await mess.edit(embed = embed_end)
for i in emoji_list:
await mess.clear_reactions()
i hope anyone have a solotion for my proplem
You are only updating the list of users and updating the message whenever there's a ✅ reaction added to the message.
You need to either have logics for both discord.on_reaction_add and discord.on_reaction_remove events,
or you can just update the reaction list at an interval.
If you update the list of users at an interval, you will have an updated user list until your desired timeout.
msg = await channel.send(embed=embed)
while True:
reactions = msg.reactions
for react in reactions:
if str(react) == "✅":
users = [user async for user in reactions.users() if user != bot.user]
break # if you don't care about other reactions
# do stuff with your users
async.sleep(1) # or something else you see fit
Currently, there's a lot of redundancy in your code. Because I don't know the whole context or if some of them are intended or not, so I'll just stick with pointing out the absolute redundancies.
mess = await channel.fetch_message(mess.id)
is not needed since you have the message object above. You can keep referencing it as long as the async method is still active.
if str(reaction) == '✅':
mess = await channel.fetch_message(mess.id)
reaction_list = mess.reactions
react = get(mess.reactions, emoji='✅')
for reactions in reaction_list:
if str(reactions) == "✅":
if react and react.count <= 2:
You already have the ✅ Reaction object. You can play with this to fetch the users; no need to grab the list again, and definitely no need to iterate through the reaction list again.
I'm inclined to suggest you use the discord.on_reaction_add and discord.on_reaction_remove events.
It will be complicated because you have to keep juggling multiple events, but it will do what you want it to do efficiently.
I am trying to make a giveaway bot. The bot is supposed to take the users who reacted and randomly select one from that list, but I can't figure out how to get the users who reacted.
#client.command()
#commands.guild_only()
#commands.has_role('giveaway')
async def giveaway(ctx, wait, *, reward):
end = int(wait)
giveEmbed = discord.Embed(title='A giveaway has begun!', description='React to this message to enter the giveaway.', color=discord.Colour.from_rgb(255, 107, 33))
giveEmbed.add_field(name='Prize:', value=f'{reward}', inline=True)
giveEmbed.add_field(name='Time:', value=f'{time} hour(s) after message sent.', inline=True)
message = await ctx.send(embed=giveEmbed)
reaction = await message.add_reaction('🎁')
time.sleep(5)
#can't figure out how to get the users who reacted here.
You have to fetch the message again to get the 'updated' reactions:
fetched_message = await ctx.channel.fetch_message(message.id)
reactions = fetched_message.reactions
for reaction in reactions:
if str(reaction) == '🎁':
# This if the list of the users that reacted with `🎁` to the message
users = await reaction.users().flatten()
And btw time.sleep(5) it's blocking your code, change it to await asyncio.sleep(5)
Reference:
TextChannel.fetch_message
Message.reactions
The problem i'm having is the code never getting through "0004" since it gets stuck on wait_for which wants additional positional argument: 'event', which should be the 'message' in bracket right next to it from what I've seen on examples from discord.py site & inside the code itself.
'''
class Test(commands.Cog):
def __init__(self, spreadsheeter):
self.spreadsheeter = spreadsheeter
#commands.command()
async def apply(self, ctx):
a_list = []
submit_channel = spreadsheeter.get_channel(718698172293316608)
channel = await ctx.author.create_dm()
def check(m):
return m.content is not None and m.channel == channel
for question in q_list:
print("0001")
sleep(.5)
print("0002")
await channel.send(question)
print("0003")
msg = await Client.wait_for('message', timeout=60, check=check)
print("0004")
a_list.append(msg.content)
print("0005")
submit_wait = True
print("0006")
while submit_wait:
print("0007")
await channel.send("End of questions 'submit' to finish.")
print("0008")
msg = await Client.wait_for("message", check=check)
print("0009")
if "submit" in msg.content.lower():
print("0010")
submit_wait =False
print("0011")
answers = "\n".join(f"{a}. {b}" for a, b in enumerate(a_list, 1))
print("0012")
submit_msg = f"Apllication from {msg.author} \nThe answers are:\n{answers}"
print("0013")
await submit_channel.send(submit_msg)
print("0014")
Error:
What I've unsuccessfully tried:
discord.client.wait_for('message', check=check)
Error: discord.client has no attribute 'wait_for'
Same for discord.member, ctx.member, ctx.client
Replacing "message" to 'message' (doesn't change anything)
Moving around the position of 'message'
Raises ton of other errors...
Giving the line bracket at start (self, "message", check=check)
Error: 'Test' object has no attribute 'loop'
#client.event instead of cog style commands.command
Error: Unresolved reference 'client'
Intent of the code:
Be called from DM as a command, then start a series of questions from q_list in that DM and then store them into a_list. Then after its done it should submit the a_list into as submit_msg into discord channel.
What it does so far?:
Asks first question from q_list
q_list = [
"Question one",
"Question two ha-ha-haaa",
"Question three ha-ha-haaa"
]
"""
After that it immediately after trying to await answer gives error.
2 Things at the beginning, you should only make a dm channel if there isn't any yet.
ctx.author.chreate_dm() doesn't return a channel, so instead of assigning the dm channel to channel you can check it's in the right channel by using ctx.author.dm_channel
#commands.command()
async def apply(self, ctx):
a_list = []
submit_channel = self.spreadsheeter.get_channel(718698172293316608)
if not ctx.author.dm_channel:
await ctx.author.create_dm()
def check(m):
return m.content is not None and m.channel == ctx.author.dm_channel
Instead of Client use spreadsheeter as that is your client
msg = await self.spreadsheeter.wait_for('message', timeout=60, check=check)
Figured it out, the thing being is it might work in cogs, but I think it won't or something is just missing...
The way i made it to work is to use it in
#Client.event (in my case #spreadsheeter.event)
Instead of ctx. I used payload.
"""
#spreadsheeter.event
async def on_raw_reaction_add(payload):
print("Hell-Yeah")
message_id = payload.message_id
if message_id == 739153263907176480:
guild_id = payload.guild_id
guild = discord.utils.find(lambda g : g.id == guild_id, spreadsheeter.guilds)
print (payload.emoji.name)
if payload.emoji.name == "No1":
role = discord.utils.find(lambda r: r.name == 'RAIDERS', guild.roles)
print(role)
if role in payload.member.roles:
print("You really want to leave?")
else:
print("Kick")
await payload.member.kick()
elif payload.emoji.name == "Yes1":
print("Yo, we got a potential raider over here..")
channel = await payload.member.create_dm()
await channel.send("This is still Work/Bot is under Development (Not actuall application yet).")
await channel.send("Whenever you are ready, please start replaying to the questions.")
print("0000")
submit_channel = spreadsheeter.get_channel(718698172293316608)
if not payload.member.dm_channel:
await payload.member.create_dm()
channel = payload.member.dm_channel
print(channel)
def check(m):
return m.content is not None and m.channel == channel
for question in q_list:
print("0001")
sleep(.5)
print("0002")
await channel.send(question)
print("0003")
msg = await spreadsheeter.wait_for(event='message', timeout=60, check=check)
print("0004")
a_list.append(msg.content)
print("0005")
submit_wait = True
print("0006")
while submit_wait:
print("0007")
await channel.send("End of questions 'submit' to finish.")
print("0008")
msg = await spreadsheeter.wait_for("message", timeout=60, check=check)
print("0009")
if "submit" in msg.content.lower():
print("0010")
submit_wait = False
print("0011")
answers = "\n".join(f"{a}. {b}" for a, b in enumerate(a_list, 1))
print("0012")
submit_msg = f"Apllication from {msg.author} \nThe answers are:\n{answers}"
print("0013")
await submit_channel.send(submit_msg)
print("0014")
elif payload.emoji.name == "Need_more_info":
print("Yo, we got a potential diplomat over here..")
channel = await payload.member.create_dm()
await channel.send("This is still Work/Bot is under Development (Not actuall application yet).")
await channel.send("Whenever you are ready, please start with \n_apply")
"""
It still doesn't have the handling for multiple users, but works fine with one at a time at this moment, which solves the original problem of wait_for not waiting for anything else then timeout to run out.