reaction_roles.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import discord
  2. from discord.ext import commands
  3. from discord.commands import Option
  4. from discord.commands import slash_command
  5. import configparser
  6. import time
  7. import json
  8. from pathlib import Path
  9. class reactionroles(commands.Cog):
  10. def __init__(self, bot: discord.Bot):
  11. self.bot = bot
  12. def _load_config(self):
  13. config = configparser.ConfigParser()
  14. configFilePath = r'config.cfg'
  15. config.read(configFilePath)
  16. return config
  17. def _get_roles(self):
  18. config = self._load_config()
  19. role_ids = [int(role_id.strip()) for role_id in config["Reactionroles"]["reactionroles_role_ids"].split(",")]
  20. roles = [self.bot.get_role(role_id) for role_id in role_ids]
  21. if any(role is None for role in roles):
  22. print(f"One or more roles with IDs {role_ids} not found.")
  23. return
  24. return roles
  25. def _get_emojis(self):
  26. config = self._load_config()
  27. emojis = [int(emoji.strip()) for emoji in config["Reactionroles"]["reactionroles_emojis"].split(",")]
  28. return emojis
  29. def _get_message_id(self):
  30. config = self._load_config()
  31. message_id = int(config["Reactionroles"]["reactionroles_message_id"].strip())
  32. return message_id
  33. def _write_message_id(self, message_id):
  34. configFile = r'config.cfg'
  35. configFile["Reactionroles"]["reactionroles_message_id"] = str(message_id)
  36. with open('config.cfg', 'w') as configfile:
  37. configFile.write(configfile)
  38. #Get the reaction role embed text from the .json file
  39. def _reaction_role_embed(self):
  40. json_path = Path(__file__).resolve().parent.parent.joinpath("json_files", "reaction_role_msg.json")
  41. if not json_path.exists():
  42. print("The .json file is missing.")
  43. return
  44. try:
  45. with json_path.open("r", encoding="utf-8") as f:
  46. json_data = json.load(f)
  47. except json.JSONDecodeError:
  48. print("The .json file is not valid JSON.")
  49. return
  50. if isinstance(json_data, dict):
  51. entries = [json_data]
  52. elif isinstance(json_data, list):
  53. entries = json_data
  54. else:
  55. print("The .json file has an unexpected structure.")
  56. return
  57. if not entries or not isinstance(entries[0], dict):
  58. print("The .json file has an unexpected structure.")
  59. return
  60. if not entries:
  61. print("The .json file is empty.")
  62. return
  63. entry = entries[0]
  64. jstitle = entry.get("title", "Reaction Roles")
  65. jsdesc = entry.get("desc", "No description provided.")
  66. embed = discord.Embed(
  67. title=f"{jstitle}",
  68. description=f"{jsdesc}",
  69. color=discord.Color.blue()
  70. )
  71. embed.set_author(name="VicePD", icon_url="https://i.imgur.com/6QteFrg.png")
  72. embed.set_footer(text="VicePD - Bot | Made by BaumSplitter41")
  73. return embed
  74. #Setup the reaction role message
  75. @slash_command(name="setup_reactionrole", description="Setup the reaction role message")
  76. async def reactionmsg(
  77. self,
  78. ctx,
  79. channel: discord.TextChannel = Option(discord.TextChannel, "Select Channel", required=True)
  80. ):
  81. if not ctx.author.guild_permissions.administrator:
  82. await ctx.respond("You don't have permission to use this command.")
  83. return
  84. embed = self._reaction_role_embed()
  85. if embed is None:
  86. await ctx.respond("Failed to load the reaction role message.")
  87. return
  88. message = await channel.send(embed=embed)
  89. await ctx.respond(f"Reaction role message has been set up in {channel.mention}.", ephemeral=True)
  90. # Add reactions to the message
  91. emojis = self._get_emojis()
  92. if emojis is None:
  93. await ctx.respond("Failed to load emojis from config.", ephemeral=True)
  94. return
  95. for emoji in emojis:
  96. try:
  97. await message.add_reaction(emoji)
  98. except Exception as e:
  99. await ctx.respond(f"Failed to add reaction {emoji}: {e}", ephemeral=True)
  100. message_id = self.bot.get_message(message)
  101. self._write_message_id(self, message_id)
  102. #-----------------------------------------------#
  103. #Add role to user
  104. @commands.Cog.listener()
  105. async def on_raw_reaction_add(self, payload):
  106. #Get variables
  107. user = self.bot.get_user(payload.user_id)
  108. guild = self.bot.get_guild(payload.guild_id)
  109. if user.bot:
  110. return
  111. message_id = self._get_message_id()
  112. if message_id is None:
  113. return
  114. message = await guild.fetch_message(message_id)
  115. emojis = self._get_emojis()
  116. if emojis is None:
  117. return
  118. if payload.emoji.id not in emojis:
  119. return
  120. roles = self._get_roles()
  121. if roles is None:
  122. return
  123. #Add the role to the user
  124. for emoji, role in zip(emojis, roles):
  125. if payload.emoji.id == emoji:
  126. await user.add_roles(role)
  127. remove_reaction = discord.utils.get(guild.emojis, id=emoji)
  128. await payload.member.remove_reaction(remove_reaction, message)
  129. break
  130. #Remove role from user
  131. @commands.Cog.listener()
  132. async def on_raw_reaction_remove(self, payload):
  133. #Get variables
  134. user = self.bot._get_user(payload.user_id)
  135. guild = self.bot._get_guild(payload.guild_id)
  136. if user.bot:
  137. return
  138. message_id = self._get_message_id()
  139. if message_id is None:
  140. return
  141. message = await guild.fetch_message(message_id)
  142. emojis = self._get_emojis()
  143. if emojis is None:
  144. return
  145. if payload.emoji.id not in emojis:
  146. return
  147. roles = self._get_roles()
  148. if roles is None:
  149. return
  150. #Add the role to the user
  151. for emoji, role in zip(emojis, roles):
  152. if payload.emoji.id == emoji:
  153. await user.remove_roles(role)
  154. remove_reaction = discord.utils.get(guild.emojis, id=emoji)
  155. await payload.member.remove_reaction(remove_reaction, message)
  156. break
  157. def setup(bot: discord.Bot):
  158. bot.add_cog(reactionroles(bot))