diff --git a/media_manager/movies/service.py b/media_manager/movies/service.py index cd88cd3..dc8e42b 100644 --- a/media_manager/movies/service.py +++ b/media_manager/movies/service.py @@ -32,7 +32,11 @@ from media_manager.movies.repository import MovieRepository from media_manager.exceptions import NotFoundError import pprint from media_manager.torrent.repository import TorrentRepository -from media_manager.torrent.utils import import_file, import_torrent +from media_manager.torrent.utils import ( + import_file, + import_torrent, + remove_special_characters, +) from media_manager.indexer.service import IndexerService from media_manager.metadataProvider.abstractMetaDataProvider import ( AbstractMetadataProvider, @@ -473,7 +477,10 @@ class MovieService: movie_file_path = ( misc_config.movie_directory - / f"{movie.name} ({movie.year}) [{movie.metadata_provider}id-{movie.external_id}]" + / f"{remove_special_characters(movie.name)} ({movie.year}) [{movie.metadata_provider}id-{movie.external_id}]" + ) + log.debug( + f"Movie {movie.name} without special characters: {remove_special_characters(movie.name)}" ) if movie.library != "Default": for library in misc_config.movie_libraries: @@ -481,7 +488,7 @@ class MovieService: log.debug(f"Using library {library.name} for movie {movie.name}") movie_file_path = ( Path(library.path) - / f"{movie.name} ({movie.year}) [{movie.metadata_provider}id-{movie.external_id}]" + / f"{remove_special_characters(movie.name)} ({movie.year}) [{movie.metadata_provider}id-{movie.external_id}]" ) break else: @@ -502,7 +509,7 @@ class MovieService: except Exception as e: log.warning(f"Could not create path {movie_file_path}: {e}") - movie_file_name = f"{movie.name} ({movie.year})" + movie_file_name = f"{remove_special_characters(movie.name)} ({movie.year})" if movie_file.file_path_suffix != "": movie_file_name += f" - {movie_file.file_path_suffix}" diff --git a/media_manager/torrent/utils.py b/media_manager/torrent/utils.py index 585092d..3f10e8d 100644 --- a/media_manager/torrent/utils.py +++ b/media_manager/torrent/utils.py @@ -1,6 +1,7 @@ import hashlib import logging import mimetypes +import re from pathlib import Path import shutil @@ -152,3 +153,19 @@ def get_torrent_hash(torrent: IndexerQueryResult) -> str: log.error(f"Failed to decode torrent file: {e}") raise return torrent_hash + + +def remove_special_characters(filename: str) -> str: + """ + Removes special characters from the filename to ensure it works with Jellyfin. + + :param filename: The original filename. + :return: A sanitized version of the filename. + """ + # Remove invalid characters + sanitized = re.sub(r"([<>:\"/\\|?*])", "", filename) + + # Remove leading and trailing dots or spaces + sanitized = sanitized.strip(" .") + + return sanitized diff --git a/media_manager/tv/service.py b/media_manager/tv/service.py index 675b4bb..b5c6293 100644 --- a/media_manager/tv/service.py +++ b/media_manager/tv/service.py @@ -37,7 +37,11 @@ from media_manager.exceptions import NotFoundError import pprint from pathlib import Path from media_manager.torrent.repository import TorrentRepository -from media_manager.torrent.utils import import_file, import_torrent +from media_manager.torrent.utils import ( + import_file, + import_torrent, + remove_special_characters, +) from media_manager.indexer.service import IndexerService from media_manager.metadataProvider.abstractMetaDataProvider import ( AbstractMetadataProvider, @@ -510,25 +514,27 @@ class TvService: f"Importing these {len(video_files)} files:\n" + pprint.pformat(video_files) ) misc_config = AllEncompassingConfig().misc - show_file_path = ( - misc_config.tv_directory - / f"{show.name} ({show.year}) [{show.metadata_provider}id-{show.external_id}]" + show_directory_name = f"{remove_special_characters(show.name)} ({show.year}) [{show.metadata_provider}id-{show.external_id}]" + show_file_path = None + log.debug( + f"Show {show.name} without special characters: {remove_special_characters(show.name)}" ) + if show.library != "Default": for library in misc_config.tv_libraries: if library.name == show.library: log.info( f"Using library {library.name} for show {show.name} ({show.year})" ) - show_file_path = ( - Path(library.path) - / f"{show.name} ({show.year}) [{show.metadata_provider}id-{show.external_id}]" - ) + show_file_path = Path(library.path) / show_directory_name break else: log.warning( f"Library {show.library} not defined in config, using default TV directory." ) + show_file_path = misc_config.tv_directory / show_directory_name + else: + show_file_path = misc_config.tv_directory / show_directory_name season_files = self.torrent_service.get_season_files_of_torrent(torrent=torrent) log.info( @@ -543,9 +549,7 @@ class TvService: except Exception as e: log.warning(f"Could not create path {season_path}: {e}") for episode in season.episodes: - episode_file_name = ( - f"{show.name} S{season.number:02d}E{episode.number:02d}" - ) + episode_file_name = f"{remove_special_characters(show.name)} S{season.number:02d}E{episode.number:02d}" if season_file.file_path_suffix != "": episode_file_name += f" - {season_file.file_path_suffix}" pattern = (