109 lines
2.7 KiB
Python
109 lines
2.7 KiB
Python
"""Movie domain value objects."""
|
|
|
|
import re
|
|
from dataclasses import dataclass
|
|
from enum import Enum
|
|
|
|
from ..shared.exceptions import ValidationError
|
|
|
|
|
|
class Quality(Enum):
|
|
"""Video quality levels."""
|
|
|
|
SD = "480p"
|
|
HD = "720p"
|
|
FULL_HD = "1080p"
|
|
UHD_4K = "2160p"
|
|
UNKNOWN = "unknown"
|
|
|
|
@classmethod
|
|
def from_string(cls, quality_str: str) -> "Quality":
|
|
"""
|
|
Parse quality from string.
|
|
|
|
Args:
|
|
quality_str: Quality string (e.g., "1080p", "720p")
|
|
|
|
Returns:
|
|
Quality enum value
|
|
"""
|
|
quality_map = {
|
|
"480p": cls.SD,
|
|
"720p": cls.HD,
|
|
"1080p": cls.FULL_HD,
|
|
"2160p": cls.UHD_4K,
|
|
}
|
|
return quality_map.get(quality_str, cls.UNKNOWN)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class MovieTitle:
|
|
"""
|
|
Value object representing a movie title.
|
|
|
|
Ensures the title is valid and normalized.
|
|
"""
|
|
|
|
value: str
|
|
|
|
def __post_init__(self):
|
|
"""Validate movie title."""
|
|
if not self.value:
|
|
raise ValidationError("Movie title cannot be empty")
|
|
|
|
if not isinstance(self.value, str):
|
|
raise ValidationError(
|
|
f"Movie title must be a string, got {type(self.value)}"
|
|
)
|
|
|
|
if len(self.value) > 500:
|
|
raise ValidationError(
|
|
f"Movie title too long: {len(self.value)} characters (max 500)"
|
|
)
|
|
|
|
def normalized(self) -> str:
|
|
"""
|
|
Return normalized title for file system usage.
|
|
|
|
Removes special characters and replaces spaces with dots.
|
|
"""
|
|
# Remove special characters except spaces, dots, and hyphens
|
|
cleaned = re.sub(r"[^\w\s\.\-]", "", self.value)
|
|
# Replace spaces with dots
|
|
normalized = cleaned.replace(" ", ".")
|
|
return normalized
|
|
|
|
def __str__(self) -> str:
|
|
return self.value
|
|
|
|
def __repr__(self) -> str:
|
|
return f"MovieTitle('{self.value}')"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ReleaseYear:
|
|
"""
|
|
Value object representing a movie release year.
|
|
|
|
Validates that the year is reasonable.
|
|
"""
|
|
|
|
value: int
|
|
|
|
def __post_init__(self):
|
|
"""Validate release year."""
|
|
if not isinstance(self.value, int):
|
|
raise ValidationError(
|
|
f"Release year must be an integer, got {type(self.value)}"
|
|
)
|
|
|
|
# Movies started around 1888, and we shouldn't have movies from the future
|
|
if self.value < 1888 or self.value > 2100:
|
|
raise ValidationError(f"Invalid release year: {self.value}")
|
|
|
|
def __str__(self) -> str:
|
|
return str(self.value)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"ReleaseYear({self.value})"
|