140 lines
7.7 KiB
Python
140 lines
7.7 KiB
Python
import discord
|
|
from discord.ext import commands
|
|
import os
|
|
from dotenv import load_dotenv
|
|
import logging
|
|
|
|
# Configure logging
|
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s:%(levelname)s:%(name)s: %(message)s')
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# Load environment variables
|
|
load_dotenv()
|
|
OWNER_USER_ID = int(os.getenv("OWNER_USER_ID")) # Although commands.is_owner() handles this, loading for clarity/potential future use
|
|
|
|
class RoleCreatorCog(commands.Cog):
|
|
def __init__(self, bot):
|
|
self.bot = bot
|
|
|
|
@commands.command(name='create_roles', help='Creates predefined roles for reaction roles. Owner only.')
|
|
@commands.is_owner() # Restricts this command to the bot owner specified during bot setup
|
|
async def create_roles(self, ctx):
|
|
"""Creates a set of predefined roles typically used with reaction roles."""
|
|
guild = ctx.guild
|
|
if not guild:
|
|
await ctx.send("This command can only be used in a server.")
|
|
return
|
|
|
|
# Check if the bot has permission to manage roles
|
|
if not ctx.me.guild_permissions.manage_roles:
|
|
await ctx.send("I don't have permission to manage roles.")
|
|
logger.warning(f"Missing 'Manage Roles' permission in guild {guild.id} ({guild.name}).")
|
|
return
|
|
|
|
# Define color mapping for specific roles
|
|
color_map = {
|
|
"Red": discord.Color.red(),
|
|
"Blue": discord.Color.blue(),
|
|
"Green": discord.Color.green(),
|
|
"Yellow": discord.Color.gold(),
|
|
"Purple": discord.Color.purple(),
|
|
"Orange": discord.Color.orange(),
|
|
"Pink": discord.Color.fuchsia(),
|
|
"Black": discord.Color(0x010101), # Near black to avoid blending with themes
|
|
"White": discord.Color(0xFEFEFE) # Near white to avoid blending
|
|
}
|
|
|
|
await ctx.send("Starting role creation/update process...")
|
|
logger.info(f"Role creation/update initiated by {ctx.author} in guild {guild.id} ({guild.name}).")
|
|
|
|
role_categories = {
|
|
"Colors": ["Red", "Blue", "Green", "Yellow", "Purple", "Orange", "Pink", "Black", "White"],
|
|
"Regions": ["NA East", "NA West", "EU", "Asia", "Oceania", "South America"],
|
|
"Pronouns": ["He/Him", "She/Her", "They/Them", "Ask Pronouns"],
|
|
"Interests": ["Art", "Music", "Movies", "Books", "Technology", "Science", "History", "Food", "Programming", "Anime", "Photography", "Travel", "Writing", "Cooking", "Fitness", "Nature", "Gaming", "Philosophy", "Psychology", "Design", "Machine Learning", "Cryptocurrency", "Astronomy", "Mythology", "Languages", "Architecture", "DIY Projects", "Hiking", "Streaming", "Virtual Reality", "Coding Challenges", "Board Games", "Meditation", "Urban Exploration", "Tattoo Art", "Comics", "Robotics", "3D Modeling", "Podcasts"],
|
|
"Gaming Platforms": ["PC", "PlayStation", "Xbox", "Nintendo Switch", "Mobile"],
|
|
"Favorite Vocaloids": ["Hatsune Miku", "Kasane Teto", "Akita Neru", "Kagamine Rin", "Kagamine Len", "Megurine Luka", "Kaito", "Meiko", "Gumi", "Kaai Yuki"],
|
|
"Notifications": ["Announcements"]
|
|
}
|
|
|
|
created_count = 0
|
|
updated_count = 0 # Renamed from eped_count
|
|
skipped_other_count = 0 # For non-color roles that exist
|
|
error_count = 0
|
|
existing_roles = {role.name.lower(): role for role in guild.roles} # Cache existing roles for faster lookup
|
|
|
|
for category, names in role_categories.items():
|
|
logger.info(f"Processing category: {category}")
|
|
for name in names:
|
|
role_color = color_map.get(name) if category == "Colors" else None
|
|
role_exists = name.lower() in existing_roles
|
|
|
|
try:
|
|
if role_exists:
|
|
existing_role = existing_roles[name.lower()]
|
|
# Only edit if it's a color role and needs a color update (or just ensure color is set)
|
|
if category == "Colors" and role_color is not None:
|
|
# Check if color needs updating to avoid unnecessary API calls
|
|
if existing_role.color != role_color:
|
|
await existing_role.edit(color=role_color)
|
|
logger.info(f"Successfully updated color for existing role: {name}")
|
|
updated_count += 1
|
|
else:
|
|
logger.info(f"Role '{name}' already exists with correct color. Skipping update.")
|
|
updated_count += 1 # Count as updated/checked even if no change needed
|
|
else:
|
|
# Non-color role exists, skip it
|
|
logger.info(f"Non-color role '{name}' already exists. Skipping.")
|
|
skipped_other_count += 1
|
|
continue # Move to next role name
|
|
|
|
# Role does not exist, create it
|
|
await guild.create_role(
|
|
name=name,
|
|
color=role_color or discord.Color.default(), # Use mapped color or default
|
|
permissions=discord.Permissions.none(),
|
|
mentionable=False
|
|
)
|
|
logger.info(f"Successfully created role: {name}" + (f" with color {role_color}" if role_color else ""))
|
|
created_count += 1
|
|
|
|
except discord.Forbidden:
|
|
logger.error(f"Forbidden to {'edit' if role_exists else 'create'} role '{name}'. Check bot permissions.")
|
|
await ctx.send(f"Error: I lack permissions to {'edit' if role_exists else 'create'} the role '{name}'.")
|
|
error_count += 1
|
|
# Stop if permission error occurs, as it likely affects subsequent operations
|
|
await ctx.send(f"Stopping role processing due to permission error on role '{name}'.")
|
|
return
|
|
except discord.HTTPException as e:
|
|
logger.error(f"Failed to {'edit' if role_exists else 'create'} role '{name}': {e}")
|
|
await ctx.send(f"Error {'editing' if role_exists else 'creating'} role '{name}': {e}")
|
|
error_count += 1
|
|
except Exception as e:
|
|
logger.exception(f"An unexpected error occurred while processing role '{name}': {e}")
|
|
await ctx.send(f"An unexpected error occurred for role '{name}'. Check logs.")
|
|
error_count += 1
|
|
|
|
|
|
summary_message = f"Role creation/update process complete.\n" \
|
|
f"Created: {created_count}\n" \
|
|
f"Updated/Checked Colors: {updated_count}\n" \
|
|
f"Skipped (Other existing): {skipped_other_count}\n" \
|
|
f"Errors: {error_count}"
|
|
await ctx.send(summary_message)
|
|
logger.info(summary_message)
|
|
|
|
|
|
async def setup(bot):
|
|
# Ensure the owner ID is loaded correctly before adding the cog
|
|
if not OWNER_USER_ID:
|
|
logger.error("OWNER_USER_ID not found in .env file. RoleCreatorCog will not be loaded.")
|
|
return
|
|
# Check if the bot object has owner_id or owner_ids set, which discord.py uses for is_owner()
|
|
if not bot.owner_id and not bot.owner_ids:
|
|
logger.warning("Bot owner_id or owner_ids not set. The 'is_owner()' check might not function correctly.")
|
|
# Potentially load from OWNER_USER_ID if needed, though discord.py usually handles this
|
|
# bot.owner_id = OWNER_USER_ID # Uncomment if necessary and discord.py doesn't auto-load
|
|
|
|
await bot.add_cog(RoleCreatorCog(bot))
|
|
logger.info("RoleCreatorCog loaded successfully.")
|