Fix staging files bypassing path template
_try_staging_match() built a minimal context missing spotify_artist, spotify_album, is_album_download, and has_clean_spotify_data. Post- processing returned early at the missing-spotify_artist guard and the copied file was left at the transfer root with its original filename. Now mirrors the sync modal worker's context-building: uses _explicit_album_context/_explicit_artist_context when available (artist-page album downloads), falls back to track.album/track.artists for playlists and sync modal. track_number and disc_number are also forwarded so multi-disc albums land in the correct Disc N/ subfolder.
This commit is contained in:
parent
ab9064d3f6
commit
61c6b6f3f9
2 changed files with 91 additions and 0 deletions
|
|
@ -28732,13 +28732,100 @@ def _try_staging_match(task_id, batch_id, track):
|
|||
context_key = f"staging_{task_id}"
|
||||
with tasks_lock:
|
||||
track_info = download_tasks.get(task_id, {}).get('track_info', {})
|
||||
if not isinstance(track_info, dict):
|
||||
track_info = {}
|
||||
|
||||
# Build spotify_artist / spotify_album context so post-processing can apply
|
||||
# the path template. Without these, _post_process_matched_download returns
|
||||
# early and the file stays at the transfer root with its original filename.
|
||||
# Mirror the context-building logic from the sync modal worker.
|
||||
has_explicit_context = track_info.get('_is_explicit_album_download', False)
|
||||
|
||||
if has_explicit_context:
|
||||
explicit_artist = track_info.get('_explicit_artist_context', {})
|
||||
if isinstance(explicit_artist, str):
|
||||
explicit_artist = {'name': explicit_artist}
|
||||
elif not isinstance(explicit_artist, dict):
|
||||
explicit_artist = {}
|
||||
spotify_artist_ctx = {
|
||||
'id': explicit_artist.get('id', 'staging'),
|
||||
'name': explicit_artist.get('name', track_artist),
|
||||
'genres': explicit_artist.get('genres', [])
|
||||
}
|
||||
explicit_album = track_info.get('_explicit_album_context', {})
|
||||
if not isinstance(explicit_album, dict):
|
||||
explicit_album = {}
|
||||
_album_image_url = explicit_album.get('image_url')
|
||||
if not _album_image_url and explicit_album.get('images'):
|
||||
_imgs = explicit_album['images']
|
||||
if isinstance(_imgs, list) and _imgs:
|
||||
_album_image_url = _imgs[0].get('url') if isinstance(_imgs[0], dict) else None
|
||||
spotify_album_ctx = {
|
||||
'id': explicit_album.get('id', 'staging'),
|
||||
'name': explicit_album.get('name', getattr(track, 'album', '') or ''),
|
||||
'release_date': explicit_album.get('release_date', ''),
|
||||
'image_url': _album_image_url,
|
||||
'album_type': explicit_album.get('album_type', 'album'),
|
||||
'total_tracks': explicit_album.get('total_tracks', 0),
|
||||
'total_discs': explicit_album.get('total_discs', 1),
|
||||
'artists': explicit_album.get('artists', [{'name': spotify_artist_ctx.get('name', '')}])
|
||||
}
|
||||
is_album_ctx = True
|
||||
has_clean_data = True
|
||||
else:
|
||||
fallback_album = track_info.get('album', {})
|
||||
if isinstance(fallback_album, str):
|
||||
fallback_album = {'name': fallback_album}
|
||||
elif not isinstance(fallback_album, dict):
|
||||
fallback_album = {}
|
||||
track_album_name = getattr(track, 'album', '') or fallback_album.get('name', '') or ''
|
||||
spotify_artist_ctx = {
|
||||
'id': 'staging',
|
||||
'name': track_artist or 'Unknown',
|
||||
'genres': []
|
||||
}
|
||||
spotify_album_ctx = {
|
||||
'id': 'staging',
|
||||
'name': track_album_name,
|
||||
'release_date': fallback_album.get('release_date', ''),
|
||||
'image_url': fallback_album.get('image_url'),
|
||||
'album_type': fallback_album.get('album_type', 'album'),
|
||||
'total_tracks': fallback_album.get('total_tracks', 0),
|
||||
'total_discs': fallback_album.get('total_discs', 1),
|
||||
'artists': [{'name': track_artist}] if track_artist else []
|
||||
}
|
||||
is_album_ctx = bool(
|
||||
track_album_name and
|
||||
track_album_name.strip() and
|
||||
track_album_name.lower() not in ('unknown album', '') and
|
||||
track_album_name.lower() != track_title.lower()
|
||||
)
|
||||
has_clean_data = bool(track_title and track_artist and track_album_name)
|
||||
|
||||
track_number = (
|
||||
track_info.get('track_number', 0) or
|
||||
getattr(track, 'track_number', 0) or 0
|
||||
)
|
||||
disc_number = (
|
||||
track_info.get('disc_number', 1) or
|
||||
getattr(track, 'disc_number', 1) or 1
|
||||
)
|
||||
|
||||
context = {
|
||||
'track_info': track_info,
|
||||
'spotify_artist': spotify_artist_ctx,
|
||||
'spotify_album': spotify_album_ctx,
|
||||
'original_search_result': {
|
||||
'title': track_title,
|
||||
'artist': track_artist,
|
||||
'spotify_clean_title': track_title,
|
||||
'spotify_clean_album': spotify_album_ctx.get('name', ''),
|
||||
'spotify_clean_artist': track_artist,
|
||||
'track_number': track_number,
|
||||
'disc_number': disc_number,
|
||||
},
|
||||
'is_album_download': is_album_ctx,
|
||||
'has_clean_spotify_data': has_clean_data,
|
||||
'staging_source': True,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3600,6 +3600,10 @@ function closeHelperSearch() {
|
|||
|
||||
const WHATS_NEW = {
|
||||
'2.2': [
|
||||
// --- April 14, 2026 ---
|
||||
{ date: 'April 14, 2026' },
|
||||
{ title: 'Fix Staging Files Ignoring Path Template', desc: 'Files matched from the Staging folder were copied to the transfer root with their original filename instead of applying the configured path template. Post-processing now receives full artist/album context for staging matches' },
|
||||
|
||||
// --- April 4, 2026 ---
|
||||
{ date: 'April 4, 2026' },
|
||||
{ title: 'Artist Map — Visualize Your Music Universe', desc: 'Three interactive canvas modes: Watchlist Constellation (your artists + similar), Genre Map (browse by genre with sidebar), and Artist Explorer (deep-dive any artist). Offscreen buffer rendering handles 1000+ nodes', page: 'discover' },
|
||||
|
|
|
|||
Loading…
Reference in a new issue