feat: add support for unique import names in format and profile import processes

This commit is contained in:
Sam Chau
2025-01-10 01:29:46 +10:30
parent 76f4f94290
commit 7428b71a32
4 changed files with 147 additions and 33 deletions

View File

@@ -382,6 +382,7 @@ def run_import_for_config(config_row):
arr_type = config_row['type']
arr_server = config_row['arrServer']
api_key = config_row['apiKey']
import_as_unique = config_row.get('import_as_unique', False)
logger.info(
f"[Pull Import] Running import for ARR config #{arr_id} ({arr_name})")
@@ -396,6 +397,13 @@ def run_import_for_config(config_row):
total_attempted = 0
total_successful = 0
# Log import_as_unique setting
if import_as_unique:
logger.info(f"Unique imports for {arr_name} are on, adjusting names")
else:
logger.info(
f"Unique imports for {arr_name} are off, using original names")
# 1) Import user-selected custom formats
if selected_formats:
total_attempted += len(selected_formats)
@@ -404,8 +412,20 @@ def run_import_for_config(config_row):
)
try:
from ..importarr.format import import_formats_to_arr
format_names = selected_formats
original_names = format_names.copy()
# Modify format names if import_as_unique is true
if import_as_unique:
format_names = [
f"{name} [Dictionarry]" for name in format_names
]
logger.info(
f"Modified format names for unique import: {format_names}")
format_result = import_formats_to_arr(
format_names=selected_formats,
format_names=format_names,
original_names=original_names,
base_url=arr_server,
api_key=api_key,
arr_type=arr_type)
@@ -453,11 +473,22 @@ def run_import_for_config(config_row):
total_attempted += len(referenced_cf_names)
try:
from ..importarr.format import import_formats_to_arr
cf_result = import_formats_to_arr(
format_names=list(referenced_cf_names),
base_url=arr_server,
api_key=api_key,
arr_type=arr_type)
format_names = list(referenced_cf_names)
original_names = format_names.copy()
# Modify format names if import_as_unique is true
if import_as_unique:
format_names = [
f"{name} [Dictionarry]" for name in format_names
]
logger.info(
f"Modified format names for unique import: {format_names}")
cf_result = import_formats_to_arr(format_names=format_names,
original_names=original_names,
base_url=arr_server,
api_key=api_key,
arr_type=arr_type)
if cf_result.get('success'):
total_successful += (cf_result.get('added', 0) +
@@ -475,12 +506,26 @@ def run_import_for_config(config_row):
total_attempted += len(selected_profiles)
try:
from ..importarr.profile import import_profiles_to_arr
profile_names = selected_profiles
original_names = profile_names.copy()
# Modify profile names if import_as_unique is true
if import_as_unique:
profile_names = [
f"{name} [Dictionarry]" for name in profile_names
]
logger.info(
f"Modified profile names for unique import: {profile_names}"
)
profile_result = import_profiles_to_arr(
profile_names=selected_profiles,
profile_names=profile_names,
original_names=original_names,
base_url=arr_server,
api_key=api_key,
arr_type=arr_type,
arr_id=arr_id)
arr_id=arr_id,
import_as_unique=import_as_unique)
if profile_result.get('success'):
total_successful += (profile_result.get('added', 0) +

View File

@@ -34,11 +34,13 @@ class ProfileConverter:
target_app: TargetApp,
base_url: str = None,
api_key: str = None,
format_importer: Callable = None):
format_importer: Callable = None,
import_as_unique: bool = False):
self.target_app = target_app
self.base_url = base_url
self.api_key = api_key
self.format_importer = format_importer
self.import_as_unique = import_as_unique
self.quality_mappings = ValueResolver.get_qualities(target_app)
def _convert_group_id(self, group_id: int) -> int:
@@ -60,8 +62,11 @@ class ProfileConverter:
})
return qualities
def _process_language_formats(self, behaviour: str,
language: str) -> List[Dict]:
def _process_language_formats(
self,
behaviour: str,
language: str,
import_as_unique: bool = False) -> List[Dict]:
if not self.base_url or not self.api_key or not self.format_importer:
logger.error("Missing required credentials or format importer")
raise ValueError(
@@ -80,7 +85,8 @@ class ProfileConverter:
for_profile=False)
modified_format = base_format.copy()
modified_format['name'] = f"Not {language_data['name']}"
base_name = f"Not {language_data['name']}"
modified_format['name'] = base_name
for condition in modified_format['conditions']:
if condition.get('type') == 'language':
@@ -113,17 +119,24 @@ class ProfileConverter:
arr_type = 'radarr' if self.target_app == TargetApp.RADARR else 'sonarr'
for format_data in formats_to_import:
try:
result = import_format_from_memory(format_data,
self.base_url,
self.api_key, arr_type)
result = import_format_from_memory(
format_data,
self.base_url,
self.api_key,
arr_type,
import_as_unique=self.import_as_unique)
if not result.get('success', False):
logger.error(
f"Format import failed for: {format_data['name']}")
raise Exception(
f"Failed to import format {format_data['name']}")
format_name = format_data['name']
if import_as_unique:
format_name = f"{format_name} [Dictionarry]"
format_configs.append({
'name': format_data['name'],
'name': format_name,
'score': -9999
})
@@ -305,9 +318,13 @@ def compile_quality_profile(profile_data: Dict,
target_app: TargetApp,
base_url: str = None,
api_key: str = None,
format_importer: Callable = None) -> List[Dict]:
converter = ProfileConverter(target_app, base_url, api_key,
format_importer)
format_importer: Callable = None,
import_as_unique: bool = False) -> List[Dict]:
converter = ProfileConverter(target_app,
base_url,
api_key,
format_importer,
import_as_unique=import_as_unique)
converted = converter.convert_profile(profile_data)
output = {

View File

@@ -81,8 +81,11 @@ def add_format(base_url: str, api_key: str, format_data: Dict) -> bool:
return False
def import_format_from_memory(format_data: Dict, base_url: str, api_key: str,
arr_type: str) -> Dict:
def import_format_from_memory(format_data: Dict,
base_url: str,
api_key: str,
arr_type: str,
import_as_unique: bool = False) -> Dict:
"""
Import a format directly from memory without requiring file loading.
@@ -91,6 +94,7 @@ def import_format_from_memory(format_data: Dict, base_url: str, api_key: str,
base_url: Arr instance base URL
api_key: API key for arr instance
arr_type: Type of arr instance (radarr/sonarr)
import_as_unique: Whether to append [Dictionarry] to format names
Returns:
Dict containing import results
@@ -104,6 +108,14 @@ def import_format_from_memory(format_data: Dict, base_url: str, api_key: str,
}
try:
# Modify format name if import_as_unique is true
original_name = format_data['name']
if import_as_unique:
format_data['name'] = f"{original_name} [Dictionarry]"
logger.info(
f"Modified format name for unique import: {format_data['name']}"
)
# Log the received memory-based format data
logger.info("Received memory-based format:\n" +
json.dumps(format_data, indent=2))

View File

@@ -81,7 +81,7 @@ def import_profiles_to_arr(profile_names: List[str], original_names: List[str],
f"Processing tweaks and importing formats for profile '{profile_name}'"
)
profile_data = process_tweaks(profile_data, base_url, api_key,
arr_type)
arr_type, import_as_unique)
logger.info("Compiling quality profile...")
compiled_profiles = compile_quality_profile(
@@ -89,7 +89,8 @@ def import_profiles_to_arr(profile_names: List[str], original_names: List[str],
target_app=target_app,
base_url=base_url,
api_key=api_key,
format_importer=import_formats_to_arr)
format_importer=import_formats_to_arr,
import_as_unique=import_as_unique)
if not compiled_profiles:
raise ValueError("Profile compilation returned no data")
@@ -216,8 +217,11 @@ def sync_format_ids(profile_data: Dict, format_id_map: Dict[str, int]) -> Dict:
return profile_data
def process_tweaks(profile_data: Dict, base_url: str, api_key: str,
arr_type: str) -> Dict:
def process_tweaks(profile_data: Dict,
base_url: str,
api_key: str,
arr_type: str,
import_as_unique: bool = False) -> Dict:
logger.debug(f"Processing tweaks for profile: {profile_data.get('name')}")
tweaks = profile_data.get('tweaks', {})
@@ -233,7 +237,8 @@ def process_tweaks(profile_data: Dict, base_url: str, api_key: str,
base_url=base_url,
api_key=api_key,
arr_type=arr_type,
feature_name="freeleech")
feature_name="freeleech",
import_as_unique=import_as_unique)
lossless_formats = [
"FLAC", "DTS-X", "DTS-HD MA", "TrueHD", "TrueHD (Missing)"
@@ -249,7 +254,8 @@ def process_tweaks(profile_data: Dict, base_url: str, api_key: str,
base_url=base_url,
api_key=api_key,
arr_type=arr_type,
feature_name="lossless audio")
feature_name="lossless audio",
import_as_unique=import_as_unique)
dv_formats = ["Dolby Vision (Without Fallback)"]
dv_score = 0 if tweaks.get('allowDVNoFallback', False) else -9999
@@ -260,7 +266,8 @@ def process_tweaks(profile_data: Dict, base_url: str, api_key: str,
base_url=base_url,
api_key=api_key,
arr_type=arr_type,
feature_name="Dolby Vision no fallback")
feature_name="Dolby Vision no fallback",
import_as_unique=import_as_unique)
codec_formats = ["AV1", "VVC"]
codec_score = 0 if tweaks.get('allowBleedingEdgeCodecs', False) else -9999
@@ -271,23 +278,56 @@ def process_tweaks(profile_data: Dict, base_url: str, api_key: str,
base_url=base_url,
api_key=api_key,
arr_type=arr_type,
feature_name="bleeding edge codecs")
feature_name="bleeding edge codecs",
import_as_unique=import_as_unique)
return profile_data
def _import_and_score_formats(formats: List[str], scores: List[Dict[str, Any]],
profile_data: Dict, base_url: str, api_key: str,
arr_type: str, feature_name: str) -> None:
def _import_and_score_formats(formats: List[str],
scores: List[Dict[str, Any]],
profile_data: Dict,
base_url: str,
api_key: str,
arr_type: str,
feature_name: str,
import_as_unique: bool = False) -> None:
logger.info(
f"Processing {feature_name} formats for profile '{profile_data.get('name')}'"
)
try:
result = import_formats_to_arr(formats, base_url, api_key, arr_type)
# Create modified format names if import_as_unique is true
format_names = [
f"{name} [Dictionarry]" if import_as_unique else name
for name in formats
]
result = import_formats_to_arr(
format_names=format_names, # Use modified names for import
original_names=formats, # Original names for file lookup
base_url=base_url,
api_key=api_key,
arr_type=arr_type)
if not result.get('success', False):
logger.warning(
f"Failed to import {feature_name} formats for '{profile_data.get('name')}'"
)
return
if 'custom_formats' not in profile_data:
profile_data['custom_formats'] = []
# Use the modified format names in the profile's format list
modified_scores = []
for i, score in enumerate(scores):
score_copy = score.copy()
# Use the same modified name that was used for import
score_copy['name'] = format_names[i]
modified_scores.append(score_copy)
profile_data['custom_formats'].extend(modified_scores)
except Exception as e:
logger.error(f"Error importing {feature_name} formats: {str(e)}")
return