Add generated TRaSH-Guides with scripts

This commit is contained in:
Johan van Eck 2025-07-26 10:10:07 +03:00
parent 8e15e62281
commit 0857ea9dc6
885 changed files with 13936 additions and 34503 deletions

View file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,86 @@
import os
import json
import yaml
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',
}
def collect_custom_format(service, file_name, input_json, output_dir):
conditions = []
for spec in input_json.get('specifications', []):
condition = {
'name': spec.get('name', ''),
'negate': spec.get('negate', False),
'required': spec.get('required', False),
'type': IMPLEMENTATION_TO_TYPE_MAPPING.get(spec.get('implementation'), 'unknown'),
}
implementation = spec.get('implementation')
if implementation in ['ReleaseTitleSpecification', 'ReleaseGroupSpecification']:
condition['pattern'] = spec.get('name', '')
elif implementation in ['ResolutionSpecification']:
condition['resolution'] = spec.get('fields', {}).get('value')
elif implementation in ['SourceSpecification']:
condition['source'] = spec.get('fields', {}).get('value')
elif implementation in ['LanguageSpecification']:
# TODO: exceptLanguage
condition['language'] = spec.get('fields', {}).get('value')
elif implementation in ['IndexerFlagSpecification']:
condition['flag'] = spec.get('fields', {}).get('value')
elif implementation in ['QualityModifierSpecification']:
condition['qualityModifier'] = spec.get('fields', {}).get('value')
elif implementation in ['ReleaseTypeSpecification']:
condition['releaseType'] = spec.get('fields', {}).get('value')
conditions.append(condition)
# Compose YAML structure
name = input_json.get('name', '')
trash_id = input_json.get('trash_id', '')
yml_data = {
'name': name,
'trash_id': trash_id,
'trash_scores': input_json.get('trash_scores', {}),
'description': f"""Custom format from TRaSH-Guides.
https://trash-guides.info/{service.capitalize()}/{service.capitalize()}-collection-of-custom-formats/#{file_name}""",
'tags': IMPLEMENTATION_TO_TAG_MAPPING[implementation],
'conditions': conditions,
'tests': []
}
# Output path
output_path = os.path.join(output_dir, f"{file_name}-{trash_id}.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):
for root, _, files in os.walk(input_dir):
for filename in files:
if not filename.endswith('.json'):
continue
file_path = os.path.join(root, filename)
file_stem = os.path.splitext(filename)[0] # Filename without extension
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
collect_custom_format(service, file_stem, data, output_dir)

115
scripts/utils/profiles.py Normal file
View file

@ -0,0 +1,115 @@
import os
import json
import yaml
def find_score_for_custom_format(trash_score_set, custom_format_name, trash_id, output_dir):
custom_formats_dir = os.path.join(output_dir, '..', 'custom_formats')
target_file = None
for fname in os.listdir(custom_formats_dir):
if fname.endswith('.yml') and trash_id in fname:
target_file = os.path.join(custom_formats_dir, fname)
break
if not target_file or not os.path.exists(target_file):
print(f"Custom format with trash_id {trash_id} not found in {custom_formats_dir}")
return 0
with open(target_file, 'r', encoding='utf-8') as f:
data = yaml.safe_load(f)
if not data or 'trash_id' not in data:
print(f"Invalid custom format data for {custom_format_name}")
return 0
if data['trash_id'] != trash_id:
# TODO: Better log
print(f"Trash ID {trash_id} not found in trash_score_set for custom format {custom_format_name}")
return 0
trash_scores = data.get('trash_scores', {})
if not trash_scores:
print(f"No trash scores found in {custom_format_name}")
return 0
return trash_scores.get(trash_score_set, trash_scores.get('default', 0))
def collect_profile_formats(trash_score_set, format_items, output_dir):
profile_format = []
for name, trash_id in format_items.items():
score = find_score_for_custom_format(trash_score_set, name, trash_id, output_dir)
if score == 0:
continue
profile_format.append({
'name': name,
'score': score
})
return profile_format
def collect_qualities(items):
qualities = []
quality_id = 1
quality_collection_id = -1
for item in items:
if item.get('allowed', False) is False:
continue
quality = {
'name': item.get('name', ''),
}
if item.get('items') is not None:
quality['id'] = quality_collection_id
quality_collection_id -= 1
quality['description'] = ''
quality['qualities'] = []
for sub_item in item['items']:
quality['qualities'].append({
'id': quality_id,
'name': sub_item
})
quality_id += 1
else:
quality['id'] = quality_id
quality_id += 1
qualities.append(quality)
return qualities
def collect_profile(service, file_name, input_json, output_dir):
# Compose YAML structure
name = input_json.get('name', '')
trash_id = input_json.get('trash_id', '')
yml_data = {
'name': name,
'description': f"""Profile from TRaSH-Guides.
{input_json.get('trash_description', '')}""",
'trash_id': trash_id,
'tags': [],
'upgradesAllowed': input_json.get('upgradeAllowed', True),
'minCustomFormatScore': input_json.get('minFormatScore', 0),
'upgradeUntilScore': input_json.get('cutoffFormatScore', 0),
'minScoreIncrement': input_json.get('minUpgradeFormatScore', 0),
'qualities': collect_qualities(input_json.get('items', [])),
'custom_formats': collect_profile_formats(input_json.get('trash_score_set'), input_json.get('formatItems', {}), output_dir),
'language': input_json.get('language', 'any').lower(),
}
# Output path
output_path = os.path.join(output_dir, f"{file_name}-{trash_id}.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_profiles(service, input_dir, output_dir):
for root, _, files in os.walk(input_dir):
for filename in files:
if not filename.endswith('.json'):
continue
file_path = os.path.join(root, filename)
file_stem = os.path.splitext(filename)[0] # Filename without extension
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
collect_profile(service, file_stem, data, output_dir)

View file

@ -0,0 +1,43 @@
import os
import json
import yaml
def collect_regex_pattern(service, file_name, input_json, output_dir):
# Find the first pattern in specifications
pattern = None
for spec in input_json.get('specifications', []):
implementation = spec.get('implementation')
if implementation not in ['ReleaseTitleSpecification', 'ReleaseGroupSpecification']:
continue
pattern = spec.get('fields', {}).get('value')
if not pattern:
continue
# Compose YAML structure
name = input_json.get('name', '')
yml_data = {
'name': name,
'pattern': pattern,
'description': "Regex pattern from TRaSH-Guides.",
'tags': [],
}
# Output path
output_path = os.path.join(output_dir, f"{file_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_regex_patterns(service, input_dir, output_dir):
for root, _, files in os.walk(input_dir):
for filename in files:
if not filename.endswith('.json'):
continue
file_path = os.path.join(root, filename)
file_stem = os.path.splitext(filename)[0] # Filename without extension
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
collect_regex_pattern(service, file_stem, data, output_dir)