refactor: remove tweaks functionality from profile handling (#145)

- removed because I couldn't integrate it nicely with the rest of the application, will keep in the todo pile for later.
This commit is contained in:
santiagosayshey
2025-02-21 00:30:01 +10:30
committed by GitHub
parent 1272e40098
commit b9289510eb
5 changed files with 4 additions and 342 deletions

View File

@@ -201,15 +201,10 @@ class ProfileConverter:
language=selected_language)
used_qualities = set()
tweaks = profile.get('tweaks', {})
allow_prereleases = tweaks.get('allowPrereleases', False)
for quality_entry in profile.get("qualities", []):
if quality_entry.get("id", 0) < 0:
converted_group = self.convert_quality_group(quality_entry)
if (quality_entry.get("name") == "Prereleases"
and not allow_prereleases):
converted_group["allowed"] = False
if converted_group["items"]:
converted_profile.items.append(converted_group)
for q in quality_entry.get("qualities", []):
@@ -246,7 +241,6 @@ class ProfileConverter:
if cutoff_id < 0:
converted_profile.cutoff = self._convert_group_id(cutoff_id)
else:
# And use mapped_cutoff_name here instead of cutoff_name
converted_profile.cutoff = self.quality_mappings[
mapped_cutoff_name]["id"]

View File

@@ -33,8 +33,7 @@ PROFILE_FIELDS = [
"custom_formats", # Array of {name, score} objects
"qualities", # Array of strings
"upgrade_until",
"language",
"tweaks"
"language"
]
# Category mappings

View File

@@ -77,12 +77,6 @@ def import_profiles_to_arr(profile_names: List[str], original_names: List[str],
f"Profile '{profile_name}' has language override: {profile_language}"
)
logger.info(
f"Processing tweaks and importing formats for profile '{profile_name}'"
)
profile_data = process_tweaks(profile_data, base_url, api_key,
arr_type, import_as_unique)
logger.info("Compiling quality profile...")
compiled_profiles = compile_quality_profile(
profile_data=profile_data,
@@ -221,123 +215,6 @@ 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,
import_as_unique: bool = False) -> Dict:
logger.debug(f"Processing tweaks for profile: {profile_data.get('name')}")
tweaks = profile_data.get('tweaks', {})
if tweaks.get('preferFreeleech', False):
freeleech_formats = ["Free25", "Free50", "Free75", "Free100"]
freeleech_scores = [{
"name": n,
"score": s
} for n, s in zip(freeleech_formats, range(1, 5))]
_import_and_score_formats(formats=freeleech_formats,
scores=freeleech_scores,
profile_data=profile_data,
base_url=base_url,
api_key=api_key,
arr_type=arr_type,
feature_name="freeleech",
import_as_unique=import_as_unique)
lossless_formats = [
"FLAC", "DTS-X", "DTS-HD MA", "TrueHD", "TrueHD (Missing)"
]
default_score = 0 if tweaks.get('allowLosslessAudio', False) else -9999
lossless_scores = [{
"name": f,
"score": default_score
} for f in lossless_formats]
_import_and_score_formats(formats=lossless_formats,
scores=lossless_scores,
profile_data=profile_data,
base_url=base_url,
api_key=api_key,
arr_type=arr_type,
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
dv_scores = [{"name": n, "score": dv_score} for n in dv_formats]
_import_and_score_formats(formats=dv_formats,
scores=dv_scores,
profile_data=profile_data,
base_url=base_url,
api_key=api_key,
arr_type=arr_type,
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
codec_scores = [{"name": f, "score": codec_score} for f in codec_formats]
_import_and_score_formats(formats=codec_formats,
scores=codec_scores,
profile_data=profile_data,
base_url=base_url,
api_key=api_key,
arr_type=arr_type,
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,
import_as_unique: bool = False) -> None:
logger.info(
f"Processing {feature_name} formats for profile '{profile_data.get('name')}'"
)
try:
# 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)
# Only append once with the modified scores
profile_data['custom_formats'].extend(modified_scores)
except Exception as e:
logger.error(f"Error importing {feature_name} formats: {str(e)}")
return
def process_profile(profile_data: Dict, existing_names: Dict[str, int],
base_url: str, api_key: str) -> Dict:
profile_name = profile_data['name']

View File

@@ -8,17 +8,8 @@ import ProfileGeneralTab from './ProfileGeneralTab';
import ProfileScoringTab from './scoring/ProfileScoringTab';
import ProfileQualitiesTab from './ProfileQualitiesTab';
import ProfileLangaugesTab from './ProfileLangaugesTab';
import ProfileTweaksTab from './ProfileTweaksTab';
import QUALITIES from '../../constants/qualities';
const DEFAULT_TWEAKS = {
preferFreeleech: true,
allowLosslessAudio: true,
allowDVNoFallback: false,
allowBleedingEdgeCodecs: false,
allowPrereleases: false
};
function unsanitize(text) {
if (!text) return '';
return text.replace(/\\:/g, ':').replace(/\\n/g, '\n');
@@ -70,15 +61,11 @@ function ProfileModal({
// Language state
const [language, setLanguage] = useState('must_english');
// Tweaks state
const [tweaks, setTweaks] = useState(DEFAULT_TWEAKS);
const tabs = [
{id: 'general', label: 'General'},
{id: 'scoring', label: 'Scoring'},
{id: 'qualities', label: 'Qualities'},
{id: 'languages', label: 'Languages'},
{id: 'tweaks', label: 'Tweaks'}
{id: 'languages', label: 'Languages'}
];
const resetState = () => {
@@ -124,7 +111,6 @@ function ProfileModal({
// Reset other states
setLanguage('must_english');
setTweaks(DEFAULT_TWEAKS);
};
useEffect(() => {
@@ -185,12 +171,6 @@ function ProfileModal({
});
setTagScores(initialTagScores);
// Tweaks
setTweaks({
...DEFAULT_TWEAKS,
...(content.tweaks || {})
});
// Qualities setup - include all qualities, set enabled status
const allQualitiesMap = {}; // Map of all qualities by id
QUALITIES.forEach(quality => {
@@ -335,7 +315,6 @@ function ProfileModal({
// Initialize with defaults
setLanguage('must_english');
setTweaks(DEFAULT_TWEAKS);
}
setLoading(false);
@@ -401,8 +380,7 @@ function ProfileModal({
})
}
: null,
language,
tweaks
language
};
if (isCloning || !initialProfile) {
@@ -589,12 +567,6 @@ function ProfileModal({
onLanguageChange={setLanguage}
/>
)}
{activeTab === 'tweaks' && (
<ProfileTweaksTab
tweaks={tweaks}
onTweaksChange={setTweaks}
/>
)}
</div>
)}
</div>
@@ -638,8 +610,7 @@ ProfileModal.propTypes = {
id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired
}),
language: PropTypes.string,
tweaks: PropTypes.object
language: PropTypes.string
})
}),
isOpen: PropTypes.bool.isRequired,

View File

@@ -1,179 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import {InfoIcon, AlertTriangle} from 'lucide-react';
const ProfileTweaksTab = ({tweaks, onTweaksChange}) => {
const handleTweakChange = key => {
onTweaksChange({
...tweaks,
[key]: !tweaks[key]
});
};
return (
<div className='h-full flex flex-col'>
<div className='mt-4 space-y-4'>
<div className='flex gap-2 p-3 text-xs bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg'>
<InfoIcon className='h-4 w-4 text-blue-600 dark:text-blue-400 flex-shrink-0' />
<p className='text-blue-700 dark:text-blue-300'>
Tweaks are custom changes that can be toggled according
to your preference. These settings are profile-specific
and won't create merge conflicts when synchronizing with
remote repositories. Use tweaks to fine-tune your
profile's behavior without affecting the core
configuration.
</p>
</div>
<div className='space-y-2'>
{/* Allow Dolby Vision without Fallback */}
<div
onClick={() => handleTweakChange('allowDVNoFallback')}
className={`
p-4 rounded-lg cursor-pointer select-none
border transition-colors duration-200
${
tweaks.allowDVNoFallback
? 'border-blue-200 dark:border-blue-800 bg-blue-50 dark:bg-blue-900/20'
: 'border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800'
}
hover:border-blue-500 dark:hover:border-blue-400
`}>
<div className='space-y-1'>
<h3 className='text-sm font-medium text-gray-900 dark:text-gray-100'>
Allow Dolby Vision without Fallback
</h3>
<p className='text-xs text-gray-500 dark:text-gray-400'>
Allow Dolby Vision releases that don't include
HDR10 fallback. These may display incorrectly on
non-Dolby Vision displays.
</p>
<div className='flex items-center gap-1.5 mt-2'>
<AlertTriangle className='h-3 w-3 text-amber-500' />
<p className='text-[10px] text-amber-600 dark:text-amber-400'>
Only enable if your display supports Dolby
Vision
</p>
</div>
</div>
</div>
{/* Allow Bleeding Edge Codecs */}
<div
onClick={() =>
handleTweakChange('allowBleedingEdgeCodecs')
}
className={`
p-4 rounded-lg cursor-pointer select-none
border transition-colors duration-200
${
tweaks.allowBleedingEdgeCodecs
? 'border-blue-200 dark:border-blue-800 bg-blue-50 dark:bg-blue-900/20'
: 'border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800'
}
hover:border-blue-500 dark:hover:border-blue-400
`}>
<div className='space-y-1'>
<h3 className='text-sm font-medium text-gray-900 dark:text-gray-100'>
Allow Bleeding Edge Codecs
</h3>
<p className='text-xs text-gray-500 dark:text-gray-400'>
Allow releases using newer codecs like AV1 and
H.266/VVC. These may offer better compression
but have limited hardware support.
</p>
</div>
</div>
{/* Allow Lossless Audio */}
<div
onClick={() => handleTweakChange('allowLosslessAudio')}
className={`
p-4 rounded-lg cursor-pointer select-none
border transition-colors duration-200
${
tweaks.allowLosslessAudio ?? true
? 'border-blue-200 dark:border-blue-800 bg-blue-50 dark:bg-blue-900/20'
: 'border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800'
}
hover:border-blue-500 dark:hover:border-blue-400
`}>
<div className='space-y-1'>
<h3 className='text-sm font-medium text-gray-900 dark:text-gray-100'>
Allow Lossless Audio
</h3>
<p className='text-xs text-gray-500 dark:text-gray-400'>
Allow high-quality lossless audio formats
including TrueHD + Atmos, DTS-HD MA, DTS-X,
FLAC, and PCM.
</p>
<div className='flex items-center gap-1.5 mt-2'>
<AlertTriangle className='h-3 w-3 text-amber-500' />
<p className='text-[10px] text-amber-600 dark:text-amber-400'>
May skip better quality releases if disabled
</p>
</div>
</div>
</div>
{/* Allow Prereleases */}
<div
onClick={() => handleTweakChange('allowPrereleases')}
className={`
p-4 rounded-lg cursor-pointer select-none
border transition-colors duration-200
${
tweaks.allowPrereleases
? 'border-blue-200 dark:border-blue-800 bg-blue-50 dark:bg-blue-900/20'
: 'border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800'
}
hover:border-blue-500 dark:hover:border-blue-400
`}>
<div className='space-y-1'>
<h3 className='text-sm font-medium text-gray-900 dark:text-gray-100'>
Allow Prereleases
</h3>
<p className='text-xs text-gray-500 dark:text-gray-400'>
Allow early releases like CAMs, Telecines,
Telesyncs, and Screeners. These are typically
available before official releases but at lower
quality.
</p>
</div>
</div>
{/* Prefer Freeleech */}
<div
onClick={() => handleTweakChange('preferFreeleech')}
className={`
p-4 rounded-lg cursor-pointer select-none
border transition-colors duration-200
${
tweaks.preferFreeleech
? 'border-blue-200 dark:border-blue-800 bg-blue-50 dark:bg-blue-900/20'
: 'border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800'
}
hover:border-blue-500 dark:hover:border-blue-400
`}>
<div className='space-y-1'>
<h3 className='text-sm font-medium text-gray-900 dark:text-gray-100'>
Prefer Freeleech
</h3>
<p className='text-xs text-gray-500 dark:text-gray-400'>
Prioritize releases tagged as freeleech when
choosing between different indexers' releases.
</p>
</div>
</div>
</div>
</div>
</div>
);
};
ProfileTweaksTab.propTypes = {
tweaks: PropTypes.object.isRequired,
onTweaksChange: PropTypes.func.isRequired
};
export default ProfileTweaksTab;