Complete Hydrabase as selectable fallback metadata source
- Remove redundant enable checkbox — fallback dropdown is the enable - Hydrabase option only appears in dropdown when connected - Connect/disconnect dynamically adds/removes dropdown option - _is_hydrabase_active checks fallback_source == hydrabase (not config toggle) - Fallback client returns hydrabase_client when selected, iTunes if disconnected - Auto-reconnect respects fallback selection for dev_mode handling - hydrabase added to settings save service list for persistence - Status shows green Connected on page load when auto-connected
This commit is contained in:
parent
214985482d
commit
10361bb837
4 changed files with 73 additions and 24 deletions
|
|
@ -31,6 +31,19 @@ def _create_fallback_client():
|
|||
if source == 'deezer':
|
||||
from core.deezer_client import DeezerClient
|
||||
return DeezerClient()
|
||||
if source == 'hydrabase':
|
||||
try:
|
||||
from core.hydrabase_client import HydrabaseClient
|
||||
# Hydrabase client is managed globally — try to import the running instance
|
||||
import importlib
|
||||
ws_module = importlib.import_module('web_server')
|
||||
client = getattr(ws_module, 'hydrabase_client', None)
|
||||
if client and client.is_connected():
|
||||
return client
|
||||
except Exception:
|
||||
pass
|
||||
# Hydrabase not available — fall back to iTunes
|
||||
return iTunesClient()
|
||||
return iTunesClient()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4481,7 +4481,7 @@ def handle_settings():
|
|||
if 'active_media_server' in new_settings:
|
||||
config_manager.set_active_media_server(new_settings['active_media_server'])
|
||||
|
||||
for service in ['spotify', 'plex', 'jellyfin', 'navidrome', 'soulseek', 'download_source', 'settings', 'database', 'metadata_enhancement', 'file_organization', 'playlist_sync', 'tidal', 'tidal_download', 'qobuz', 'hifi_download', 'listenbrainz', 'acoustid', 'lastfm', 'genius', 'import', 'lossy_copy', 'ui_appearance', 'youtube', 'content_filter', 'itunes', 'm3u_export', 'musicbrainz', 'deezer', 'audiodb', 'metadata']:
|
||||
for service in ['spotify', 'plex', 'jellyfin', 'navidrome', 'soulseek', 'download_source', 'settings', 'database', 'metadata_enhancement', 'file_organization', 'playlist_sync', 'tidal', 'tidal_download', 'qobuz', 'hifi_download', 'listenbrainz', 'acoustid', 'lastfm', 'genius', 'import', 'lossy_copy', 'ui_appearance', 'youtube', 'content_filter', 'itunes', 'm3u_export', 'musicbrainz', 'deezer', 'audiodb', 'metadata', 'hydrabase']:
|
||||
if service in new_settings:
|
||||
for key, value in new_settings[service].items():
|
||||
config_manager.set(f'{service}.{key}', value)
|
||||
|
|
@ -4560,15 +4560,15 @@ _comparison_lock = threading.Lock()
|
|||
|
||||
def _is_hydrabase_active():
|
||||
"""Check if Hydrabase should be used as the primary metadata source.
|
||||
Active when: (dev_mode OR hydrabase.enabled config) AND client connected."""
|
||||
Active when: (dev_mode OR selected as fallback source) AND client connected."""
|
||||
try:
|
||||
if hydrabase_client is None or not hydrabase_client.is_connected():
|
||||
return False
|
||||
# Dev mode always enables Hydrabase (legacy behavior)
|
||||
if dev_mode_enabled:
|
||||
return True
|
||||
# Config toggle: user enabled Hydrabase as metadata source
|
||||
return config_manager.get('hydrabase.enabled', False)
|
||||
# Selected as the fallback metadata source
|
||||
return _get_metadata_fallback_source() == 'hydrabase'
|
||||
except (NameError, Exception):
|
||||
return False
|
||||
|
||||
|
|
@ -4650,8 +4650,6 @@ def _run_background_comparison(query, hydrabase_counts=None):
|
|||
def hydrabase_connect():
|
||||
"""Connect to a Hydrabase instance via WebSocket."""
|
||||
global _hydrabase_ws
|
||||
if not dev_mode_enabled:
|
||||
return jsonify({"success": False, "error": "Dev mode not active"}), 403
|
||||
data = request.get_json()
|
||||
url = data.get('url', '').strip()
|
||||
api_key = data.get('api_key', '').strip()
|
||||
|
|
@ -4694,8 +4692,10 @@ def hydrabase_disconnect():
|
|||
pass
|
||||
_hydrabase_ws = None
|
||||
config_manager.set('hydrabase.auto_connect', False)
|
||||
dev_mode_enabled = False
|
||||
print("🧪 [Hydrabase] Disconnected — dev mode disabled")
|
||||
# Only disable dev mode if not using Hydrabase as a regular fallback source
|
||||
if _get_metadata_fallback_source() != 'hydrabase':
|
||||
dev_mode_enabled = False
|
||||
print("🧪 [Hydrabase] Disconnected")
|
||||
return jsonify({"success": True})
|
||||
|
||||
@app.route('/api/hydrabase/status')
|
||||
|
|
@ -27441,7 +27441,7 @@ def _get_deezer_client():
|
|||
return _deezer_client_instance
|
||||
|
||||
def _get_metadata_fallback_source():
|
||||
"""Get the configured metadata fallback source ('itunes' or 'deezer')."""
|
||||
"""Get the configured metadata fallback source ('itunes', 'deezer', or 'hydrabase')."""
|
||||
try:
|
||||
return config_manager.get('metadata.fallback_source', 'itunes') or 'itunes'
|
||||
except Exception:
|
||||
|
|
@ -27449,10 +27449,16 @@ def _get_metadata_fallback_source():
|
|||
|
||||
def _get_metadata_fallback_client():
|
||||
"""Get the active metadata fallback client based on settings.
|
||||
Returns an iTunesClient or DeezerClient instance with identical interfaces."""
|
||||
Returns an iTunesClient, DeezerClient, or HydrabaseClient instance with identical interfaces."""
|
||||
source = _get_metadata_fallback_source()
|
||||
if source == 'deezer':
|
||||
return _get_deezer_client()
|
||||
if source == 'hydrabase':
|
||||
if hydrabase_client and hydrabase_client.is_connected():
|
||||
return hydrabase_client
|
||||
# Hydrabase not connected — fall back to iTunes
|
||||
from core.itunes_client import iTunesClient
|
||||
return iTunesClient()
|
||||
from core.itunes_client import iTunesClient
|
||||
return iTunesClient()
|
||||
|
||||
|
|
@ -40772,9 +40778,8 @@ try:
|
|||
timeout=10
|
||||
)
|
||||
_hydrabase_ws = _auto_ws
|
||||
# Enable dev mode only if Hydrabase was previously in dev mode
|
||||
# The config toggle (hydrabase.enabled) handles non-dev usage
|
||||
if not _hydra_cfg.get('enabled'):
|
||||
# Enable dev mode only if not using Hydrabase as a regular fallback source
|
||||
if _get_metadata_fallback_source() != 'hydrabase':
|
||||
dev_mode_enabled = True
|
||||
print(f"✅ Hydrabase auto-connected to {_hydra_cfg['url']}")
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -3673,19 +3673,14 @@
|
|||
</select>
|
||||
</div>
|
||||
<div class="callback-info">
|
||||
<div class="callback-help">When Spotify is not connected, this source provides artist, album, and track metadata. Both are free and require no API key.</div>
|
||||
<div class="callback-help">When Spotify is not connected, this source provides artist, album, and track metadata. Hydrabase requires a connection configured above.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hydrabase P2P Metadata -->
|
||||
<div class="api-service-frame" data-stg="connections">
|
||||
<h4 class="service-title" style="color: #00b4d8;">Hydrabase</h4>
|
||||
<div class="form-group" style="margin-bottom: 8px;">
|
||||
<label class="checkbox-label" style="display: flex; align-items: center; gap: 8px; cursor: pointer; padding: 0;">
|
||||
<input type="checkbox" id="hydrabase-enabled" style="width: 16px; height: 16px;">
|
||||
<span>Enable Hydrabase as metadata source</span>
|
||||
</label>
|
||||
</div>
|
||||
<input type="hidden" id="hydrabase-enabled" value="false">
|
||||
<div class="form-group">
|
||||
<label>WebSocket URL:</label>
|
||||
<input type="text" id="hydrabase-url" placeholder="ws://localhost:4545">
|
||||
|
|
|
|||
|
|
@ -5469,10 +5469,30 @@ async function loadSettingsData() {
|
|||
|
||||
// Populate Hydrabase settings
|
||||
const hbConfig = settings.hydrabase || {};
|
||||
document.getElementById('hydrabase-enabled').checked = hbConfig.enabled || false;
|
||||
document.getElementById('hydrabase-url').value = hbConfig.url || '';
|
||||
document.getElementById('hydrabase-api-key').value = hbConfig.api_key || '';
|
||||
document.getElementById('hydrabase-auto-connect').checked = hbConfig.auto_connect || false;
|
||||
// Check live connection status + add Hydrabase to fallback dropdown if connected
|
||||
fetch('/api/hydrabase/status').then(r => r.json()).then(s => {
|
||||
const btn = document.getElementById('hydrabase-connect-btn');
|
||||
const statusEl = document.getElementById('hydrabase-settings-status');
|
||||
if (s.connected) {
|
||||
if (btn) btn.textContent = 'Disconnect';
|
||||
if (statusEl) { statusEl.textContent = 'Connected'; statusEl.style.color = '#4caf50'; }
|
||||
// Add Hydrabase to fallback source dropdown
|
||||
const fbSelect = document.getElementById('metadata-fallback-source');
|
||||
if (fbSelect && !fbSelect.querySelector('option[value="hydrabase"]')) {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = 'hydrabase';
|
||||
opt.textContent = 'Hydrabase (P2P)';
|
||||
fbSelect.appendChild(opt);
|
||||
}
|
||||
// Restore selection if it was hydrabase
|
||||
if ((settings.metadata?.fallback_source) === 'hydrabase') {
|
||||
fbSelect.value = 'hydrabase';
|
||||
}
|
||||
}
|
||||
}).catch(() => {});
|
||||
|
||||
// Populate Download settings (right column)
|
||||
document.getElementById('download-path').value = settings.soulseek?.download_path || './downloads';
|
||||
|
|
@ -6107,7 +6127,16 @@ async function toggleHydrabaseFromSettings() {
|
|||
// Disconnect
|
||||
await fetch('/api/hydrabase/disconnect', { method: 'POST' });
|
||||
if (btn) btn.textContent = 'Connect';
|
||||
if (statusEl) statusEl.textContent = 'Disconnected';
|
||||
if (statusEl) { statusEl.textContent = 'Disconnected'; statusEl.style.color = 'rgba(255,255,255,0.4)'; }
|
||||
// Remove from fallback dropdown + reset to iTunes if was selected
|
||||
const fbSel2 = document.getElementById('metadata-fallback-source');
|
||||
if (fbSel2) {
|
||||
const hbOpt = fbSel2.querySelector('option[value="hydrabase"]');
|
||||
if (hbOpt) {
|
||||
if (fbSel2.value === 'hydrabase') fbSel2.value = 'itunes';
|
||||
hbOpt.remove();
|
||||
}
|
||||
}
|
||||
showToast('Hydrabase disconnected', 'info');
|
||||
} else {
|
||||
// Connect
|
||||
|
|
@ -6119,7 +6148,15 @@ async function toggleHydrabaseFromSettings() {
|
|||
const data = await res.json();
|
||||
if (data.success) {
|
||||
if (btn) btn.textContent = 'Disconnect';
|
||||
if (statusEl) statusEl.textContent = 'Connected';
|
||||
if (statusEl) { statusEl.textContent = 'Connected'; statusEl.style.color = '#4caf50'; }
|
||||
// Add to fallback dropdown
|
||||
const fbSel = document.getElementById('metadata-fallback-source');
|
||||
if (fbSel && !fbSel.querySelector('option[value="hydrabase"]')) {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = 'hydrabase';
|
||||
opt.textContent = 'Hydrabase (P2P)';
|
||||
fbSel.appendChild(opt);
|
||||
}
|
||||
showToast('Hydrabase connected', 'success');
|
||||
} else {
|
||||
if (statusEl) statusEl.textContent = data.error || 'Connection failed';
|
||||
|
|
@ -6440,7 +6477,6 @@ async function saveSettings(quiet = false) {
|
|||
fallback_source: document.getElementById('metadata-fallback-source').value || 'itunes'
|
||||
},
|
||||
hydrabase: {
|
||||
enabled: document.getElementById('hydrabase-enabled').checked,
|
||||
url: document.getElementById('hydrabase-url').value,
|
||||
api_key: document.getElementById('hydrabase-api-key').value,
|
||||
auto_connect: document.getElementById('hydrabase-auto-connect').checked
|
||||
|
|
|
|||
Loading…
Reference in a new issue