Added spotify_metadata support for albums
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
#!/usr/bin/python3
|
||||
import os
|
||||
import json
|
||||
import requests
|
||||
@@ -277,6 +276,32 @@ class EASY_DW:
|
||||
# Maintain legacy attribute expected elsewhere
|
||||
self.__song_metadata = self.__song_metadata_dict
|
||||
self.__download_type = "track"
|
||||
# Backfill missing album fields when using Spotify minimal track objects
|
||||
try:
|
||||
if use_spotify and 'album' not in self.__song_metadata_dict and getattr(preferences, 'spotify_album_obj', None):
|
||||
spo_album = preferences.spotify_album_obj
|
||||
# Basic album fields
|
||||
self.__song_metadata_dict['album'] = getattr(spo_album, 'title', '')
|
||||
if getattr(spo_album, 'artists', None):
|
||||
self.__song_metadata_dict['ar_album'] = artist_separator.join([getattr(a, 'name', '') for a in spo_album.artists])
|
||||
self.__song_metadata_dict['nb_tracks'] = getattr(spo_album, 'total_tracks', 0)
|
||||
# Total discs if available
|
||||
if hasattr(spo_album, 'total_discs') and getattr(spo_album, 'total_discs'):
|
||||
self.__song_metadata_dict['nb_discs'] = getattr(spo_album, 'total_discs')
|
||||
# Year from release date
|
||||
from deezspot.libutils.metadata_converter import _format_release_date, _get_best_image_url
|
||||
self.__song_metadata_dict['year'] = _format_release_date(getattr(spo_album, 'release_date', None), 'spotify')
|
||||
# IDs
|
||||
if getattr(spo_album, 'ids', None):
|
||||
self.__song_metadata_dict['upc'] = getattr(spo_album.ids, 'upc', None)
|
||||
self.__song_metadata_dict['album_id'] = getattr(spo_album.ids, 'spotify', None)
|
||||
# Prefer Spotify album image
|
||||
if getattr(spo_album, 'images', None):
|
||||
img_url = _get_best_image_url(spo_album.images, 'spotify')
|
||||
if img_url:
|
||||
self.__song_metadata_dict['image'] = img_url
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self.__c_quality = qualities[self.__quality_download]
|
||||
self.__fallback_ids = self.__ids
|
||||
@@ -1120,6 +1145,9 @@ class DW_ALBUM:
|
||||
album_obj: albumCbObject = self.__preferences.song_metadata
|
||||
self.__song_metadata = self._album_object_to_dict(album_obj)
|
||||
self.__song_metadata['artist_separator'] = getattr(self.__preferences, 'artist_separator', '; ')
|
||||
# New: Spotify metadata context for album-level tagging
|
||||
self.__use_spotify = getattr(self.__preferences, 'spotify_metadata', False)
|
||||
self.__spotify_album_obj = getattr(self.__preferences, 'spotify_album_obj', None)
|
||||
|
||||
def dw(self) -> Album:
|
||||
from deezspot.deezloader.deegw_api import API_GW
|
||||
@@ -1132,12 +1160,33 @@ class DW_ALBUM:
|
||||
md5_image = infos_dw[0]['ALB_PICTURE']
|
||||
image_bytes = API.choose_img(md5_image, size="1400x1400")
|
||||
|
||||
# Convert album object to dictionary for legacy functions
|
||||
# Choose album_dict source: Spotify if requested and available, else Deezer
|
||||
artist_separator = getattr(self.__preferences, 'artist_separator', '; ')
|
||||
if self.__use_spotify and self.__spotify_album_obj:
|
||||
album_dict = album_object_to_dict(self.__spotify_album_obj, source_type='spotify', artist_separator=artist_separator)
|
||||
else:
|
||||
album_dict = self._album_object_to_dict(album_obj)
|
||||
# Prefer Spotify image if requested and available
|
||||
if self.__use_spotify and self.__spotify_album_obj and getattr(self.__spotify_album_obj, 'images', None):
|
||||
from deezspot.libutils.metadata_converter import _get_best_image_url
|
||||
spo_img_url = _get_best_image_url(self.__spotify_album_obj.images, 'spotify')
|
||||
if spo_img_url:
|
||||
album_dict['image'] = spo_img_url
|
||||
else:
|
||||
album_dict['image'] = image_bytes
|
||||
else:
|
||||
album_dict['image'] = image_bytes
|
||||
|
||||
album = Album(self.__ids)
|
||||
album.image = image_bytes
|
||||
# album.image should be raw bytes; fetch URL if needed
|
||||
if isinstance(album_dict['image'], bytes):
|
||||
album.image = album_dict['image']
|
||||
else:
|
||||
try:
|
||||
from deezspot.libutils.taggers import fetch_and_process_image
|
||||
album.image = fetch_and_process_image(album_dict['image']) or API.choose_img(md5_image, size="1400x1400")
|
||||
except Exception:
|
||||
album.image = API.choose_img(md5_image, size="1400x1400")
|
||||
album.md5_image = md5_image
|
||||
album.nb_tracks = album_obj.total_tracks
|
||||
album.album_name = album_obj.title
|
||||
@@ -1159,6 +1208,20 @@ class DW_ALBUM:
|
||||
save_cover_image(album.image, album_base_directory, "cover.jpg")
|
||||
|
||||
total_tracks = len(infos_dw)
|
||||
# If spotify album metadata is requested and available, build a map of spotify track objects by ISRC or index
|
||||
spotify_tracks_by_isrc = {}
|
||||
spotify_tracks_in_order = []
|
||||
if self.__use_spotify and self.__spotify_album_obj and getattr(self.__spotify_album_obj, 'tracks', None):
|
||||
# The spotify album object contains trackAlbumObjects with ids (including isrc)
|
||||
for spo_track in self.__spotify_album_obj.tracks:
|
||||
spotify_tracks_in_order.append(spo_track)
|
||||
try:
|
||||
isrc_val = getattr(spo_track.ids, 'isrc', None)
|
||||
if isrc_val:
|
||||
spotify_tracks_by_isrc[isrc_val.upper()] = spo_track
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
for a, album_track_obj in enumerate(album_obj.tracks):
|
||||
c_infos_dw_item = infos_dw[a]
|
||||
|
||||
@@ -1197,6 +1260,25 @@ class DW_ALBUM:
|
||||
c_preferences.track_number = a + 1 # For progress reporting only
|
||||
c_preferences.total_tracks = total_tracks
|
||||
c_preferences.link = f"https://deezer.com/track/{c_preferences.ids}"
|
||||
# Inject Spotify per-track object if available without extra API calls
|
||||
if self.__use_spotify and spotify_tracks_in_order:
|
||||
spo_track_for_tag = None
|
||||
# Prefer ISRC matching if possible
|
||||
deezer_isrc = None
|
||||
try:
|
||||
deezer_isrc = c_infos_dw_item.get('ISRC') or c_infos_dw_item.get('isrc')
|
||||
deezer_isrc = deezer_isrc.upper() if isinstance(deezer_isrc, str) else None
|
||||
except Exception:
|
||||
deezer_isrc = None
|
||||
if deezer_isrc and deezer_isrc in spotify_tracks_by_isrc:
|
||||
spo_track_for_tag = spotify_tracks_by_isrc[deezer_isrc]
|
||||
else:
|
||||
# Fallback to index position
|
||||
if a < len(spotify_tracks_in_order):
|
||||
spo_track_for_tag = spotify_tracks_in_order[a]
|
||||
if spo_track_for_tag:
|
||||
c_preferences.spotify_metadata = True
|
||||
c_preferences.spotify_track_obj = spo_track_for_tag
|
||||
|
||||
current_track_object = EASY_DW(c_infos_dw_item, c_preferences, parent='album').easy_dw()
|
||||
except Exception as e:
|
||||
|
||||
@@ -251,7 +251,9 @@ class DeeLogin:
|
||||
save_cover=stock_save_cover,
|
||||
market=stock_market,
|
||||
playlist_context=None,
|
||||
artist_separator: str = "; "
|
||||
artist_separator: str = "; ",
|
||||
spotify_metadata: bool = False,
|
||||
spotify_album_obj=None
|
||||
) -> Album:
|
||||
|
||||
link_is_valid(link_album)
|
||||
@@ -299,6 +301,8 @@ class DeeLogin:
|
||||
preferences.save_cover = save_cover
|
||||
preferences.market = market
|
||||
preferences.artist_separator = artist_separator
|
||||
preferences.spotify_metadata = bool(spotify_metadata)
|
||||
preferences.spotify_album_obj = spotify_album_obj
|
||||
|
||||
if playlist_context:
|
||||
preferences.json_data = playlist_context['json_data']
|
||||
@@ -637,11 +641,24 @@ class DeeLogin:
|
||||
save_cover=stock_save_cover,
|
||||
market=stock_market,
|
||||
playlist_context=None,
|
||||
artist_separator: str = "; "
|
||||
artist_separator: str = "; ",
|
||||
spotify_metadata: bool = False
|
||||
) -> Album:
|
||||
|
||||
link_dee = self.convert_spoty_to_dee_link_album(link_album)
|
||||
|
||||
spotify_album_obj = None
|
||||
if spotify_metadata:
|
||||
try:
|
||||
# Fetch full Spotify album with tracks once and convert to albumObject
|
||||
from deezspot.spotloader.__spo_api__ import tracking_album as spo_tracking_album
|
||||
spo_ids = get_ids(link_album)
|
||||
spotify_album_json = Spo.get_album(spo_ids)
|
||||
if spotify_album_json:
|
||||
spotify_album_obj = spo_tracking_album(spotify_album_json)
|
||||
except Exception:
|
||||
spotify_album_obj = None
|
||||
|
||||
album = self.download_albumdee(
|
||||
link_dee, output_dir,
|
||||
quality_download, recursive_quality,
|
||||
@@ -658,7 +675,9 @@ class DeeLogin:
|
||||
save_cover=save_cover,
|
||||
market=market,
|
||||
playlist_context=playlist_context,
|
||||
artist_separator=artist_separator
|
||||
artist_separator=artist_separator,
|
||||
spotify_metadata=spotify_metadata,
|
||||
spotify_album_obj=spotify_album_obj
|
||||
)
|
||||
|
||||
return album
|
||||
|
||||
@@ -27,3 +27,5 @@ class Preferences:
|
||||
self.spotify_metadata: bool = False
|
||||
# New: optional Spotify trackObject to use when spotify_metadata is True
|
||||
self.spotify_track_obj = None
|
||||
# New: optional Spotify albumObject (from spotloader tracking_album) for album-level spotify_metadata
|
||||
self.spotify_album_obj = None
|
||||
Reference in New Issue
Block a user