iTunes storefront fallback with configurable country setting
This commit is contained in:
parent
03442327ee
commit
87d567151e
3 changed files with 84 additions and 10 deletions
|
|
@ -227,15 +227,24 @@ class iTunesClient:
|
|||
|
||||
SEARCH_URL = "https://itunes.apple.com/search"
|
||||
LOOKUP_URL = "https://itunes.apple.com/lookup"
|
||||
|
||||
def __init__(self, country: str = "US"):
|
||||
self.country = country
|
||||
|
||||
# Fallback storefronts to try when primary country returns no results
|
||||
FALLBACK_COUNTRIES = ['US', 'GB', 'FR', 'DE', 'JP', 'AU', 'CA', 'BR', 'KR', 'SE']
|
||||
|
||||
def __init__(self, country: str = None):
|
||||
if country is None:
|
||||
try:
|
||||
from config.settings import config_manager
|
||||
country = config_manager.get('itunes.country', 'US')
|
||||
except Exception:
|
||||
country = 'US'
|
||||
self.country = country.upper() if country else "US"
|
||||
self.session = requests.Session()
|
||||
self.session.headers.update({
|
||||
'User-Agent': 'SoulSync/1.0',
|
||||
'Accept': 'application/json'
|
||||
})
|
||||
logger.info(f"iTunes client initialized for country: {country}")
|
||||
logger.info(f"iTunes client initialized for country: {self.country}")
|
||||
|
||||
def is_authenticated(self) -> bool:
|
||||
"""
|
||||
|
|
@ -281,23 +290,53 @@ class iTunesClient:
|
|||
return []
|
||||
|
||||
def _lookup(self, **params) -> List[Dict[str, Any]]:
|
||||
"""Generic lookup method (not rate limited)"""
|
||||
"""Generic lookup method with storefront fallback.
|
||||
Tries the configured country first, then falls back to other storefronts
|
||||
if the result is empty (album/track may be region-restricted)."""
|
||||
try:
|
||||
params['country'] = self.country
|
||||
|
||||
|
||||
response = self.session.get(
|
||||
self.LOOKUP_URL,
|
||||
params=params,
|
||||
timeout=30
|
||||
)
|
||||
|
||||
|
||||
if response.status_code != 200:
|
||||
logger.error(f"iTunes lookup failed with status {response.status_code}")
|
||||
return []
|
||||
|
||||
|
||||
data = response.json()
|
||||
return data.get('results', [])
|
||||
|
||||
results = data.get('results', [])
|
||||
|
||||
# If we got results, return them
|
||||
if results:
|
||||
return results
|
||||
|
||||
# No results — try fallback storefronts for ID-based lookups
|
||||
# (only worth retrying when looking up a specific ID, not general searches)
|
||||
if 'id' in params:
|
||||
for fallback in self.FALLBACK_COUNTRIES:
|
||||
if fallback == self.country:
|
||||
continue
|
||||
try:
|
||||
params['country'] = fallback
|
||||
response = self.session.get(
|
||||
self.LOOKUP_URL,
|
||||
params=params,
|
||||
timeout=15
|
||||
)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
results = data.get('results', [])
|
||||
if results:
|
||||
logger.info(f"iTunes lookup found results via fallback storefront: {fallback}")
|
||||
return results
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
return []
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in iTunes lookup: {e}")
|
||||
return []
|
||||
|
|
|
|||
|
|
@ -3322,6 +3322,35 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- iTunes Settings -->
|
||||
<div class="api-service-frame">
|
||||
<h4 class="service-title itunes-title">iTunes / Apple Music</h4>
|
||||
<div class="form-group">
|
||||
<label>Storefront Country:</label>
|
||||
<select id="itunes-country">
|
||||
<option value="US">United States (US)</option>
|
||||
<option value="GB">United Kingdom (GB)</option>
|
||||
<option value="CA">Canada (CA)</option>
|
||||
<option value="AU">Australia (AU)</option>
|
||||
<option value="DE">Germany (DE)</option>
|
||||
<option value="FR">France (FR)</option>
|
||||
<option value="JP">Japan (JP)</option>
|
||||
<option value="KR">South Korea (KR)</option>
|
||||
<option value="BR">Brazil (BR)</option>
|
||||
<option value="SE">Sweden (SE)</option>
|
||||
<option value="NL">Netherlands (NL)</option>
|
||||
<option value="IT">Italy (IT)</option>
|
||||
<option value="ES">Spain (ES)</option>
|
||||
<option value="MX">Mexico (MX)</option>
|
||||
<option value="IN">India (IN)</option>
|
||||
<option value="RU">Russia (RU)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="callback-info">
|
||||
<div class="callback-help">Sets the primary Apple Music storefront. Region-specific albums are auto-searched across other storefronts as fallback.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Test Connection Buttons -->
|
||||
<div class="api-test-buttons">
|
||||
<button class="test-button" onclick="testConnection('spotify')">Test
|
||||
|
|
|
|||
|
|
@ -3913,6 +3913,9 @@ async function loadSettingsData() {
|
|||
// Populate Genius settings
|
||||
document.getElementById('genius-access-token').value = settings.genius?.access_token || '';
|
||||
|
||||
// Populate iTunes settings
|
||||
document.getElementById('itunes-country').value = settings.itunes?.country || 'US';
|
||||
|
||||
// Populate Download settings (right column)
|
||||
document.getElementById('download-path').value = settings.soulseek?.download_path || './downloads';
|
||||
document.getElementById('transfer-path').value = settings.soulseek?.transfer_path || './Transfer';
|
||||
|
|
@ -4629,6 +4632,9 @@ async function saveSettings(quiet = false) {
|
|||
genius: {
|
||||
access_token: document.getElementById('genius-access-token').value
|
||||
},
|
||||
itunes: {
|
||||
country: document.getElementById('itunes-country').value || 'US'
|
||||
},
|
||||
download_source: {
|
||||
mode: document.getElementById('download-source-mode').value,
|
||||
hybrid_primary: document.getElementById('hybrid-primary-source').value,
|
||||
|
|
|
|||
Loading…
Reference in a new issue