From a7cb04eea49e8e4d87e896c234302dc19f54d6ba Mon Sep 17 00:00:00 2001 From: Johan van Eck Date: Tue, 19 Aug 2025 21:43:26 +0300 Subject: [PATCH] Add media_management --- .gitignore | 1 + media_management/misc.yml | 6 + media_management/naming.yml | 17 +++ media_management/quality_definitions.yml | 114 ++++++++++++++++++ scripts/generate.py | 7 ++ .../utils/mappings/misc_media_management.py | 4 + scripts/utils/media_management.py | 113 +++++++++++++++++ 7 files changed, 262 insertions(+) create mode 100644 media_management/misc.yml create mode 100644 media_management/naming.yml create mode 100644 media_management/quality_definitions.yml create mode 100644 scripts/utils/mappings/misc_media_management.py create mode 100644 scripts/utils/media_management.py diff --git a/.gitignore b/.gitignore index 06006a6..895b4f6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /.obsidian __pycache__ +TRaSH-Guides diff --git a/media_management/misc.yml b/media_management/misc.yml new file mode 100644 index 0000000..a0cfe7d --- /dev/null +++ b/media_management/misc.yml @@ -0,0 +1,6 @@ +radarr: + propersRepacks: doNotPrefer + enableMediaInfo: true +sonarr: + propersRepacks: doNotPrefer + enableMediaInfo: true diff --git a/media_management/naming.yml b/media_management/naming.yml new file mode 100644 index 0000000..b57ead1 --- /dev/null +++ b/media_management/naming.yml @@ -0,0 +1,17 @@ +radarr: + rename: true + movieFormat: "{Movie CleanTitle} {(Release Year)} - {{Edition Tags}} {[MediaInfo 3D]}{[Custom Formats]}{[Quality Full]}{[Mediainfo AudioCodec}{ Mediainfo AudioChannels]}{[MediaInfo VideoDynamicRangeType]}{[Mediainfo VideoCodec]}{-Release Group}" + movieFolderFormat: "{Movie CleanTitle} ({Release Year})" + replaceIllegalCharacters: false + colonReplacementFormat: smart +sonarr: + rename: true + standardEpisodeFormat: "{Series TitleYear} - S{season:00}E{episode:00} - {Episode CleanTitle:90} {[Custom Formats]}{[Quality Full]}{[Mediainfo AudioCodec}{ Mediainfo AudioChannels]}{[MediaInfo VideoDynamicRangeType]}{[Mediainfo VideoCodec]}{-Release Group}" + dailyEpisodeFormat: "{Series TitleYear} - {Air-Date} - {Episode CleanTitle:90} {[Custom Formats]}{[Quality Full]}{[Mediainfo AudioCodec}{ Mediainfo AudioChannels]}{[MediaInfo VideoDynamicRangeType]}{[Mediainfo VideoCodec]}{-Release Group}" + animeEpisodeFormat: "{Series TitleYear} - S{season:00}E{episode:00} - {absolute:000} - {Episode CleanTitle:90} {[Custom Formats]}{[Quality Full]}{[Mediainfo AudioCodec}{ Mediainfo AudioChannels]}{MediaInfo AudioLanguages}{[MediaInfo VideoDynamicRangeType]}[{Mediainfo VideoCodec }{MediaInfo VideoBitDepth}bit]{-Release Group}" + seriesFolderFormat: "{Series TitleYear}" + seasonFolderFormat: Season {season:00} + replaceIllegalCharacters: false + colonReplacementFormat: 4 + customColonReplacementFormat: "" + multiEpisodeStyle: 5 diff --git a/media_management/quality_definitions.yml b/media_management/quality_definitions.yml new file mode 100644 index 0000000..91ea471 --- /dev/null +++ b/media_management/quality_definitions.yml @@ -0,0 +1,114 @@ +radarr: + Remux-2160p: + max: 2000 + min: 187.4 + preferred: 1999 + Bluray-2160p: + max: 2000 + min: 102 + preferred: 1999 + WEBRip-2160p: + max: 2000 + min: 34.5 + preferred: 1999 + WEBDL-2160p: + max: 2000 + min: 34.5 + preferred: 1999 + HDTV-2160p: + max: 2000 + min: 85 + preferred: 1999 + Remux-1080p: + max: 2000 + min: 102 + preferred: 1999 + Bluray-1080p: + max: 2000 + min: 50.8 + preferred: 1999 + WEBRip-1080p: + max: 2000 + min: 12.5 + preferred: 1999 + WEBDL-1080p: + max: 2000 + min: 12.5 + preferred: 1999 + HDTV-1080p: + max: 2000 + min: 33.8 + preferred: 1999 + Bluray-720p: + max: 2000 + min: 25.7 + preferred: 1999 + WEBRip-720p: + max: 2000 + min: 12.5 + preferred: 1999 + WEBDL-720p: + max: 2000 + min: 12.5 + preferred: 1999 + HDTV-720p: + max: 2000 + min: 17.1 + preferred: 1999 +sonarr: + Bluray-2160p Remux: + max: 1000 + min: 187.4 + preferred: 995 + Bluray-2160p: + max: 1000 + min: 94.6 + preferred: 995 + WEBDL-2160p: + max: 1000 + min: 25 + preferred: 995 + WEBRip-2160p: + max: 1000 + min: 25 + preferred: 995 + HDTV-2160p: + max: 1000 + min: 25 + preferred: 995 + Bluray-1080p Remux: + max: 1000 + min: 69.1 + preferred: 995 + Bluray-1080p: + max: 1000 + min: 50.4 + preferred: 995 + WEBDL-1080p: + max: 1000 + min: 15 + preferred: 995 + WEBRip-1080p: + max: 1000 + min: 15 + preferred: 995 + Bluray-720p: + max: 1000 + min: 17.1 + preferred: 995 + WEBDL-720p: + max: 1000 + min: 10 + preferred: 995 + WEBRip-720p: + max: 1000 + min: 10 + preferred: 995 + HDTV-1080p: + max: 1000 + min: 15 + preferred: 995 + HDTV-720p: + max: 1000 + min: 10 + preferred: 995 diff --git a/scripts/generate.py b/scripts/generate.py index 95e354d..073d4a8 100644 --- a/scripts/generate.py +++ b/scripts/generate.py @@ -12,6 +12,7 @@ import yaml from utils.custom_formats import collect_custom_formats from utils.regex_patterns import collect_regex_patterns from utils.profiles import collect_profiles +from utils.media_management import collect_media_management # Prevent aliases from showing up yaml.Dumper.ignore_aliases = lambda *args: True @@ -46,6 +47,10 @@ def main(): os.makedirs(profiles_dir, exist_ok=True) clear_output_dir(profiles_dir) + media_management_dir = os.path.join(output_dir, "media_management") + os.makedirs(media_management_dir, exist_ok=True) + clear_output_dir(media_management_dir) + for service in ["radarr", "sonarr"]: trash_custom_formats_dir = os.path.join(input_dir, f"{service}/cf") if not os.path.exists(trash_custom_formats_dir): @@ -83,6 +88,8 @@ def main(): trash_id_to_scoring_mapping, ) + collect_media_management(input_dir, media_management_dir) + if __name__ == "__main__": main() diff --git a/scripts/utils/mappings/misc_media_management.py b/scripts/utils/mappings/misc_media_management.py new file mode 100644 index 0000000..086a290 --- /dev/null +++ b/scripts/utils/mappings/misc_media_management.py @@ -0,0 +1,4 @@ +MISC_MEDIA_MANAGEMENT = { + "radarr": {"propersRepacks": "doNotPrefer", "enableMediaInfo": True}, + "sonarr": {"propersRepacks": "doNotPrefer", "enableMediaInfo": True}, +} diff --git a/scripts/utils/media_management.py b/scripts/utils/media_management.py new file mode 100644 index 0000000..7e07de3 --- /dev/null +++ b/scripts/utils/media_management.py @@ -0,0 +1,113 @@ +import os +import json +import yaml + +from utils.mappings.misc_media_management import MISC_MEDIA_MANAGEMENT + +BASE_NAMING_CONFIG = { + "radarr": { + "rename": True, + "movieFormat": "", + "movieFolderFormat": "", + "replaceIllegalCharacters": False, + "colonReplacementFormat": "smart", + }, + "sonarr": { + "rename": True, + "standardEpisodeFormat": "", + "dailyEpisodeFormat": "", + "animeEpisodeFormat": "", + "seriesFolderFormat": "", + "seasonFolderFormat": "", + "replaceIllegalCharacters": False, + "colonReplacementFormat": 4, + "customColonReplacementFormat": "", + "multiEpisodeStyle": 5, + }, +} +BASE_QUALITY_DEFINITIONS = {"radarr": {}, "sonarr": {}} + + +def collect_misc_config(output_dir): + output_file = os.path.join(output_dir, "misc.yml") + + with open(output_file, "w", encoding="utf-8") as f: + yaml.dump(MISC_MEDIA_MANAGEMENT, f, sort_keys=False, allow_unicode=True) + + print(f"Generated: {output_file}") + + +def collect_naming_formats(input_dir, output_dir): + output_file = os.path.join(output_dir, f"naming.yml") + new_config = BASE_NAMING_CONFIG.copy() + + radarr_input_file_path = os.path.join( + input_dir, "radarr", "naming", "radarr-naming.json" + ) + with open(radarr_input_file_path, "r", encoding="utf-8") as f: + input_json = json.load(f) + new_config["radarr"]["movieFormat"] = input_json["file"]["standard"] + new_config["radarr"]["movieFolderFormat"] = input_json["folder"]["default"] + + sonarr_input_file_path = os.path.join( + input_dir, "sonarr", "naming", "sonarr-naming.json" + ) + with open(sonarr_input_file_path, "r", encoding="utf-8") as f: + input_json = json.load(f) + standard_episode_format = input_json["episodes"]["standard"]["default"] + daily_episode_format = input_json["episodes"]["daily"]["default"] + anime_episode_format = input_json["episodes"]["anime"]["default"] + new_config["sonarr"]["standardEpisodeFormat"] = standard_episode_format + new_config["sonarr"]["dailyEpisodeFormat"] = daily_episode_format + new_config["sonarr"]["animeEpisodeFormat"] = anime_episode_format + new_config["sonarr"]["seriesFolderFormat"] = input_json["series"]["default"] + new_config["sonarr"]["seasonFolderFormat"] = input_json["season"]["default"] + + with open(output_file, "w", encoding="utf-8") as f: + f.write( + yaml.dump(new_config, sort_keys=False, allow_unicode=True, width=1000000) + ) + + print(f"Generated: {output_file}") + + +def collect_quality_definitions(input_dir, output_dir): + output_structure = BASE_QUALITY_DEFINITIONS.copy() + output_file = os.path.join(output_dir, "quality_definitions.yml") + + radarr_input_file_path = os.path.join( + input_dir, "radarr", "quality-size", "movie.json" + ) + with open(radarr_input_file_path, "r", encoding="utf-8") as f: + radarr_data = json.load(f) + for quality in reversed(radarr_data["qualities"]): + profilarr_quality = { + "max": quality["max"], + "min": quality["min"], + "preferred": quality["preferred"], + } + output_structure["radarr"][quality["quality"]] = profilarr_quality + + sonarr_input_file_path = os.path.join( + input_dir, "sonarr", "quality-size", "series.json" + ) + with open(sonarr_input_file_path, "r", encoding="utf-8") as f: + sonarr_data = json.load(f) + for quality in reversed(sonarr_data["qualities"]): + profilarr_quality = { + "max": quality["max"], + "min": quality["min"], + "preferred": quality["preferred"], + } + output_structure["sonarr"][quality["quality"]] = profilarr_quality + + with open(output_file, "w", encoding="utf-8") as f: + yaml.dump(output_structure, f, sort_keys=False, allow_unicode=True) + + print(f"Generated: {output_file}") + + +def collect_media_management(input_dir, output_dir): + collect_misc_config(output_dir) + collect_naming_formats(input_dir, output_dir) + collect_quality_definitions(input_dir, output_dir)