Fix all watchlist Discogs gaps
- Add discogs_artist_id to ALL watchlist WHERE clauses + bind params - Fix artistPrimaryId to include discogs_artist_id - Fix View Discography — add Discogs source branch - Fix openWatchlistArtistDetailView — destructure discogs_artist_id from response (was causing ReferenceError) - Discogs source/provider badges + CSS + image fetch + ID resolution
This commit is contained in:
parent
f51a8a9ee9
commit
55f7e174d8
3 changed files with 75 additions and 28 deletions
|
|
@ -6514,7 +6514,7 @@ class MusicDatabase:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def remove_artist_from_watchlist(self, artist_id: str, profile_id: int = 1) -> bool:
|
def remove_artist_from_watchlist(self, artist_id: str, profile_id: int = 1) -> bool:
|
||||||
"""Remove an artist from the watchlist (checks Spotify, iTunes, and Deezer IDs)"""
|
"""Remove an artist from the watchlist (checks Spotify, iTunes, Deezer, and Discogs IDs)"""
|
||||||
try:
|
try:
|
||||||
with self._get_connection() as conn:
|
with self._get_connection() as conn:
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
@ -6522,15 +6522,15 @@ class MusicDatabase:
|
||||||
# Get artist name for logging (check all ID columns)
|
# Get artist name for logging (check all ID columns)
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT artist_name FROM watchlist_artists
|
SELECT artist_name FROM watchlist_artists
|
||||||
WHERE (spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ?) AND profile_id = ?
|
WHERE (spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ? OR discogs_artist_id = ?) AND profile_id = ?
|
||||||
""", (artist_id, artist_id, artist_id, profile_id))
|
""", (artist_id, artist_id, artist_id, artist_id, profile_id))
|
||||||
result = cursor.fetchone()
|
result = cursor.fetchone()
|
||||||
artist_name = result['artist_name'] if result else "Unknown"
|
artist_name = result['artist_name'] if result else "Unknown"
|
||||||
|
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
DELETE FROM watchlist_artists
|
DELETE FROM watchlist_artists
|
||||||
WHERE (spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ?) AND profile_id = ?
|
WHERE (spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ? OR discogs_artist_id = ?) AND profile_id = ?
|
||||||
""", (artist_id, artist_id, artist_id, profile_id))
|
""", (artist_id, artist_id, artist_id, artist_id, profile_id))
|
||||||
|
|
||||||
if cursor.rowcount > 0:
|
if cursor.rowcount > 0:
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
@ -6545,7 +6545,7 @@ class MusicDatabase:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def is_artist_in_watchlist(self, artist_id: str, profile_id: int = 1, artist_name: str = None) -> bool:
|
def is_artist_in_watchlist(self, artist_id: str, profile_id: int = 1, artist_name: str = None) -> bool:
|
||||||
"""Check if an artist is currently in the watchlist (checks Spotify, iTunes, Deezer IDs and name)"""
|
"""Check if an artist is currently in the watchlist (checks Spotify, iTunes, Deezer, Discogs IDs and name)"""
|
||||||
try:
|
try:
|
||||||
with self._get_connection() as conn:
|
with self._get_connection() as conn:
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
@ -6554,15 +6554,15 @@ class MusicDatabase:
|
||||||
if artist_name:
|
if artist_name:
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT 1 FROM watchlist_artists
|
SELECT 1 FROM watchlist_artists
|
||||||
WHERE (spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ? OR LOWER(artist_name) = LOWER(?)) AND profile_id = ?
|
WHERE (spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ? OR discogs_artist_id = ? OR LOWER(artist_name) = LOWER(?)) AND profile_id = ?
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
""", (artist_id, artist_id, artist_id, artist_name, profile_id))
|
""", (artist_id, artist_id, artist_id, artist_id, artist_name, profile_id))
|
||||||
else:
|
else:
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT 1 FROM watchlist_artists
|
SELECT 1 FROM watchlist_artists
|
||||||
WHERE (spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ?) AND profile_id = ?
|
WHERE (spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ? OR discogs_artist_id = ?) AND profile_id = ?
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
""", (artist_id, artist_id, artist_id, profile_id))
|
""", (artist_id, artist_id, artist_id, artist_id, profile_id))
|
||||||
result = cursor.fetchone()
|
result = cursor.fetchone()
|
||||||
|
|
||||||
return result is not None
|
return result is not None
|
||||||
|
|
@ -6833,8 +6833,8 @@ class MusicDatabase:
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
UPDATE watchlist_artists
|
UPDATE watchlist_artists
|
||||||
SET image_url = ?, updated_at = CURRENT_TIMESTAMP
|
SET image_url = ?, updated_at = CURRENT_TIMESTAMP
|
||||||
WHERE spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ?
|
WHERE spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ? OR discogs_artist_id = ?
|
||||||
""", (image_url, artist_id, artist_id, artist_id))
|
""", (image_url, artist_id, artist_id, artist_id, artist_id))
|
||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
return cursor.rowcount > 0
|
return cursor.rowcount > 0
|
||||||
|
|
|
||||||
|
|
@ -36599,10 +36599,47 @@ def add_to_watchlist():
|
||||||
return jsonify({"success": False, "error": "Missing artist_id or artist_name"}), 400
|
return jsonify({"success": False, "error": "Missing artist_id or artist_name"}), 400
|
||||||
|
|
||||||
database = get_database()
|
database = get_database()
|
||||||
# Detect ID type and determine source
|
# Detect source from ID — check if it's a library DB ID first
|
||||||
is_numeric_id = artist_id.isdigit()
|
is_numeric_id = artist_id.isdigit()
|
||||||
fallback_source = _get_metadata_fallback_source()
|
source = None
|
||||||
source = fallback_source if is_numeric_id else 'spotify'
|
if is_numeric_id:
|
||||||
|
# Could be a library DB ID, iTunes ID, Deezer ID, or Discogs ID
|
||||||
|
# Check if this is a library DB artist and use their actual source IDs
|
||||||
|
try:
|
||||||
|
conn = database._get_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT spotify_artist_id, itunes_artist_id, deezer_id, discogs_id
|
||||||
|
FROM artists WHERE id = ? LIMIT 1
|
||||||
|
""", (artist_id,))
|
||||||
|
row = cursor.fetchone()
|
||||||
|
conn.close()
|
||||||
|
if row:
|
||||||
|
# Library artist — use the best available source ID
|
||||||
|
fallback = _get_metadata_fallback_source()
|
||||||
|
if fallback == 'discogs' and row['discogs_id']:
|
||||||
|
artist_id = row['discogs_id']
|
||||||
|
source = 'discogs'
|
||||||
|
elif fallback == 'deezer' and row['deezer_id']:
|
||||||
|
artist_id = row['deezer_id']
|
||||||
|
source = 'deezer'
|
||||||
|
elif row['spotify_artist_id']:
|
||||||
|
artist_id = row['spotify_artist_id']
|
||||||
|
source = 'spotify'
|
||||||
|
elif row['itunes_artist_id']:
|
||||||
|
artist_id = row['itunes_artist_id']
|
||||||
|
source = 'itunes'
|
||||||
|
elif row['deezer_id']:
|
||||||
|
artist_id = row['deezer_id']
|
||||||
|
source = 'deezer'
|
||||||
|
elif row['discogs_id']:
|
||||||
|
artist_id = row['discogs_id']
|
||||||
|
source = 'discogs'
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
if not source:
|
||||||
|
fallback_source = _get_metadata_fallback_source()
|
||||||
|
source = fallback_source if is_numeric_id else 'spotify'
|
||||||
success = database.add_artist_to_watchlist(artist_id, artist_name, profile_id=get_current_profile_id(), source=source)
|
success = database.add_artist_to_watchlist(artist_id, artist_name, profile_id=get_current_profile_id(), source=source)
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
|
|
@ -36612,7 +36649,15 @@ def add_to_watchlist():
|
||||||
if is_numeric_id:
|
if is_numeric_id:
|
||||||
# For numeric IDs, fetch image from the configured fallback source
|
# For numeric IDs, fetch image from the configured fallback source
|
||||||
try:
|
try:
|
||||||
if fallback_source == 'deezer':
|
if source == 'discogs':
|
||||||
|
# Discogs: fetch artist image from API
|
||||||
|
from core.discogs_client import DiscogsClient
|
||||||
|
dc = DiscogsClient()
|
||||||
|
dc_data = dc.get_artist(artist_id)
|
||||||
|
if dc_data:
|
||||||
|
image_url = dc_data.get('image_url')
|
||||||
|
print(f"🖼️ Discogs artist image: {image_url[:60] if image_url else 'None'}")
|
||||||
|
elif source == 'deezer' or fallback_source == 'deezer':
|
||||||
# Deezer: fetch artist image directly from API
|
# Deezer: fetch artist image directly from API
|
||||||
dz_resp = requests.get(f'https://api.deezer.com/artist/{artist_id}', timeout=5)
|
dz_resp = requests.get(f'https://api.deezer.com/artist/{artist_id}', timeout=5)
|
||||||
if dz_resp.ok:
|
if dz_resp.ok:
|
||||||
|
|
@ -37584,9 +37629,9 @@ def watchlist_artist_config(artist_id):
|
||||||
cur2.execute("""
|
cur2.execute("""
|
||||||
SELECT banner_url, summary, style, mood, label, genres
|
SELECT banner_url, summary, style, mood, label, genres
|
||||||
FROM artists
|
FROM artists
|
||||||
WHERE spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ?
|
WHERE spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ? OR discogs_artist_id = ?
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
""", (artist_id, artist_id, artist_id))
|
""", (artist_id, artist_id, artist_id, artist_id))
|
||||||
lib_row = cur2.fetchone()
|
lib_row = cur2.fetchone()
|
||||||
if lib_row:
|
if lib_row:
|
||||||
artist_info['banner_url'] = lib_row[0]
|
artist_info['banner_url'] = lib_row[0]
|
||||||
|
|
@ -37679,8 +37724,8 @@ def watchlist_artist_config(artist_id):
|
||||||
# Check if lookback_days changed — if so, clear last_scan_timestamp to force rescan
|
# Check if lookback_days changed — if so, clear last_scan_timestamp to force rescan
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT lookback_days FROM watchlist_artists
|
SELECT lookback_days FROM watchlist_artists
|
||||||
WHERE spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ?
|
WHERE spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ? OR discogs_artist_id = ?
|
||||||
""", (artist_id, artist_id, artist_id))
|
""", (artist_id, artist_id, artist_id, artist_id))
|
||||||
old_row = cursor.fetchone()
|
old_row = cursor.fetchone()
|
||||||
old_lookback = old_row[0] if old_row else None
|
old_lookback = old_row[0] if old_row else None
|
||||||
lookback_changed = old_lookback != lookback_days
|
lookback_changed = old_lookback != lookback_days
|
||||||
|
|
@ -37692,11 +37737,11 @@ def watchlist_artist_config(artist_id):
|
||||||
include_instrumentals = ?, lookback_days = ?,
|
include_instrumentals = ?, lookback_days = ?,
|
||||||
last_scan_timestamp = CASE WHEN ? THEN NULL ELSE last_scan_timestamp END,
|
last_scan_timestamp = CASE WHEN ? THEN NULL ELSE last_scan_timestamp END,
|
||||||
updated_at = CURRENT_TIMESTAMP
|
updated_at = CURRENT_TIMESTAMP
|
||||||
WHERE spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ?
|
WHERE spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ? OR discogs_artist_id = ?
|
||||||
""", (int(include_albums), int(include_eps), int(include_singles),
|
""", (int(include_albums), int(include_eps), int(include_singles),
|
||||||
int(include_live), int(include_remixes), int(include_acoustic), int(include_compilations),
|
int(include_live), int(include_remixes), int(include_acoustic), int(include_compilations),
|
||||||
int(include_instrumentals), lookback_days, lookback_changed,
|
int(include_instrumentals), lookback_days, lookback_changed,
|
||||||
artist_id, artist_id, artist_id))
|
artist_id, artist_id, artist_id, artist_id))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
if cursor.rowcount == 0:
|
if cursor.rowcount == 0:
|
||||||
|
|
@ -37752,8 +37797,8 @@ def watchlist_artist_link_provider(artist_id):
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT id, artist_name, spotify_artist_id, itunes_artist_id
|
SELECT id, artist_name, spotify_artist_id, itunes_artist_id
|
||||||
FROM watchlist_artists
|
FROM watchlist_artists
|
||||||
WHERE spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ?
|
WHERE spotify_artist_id = ? OR itunes_artist_id = ? OR deezer_artist_id = ? OR discogs_artist_id = ?
|
||||||
""", (artist_id, artist_id, artist_id))
|
""", (artist_id, artist_id, artist_id, artist_id))
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
|
|
||||||
if not row:
|
if not row:
|
||||||
|
|
|
||||||
|
|
@ -38782,7 +38782,7 @@ async function showWatchlistModal() {
|
||||||
if (artist.itunes_artist_id) sourceBadges.push('<span class="watchlist-source-badge watchlist-source-itunes">iTunes</span>');
|
if (artist.itunes_artist_id) sourceBadges.push('<span class="watchlist-source-badge watchlist-source-itunes">iTunes</span>');
|
||||||
if (artist.deezer_artist_id) sourceBadges.push('<span class="watchlist-source-badge watchlist-source-deezer">Deezer</span>');
|
if (artist.deezer_artist_id) sourceBadges.push('<span class="watchlist-source-badge watchlist-source-deezer">Deezer</span>');
|
||||||
if (artist.discogs_artist_id) sourceBadges.push('<span class="watchlist-source-badge watchlist-source-discogs">Discogs</span>');
|
if (artist.discogs_artist_id) sourceBadges.push('<span class="watchlist-source-badge watchlist-source-discogs">Discogs</span>');
|
||||||
const artistPrimaryId = artist.spotify_artist_id || artist.itunes_artist_id || artist.deezer_artist_id;
|
const artistPrimaryId = artist.spotify_artist_id || artist.itunes_artist_id || artist.deezer_artist_id || artist.discogs_artist_id;
|
||||||
return `
|
return `
|
||||||
<div class="watchlist-artist-card"
|
<div class="watchlist-artist-card"
|
||||||
data-artist-name="${artist.artist_name.toLowerCase().replace(/"/g, '"')}"
|
data-artist-name="${artist.artist_name.toLowerCase().replace(/"/g, '"')}"
|
||||||
|
|
@ -39278,7 +39278,7 @@ async function openWatchlistArtistDetailView(artistId, artistName) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { config, artist, recent_releases, spotify_artist_id, itunes_artist_id, deezer_artist_id } = data;
|
const { config, artist, recent_releases, spotify_artist_id, itunes_artist_id, deezer_artist_id, discogs_artist_id } = data;
|
||||||
|
|
||||||
// Remove existing overlay if any
|
// Remove existing overlay if any
|
||||||
const existing = document.querySelector('.watchlist-artist-detail-overlay');
|
const existing = document.querySelector('.watchlist-artist-detail-overlay');
|
||||||
|
|
@ -39407,13 +39407,15 @@ async function openWatchlistArtistDetailView(artistId, artistName) {
|
||||||
const activeSrc = (currentMusicSourceName || '').toLowerCase();
|
const activeSrc = (currentMusicSourceName || '').toLowerCase();
|
||||||
if (activeSrc.includes('spotify') && spotify_artist_id) {
|
if (activeSrc.includes('spotify') && spotify_artist_id) {
|
||||||
discogId = spotify_artist_id; source = 'spotify';
|
discogId = spotify_artist_id; source = 'spotify';
|
||||||
|
} else if (activeSrc.includes('discogs') && discogs_artist_id) {
|
||||||
|
discogId = discogs_artist_id; source = 'discogs';
|
||||||
} else if (activeSrc.includes('deezer') && deezer_artist_id) {
|
} else if (activeSrc.includes('deezer') && deezer_artist_id) {
|
||||||
discogId = deezer_artist_id; source = 'deezer';
|
discogId = deezer_artist_id; source = 'deezer';
|
||||||
} else if (itunes_artist_id) {
|
} else if (itunes_artist_id) {
|
||||||
discogId = itunes_artist_id; source = 'itunes';
|
discogId = itunes_artist_id; source = 'itunes';
|
||||||
} else {
|
} else {
|
||||||
discogId = spotify_artist_id || deezer_artist_id || itunes_artist_id;
|
discogId = spotify_artist_id || discogs_artist_id || deezer_artist_id || itunes_artist_id;
|
||||||
source = spotify_artist_id ? 'spotify' : deezer_artist_id ? 'deezer' : 'itunes';
|
source = spotify_artist_id ? 'spotify' : discogs_artist_id ? 'discogs' : deezer_artist_id ? 'deezer' : 'itunes';
|
||||||
}
|
}
|
||||||
if (discogId) {
|
if (discogId) {
|
||||||
// Close watchlist modal + detail overlay
|
// Close watchlist modal + detail overlay
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue