import re import json import os import asyncio import shutil import discord from pathlib import Path intents = discord.Intents(messages=True, guilds=True, message_content=True, reactions=True) client = discord.Client(intents=intents) settings = {} def touch(input_path): path = Path(input_path) path.parent.mkdir(parents=True, exist_ok=True) path.touch(exist_ok=True) @client.event async def on_message(msg): chl = await client.fetch_channel(msg.channel.id) msg = await chl.fetch_message(msg.id) guild = await client.fetch_guild(chl.guild.id) member = await guild.fetch_member(msg.author.id) bot = await guild.fetch_member(client.user.id) args = msg.content.split(" ") tree = f"guilds/{guild.id}" stub = f"{tree}/{member.id}" if len(args) > 0: if args[0] == ".register": if member.guild_permissions.administrator: touch(stub) await msg.add_reaction("✅") await asyncio.sleep(10) await msg.delete() return if args[0] == ".revoke": if member.guild_permissions.administrator: shutil.rmtree(tree) await msg.add_reaction("✅") await asyncio.sleep(10) await msg.delete() return if len(args) > 1: # Handle .color command: if args[0] == ".color": color = args[1] existing_role = None color_regex = r"^#[A-Fa-f0-9]{6}$" # Discord treats all zeroes as transparent: if color.lower() == "#000000": color = "#010101" if not re.search(color_regex, color): await msg.add_reaction("❌") await asyncio.sleep(10) await msg.delete() return # Remove any previously assigned color roles: for role in member.roles: if re.search(color_regex, role.name): await member.remove_roles(role) # Iterate through all guild roles, find existing role, and delete those without members: for role in guild.roles: if not re.match(color_regex, role.name): continue if role.name.lower() == color.lower(): existing_role = role continue if len(role.members) < 1: try: await role.delete(reason="Role contains no more members.") except: pass if existing_role is None: color_value = discord.Color(int(color.strip("#"), 16)) existing_role = await guild.create_role(name=color, color=color_value) await existing_role.edit(position=bot.top_role.position - 1) await member.add_roles(existing_role) await msg.delete() if args[0] == ".new": role_name = args[1] if member.guild_permissions.administrator: new_role = await guild.create_role(name=role_name) await new_role.edit(position=bot.top_role.position - 1) await msg.add_reaction("✅") await asyncio.sleep(10) await msg.delete() return async def on_raw_reaction_add_or_remove(rxn, add=True): print("Reaction add or remove?") print(rxn) guild_id = rxn.guild_id channel_id = rxn.channel_id message_id = rxn.message_id guild = await client.fetch_guild(guild_id) chl = await client.fetch_channel(rxn.channel_id) msg = await chl.fetch_message(rxn.message_id) author_id = msg.author.id tree = f"guilds/{guild.id}" stub = f"{tree}/{author_id}" if not os.path.exists(stub): return #if re.match(r"^Roles:", msg.content, re.IGNORECASE): if client.user in msg.mentions: lines = msg.content.split("\n") found_line = None for line in lines: if rxn.emoji.name in line: print("REACTION FOUND IN STR") found_line = line break role_id = re.search(r"<@&([0-9]{1,})>", found_line) if role_id is not None: role_id = int(role_id.group(1)) role = await guild.fetch_role(role_id) member = await guild.fetch_member(rxn.user_id) if member.bot: return if add: await msg.add_reaction(rxn.emoji.name) await member.add_roles(role) else: await member.remove_roles(role) @client.event async def on_raw_reaction_add(rxn): await on_raw_reaction_add_or_remove(rxn, True) @client.event async def on_raw_reaction_remove(rxn): await on_raw_reaction_add_or_remove(rxn, False) @client.event async def on_ready(): print("READY.") def main(): token = None with open("token.txt") as f: token = f.read() client.run(token) if __name__ == "__main__": main()