Skip to content

Instantly share code, notes, and snippets.

@makupi
Last active January 25, 2023 20:52
Show Gist options
  • Save makupi/c508c9d33bb01dcc04e57d1a93c23ae1 to your computer and use it in GitHub Desktop.
Save makupi/c508c9d33bb01dcc04e57d1a93c23ae1 to your computer and use it in GitHub Desktop.
reaction role cog for discord.py
import discord
from discord.ext import commands
import json
import atexit
import uuid
reaction_roles_data = {}
try:
with open("reaction_roles.json") as file:
reaction_roles_data = json.load(file)
except (FileNotFoundError, json.JSONDecodeError) as ex:
with open("reaction_roles.json", "w") as file:
json.dump({}, file)
@atexit.register
def store_reaction_roles():
with open("reaction_roles.json", "w") as file:
json.dump(reaction_roles_data, file)
class ReactionRoles(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.Cog.listener()
async def on_ready(self):
print(f"ReactionRoles ready.")
@commands.Cog.listener()
async def on_raw_reaction_add(self, payload: discord.RawReactionActionEvent):
role, user = self.parse_reaction_payload(payload)
if role is not None and user is not None:
await user.add_roles(role, reason="ReactionRole")
@commands.Cog.listener()
async def on_raw_reaction_remove(self, payload: discord.RawReactionActionEvent):
role, user = self.parse_reaction_payload(payload)
if role is not None and user is not None:
await user.remove_roles(role, reason="ReactionRole")
@commands.has_permissions(manage_channels=True)
@commands.command()
async def reaction(
self,
ctx,
emote,
role: discord.Role,
channel: discord.TextChannel,
title,
message,
):
embed = discord.Embed(title=title, description=message)
msg = await channel.send(embed=embed)
await msg.add_reaction(emote)
self.add_reaction(ctx.guild.id, emote, role.id, channel.id, msg.id)
@commands.has_permissions(manage_channels=True)
@commands.command()
async def reaction_add(
self, ctx, emote, role: discord.Role, channel: discord.TextChannel, message_id
):
self.add_reaction(ctx.guild.id, emote, role.id, channel.id, message_id)
@commands.has_permissions(manage_channels=True)
@commands.command()
async def reactions(self, ctx):
guild_id = ctx.guild.id
data = reaction_roles_data.get(str(guild_id), None)
embed = discord.Embed(title="Reaction Roles")
if data is None:
embed.description = "There are no reaction roles set up right now."
else:
for index, rr in enumerate(data):
emote = rr.get("emote")
role_id = rr.get("roleID")
role = ctx.guild.get_role(role_id)
channel_id = rr.get("channelID")
message_id = rr.get("messageID")
embed.add_field(
name=index,
value=f"{emote} - @{role} - [message](https://www.discordapp.com/channels/{guild_id}/{channel_id}/{message_id})",
inline=False,
)
await ctx.send(embed=embed)
@commands.has_permissions(manage_channels=True)
@commands.command()
async def reaction_remove(self, ctx, index: int):
guild_id = ctx.guild.id
data = reaction_roles_data.get(str(guild_id), None)
embed = discord.Embed(title=f"Remove Reaction Role {index}")
rr = None
if data is None:
embed.description = "Given Reaction Role was not found."
else:
embed.description = (
"Do you wish to remove the reaction role below? Please react with 🗑️."
)
rr = data[index]
emote = rr.get("emote")
role_id = rr.get("roleID")
role = ctx.guild.get_role(role_id)
channel_id = rr.get("channelID")
message_id = rr.get("messageID")
_id = rr.get("id")
embed.set_footer(text=_id)
embed.add_field(
name=index,
value=f"{emote} - @{role} - [message](https://www.discordapp.com/channels/{guild_id}/{channel_id}/{message_id})",
inline=False,
)
msg = await ctx.send(embed=embed)
if rr is not None:
await msg.add_reaction("🗑️")
def check(reaction, user):
return (
reaction.message.id == msg.id
and user == ctx.message.author
and str(reaction.emoji) == "🗑️"
)
reaction, user = await self.bot.wait_for("reaction_add", check=check)
data.remove(rr)
reaction_roles_data[str(guild_id)] = data
store_reaction_roles()
def add_reaction(self, guild_id, emote, role_id, channel_id, message_id):
if not str(guild_id) in reaction_roles_data:
reaction_roles_data[str(guild_id)] = []
reaction_roles_data[str(guild_id)].append(
{
"id": str(uuid.uuid4()),
"emote": emote,
"roleID": role_id,
"channelID": channel_id,
"messageID": message_id,
}
)
store_reaction_roles()
def parse_reaction_payload(self, payload: discord.RawReactionActionEvent):
guild_id = payload.guild_id
data = reaction_roles_data.get(str(guild_id), None)
if data is not None:
for rr in data:
emote = rr.get("emote")
if payload.message_id == rr.get("messageID"):
if payload.channel_id == rr.get("channelID"):
if str(payload.emoji) == emote:
guild = self.bot.get_guild(guild_id)
role = guild.get_role(rr.get("roleID"))
user = guild.get_member(payload.user_id)
return role, user
return None, None
def setup(bot):
bot.add_cog(ReactionRoles(bot))
@NotGarrettE
Copy link

Pretty Nice, Although there is an error the bot does not add the role after reacting? Is there a way to fix that?

@makupi
Copy link
Author

makupi commented Nov 5, 2020

Pretty Nice, Although there is an error the bot does not add the role after reacting? Is there a way to fix that?

What is the error exactly? Or is it just not doing anything? I honestly forgot I had this up here, only uploaded this for a friend a long time ago.

@spiri2
Copy link

spiri2 commented Nov 6, 2020

Error I’m getting is “ File "/usr/local/lib/python3.8/dist-packages/discord/ext/commands/core.py", line 85, in wrapped
��ret = await coro(*args, **kwargs)
��File "/root/m2mod/mod/cogs/ReactionRole.py", line 57, in reaction
��await msg.add_reaction(emote)
��File "/usr/local/lib/python3.8/dist-packages/discord/message.py", line 994, in add_reaction
��await self._state.http.add_reaction(self.channel.id, self.id, emoji)
��File "/usr/local/lib/python3.8/dist-packages/discord/http.py", line 245, in request
����raise HTTPException(r, data)
discord.errors.HTTPException: 400 Bad Request (error code: 10014): Unknown Emoji

The above exception was the direct cause of the following exception:

@spiri2
Copy link

spiri2 commented Nov 6, 2020

Also, had no idea how to use it at first so I went off the code and had to read missing arg errors in terminal and got to this point
.reaction add <@Role_Name> <#Channel_ID> “React below to unlock server” “hello”

@Jaybat0
Copy link

Jaybat0 commented Nov 10, 2020

Pretty Nice, Although there is an error the bot does not add the role after reacting? Is there a way to fix that?

What is the error exactly? Or is it just not doing anything? I honestly forgot I had this up here, only uploaded this for a friend a long time ago.

its not a error it just dosent add the role when some one reacts
or click the reaction

@spiri2
Copy link

spiri2 commented Nov 10, 2020

Pretty Nice, Although there is an error the bot does not add the role after reacting? Is there a way to fix that?

What is the error exactly? Or is it just not doing anything? I honestly forgot I had this up here, only uploaded this for a friend a long time ago.

its not a error it just dosent add the role when some one reacts
or click the reaction

That’s the thing, no reaction gets added. I’m not sure what I did wrong here. I made a
Reaction_roles.json and put a {“😂”} in it

@NotGarrettE
Copy link

Oh lol I dont use discord anymore and I was reading my emails, but yes it just did not add the role.

@Wasdeq68
Copy link

Pretty Nice, Although there is an error the bot does not add the role after reacting? Is there a way to fix that?

What is the error exactly? Or is it just not doing anything? I honestly forgot I had this up here, only uploaded this for a friend a long time ago.

It does nothing, no errors

@TheRegularDX
Copy link

it kinda worked once an then died

@BlueWaveDev
Copy link

How would I ignore a bot when it reacts? The bot gives itself the role when it reacts!

@spiri2
Copy link

spiri2 commented Feb 22, 2021

How would I ignore a bot when it reacts? The bot gives itself the role when it reacts!

You need to add in and not message.author.bot: in your if or elif statement

@Blake-McCullough
Copy link

Just wanted to say, this worked almost perfectly out the box, I have updated this to the slash commands (using pycord) https://gist.github.com/Blake-McCullough/320ba2f45a55581e9970a1cee54ac45a
Thanks tho!

@YTPSDanDie
Copy link

YTPSDanDie commented Aug 13, 2022

helpful you can help. I have failed to load! "RuntimeError: The ReactionRoles cog in the ReactionRole package does not inherit from the commands.Cog base class. The cog author must update the cog to adhere to this requirement." thank you in advance for help!

[14:24:49] ERROR [red] Package loading failed
╭───────────── Traceback (most recent call last) ─────────────╮
│ G:\Downloads\Afrosky\redenv\lib\site-packages\redbot\core\core_commands.py:172 in _load │
│ ❱ 172 await bot.load_extension(spec) │
│ G:\Downloads\Afrosky\redenv\lib\site-packages\redbot\core\bot.py:1563 in load_extension │
│ ❱ 1563 lib.setup(self) │
│ G:\Downloads\Afrosky\redenv\Red-DiscordBot\data\AfroSkyAdminBot\cogs\PSDanDie\ReactionRole.py:162 in setup │
│ ❱ 162 bot.add_cog(ReactionRoles(bot)) │
│ G:\Downloads\Afrosky\redenv\lib\site-packages\redbot\core\bot.py:1674 in add_cog │
│ ❱ 1674 raise RuntimeError( │
╰──────────────────╯
RuntimeError: The ReactionRoles cog in the ReactionRole package does not inherit from the commands.Cog base class. The
cog author must update the cog to adhere to this requirement.

@veroxsity
Copy link

Can anyone tell me how to actually use this? i dont know how to add the roles

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment