py-discord-role-selector/bot.py

184 lines
5.2 KiB
Python

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()