ChannelManager Cog Documentation¶
Overview¶
The ChannelManager cog provides comprehensive server and channel permission management capabilities. It enables administrators to configure bot response modes, manage whitelists/blacklists, set channel-specific modes, and control automatic responses on a per-channel basis.
Features¶
Core Functionality¶
- Server-wide Response Modes: Unrestricted, whitelist, or blacklist modes
- Channel-specific Modes: Special modes like story mode for individual channels
- Whitelist/Blacklist Management: Fine-grained channel access control
- Auto-response Configuration: Enable/disable automatic bot responses per channel
- Multi-language Support: Fully localized administrative interface
Key Components¶
ChannelManagerclass - Main cog implementation- JSON-based configuration storage
- Permission validation system
- Channel mode resolution logic
Commands¶
/set_server_mode¶
Sets the server-wide response mode for all channels.
Parameters:
- mode: Server response mode selection
- unrestricted: Bot responds in all channels
- whitelist: Bot responds only in whitelisted channels
- blacklist: Bot responds in all channels except blacklisted ones
Permissions: Administrator only
/set_channel_mode¶
Sets a special mode for a specific channel.
Parameters:
- channel: Target Discord text channel
- mode: Channel mode selection
- default: Use server-wide settings
- story: Enable story mode for interactive storytelling
Permissions: Administrator only
/add_channel¶
Adds a channel to the whitelist or blacklist.
Parameters:
- channel: Target Discord text channel
- list_type: List type selection
- whitelist: Add to allowed channels list
- blacklist: Add to blocked channels list
Permissions: Administrator only
/remove_channel¶
Removes a channel from the whitelist or blacklist.
Parameters:
- channel: Target Discord text channel
- list_type: List type selection
- whitelist: Remove from allowed channels list
- blacklist: Remove from blocked channels list
Permissions: Administrator only
/auto_response¶
Sets how the bot replies, unprompted, to messages in a channel.
Parameters:
- channel: Target Discord text channel
- mode: off, all (every message), chance (a share of messages) or relevant (only when the topic is relevant)
- chance: For chance, the percent of messages that get a reply (1-100, default 20)
- keywords: For relevant, extra comma-separated words that count as relevant
- reaction_chance: The percent of unprompted replies that are just one emoji reaction instead of a message (0-100, default 0 = off). The emoji is one of the server's most used emojis this week, or a common one; it does not count toward the chat rate limit. Mentions and replies to the bot always get a real answer
In relevant mode the bot first checks cheap rules: the message names it (its username or server nickname) or one
of the keywords, or comes from someone it answered in the last 3 minutes. If none matches, a small model
(the first available model in relevance_model in llm.yaml, or in message_model when that list is left out) reads the last 8 messages and answers YES or NO
(llm/relevance_judge.py); the keywords are given to it as the channel's topics. To bound the cost, the model is
asked at most once every 15 seconds per channel and never for messages under 4 characters, and a model failure
means no reply. The bot owner can change these numbers (and the 3-minute window and the 8 messages) under
auto_response in base.yaml. Unprompted replies count toward the
per-user chat limit in base.yaml (rate_limits); a user who is over it is skipped quietly.
Permissions: Administrator only
Technical Implementation¶
Class Structure¶
class ChannelManager(commands.Cog):
def __init__(self, bot)
async def cog_load(self)
def get_config_path(self, guild_id) -> str
def load_config(self, guild_id) -> dict
def save_config(self, guild_id, config)
async def check_admin_permissions(self, interaction: discord.Interaction, *, defer: bool = False) -> bool
# Command handlers
async def set_server_mode(self, interaction: discord.Interaction, mode: app_commands.Choice[str])
async def set_channel_mode(self, interaction: discord.Interaction, channel: discord.TextChannel, mode: app_commands.Choice[str])
async def add_channel_command(self, interaction: discord.Interaction, channel: discord.TextChannel, list_type: app_commands.Choice[str])
async def remove_channel_command(self, interaction: discord.Interaction, channel: discord.TextChannel, list_type: app_commands.Choice[str])
async def auto_response_command(self, interaction, channel, mode, chance=None, keywords=None, reaction_chance=None)
Configuration System¶
Data Structure¶
{
"mode": "unrestricted", // Server-wide mode
"whitelist": [], // Array of channel IDs
"blacklist": [], // Array of channel IDs
"auto_response": {}, // Channel ID -> boolean mapping (on/off; the dashboard toggles this)
"auto_response_settings": {}, // Channel ID -> {"mode", "chance", "keywords", "reaction_chance"}; missing = "all"
"channel_modes": {} // Channel ID -> mode string mapping
}
Configuration Management¶
- Storage Location:
data/channel_configs/{guild_id}.json - File Format: JSON with UTF-8 encoding
- Atomic Updates: Safe file writing with error handling
- Default Config: Automatic creation for new servers
Permission System¶
Administrator Validation¶
async def check_admin_permissions(self, interaction: discord.Interaction, *, defer: bool = False) -> bool:
if defer and not interaction.response.is_done():
await interaction.response.defer(ephemeral=True, thinking=True)
bot_owner_id = getattr(self.tokens, 'bot_owner_id', 0)
if interaction.user.guild_permissions.administrator or interaction.user.id == bot_owner_id:
return True
# Send localized permission denied message
error_message = self.lang_manager.translate(...) or "You do not have permission to perform this action. This command is restricted to administrators."
if interaction.response.is_done():
await interaction.followup.send(error_message, ephemeral=True)
else:
await interaction.response.send_message(error_message, ephemeral=True)
return False
Bot Owner Override¶
- Bot owner has full administrative access regardless of server permissions
- Configurable through
addons.tokens.bot_owner_id - Provides emergency access for maintenance
Channel Resolution Logic¶
Mode Evaluation Flow¶
def is_allowed_channel(self, channel: discord.TextChannel, guild_id: str) -> Tuple[bool, bool, Optional[str]]:
config = self.load_config(guild_id)
channel_id = str(channel.id)
auto_response_enabled = config.get("auto_response", {}).get(channel_id, False)
# 1. Check channel-specific mode override
channel_mode = config.get("channel_modes", {}).get(channel_id)
if channel_mode: # e.g., 'story'
return True, auto_response_enabled, channel_mode
# 2. Use server-wide mode
server_mode = config.get("mode", "unrestricted")
if server_mode == "unrestricted":
return True, auto_response_enabled, server_mode
elif server_mode == "whitelist":
is_allowed = channel_id in config.get("whitelist", [])
return is_allowed, auto_response_enabled, server_mode
elif server_mode == "blacklist":
is_allowed = channel_id not in config.get("blacklist", [])
return is_allowed, auto_response_enabled, server_mode
return False, False, server_mode
Priority Order¶
- Channel-specific modes (highest priority)
- Server-wide unrestricted mode
- Server-wide whitelist mode
- Server-wide blacklist mode
- Default deny (lowest priority)
Data Migration and Validation¶
Configuration Sanitization¶
def _sanitize_schedule_data(self, data, fallback_channel_id: int):
"""Ensure config has required keys and proper types"""
repaired = False
if not isinstance(data, dict):
data = {}
repaired = True
if 'mode' not in data:
data['mode'] = "unrestricted"
repaired = True
# Ensure arrays exist
for key in ['whitelist', 'blacklist']:
if key not in data or not isinstance(data[key], list):
data[key] = []
repaired = True
# Ensure dictionaries exist
for key in ['auto_response', 'channel_modes']:
if key not in data or not isinstance(data[key], dict):
data[key] = {}
repaired = True
return data, repaired
Configuration Management¶
File Operations¶
- Atomic Writes: Temporary file + rename for safety
- Error Handling: Graceful handling of file system errors
- UTF-8 Encoding: Proper text encoding for internationalization
- Backup Creation: Optional backup of existing configurations
Server Onboarding¶
- Automatic Defaults: New servers get default configuration
- Migration Support: Automatic upgrade of old configuration formats
- Validation: Configuration integrity checking
Error Handling¶
Robust Error Recovery¶
- JSON Parsing Errors: Fallback to default configuration
- File System Issues: Graceful handling of disk problems
- Permission Errors: User-friendly permission denial messages
- Network Issues: Localized error message delivery
Validation System¶
- Input Validation: Sanitize all user inputs
- Type Checking: Ensure proper data types in configuration
- Range Validation: Validate channel IDs and boolean values
Performance Considerations¶
Efficient Configuration Loading¶
- Cached Configurations: In-memory caching of server configs
- Lazy Loading: Load config only when needed
- Minimal I/O: Read/write operations minimized
Memory Management¶
- Config Caching: Cache configurations in memory
- Automatic Cleanup: Remove cached configs for departed servers
- Memory Limits: Prevent excessive memory usage
Security & Permissions¶
Access Control Matrix¶
| Action | Required Permission | Bot Owner Override |
|---|---|---|
| Set server mode | Administrator | Yes |
| Set channel mode | Administrator | Yes |
| Add/remove from lists | Administrator | Yes |
| Configure auto-response | Administrator | Yes |
| View current settings | Read Messages | Yes |
Data Protection¶
- Server Isolation: Configurations separated by server ID
- Secure File Storage: Proper file permissions
- Input Sanitization: Protection against injection attacks
Integration Points¶
With Other Cogs¶
# ChannelManager provides access control for other features
from cogs.channel_manager import ChannelManager
# Check if bot can respond in channel
channel_manager = bot.get_cog("ChannelManager")
allowed, auto_response, mode = channel_manager.is_allowed_channel(channel, guild_id)
Usage Patterns¶
- Story Mode: Story manager checks for story mode channel setting
- Auto-response: AI responses respect auto-response configuration
- Permission System: Centralized permission checking for all features
Usage Examples¶
Basic Server Configuration¶
Admin: /set_server_mode whitelist
Bot: Server response mode set to: Whitelist
Admin: /add_channel #general whitelist
Bot: Channel #general added to whitelist
Channel-specific Modes¶
Auto-response Control¶
Admin: /auto_response #support-channel enabled
Bot: Channel #support-channel auto-response set to: True
Related Files¶
cogs/channel_manager.py- Main implementationdata/channel_configs/- Configuration storage directoryLanguageManager- Translation systemaddons.tokens- Bot owner configuration
Future Enhancements¶
Potential improvements: - Configuration import/export - Bulk channel operations - Advanced permission roles - Configuration templates - Audit logging - Web-based configuration interface