Hi I'm wanting to remove a reaction when another reaction is adeed. For example if user had reacted to emoji 1 but reacts to emoji 2 then emoji 1 is removed or if the user had react to emoji 1 but reacts to emoji 4 instead then emoji 1 is removed.
I'm using a async def on_raw_reaction_add(): event and defined the emojis I'd like to use however if I dide:
await member.add_roles(role, reason='Added role')
await message.remove_reaction(one, user)
await message.remove_reaction(two, user)
await message.remove_reaction(three, user)
This would remove all the emojis including the emoji the user selected.
Here is what I'm working with:
one = "1\N{COMBINING ENCLOSING KEYCAP}"
two = "2\N{COMBINING ENCLOSING KEYCAP}"
three = "3\N{COMBINING ENCLOSING KEYCAP}"
#commands.Cog.listener()
async def on_raw_reaction_add(self, payload):
message_ids = [649600853048688642, ]
channel = self.bot.get_channel(634023419482079232)
message = await channel.fetch_message(649600853048688642)
user = self.bot.get_user(payload.user_id)
if not payload.guild_id:
return
if payload.message_id not in message_ids:
return
guild = self.bot.get_guild(payload.guild_id) # You need the guild to get the member who reacted
member = guild.get_member(payload.user_id) # Now you have the key part, the member who should receive the role
restricted_role = discord.utils.get(guild.roles, name="Commands Revoked")
role_name = emoji_role_map.get(payload.emoji.name)
if restricted_role in member.roles:
return
if role_name: # None if not found
role = discord.utils.get(guild.roles, name=role_name)
await member.add_roles(role, reason='Added role')
await message.remove_reaction(one, user)
await message.remove_reaction(two, user)
await message.remove_reaction(three, user)
Help appreciated.
Related
So I made a mute command and converted it to an optional tempmute yesterday, it worked fine except for when I specified a reason and no time. Obviously that would create a problem but sadly I could not figure out how to fix it. i.e: N?mute user time reason works but N?mute user reason doesn't. If I don't specify the reason nor time it mutes them for 2 years. I want to be able to perm mute people with a reason and also temp mute people with a reason (already works). Hereby the code:
#commands.command()
#commands.has_permissions(manage_roles=True)
async def mute(self, ctx, member: discord.Member, time="670d", *, reason="no reason provided"):
role = discord.utils.get(ctx.guild.roles, name="Muted")
admin = discord.utils.get(ctx.guild.roles, name="Admin")
mod = discord.utils.get(ctx.guild.roles, name="Moderator")
guild = ctx.guild
pfp = member.avatar_url
time_convert = {"s":1, "m":60, "h":3600,"d":86400}
tempmute= int(time[0]) * time_convert[time[-1]]
if admin in member.roles or mod in member.roles:
embed = discord.Embed(title="Mute failed", description="Staff cannot be muted.", color=0xff4654)
await ctx.channel.send(embed=embed)
return
if role in member.roles:
embed = discord.Embed(title="Mute failed", description="**{0}** is already muted!".format(member), color=0xff4654)
await ctx.channel.send(embed=embed)
if role not in guild.roles:
perms = discord.Permissions(send_messages=False, speak=False)
await guild.create_role(name="Muted", permissions=perms)
await member.add_roles(role, reason=reason) #User muted
embed = discord.Embed(title="User muted!", description="**{0}** was succesfully muted by **{1}** for **{2}**.".format(member, ctx.message.author, reason), color=0xff4654)
await ctx.channel.send(embed=embed)
channel = discord.utils.get(guild.channels, name="logs")
embed = discord.Embed(title=" ", description="**{0}** was muted by **{1}**. Reason: **{2}**".format(member, ctx.message.author, reason), color=0xff4654)
embed.set_author(name="{0}".format(member), icon_url=pfp)
await channel.send(embed=embed) #Log
await asyncio.sleep(tempmute)
await member.remove_roles(role)
else:
await member.add_roles(role, reason=reason) #User muted
embed = discord.Embed(title="User muted!", description="**{0}** was succesfully muted by **{1}** for **{2}**.".format(member, ctx.message.author, reason), color=0xff4654)
await ctx.channel.send(embed=embed)
channel = discord.utils.get(guild.text_channels, name="logs")
embed = discord.Embed(title=" ", description="<#{0}> was muted by <#{1}>. Reason: **{2}**".format(member.id, ctx.message.author.id, reason), color=0xff4654)
embed.set_author(name="{0}".format(member), icon_url=pfp)
await channel.send(embed=embed) #Log
await asyncio.sleep(tempmute)
await member.remove_roles(role)
I tried doing time: Optional[int] as someone else suggested but alas it broke it entirely.
To answer bluntly, there isn't a nice way of doing this. What I recommend is that you split the command into two separate ones, mute and tempmute.
If you really do want it as one function, you could do something like this:
import re
async def mute(self, ctx, member: discord.Member, *options):
if len(options) == 2: # User specified date and reason
expiry, reason = options
if len(options) == 1: # User specified one of the above so we need to find out which
if re.match(r"\d+\D", options[0]):
# Regex to check for one or more digit then a single non-digit
expiry = options[0]
reason = None
else:
expiry = None
reason = options[0]
On a slightly unrelated note, you should not do await asyncio.sleep(tempmute). Long sleeps are innacurate and if the bot restarts, the person will never be unmuted. You should create a database with datetimes of when the user should be unmuted and have a looping task which queries the database and unmutes users when their time is up.
This is my current code :
#client.event
async def on_member_join(member):
guild = client.get_guild(761604402142248960)
channel = client.get_channel(762721485193740348)
inviter = await tracker.fetch_inviter(member)
emoji = discord.utils.get(guild.emojis, name='verify')
totalInvites = 0
for i in await guild.invites():
if i.inviter == inviter:
totalInvites += i.uses
await channel.send(f"{member.mention} a été invité par {inviter} qui possède désormais {totalInvites} invitations {emoji} !")
But I don't know how to remove the users that left the guild. Can anybody help?
As derw said in his reply, you will want to use the on_member_remove event. You will also want to iterate through the guild invites, find the one who's inviter id matches the invite id, and delete the invite.
#client.event
async def on_member_remove(member):
for i in member.guild.invites: # Iterate through every invite...
if i.inviter.id == member.id: # Check if the invite's inviter id is the member id
await invite.delete(reason="User left the guild") # Delete the invite!
Hi I'm having an issue where my code is creating more than one channels. The function of the code should:
Check to see if the channel exists
If Channel does exist don't create a new one.
Otherwise, if the channel does not exist create one.
In a nutshell, how it supposed to work, The on_message event checks for a response from a user in a direct message sent to the bot, their message is then relayed to a guild channel that either already exists otherwise a new one is created before the message is sent.
In this is the issue is that I can't get around it with a check to see if the channel exists, it sure does but it just duplicates everytime a message is sent:
I have tried both these methods to check:
#Check 1
for channel in guild.text_channels:
if channel.name == f"{message.author.name.lower()}{message.author.discriminator}" and channel.name is not None:
await channel.send(embed=embed)
else:
channel_non = await guild.create_text_channel(f'{message.author.name}{message.author.discriminator}', overwrites=overwrites, category=self.bot.get_channel(744944688271720518))
await channel_non.send(embed=embed)
#Check 2
channel_present = False
for channel in guild.text_channels:
if channel.name == f"{message.author.name.lower()}{message.author.discriminator}":
await channel.send(embed=embed)
channel_present = True
if channel_present:
channel_non = await guild.create_text_channel(f'{message.author.name}{message.author.discriminator}', overwrites=overwrites, category=self.bot.get_channel(744944688271720518))
await channel_non.send(embed=embed)
The check 2 code causes the on_message event to do nothing. Help would be much appreciated I don't know where I'm going wrong here.
Honestly, I would just do it by a command.
#client.command()
async def command(ctx):
author = ctx.message.author
guild = ctx.guild
for channel in guild.text_channels:
if channel.name == ctx.message.author:
await channel.send(embed = embed)
return
channel = await guild.create_text_channel(f"{ctx.message.author}", overwrites = overwrites, category = self.bot.get_channel(744944688271720518))
await channel.send(embed = embed)
There is a command to request a role. I don't understand how to set some functions for reactions.
#client.command()
async def role(ctx):
role = ctx.guild.get_role(703596629860548643)
zapros_chanell = client.get_channel(729733881129074768 )
zapros2_chanell = client.get_channel(703596629923725339 )
embed = discord.Embed(title="Запрос роли")
embed.add_field(name='Запросивший роль', value=ctx.message.author.mention)
embed.add_field(name='Роль для выдачи', value=role.mention)
embed.set_thumbnail(url=ctx.guild.icon_url)
message = await zapros_chanell.send(embed=embed)
await zapros2_chanell.send(embed = discord.Embed(description = f'{ctx.message.author.mention}, `запрос на выдачу роли был успешно отправлен, ожидайте его рассмотрения модерацией Discord`', color=discord.Color.purple()))
await message.add_reaction('✅')
await message.add_reaction('❎')
The bottom line is that if when you click on ✅, the role was issued and a text was written to the person in zapros2_chanell.
When you click on ❎, the person was not given a role, therefore, but a certain text was also written in zapros2_chanell.
I used an event called on_raw_reaction_add. Made a check to the reaction, keep in mind the will give the role to any message in the guild with ✅.It it just a proof of concept.
You can make it only accept reactions on certain channel, or even only for given message IDs
#client.command()
async def role(ctx):
zapros_chanell = client.get_channel(729733881129074768)
embed = discord.Embed(title="Запрос роли")
embed.add_field(name='Запросивший роль', value=ctx.message.author.mention)
embed.add_field(name='Роль для выдачи', value=role.mention)
embed.set_thumbnail(url=ctx.guild.icon_url)
message = await zapros_chanell.send(embed=embed)
await zapros2_chanell.send(embed = discord.Embed(description = f'{ctx.message.author.mention}, `запрос на выдачу роли был успешно отправлен, ожидайте его рассмотрения модерацией Discord`', color=discord.Color.purple()))
await message.add_reaction('✅')
await message.add_reaction('❎')
#client.event
async def on_raw_reaction_add(payload):
channel = await client.fetch_channel(payload.channel_id)
message = await channel.fetch_message(payload.message_id)
user = await client.fetch_user(payload.user_id)
emoji = payload.emoji.name
guild = client.get_guild(ID_HERE)
role = guild.get_role(703596629860548643)
zapros2_chanell = client.get_channel(703596629923725339 )
if user.id != bot.user.id: # bot to count itself
if emoji == '✅':
await client.add_roles(user, role)
await zapros2_chanell.send(f'{user.name} has been given {role.name}')
elif emoji == '❎':
await zapros2_chanell.send(f'{user.name} did not want {role.name}')
I'm having a slight issue checking for roles a user has. I'm currently getting a
if member_role in message.author.roles]
AttributeError: 'User' object has no attribute 'roles'
It seems I cannot pass roles with the message argument when checking to see if the message author has them roles.
Help Appreciated.
Here is my code I'm working with:
async def on_message(self, message):
if not isinstance(message.channel, discord.DMChannel) or
message.author.id == self.bot.user.id:
# not a DM, or it's just the bot itself
return
channel = self.bot.get_channel(578731262550736910)
if not channel:
print("Mail channel not found! Reconfigure bot!")
time = datetime.utcnow()
guild = self.bot.get_guild(555844758778544158)
member_role = get(guild.roles, name='Members')
muted_role = get(guild.roles, name='Modmail Muted')
content = message.clean_content
verified = [member for member in guild.members
if member_role in message.author.roles]
muted = [member for member in guild.members
if muted_role in message.author.roles]
if muted:
await message.channel.send("You're not allowed to use modmail.")
return
if verified:
embed = discord.Embed(title="📬 You've got modmail!")
embed.add_field(name="Sent by:", value=f"{message.author.mention} ({message.author.id})" ,inline=False)
embed.add_field(name="Message:", value=content[:1000] or "blank")
embed.set_footer(text="Mods: React with icon below this message to notify us that you're dealing with this modmail. (First reaction already set by the bot)")
if message.attachments:
embed.add_field(name="Attachments", value=", ".join([i.url for i in message.attachments]))
if len(content[1000:]) > 0:
embed.add_field(name="Message (continued):", value=content[1000:])
msg = await channel.send(embed=embed)
await msg.add_reaction('📤')
try:
embed = discord.Embed(title=f"Thanks {message.author.display_name}! your message has been sent to the Mods.", timestamp=time)
embed.set_footer(text="Message Sent")
await message.add_reaction('📬')
await message.channel.send(embed=embed)
except discord.ext.commands.errors.CommandInvokeError:
await message.channel.send('📬')
else:
await message.channel.send("Only members can use modmail.")
as suggested by #Patrick Haugh in replies I used get_member.
user_id = message.author.id
author = guild.get_member(user_id)