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
226 lines
7.5 KiB
Python
226 lines
7.5 KiB
Python
"""Module for managing Discord channel configurations"""
|
|
|
|
import logging
|
|
from typing import Dict, List, Optional, Tuple
|
|
import discord
|
|
|
|
from .exceptions import ConfigurationError as ConfigError, DiscordAPIError
|
|
|
|
logger = logging.getLogger("ChannelManager")
|
|
|
|
class ChannelManager:
|
|
"""Manages Discord channel configurations"""
|
|
|
|
def __init__(self, config_manager):
|
|
self.config_manager = config_manager
|
|
|
|
async def get_channel(
|
|
self,
|
|
guild: discord.Guild,
|
|
channel_type: str
|
|
) -> Optional[discord.TextChannel]:
|
|
"""Get a channel by type
|
|
|
|
Args:
|
|
guild: Discord guild
|
|
channel_type: Type of channel (archive, notification, log)
|
|
|
|
Returns:
|
|
Optional[discord.TextChannel]: Channel if found and valid
|
|
|
|
Raises:
|
|
ConfigError: If channel type is invalid
|
|
DiscordAPIError: If channel exists but is invalid type
|
|
"""
|
|
try:
|
|
if channel_type not in ["archive", "notification", "log"]:
|
|
raise ConfigError(f"Invalid channel type: {channel_type}")
|
|
|
|
settings = await self.config_manager.get_guild_settings(guild.id)
|
|
channel_id = settings.get(f"{channel_type}_channel")
|
|
|
|
if channel_id is None:
|
|
return None
|
|
|
|
channel = guild.get_channel(channel_id)
|
|
if channel is None:
|
|
logger.warning(f"Channel {channel_id} not found in guild {guild.id}")
|
|
return None
|
|
|
|
if not isinstance(channel, discord.TextChannel):
|
|
raise DiscordAPIError(f"Channel {channel_id} is not a text channel")
|
|
|
|
return channel
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to get {channel_type} channel for guild {guild.id}: {e}")
|
|
raise ConfigError(f"Failed to get channel: {str(e)}")
|
|
|
|
async def get_monitored_channels(
|
|
self,
|
|
guild: discord.Guild
|
|
) -> List[discord.TextChannel]:
|
|
"""Get all monitored channels for a guild
|
|
|
|
Args:
|
|
guild: Discord guild
|
|
|
|
Returns:
|
|
List[discord.TextChannel]: List of monitored channels
|
|
|
|
Raises:
|
|
ConfigError: If channel retrieval fails
|
|
"""
|
|
try:
|
|
settings = await self.config_manager.get_guild_settings(guild.id)
|
|
monitored_channel_ids = settings["monitored_channels"]
|
|
|
|
# If no channels are set to be monitored, return all text channels
|
|
if not monitored_channel_ids:
|
|
return [
|
|
channel for channel in guild.channels
|
|
if isinstance(channel, discord.TextChannel)
|
|
]
|
|
|
|
# Otherwise, return only the specified channels
|
|
channels: List[discord.TextChannel] = []
|
|
invalid_channels: List[int] = []
|
|
|
|
for channel_id in monitored_channel_ids:
|
|
channel = guild.get_channel(channel_id)
|
|
if channel and isinstance(channel, discord.TextChannel):
|
|
channels.append(channel)
|
|
else:
|
|
invalid_channels.append(channel_id)
|
|
logger.warning(f"Invalid monitored channel {channel_id} in guild {guild.id}")
|
|
|
|
# Clean up invalid channels if found
|
|
if invalid_channels:
|
|
await self._remove_invalid_channels(guild.id, invalid_channels)
|
|
|
|
return channels
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to get monitored channels for guild {guild.id}: {e}")
|
|
raise ConfigError(f"Failed to get monitored channels: {str(e)}")
|
|
|
|
async def verify_channel_permissions(
|
|
self,
|
|
channel: discord.TextChannel,
|
|
required_permissions: List[str]
|
|
) -> Tuple[bool, List[str]]:
|
|
"""Verify bot has required permissions in a channel
|
|
|
|
Args:
|
|
channel: Channel to check
|
|
required_permissions: List of required permission names
|
|
|
|
Returns:
|
|
Tuple[bool, List[str]]: (Has all permissions, List of missing permissions)
|
|
"""
|
|
try:
|
|
bot_member = channel.guild.me
|
|
channel_perms = channel.permissions_for(bot_member)
|
|
|
|
missing_perms = [
|
|
perm for perm in required_permissions
|
|
if not getattr(channel_perms, perm, False)
|
|
]
|
|
|
|
return not bool(missing_perms), missing_perms
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error checking channel permissions: {e}")
|
|
return False, ["Failed to check permissions"]
|
|
|
|
async def add_monitored_channel(
|
|
self,
|
|
guild_id: int,
|
|
channel_id: int
|
|
) -> None:
|
|
"""Add a channel to monitored channels
|
|
|
|
Args:
|
|
guild_id: Guild ID
|
|
channel_id: Channel ID to add
|
|
|
|
Raises:
|
|
ConfigError: If channel cannot be added
|
|
"""
|
|
try:
|
|
await self.config_manager.add_to_list(
|
|
guild_id,
|
|
"monitored_channels",
|
|
channel_id
|
|
)
|
|
except Exception as e:
|
|
logger.error(f"Failed to add monitored channel {channel_id}: {e}")
|
|
raise ConfigError(f"Failed to add monitored channel: {str(e)}")
|
|
|
|
async def remove_monitored_channel(
|
|
self,
|
|
guild_id: int,
|
|
channel_id: int
|
|
) -> None:
|
|
"""Remove a channel from monitored channels
|
|
|
|
Args:
|
|
guild_id: Guild ID
|
|
channel_id: Channel ID to remove
|
|
|
|
Raises:
|
|
ConfigError: If channel cannot be removed
|
|
"""
|
|
try:
|
|
await self.config_manager.remove_from_list(
|
|
guild_id,
|
|
"monitored_channels",
|
|
channel_id
|
|
)
|
|
except Exception as e:
|
|
logger.error(f"Failed to remove monitored channel {channel_id}: {e}")
|
|
raise ConfigError(f"Failed to remove monitored channel: {str(e)}")
|
|
|
|
async def _remove_invalid_channels(
|
|
self,
|
|
guild_id: int,
|
|
channel_ids: List[int]
|
|
) -> None:
|
|
"""Remove invalid channels from monitored channels
|
|
|
|
Args:
|
|
guild_id: Guild ID
|
|
channel_ids: List of invalid channel IDs to remove
|
|
"""
|
|
try:
|
|
for channel_id in channel_ids:
|
|
await self.remove_monitored_channel(guild_id, channel_id)
|
|
except Exception as e:
|
|
logger.error(f"Error removing invalid channels: {e}")
|
|
|
|
async def get_channel_info(
|
|
self,
|
|
guild: discord.Guild
|
|
) -> Dict[str, Optional[discord.TextChannel]]:
|
|
"""Get all configured channels for a guild
|
|
|
|
Args:
|
|
guild: Discord guild
|
|
|
|
Returns:
|
|
Dict[str, Optional[discord.TextChannel]]: Dictionary of channel types to channels
|
|
"""
|
|
try:
|
|
return {
|
|
'archive': await self.get_channel(guild, "archive"),
|
|
'notification': await self.get_channel(guild, "notification"),
|
|
'log': await self.get_channel(guild, "log")
|
|
}
|
|
except Exception as e:
|
|
logger.error(f"Error getting channel info: {e}")
|
|
return {
|
|
'archive': None,
|
|
'notification': None,
|
|
'log': None
|
|
}
|