mirror of
https://github.com/pacnpal/Pac-cogs.git
synced 2025-12-20 02:41:06 -05:00
149 lines
5.7 KiB
Python
149 lines
5.7 KiB
Python
"""Module for validating configuration settings"""
|
|
|
|
import logging
|
|
from typing import Any, Dict, List, Union
|
|
|
|
# try:
|
|
# Try relative imports first
|
|
from exceptions import ConfigurationError as ConfigError
|
|
|
|
# except ImportError:
|
|
# Fall back to absolute imports if relative imports fail
|
|
# from videoarchiver.config.exceptions import ConfigurationError as ConfigError
|
|
|
|
logger = logging.getLogger("ConfigValidation")
|
|
|
|
|
|
class ValidationManager:
|
|
"""Manages validation of configuration settings"""
|
|
|
|
# Valid settings constraints
|
|
VALID_VIDEO_FORMATS = ["mp4", "webm", "mkv"]
|
|
MAX_QUALITY_RANGE = (144, 4320) # 144p to 4K
|
|
MAX_FILE_SIZE_RANGE = (1, 100) # 1MB to 100MB
|
|
MAX_CONCURRENT_DOWNLOADS = 5
|
|
MAX_MESSAGE_DURATION = 168 # 1 week in hours
|
|
MAX_RETRIES = 10
|
|
MAX_RETRY_DELAY = 30
|
|
|
|
def validate_setting(self, setting: str, value: Any) -> None:
|
|
"""Validate a setting value against constraints
|
|
|
|
Args:
|
|
setting: Name of the setting to validate
|
|
value: Value to validate
|
|
|
|
Raises:
|
|
ConfigError: If validation fails
|
|
"""
|
|
try:
|
|
validator = getattr(self, f"_validate_{setting}", None)
|
|
if validator:
|
|
validator(value)
|
|
else:
|
|
self._validate_generic(setting, value)
|
|
except Exception as e:
|
|
logger.error(f"Validation error for {setting}: {e}")
|
|
raise ConfigError(f"Validation error for {setting}: {str(e)}")
|
|
|
|
def _validate_video_format(self, value: str) -> None:
|
|
"""Validate video format setting"""
|
|
if value not in self.VALID_VIDEO_FORMATS:
|
|
raise ConfigError(
|
|
f"Invalid video format. Must be one of: {', '.join(self.VALID_VIDEO_FORMATS)}"
|
|
)
|
|
|
|
def _validate_video_quality(self, value: int) -> None:
|
|
"""Validate video quality setting"""
|
|
if not isinstance(value, int) or not (
|
|
self.MAX_QUALITY_RANGE[0] <= value <= self.MAX_QUALITY_RANGE[1]
|
|
):
|
|
raise ConfigError(
|
|
f"Video quality must be between {self.MAX_QUALITY_RANGE[0]} and {self.MAX_QUALITY_RANGE[1]}"
|
|
)
|
|
|
|
def _validate_max_file_size(self, value: Union[int, float]) -> None:
|
|
"""Validate max file size setting"""
|
|
if not isinstance(value, (int, float)) or not (
|
|
self.MAX_FILE_SIZE_RANGE[0] <= value <= self.MAX_FILE_SIZE_RANGE[1]
|
|
):
|
|
raise ConfigError(
|
|
f"Max file size must be between {self.MAX_FILE_SIZE_RANGE[0]} and {self.MAX_FILE_SIZE_RANGE[1]} MB"
|
|
)
|
|
|
|
def _validate_concurrent_downloads(self, value: int) -> None:
|
|
"""Validate concurrent downloads setting"""
|
|
if not isinstance(value, int) or not (
|
|
1 <= value <= self.MAX_CONCURRENT_DOWNLOADS
|
|
):
|
|
raise ConfigError(
|
|
f"Concurrent downloads must be between 1 and {self.MAX_CONCURRENT_DOWNLOADS}"
|
|
)
|
|
|
|
def _validate_message_duration(self, value: int) -> None:
|
|
"""Validate message duration setting"""
|
|
if not isinstance(value, int) or not (0 <= value <= self.MAX_MESSAGE_DURATION):
|
|
raise ConfigError(
|
|
f"Message duration must be between 0 and {self.MAX_MESSAGE_DURATION} hours"
|
|
)
|
|
|
|
def _validate_max_retries(self, value: int) -> None:
|
|
"""Validate max retries setting"""
|
|
if not isinstance(value, int) or not (0 <= value <= self.MAX_RETRIES):
|
|
raise ConfigError(f"Max retries must be between 0 and {self.MAX_RETRIES}")
|
|
|
|
def _validate_retry_delay(self, value: int) -> None:
|
|
"""Validate retry delay setting"""
|
|
if not isinstance(value, int) or not (1 <= value <= self.MAX_RETRY_DELAY):
|
|
raise ConfigError(
|
|
f"Retry delay must be between 1 and {self.MAX_RETRY_DELAY} seconds"
|
|
)
|
|
|
|
def _validate_message_template(self, value: str) -> None:
|
|
"""Validate message template setting"""
|
|
if not isinstance(value, str):
|
|
raise ConfigError("Message template must be a string")
|
|
|
|
# Check for required placeholders
|
|
required_placeholders = ["{username}", "{channel}"]
|
|
for placeholder in required_placeholders:
|
|
if placeholder not in value:
|
|
raise ConfigError(f"Message template must contain {placeholder}")
|
|
|
|
def _validate_boolean(self, value: bool) -> None:
|
|
"""Validate boolean settings"""
|
|
if not isinstance(value, bool):
|
|
raise ConfigError("Value must be a boolean")
|
|
|
|
def _validate_list(self, value: List[Any]) -> None:
|
|
"""Validate list settings"""
|
|
if not isinstance(value, list):
|
|
raise ConfigError("Value must be a list")
|
|
|
|
def _validate_generic(self, setting: str, value: Any) -> None:
|
|
"""Generic validation for settings without specific validators"""
|
|
if setting.endswith("_channel") and value is not None:
|
|
if not isinstance(value, int):
|
|
raise ConfigError(f"{setting} must be a channel ID (int) or None")
|
|
elif setting in [
|
|
"enabled",
|
|
"delete_after_repost",
|
|
"disable_update_check",
|
|
"use_database",
|
|
]:
|
|
self._validate_boolean(value)
|
|
elif setting in ["monitored_channels", "allowed_roles", "enabled_sites"]:
|
|
self._validate_list(value)
|
|
|
|
def validate_all_settings(self, settings: Dict[str, Any]) -> None:
|
|
"""Validate all settings in a configuration dictionary
|
|
|
|
Args:
|
|
settings: Dictionary of settings to validate
|
|
|
|
Raises:
|
|
ConfigError: If any validation fails
|
|
"""
|
|
for setting, value in settings.items():
|
|
self.validate_setting(setting, value)
|