Fix Discogs completion: lazy track counts, edition matching, type reclassify

- Fetch real track count from source during completion check when
  total_tracks is 0 (Discogs masters) — one API call per album, runs
  during existing per-album ownership check phase
- Reclassify album cards to single/EP when track count reveals 1-3/4-6
  tracks — updates type label and data attribute in place
- Add collectors edition to album title variation patterns for matching
  "Damn" against "DAMN. COLLECTORS EDITION." in library
- Hide 0/0 fraction when expected_tracks is 0, show proper count when
  fetched
This commit is contained in:
Broque Thomas 2026-04-02 19:02:23 -07:00
parent 69a09826f4
commit 7ea5eb2c06
3 changed files with 39 additions and 6 deletions

View file

@ -5424,6 +5424,8 @@ class MusicDatabase:
r'\s+special\s*edition?$': ['special', 'special edition'],
r'\s*-\s*deluxe': ['deluxe'],
r'\s*-\s*platinum\s*edition?': ['platinum', 'platinum edition'],
r'\s+collector\'?s?\s*edition?$': ['collectors', 'collectors edition'],
r'\s*\(collector\'?s?\s*edition?\)': ['collectors', 'collectors edition'],
# Generic catch-alls for any edition in parens/brackets (e.g. Silver Edition, MMXI Special Edition)
r'\s*\([^)]*\bedition\b[^)]*\)': ['edition'],
r'\s*\[[^\]]*\bedition\b[^\]]*\]': ['edition'],

View file

@ -10250,6 +10250,18 @@ def _check_album_completion(db, album_data: dict, artist_name: str, test_mode: b
album_name = album_data.get('name', '')
total_tracks = album_data.get('total_tracks', 0)
album_id = album_data.get('id', '')
# If total_tracks is 0 (Discogs masters don't include track counts),
# try to fetch the real count from the source
if total_tracks == 0 and album_id:
try:
fallback = _get_metadata_fallback_client()
album_detail = fallback.get_album_tracks(str(album_id))
if album_detail and album_detail.get('items'):
total_tracks = len(album_detail['items'])
logger.debug(f"Fetched track count for '{album_name}': {total_tracks}")
except Exception:
pass
print(f"🔍 Checking album: '{album_name}' ({total_tracks} tracks)")

View file

@ -34371,6 +34371,23 @@ function updateAlbumCompletionOverlay(completionData, containerType) {
return;
}
// Reclassify album type if we now know the track count (Discogs lazy fetch)
const currentType = albumCard.dataset.albumType;
const expectedTracks = completionData.expected_tracks || 0;
if (currentType === 'album' && expectedTracks > 0 && expectedTracks <= 3) {
albumCard.dataset.albumType = 'single';
const typeEl = albumCard.querySelector('.album-card-type');
if (typeEl) typeEl.textContent = 'Single';
} else if (currentType === 'album' && expectedTracks > 3 && expectedTracks <= 6) {
albumCard.dataset.albumType = 'ep';
const typeEl = albumCard.querySelector('.album-card-type');
if (typeEl) typeEl.textContent = 'EP';
}
// Update stored total tracks
if (expectedTracks > 0) {
albumCard.dataset.totalTracks = expectedTracks;
}
const overlay = albumCard.querySelector('.completion-overlay');
if (!overlay) {
console.warn(`Completion overlay not found for album: ${completionData.name}`);
@ -34385,12 +34402,13 @@ function updateAlbumCompletionOverlay(completionData, containerType) {
// Update overlay text and content
const statusText = getCompletionStatusText(completionData);
const progressText = `${completionData.owned_tracks}/${completionData.expected_tracks}`;
const progressText = completionData.expected_tracks > 0
? `${completionData.owned_tracks}/${completionData.expected_tracks}`
: '';
overlay.innerHTML = `
<span class="completion-status">${statusText}</span>
<span class="completion-progress">${progressText}</span>
`;
overlay.innerHTML = progressText
? `<span class="completion-status">${statusText}</span><span class="completion-progress">${progressText}</span>`
: `<span class="completion-status">${statusText}</span>`;
// Add tooltip with more details
overlay.title = `${completionData.name}\n${statusText} (${completionData.completion_percentage}%)\nTracks: ${completionData.owned_tracks}/${completionData.expected_tracks}\nConfidence: ${completionData.confidence}`;
@ -42227,7 +42245,8 @@ function createReleaseCard(release) {
}
}
} else {
completionText.textContent = "Missing";
const totalTr = release.total_tracks || release.track_completion?.total_tracks || 0;
completionText.textContent = totalTr > 0 ? `Missing (${totalTr} tracks)` : "Not in library";
completionText.className = "completion-text missing";
completionFill.className += " missing";
completionFill.style.width = "0%";