144 lines
4.2 KiB
Python
144 lines
4.2 KiB
Python
"""Media organizer - Organizes movies and TV shows into proper folder structures."""
|
|
|
|
import logging
|
|
from pathlib import Path
|
|
|
|
from domain.movies.entities import Movie
|
|
from domain.tv_shows.entities import Episode, Season, TVShow
|
|
from domain.tv_shows.value_objects import SeasonNumber
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class MediaOrganizer:
|
|
"""
|
|
Organizes media files into proper folder structures.
|
|
|
|
This service knows how to organize movies and TV shows according to
|
|
common media server conventions (Plex, Jellyfin, etc.).
|
|
"""
|
|
|
|
def __init__(self, movie_folder: Path, tvshow_folder: Path):
|
|
"""
|
|
Initialize media organizer.
|
|
|
|
Args:
|
|
movie_folder: Root folder for movies
|
|
tvshow_folder: Root folder for TV shows
|
|
"""
|
|
self.movie_folder = movie_folder
|
|
self.tvshow_folder = tvshow_folder
|
|
|
|
def get_movie_destination(self, movie: Movie, filename: str) -> Path:
|
|
"""
|
|
Get the destination path for a movie file.
|
|
|
|
Structure: /movies/Movie Title (Year)/Movie.Title.Year.Quality.ext
|
|
|
|
Args:
|
|
movie: Movie entity
|
|
filename: Original filename (to extract extension)
|
|
|
|
Returns:
|
|
Full destination path
|
|
"""
|
|
# Create movie folder
|
|
folder_name = movie.get_folder_name()
|
|
movie_dir = self.movie_folder / folder_name
|
|
|
|
# Get extension from original filename
|
|
extension = Path(filename).suffix
|
|
|
|
# Create new filename
|
|
new_filename = movie.get_filename() + extension
|
|
|
|
return movie_dir / new_filename
|
|
|
|
def get_episode_destination(
|
|
self, show: TVShow, episode: Episode, filename: str
|
|
) -> Path:
|
|
"""
|
|
Get the destination path for a TV show episode file.
|
|
|
|
Structure: /tvshows/Show.Name/Season 01/S01E05.Episode.Title.ext
|
|
|
|
Args:
|
|
show: TVShow entity
|
|
episode: Episode entity
|
|
filename: Original filename (to extract extension)
|
|
|
|
Returns:
|
|
Full destination path
|
|
"""
|
|
# Create show folder
|
|
show_folder_name = show.get_folder_name()
|
|
show_dir = self.tvshow_folder / show_folder_name
|
|
|
|
# Create season folder
|
|
season = Season(
|
|
show_imdb_id=show.imdb_id,
|
|
season_number=episode.season_number,
|
|
episode_count=0, # Not needed for folder name
|
|
)
|
|
season_folder_name = season.get_folder_name()
|
|
season_dir = show_dir / season_folder_name
|
|
|
|
# Get extension from original filename
|
|
extension = Path(filename).suffix
|
|
|
|
# Create new filename
|
|
new_filename = episode.get_filename() + extension
|
|
|
|
return season_dir / new_filename
|
|
|
|
def create_movie_directory(self, movie: Movie) -> bool:
|
|
"""
|
|
Create the directory structure for a movie.
|
|
|
|
Args:
|
|
movie: Movie entity
|
|
|
|
Returns:
|
|
True if successful
|
|
"""
|
|
folder_name = movie.get_folder_name()
|
|
movie_dir = self.movie_folder / folder_name
|
|
|
|
try:
|
|
movie_dir.mkdir(parents=True, exist_ok=True)
|
|
logger.info(f"Created movie directory: {movie_dir}")
|
|
return True
|
|
except Exception as e:
|
|
logger.error(f"Failed to create movie directory: {e}")
|
|
return False
|
|
|
|
def create_episode_directory(self, show: TVShow, season_number: int) -> bool:
|
|
"""
|
|
Create the directory structure for a TV show season.
|
|
|
|
Args:
|
|
show: TVShow entity
|
|
season_number: Season number
|
|
|
|
Returns:
|
|
True if successful
|
|
"""
|
|
show_folder_name = show.get_folder_name()
|
|
show_dir = self.tvshow_folder / show_folder_name
|
|
|
|
season = Season(
|
|
show_imdb_id=show.imdb_id,
|
|
season_number=SeasonNumber(season_number),
|
|
episode_count=0,
|
|
)
|
|
season_folder_name = season.get_folder_name()
|
|
season_dir = show_dir / season_folder_name
|
|
|
|
try:
|
|
season_dir.mkdir(parents=True, exist_ok=True)
|
|
logger.info(f"Created season directory: {season_dir}")
|
|
return True
|
|
except Exception as e:
|
|
logger.error(f"Failed to create season directory: {e}")
|
|
return False
|