mirror of
https://github.com/Dictionarry-Hub/database.git
synced 2025-12-10 15:57:00 +00:00
create(script): Add tierCreator script for generating group tier custom formats + release group regex patterns fix(tierCreator): Update YAML handling and improve template processing for group tiers remove(template): release group condition placeholder create(format): 2160p Quality Tiers - 69 new release group regex patterns - 6 new tiers for 2160p Quality create(data): Add 2160p Quality Tiers JSON file with detailed statistics and scoring docs(README): Update README to include utility scripts and tier creator usage instructions fix(tierCreator): Improve output message to indicate whether a file is being created or overwritten feat(tierCreator): Add show_preview option for dry run mode to display regex patterns and custom formats add(tier): more data for 2160p Quality add(tiers): new regex patterns for various groups, tweaks to 2160p quality tiers tweak(format): add WOU and MALUS to unwanted x265 tweak(format): Seperate streaming services into 1080p / 2160p - Existing ones still exist, there are just needed for the 2160p Quality profile since it needs different scores based on the resolution create(format): Standard Dynamic Range create(format): Match x265 only for 1080p - Used to get rid of 1080p x265 encodes for 2160p Quality (since x265 is needed for 2160p Encodes) tweak(regex): DTS & X can now be seperated by a colon tweak(format): Add STRiKE to missing HDR Groups create(profile): Initialise 2160p Quality tweak(tier): adjustments to scoring algorithm - hard limits on efficiency delta / num releases for tier 3+ tweaks(tier): new groups / tier adjustments for 2160p quality add(format): x264 (1080p) - Match x264 2160p encodes tweak(profile): Various improvements - Remove UHD Bluray scores, they bloat the scoring logic - Reduce SDR WEBs to below tier ~4 - Add some notes on scoring logic to description fix(tier): Remove bad data fix(tier): remove groups added via bad data tweak(tier): target 55% efficiency, new data for SA89, Mainframe add(profile): x265 (Missing 2160p) - Append x265 to 2160 Blu-ray encodes that are not explicitly labelled x264 tweak(profile): Various improvements / tweaks - Remove required groups for HDR missing CF - New CF for unknown lossless audio - New 2160p Balanced tiers - Normalise lossless audio / quality tier scores tweak(profile): Adjust fallbacks / improve descriptions - Removed HDTV for 1080p profiles - Renamed 'fallbacks' to 'SD' tweak(profile): Finalise 2160p Quality v1 - Set upgrade until to 2160p Transparent, score = 800, min score increment = 5 - Add comprehensive description
211 lines
6.9 KiB
Python
211 lines
6.9 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
import yaml
|
|
|
|
|
|
def load_template(template_path):
|
|
"""Load a YAML template file."""
|
|
try:
|
|
with open(template_path, 'r') as f:
|
|
return yaml.safe_load(f)
|
|
except FileNotFoundError:
|
|
print(f"Error: Template file not found: {template_path}")
|
|
sys.exit(1)
|
|
|
|
|
|
def create_regex_pattern(group_name,
|
|
template_dir,
|
|
output_dir,
|
|
dry_run=False,
|
|
show_preview=False):
|
|
"""Create a regex pattern file for a release group if it doesn't exist."""
|
|
output_path = output_dir / f"{group_name}.yml"
|
|
|
|
# Skip if pattern already exists
|
|
if output_path.exists():
|
|
print(f"Skipping existing regex pattern: {output_path}")
|
|
return
|
|
|
|
print(
|
|
f"{'Would create' if dry_run else 'Creating'} regex pattern: {output_path}"
|
|
)
|
|
|
|
# Load and fill template
|
|
template = load_template(template_dir / "releaseGroup.yml")
|
|
template['name'] = group_name
|
|
template['pattern'] = f"(?<=^|[\\s.-]){group_name}\\b"
|
|
|
|
# Show preview in dry run mode if this is the first pattern
|
|
if dry_run and show_preview:
|
|
print("\nPreview of first regex pattern:")
|
|
print("---")
|
|
print(
|
|
yaml.dump(template,
|
|
sort_keys=False,
|
|
default_flow_style=False,
|
|
indent=2))
|
|
print("---\n")
|
|
|
|
# Create output directory if it doesn't exist
|
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
# Write pattern file if not dry run
|
|
if not dry_run:
|
|
with open(output_path, 'w') as f:
|
|
yaml.dump(template, f, sort_keys=False)
|
|
|
|
|
|
def create_tier_format(tier,
|
|
resolution,
|
|
type_name,
|
|
groups,
|
|
template_dir,
|
|
output_dir,
|
|
dry_run=False,
|
|
show_preview=False):
|
|
"""Create a custom format file for a specific tier."""
|
|
# Get groups for this tier
|
|
tier_groups = [group["name"] for group in groups if group["tier"] == tier]
|
|
if not tier_groups:
|
|
return
|
|
|
|
# Load and fill template
|
|
template = load_template(template_dir / "groupTier.yml")
|
|
|
|
# Replace template variables
|
|
template['name'] = f"{resolution} {type_name} Tier {tier}"
|
|
template[
|
|
'description'] = f"Matches release groups who fall under {resolution} {type_name} Tier {tier}"
|
|
|
|
# Find and update resolution condition
|
|
for condition in template['conditions']:
|
|
if condition.get('resolution'):
|
|
condition['name'] = resolution
|
|
condition['resolution'] = resolution
|
|
|
|
# Add release group conditions
|
|
for group_name in tier_groups:
|
|
release_group_condition = {
|
|
'name': group_name,
|
|
'negate': False,
|
|
'pattern': group_name,
|
|
'required': False,
|
|
'type': 'release_group'
|
|
}
|
|
template['conditions'].append(release_group_condition)
|
|
|
|
# Ensure tests is an empty list, not null
|
|
template['tests'] = []
|
|
|
|
# Create output directory if it doesn't exist
|
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
# Write custom format file
|
|
output_path = output_dir / f"{resolution} {type_name} Tier {tier}.yml"
|
|
existing = "Overwriting" if output_path.exists() else "Creating"
|
|
print(
|
|
f"{'Would ' + existing.lower() if dry_run else existing} custom format: {output_path} (includes {len(tier_groups)} groups)"
|
|
)
|
|
|
|
# Show preview in dry run mode if this is the first format
|
|
if dry_run and show_preview:
|
|
print("\nPreview of first custom format:")
|
|
print("---")
|
|
print(
|
|
yaml.dump(template,
|
|
sort_keys=False,
|
|
default_flow_style=False,
|
|
indent=2))
|
|
print("---\n")
|
|
|
|
if not dry_run:
|
|
with open(output_path, 'w') as f:
|
|
yaml.dump(template,
|
|
f,
|
|
sort_keys=False,
|
|
default_flow_style=False,
|
|
indent=2)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description='Create Radarr custom formats for release group tiers')
|
|
parser.add_argument('json_file',
|
|
help='Input JSON file containing tier data')
|
|
parser.add_argument('--resolution',
|
|
choices=['SD', '720p', '1080p', '2160p'],
|
|
required=True,
|
|
help='Resolution for custom formats')
|
|
parser.add_argument('--type',
|
|
choices=['Quality', 'Balanced'],
|
|
required=True,
|
|
help='Type of custom format')
|
|
parser.add_argument(
|
|
'--dry-run',
|
|
action='store_true',
|
|
help='Show what would be done without making any changes')
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Setup paths
|
|
script_dir = Path(__file__).parent
|
|
template_dir = script_dir.parent / "templates"
|
|
regex_dir = script_dir.parent / "regex_patterns"
|
|
format_dir = script_dir.parent / "custom_formats"
|
|
|
|
# Load and parse input JSON
|
|
try:
|
|
with open(args.json_file, 'r') as f:
|
|
data = json.load(f)
|
|
except FileNotFoundError:
|
|
print(f"Error: Input JSON file not found: {args.json_file}")
|
|
sys.exit(1)
|
|
except json.JSONDecodeError:
|
|
print(f"Error: Invalid JSON file: {args.json_file}")
|
|
sys.exit(1)
|
|
|
|
# Print summary of what we found
|
|
print(f"\nAnalyzing input file: {args.json_file}")
|
|
print(
|
|
f"Found {len(data['tiered_groups'])} release groups across {len(set(group['tier'] for group in data['tiered_groups']))} tiers"
|
|
)
|
|
|
|
if args.dry_run:
|
|
print("\nDRY RUN - No files will be created or modified\n")
|
|
|
|
# Create regex patterns for all groups
|
|
print("\nProcessing regex patterns:")
|
|
for i, group in enumerate(data["tiered_groups"]):
|
|
create_regex_pattern(group["name"],
|
|
template_dir,
|
|
regex_dir,
|
|
args.dry_run,
|
|
show_preview=(i == 0))
|
|
|
|
# Create tier formats
|
|
print("\nProcessing custom formats:")
|
|
unique_tiers = sorted(set(group["tier"]
|
|
for group in data["tiered_groups"]))
|
|
for i, tier in enumerate(unique_tiers):
|
|
create_tier_format(tier,
|
|
args.resolution,
|
|
args.type,
|
|
data["tiered_groups"],
|
|
template_dir,
|
|
format_dir,
|
|
args.dry_run,
|
|
show_preview=(i == 0))
|
|
|
|
print(
|
|
f"\nSuccessfully {'simulated' if args.dry_run else 'created'} custom formats for {args.resolution} {args.type}"
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|