mirror of
https://github.com/pacnpal/Pac-cogs.git
synced 2025-12-20 02:41:06 -05:00
Component-based architecture with lifecycle management Enhanced error handling and recovery mechanisms Comprehensive state management and tracking Event-driven architecture with monitoring Queue Management: Multiple processing strategies for different scenarios Advanced state management with recovery Comprehensive metrics and health monitoring Sophisticated cleanup system with multiple strategies Processing Pipeline: Enhanced message handling with validation Improved URL extraction and processing Better queue management and monitoring Advanced cleanup mechanisms Overall Benefits: Better code organization and maintainability Improved error handling and recovery Enhanced monitoring and reporting More robust and reliable system
243 lines
7.2 KiB
Python
243 lines
7.2 KiB
Python
"""Module for managing Discord role configurations"""
|
|
|
|
import logging
|
|
from typing import Dict, List, Set, Tuple
|
|
import discord
|
|
|
|
from .exceptions import ConfigurationError as ConfigError
|
|
|
|
logger = logging.getLogger("RoleManager")
|
|
|
|
class RoleManager:
|
|
"""Manages Discord role configurations"""
|
|
|
|
def __init__(self, config_manager):
|
|
self.config_manager = config_manager
|
|
|
|
async def check_user_roles(
|
|
self,
|
|
member: discord.Member
|
|
) -> Tuple[bool, Optional[str]]:
|
|
"""Check if user has permission based on allowed roles
|
|
|
|
Args:
|
|
member: Discord member to check
|
|
|
|
Returns:
|
|
Tuple[bool, Optional[str]]: (Has permission, Reason if denied)
|
|
|
|
Raises:
|
|
ConfigError: If role check fails
|
|
"""
|
|
try:
|
|
allowed_roles = await self.config_manager.get_setting(
|
|
member.guild.id,
|
|
"allowed_roles"
|
|
)
|
|
|
|
# If no roles are set, allow all users
|
|
if not allowed_roles:
|
|
return True, None
|
|
|
|
# Check user roles
|
|
user_roles = {role.id for role in member.roles}
|
|
allowed_role_set = set(allowed_roles)
|
|
|
|
if user_roles & allowed_role_set: # Intersection
|
|
return True, None
|
|
|
|
# Get role names for error message
|
|
missing_roles = await self._get_role_names(
|
|
member.guild,
|
|
allowed_role_set
|
|
)
|
|
return False, f"Missing required roles: {', '.join(missing_roles)}"
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to check roles for user {member.id} in guild {member.guild.id}: {e}")
|
|
raise ConfigError(f"Failed to check user roles: {str(e)}")
|
|
|
|
async def add_allowed_role(
|
|
self,
|
|
guild_id: int,
|
|
role_id: int
|
|
) -> None:
|
|
"""Add a role to allowed roles
|
|
|
|
Args:
|
|
guild_id: Guild ID
|
|
role_id: Role ID to add
|
|
|
|
Raises:
|
|
ConfigError: If role cannot be added
|
|
"""
|
|
try:
|
|
await self.config_manager.add_to_list(
|
|
guild_id,
|
|
"allowed_roles",
|
|
role_id
|
|
)
|
|
except Exception as e:
|
|
logger.error(f"Failed to add allowed role {role_id}: {e}")
|
|
raise ConfigError(f"Failed to add allowed role: {str(e)}")
|
|
|
|
async def remove_allowed_role(
|
|
self,
|
|
guild_id: int,
|
|
role_id: int
|
|
) -> None:
|
|
"""Remove a role from allowed roles
|
|
|
|
Args:
|
|
guild_id: Guild ID
|
|
role_id: Role ID to remove
|
|
|
|
Raises:
|
|
ConfigError: If role cannot be removed
|
|
"""
|
|
try:
|
|
await self.config_manager.remove_from_list(
|
|
guild_id,
|
|
"allowed_roles",
|
|
role_id
|
|
)
|
|
except Exception as e:
|
|
logger.error(f"Failed to remove allowed role {role_id}: {e}")
|
|
raise ConfigError(f"Failed to remove allowed role: {str(e)}")
|
|
|
|
async def get_allowed_roles(
|
|
self,
|
|
guild: discord.Guild
|
|
) -> List[discord.Role]:
|
|
"""Get all allowed roles for a guild
|
|
|
|
Args:
|
|
guild: Discord guild
|
|
|
|
Returns:
|
|
List[discord.Role]: List of allowed roles
|
|
|
|
Raises:
|
|
ConfigError: If roles cannot be retrieved
|
|
"""
|
|
try:
|
|
settings = await self.config_manager.get_guild_settings(guild.id)
|
|
role_ids = settings["allowed_roles"]
|
|
|
|
roles = []
|
|
invalid_roles = []
|
|
|
|
for role_id in role_ids:
|
|
role = guild.get_role(role_id)
|
|
if role:
|
|
roles.append(role)
|
|
else:
|
|
invalid_roles.append(role_id)
|
|
logger.warning(f"Invalid role {role_id} in guild {guild.id}")
|
|
|
|
# Clean up invalid roles if found
|
|
if invalid_roles:
|
|
await self._remove_invalid_roles(guild.id, invalid_roles)
|
|
|
|
return roles
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to get allowed roles for guild {guild.id}: {e}")
|
|
raise ConfigError(f"Failed to get allowed roles: {str(e)}")
|
|
|
|
async def verify_role_hierarchy(
|
|
self,
|
|
guild: discord.Guild,
|
|
role: discord.Role
|
|
) -> Tuple[bool, Optional[str]]:
|
|
"""Verify bot's role hierarchy position for managing a role
|
|
|
|
Args:
|
|
guild: Discord guild
|
|
role: Role to check
|
|
|
|
Returns:
|
|
Tuple[bool, Optional[str]]: (Can manage role, Reason if not)
|
|
"""
|
|
try:
|
|
bot_member = guild.me
|
|
bot_top_role = bot_member.top_role
|
|
|
|
if role >= bot_top_role:
|
|
return False, f"Role {role.name} is higher than or equal to bot's highest role"
|
|
|
|
return True, None
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error checking role hierarchy: {e}")
|
|
return False, "Failed to check role hierarchy"
|
|
|
|
async def _get_role_names(
|
|
self,
|
|
guild: discord.Guild,
|
|
role_ids: Set[int]
|
|
) -> List[str]:
|
|
"""Get role names from role IDs
|
|
|
|
Args:
|
|
guild: Discord guild
|
|
role_ids: Set of role IDs
|
|
|
|
Returns:
|
|
List[str]: List of role names
|
|
"""
|
|
role_names = []
|
|
for role_id in role_ids:
|
|
role = guild.get_role(role_id)
|
|
if role:
|
|
role_names.append(role.name)
|
|
return role_names
|
|
|
|
async def _remove_invalid_roles(
|
|
self,
|
|
guild_id: int,
|
|
role_ids: List[int]
|
|
) -> None:
|
|
"""Remove invalid roles from allowed roles
|
|
|
|
Args:
|
|
guild_id: Guild ID
|
|
role_ids: List of invalid role IDs to remove
|
|
"""
|
|
try:
|
|
for role_id in role_ids:
|
|
await self.remove_allowed_role(guild_id, role_id)
|
|
except Exception as e:
|
|
logger.error(f"Error removing invalid roles: {e}")
|
|
|
|
async def get_role_info(
|
|
self,
|
|
guild: discord.Guild
|
|
) -> Dict[str, Any]:
|
|
"""Get role configuration information
|
|
|
|
Args:
|
|
guild: Discord guild
|
|
|
|
Returns:
|
|
Dict[str, Any]: Dictionary containing role information
|
|
"""
|
|
try:
|
|
allowed_roles = await self.get_allowed_roles(guild)
|
|
bot_member = guild.me
|
|
|
|
return {
|
|
'allowed_roles': allowed_roles,
|
|
'bot_top_role': bot_member.top_role,
|
|
'bot_permissions': bot_member.guild_permissions,
|
|
'role_count': len(allowed_roles)
|
|
}
|
|
except Exception as e:
|
|
logger.error(f"Error getting role info: {e}")
|
|
return {
|
|
'allowed_roles': [],
|
|
'bot_top_role': None,
|
|
'bot_permissions': None,
|
|
'role_count': 0
|
|
}
|