Files
alfred/domain/subtitles/services.py
Francwa 2c8cdd3ab1 New archi: domain driven development
Working but need to check out code
2025-12-01 07:10:03 +01:00

155 lines
4.5 KiB
Python

"""Subtitle domain services - Business logic."""
import logging
from typing import List, Optional
from ..shared.value_objects import ImdbId, FilePath
from .entities import Subtitle
from .value_objects import Language, SubtitleFormat
from .repositories import SubtitleRepository
from .exceptions import SubtitleNotFound
logger = logging.getLogger(__name__)
class SubtitleService:
"""
Domain service for subtitle-related business logic.
This service is SHARED between movies and TV shows domains.
Both can use this service to manage subtitles.
"""
def __init__(self, repository: SubtitleRepository):
"""
Initialize subtitle service.
Args:
repository: Subtitle repository for persistence
"""
self.repository = repository
def add_subtitle(self, subtitle: Subtitle) -> None:
"""
Add a subtitle to the library.
Args:
subtitle: Subtitle entity to add
"""
self.repository.save(subtitle)
logger.info(f"Added subtitle: {subtitle.language.value} for {subtitle.media_imdb_id}")
def find_subtitles_for_movie(
self,
imdb_id: ImdbId,
languages: Optional[List[Language]] = None
) -> List[Subtitle]:
"""
Find subtitles for a movie.
Args:
imdb_id: IMDb ID of the movie
languages: Optional list of languages to filter by
Returns:
List of matching subtitles
"""
if languages:
all_subtitles = []
for lang in languages:
subs = self.repository.find_by_media(imdb_id, language=lang)
all_subtitles.extend(subs)
return all_subtitles
else:
return self.repository.find_by_media(imdb_id)
def find_subtitles_for_episode(
self,
imdb_id: ImdbId,
season: int,
episode: int,
languages: Optional[List[Language]] = None
) -> List[Subtitle]:
"""
Find subtitles for a TV show episode.
Args:
imdb_id: IMDb ID of the TV show
season: Season number
episode: Episode number
languages: Optional list of languages to filter by
Returns:
List of matching subtitles
"""
if languages:
all_subtitles = []
for lang in languages:
subs = self.repository.find_by_media(
imdb_id,
language=lang,
season=season,
episode=episode
)
all_subtitles.extend(subs)
return all_subtitles
else:
return self.repository.find_by_media(
imdb_id,
season=season,
episode=episode
)
def remove_subtitle(self, subtitle: Subtitle) -> None:
"""
Remove a subtitle from the library.
Args:
subtitle: Subtitle to remove
Raises:
SubtitleNotFound: If subtitle not found
"""
if not self.repository.delete(subtitle):
raise SubtitleNotFound(f"Subtitle not found: {subtitle}")
logger.info(f"Removed subtitle: {subtitle}")
def detect_format_from_file(self, file_path: FilePath) -> SubtitleFormat:
"""
Detect subtitle format from file extension.
Args:
file_path: Path to subtitle file
Returns:
Detected subtitle format
"""
extension = file_path.value.suffix
return SubtitleFormat.from_extension(extension)
def validate_subtitle_file(self, file_path: FilePath) -> bool:
"""
Validate that a file is a valid subtitle file.
Args:
file_path: Path to the file
Returns:
True if valid subtitle file, False otherwise
"""
if not file_path.exists():
logger.warning(f"File does not exist: {file_path}")
return False
if not file_path.is_file():
logger.warning(f"Path is not a file: {file_path}")
return False
# Check file extension
try:
self.detect_format_from_file(file_path)
return True
except Exception as e:
logger.warning(f"Invalid subtitle format: {e}")
return False