148 lines
5.5 KiB
Python
148 lines
5.5 KiB
Python
import os
|
|
|
|
import yaml
|
|
from markdownify import markdownify
|
|
|
|
from utils.file_utils import iterate_json_files
|
|
from utils.mappings.indexer_flags import INDEXER_FLAG_MAPPING
|
|
from utils.mappings.languages import LANGUAGE_MAPPING
|
|
from utils.mappings.quality_modifiers import QUALITY_MODIFIER_MAPPING
|
|
from utils.mappings.release_type import RELEASE_TYPE_MAPPING
|
|
from utils.mappings.source import SOURCE_MAPPING
|
|
from utils.strings import get_name
|
|
|
|
|
|
IMPLEMENTATION_TO_TAG_MAPPING = {
|
|
"ReleaseTitleSpecification": "Release Title",
|
|
"ResolutionSpecification": "Resolution",
|
|
"SourceSpecification": "Source",
|
|
"LanguageSpecification": "Language",
|
|
"ReleaseGroupSpecification": "Release Group",
|
|
"IndexerFlagSpecification": "Indexer Flag",
|
|
"QualityModifierSpecification": "Quality Modifier",
|
|
"ReleaseTypeSpecification": "Release Type",
|
|
}
|
|
|
|
IMPLEMENTATION_TO_TYPE_MAPPING = {
|
|
"ReleaseTitleSpecification": "release_title",
|
|
"ResolutionSpecification": "resolution",
|
|
"SourceSpecification": "source",
|
|
"LanguageSpecification": "language",
|
|
"ReleaseGroupSpecification": "release_group",
|
|
"IndexerFlagSpecification": "indexer_flag",
|
|
"QualityModifierSpecification": "quality_modifier",
|
|
"ReleaseTypeSpecification": "release_type",
|
|
}
|
|
|
|
SERVICE_TO_TRASH_GUIDES_URL = {
|
|
"radarr": "https://trash-guides.info/Radarr/Radarr-collection-of-custom-formats",
|
|
"sonarr": "https://trash-guides.info/Sonarr/sonarr-collection-of-custom-formats",
|
|
}
|
|
|
|
|
|
def _create_condition_base(service, spec):
|
|
"""Create base condition structure from specification."""
|
|
return {
|
|
"name": get_name(service, spec.get("name", "")),
|
|
"negate": spec.get("negate", False),
|
|
"required": spec.get("required", False),
|
|
"type": IMPLEMENTATION_TO_TYPE_MAPPING.get(
|
|
spec.get("implementation"), "unknown"
|
|
),
|
|
}
|
|
|
|
|
|
def _add_condition_value(
|
|
condition, implementation, spec, *, service, regex_patterns, file_name
|
|
):
|
|
"""Add implementation-specific value to condition."""
|
|
fields = spec.get("fields", {})
|
|
value = fields.get("value")
|
|
|
|
if implementation in ["ReleaseTitleSpecification", "ReleaseGroupSpecification"]:
|
|
pattern_name = regex_patterns["by_pattern"].get(value)["name"]
|
|
if not pattern_name:
|
|
raise ValueError(
|
|
f"Pattern '{value}' not found in collected regex patterns "
|
|
f"for {service} in custom format {file_name}."
|
|
)
|
|
condition["pattern"] = pattern_name
|
|
elif implementation == "ResolutionSpecification":
|
|
condition["resolution"] = f"{value}p"
|
|
elif implementation == "SourceSpecification":
|
|
condition["source"] = SOURCE_MAPPING[service][value]
|
|
elif implementation == "LanguageSpecification":
|
|
condition["language"] = LANGUAGE_MAPPING[service][value]
|
|
elif implementation == "IndexerFlagSpecification":
|
|
condition["flag"] = INDEXER_FLAG_MAPPING[service][value]
|
|
elif implementation == "QualityModifierSpecification":
|
|
condition["qualityModifier"] = QUALITY_MODIFIER_MAPPING[service][value]
|
|
elif implementation == "ReleaseTypeSpecification":
|
|
condition["releaseType"] = RELEASE_TYPE_MAPPING[service][value]
|
|
else:
|
|
return False
|
|
return True
|
|
|
|
|
|
def _collect_custom_format(
|
|
service, file_name, input_json, output_dir, regex_patterns
|
|
):
|
|
conditions = []
|
|
implementation_tags = set()
|
|
for spec in input_json.get("specifications", []):
|
|
implementation = spec.get("implementation")
|
|
implementation_tags.add(IMPLEMENTATION_TO_TAG_MAPPING[implementation])
|
|
|
|
condition = _create_condition_base(service, spec)
|
|
if not _add_condition_value(
|
|
condition,
|
|
implementation,
|
|
spec,
|
|
service=service,
|
|
regex_patterns=regex_patterns,
|
|
file_name=file_name,
|
|
):
|
|
print(f"Unrecognised implementation ({implementation}), skipping for now.")
|
|
continue
|
|
|
|
conditions.append(condition)
|
|
|
|
# Compose YAML structure
|
|
name = input_json.get("name", "")
|
|
yml_data = {
|
|
"name": get_name(service, name),
|
|
"description": f"""[Custom format from TRaSH-Guides.]({SERVICE_TO_TRASH_GUIDES_URL[service]}#{file_name})
|
|
|
|
{markdownify(input_json.get('description', ''))}""".strip(),
|
|
"tags": [service.capitalize(), *sorted(implementation_tags)],
|
|
"conditions": conditions,
|
|
"tests": [],
|
|
}
|
|
|
|
# Include in rename is currently not supported from the file system
|
|
# It would require inserting into the DB
|
|
# TODO: Write a script that can do this?
|
|
# include_in_rename = input_json.get("includeCustomFormatWhenRenaming", False)
|
|
# if include_in_rename:
|
|
# yml_data["metadata"] = {"includeInRename": include_in_rename}
|
|
|
|
# Output path
|
|
output_path = os.path.join(output_dir, f"{get_name(service, name)}.yml")
|
|
with open(output_path, "w", encoding="utf-8") as f:
|
|
yaml.dump(yml_data, f, sort_keys=False, allow_unicode=True)
|
|
print(f"Generated: {output_path}")
|
|
|
|
|
|
def collect_custom_formats(service, input_dir, output_dir, custom_regex_patterns):
|
|
trash_id_to_scoring_mapping = {}
|
|
for _, file_stem, data in iterate_json_files(input_dir):
|
|
trash_id = data.get("trash_id")
|
|
trash_scores = data.get("trash_scores", {})
|
|
if trash_id:
|
|
trash_id_to_scoring_mapping[trash_id] = trash_scores
|
|
|
|
_collect_custom_format(
|
|
service, file_stem, data, output_dir, custom_regex_patterns
|
|
)
|
|
|
|
return trash_id_to_scoring_mapping
|