implemented summary at the end of every download
fixed year placeholder
This commit is contained in:
@@ -42,7 +42,7 @@ from mutagen.mp3 import MP3
|
||||
from mutagen.id3 import ID3
|
||||
from mutagen.mp4 import MP4
|
||||
from mutagen import File
|
||||
from deezspot.libutils.logging_utils import logger, ProgressReporter
|
||||
from deezspot.libutils.logging_utils import logger, ProgressReporter, report_progress
|
||||
from deezspot.libutils.skip_detection import check_track_exists
|
||||
from deezspot.libutils.cleanup_utils import register_active_download, unregister_active_download
|
||||
from deezspot.libutils.audio_converter import AUDIO_FORMATS # Added for parse_format_string
|
||||
@@ -54,15 +54,6 @@ class Download_JOB:
|
||||
def set_progress_reporter(cls, reporter):
|
||||
cls.progress_reporter = reporter
|
||||
|
||||
@classmethod
|
||||
def report_progress(cls, progress_data):
|
||||
"""Report progress if a reporter is configured."""
|
||||
if cls.progress_reporter:
|
||||
cls.progress_reporter.report(progress_data)
|
||||
else:
|
||||
# Fallback to logger if no reporter is configured
|
||||
logger.info(json.dumps(progress_data))
|
||||
|
||||
@classmethod
|
||||
def __get_url(cls, c_track: Track, quality_download: str) -> dict:
|
||||
if c_track.get('__TYPE__') == 'episode':
|
||||
@@ -324,17 +315,11 @@ class EASY_DW:
|
||||
self.__c_track.success = True
|
||||
self.__c_track.was_skipped = True
|
||||
|
||||
progress_data = {
|
||||
"type": "track",
|
||||
"song": current_title,
|
||||
"artist": self.__song_metadata['artist'],
|
||||
"status": "skipped",
|
||||
"url": self.__link,
|
||||
"reason": f"Track already exists in desired format at {existing_file_path}",
|
||||
"convert_to": self.__convert_to,
|
||||
"bitrate": self.__bitrate
|
||||
}
|
||||
|
||||
parent = None
|
||||
current_track = None
|
||||
total_tracks = None
|
||||
summary = None
|
||||
|
||||
# Add parent info based on parent type
|
||||
if self.__parent == "playlist" and hasattr(self.__preferences, "json_data"):
|
||||
playlist_data = self.__preferences.json_data
|
||||
@@ -343,17 +328,13 @@ class EASY_DW:
|
||||
current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
|
||||
# Format for playlist-parented tracks exactly as required
|
||||
progress_data.update({
|
||||
"current_track": current_track,
|
||||
parent = {
|
||||
"type": "playlist",
|
||||
"name": playlist_name,
|
||||
"owner": playlist_data.get('creator', {}).get('name', 'unknown'),
|
||||
"total_tracks": total_tracks,
|
||||
"parent": {
|
||||
"type": "playlist",
|
||||
"name": playlist_name,
|
||||
"owner": playlist_data.get('creator', {}).get('name', 'unknown'),
|
||||
"total_tracks": total_tracks,
|
||||
"url": f"https://deezer.com/playlist/{self.__preferences.json_data.get('id', '')}"
|
||||
}
|
||||
})
|
||||
"url": f"https://deezer.com/playlist/{self.__preferences.json_data.get('id', '')}"
|
||||
}
|
||||
elif self.__parent == "album":
|
||||
album_name = self.__song_metadata.get('album', '')
|
||||
album_artist = self.__song_metadata.get('album_artist', self.__song_metadata.get('album_artist', ''))
|
||||
@@ -361,19 +342,43 @@ class EASY_DW:
|
||||
current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
|
||||
# Format for album-parented tracks exactly as required
|
||||
progress_data.update({
|
||||
"current_track": current_track,
|
||||
parent = {
|
||||
"type": "album",
|
||||
"title": album_name,
|
||||
"artist": album_artist,
|
||||
"total_tracks": total_tracks,
|
||||
"parent": {
|
||||
"type": "album",
|
||||
"title": album_name,
|
||||
"artist": album_artist,
|
||||
"total_tracks": total_tracks,
|
||||
"url": f"https://deezer.com/album/{self.__preferences.song_metadata.get('album_id', '')}"
|
||||
}
|
||||
})
|
||||
"url": f"https://deezer.com/album/{self.__preferences.song_metadata.get('album_id', '')}"
|
||||
}
|
||||
|
||||
Download_JOB.report_progress(progress_data)
|
||||
if self.__parent is None:
|
||||
track_info = {
|
||||
"name": current_title,
|
||||
"artist": current_artist
|
||||
}
|
||||
summary = {
|
||||
"successful_tracks": [],
|
||||
"skipped_tracks": [f"{track_info['name']} - {track_info['artist']}"],
|
||||
"failed_tracks": [],
|
||||
"total_successful": 0,
|
||||
"total_skipped": 1,
|
||||
"total_failed": 0,
|
||||
}
|
||||
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="track",
|
||||
song=current_title,
|
||||
artist=self.__song_metadata['artist'],
|
||||
status="skipped",
|
||||
url=self.__link,
|
||||
reason=f"Track already exists in desired format at {existing_file_path}",
|
||||
convert_to=self.__convert_to,
|
||||
bitrate=self.__bitrate,
|
||||
parent=parent,
|
||||
current_track=current_track,
|
||||
total_tracks=total_tracks,
|
||||
summary=summary
|
||||
)
|
||||
# self.__c_track might not be fully initialized here if __write_track() hasn't been called
|
||||
# Create a minimal track object for skipped scenario
|
||||
skipped_item = Track(
|
||||
@@ -407,45 +412,49 @@ class EASY_DW:
|
||||
# Create done status report using the new required format (only if download_try didn't fail)
|
||||
# This part should only execute if download_try itself was successful (i.e., no exception)
|
||||
if self.__c_track.success : # Check if download_try marked it as successful
|
||||
progress_data = {
|
||||
"type": "track",
|
||||
"song": self.__song_metadata['music'],
|
||||
"artist": self.__song_metadata['artist'],
|
||||
"status": "done",
|
||||
"convert_to": self.__convert_to
|
||||
}
|
||||
parent = None
|
||||
current_track = None
|
||||
total_tracks = None
|
||||
|
||||
spotify_url = getattr(self.__preferences, 'spotify_url', None)
|
||||
progress_data["url"] = spotify_url if spotify_url else self.__link
|
||||
url = spotify_url if spotify_url else self.__link
|
||||
|
||||
if self.__parent == "playlist" and hasattr(self.__preferences, "json_data"):
|
||||
playlist_data = self.__preferences.json_data
|
||||
# ... (rest of playlist parent data) ...
|
||||
progress_data.update({
|
||||
"current_track": getattr(self.__preferences, 'track_number', 0),
|
||||
"total_tracks": getattr(self.__preferences, 'total_tracks', 0),
|
||||
"parent": {
|
||||
"type": "playlist",
|
||||
"name": playlist_data.get('title', 'unknown'),
|
||||
"owner": playlist_data.get('creator', {}).get('name', 'unknown')
|
||||
}
|
||||
})
|
||||
elif self.__parent == "album":
|
||||
album_name = self.__song_metadata.get('album', '')
|
||||
album_artist = self.__song_metadata.get('album_artist', self.__song_metadata.get('album_artist', ''))
|
||||
total_tracks = getattr(self.__preferences, 'total_tracks', 0)
|
||||
current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
|
||||
progress_data.update({
|
||||
"current_track": current_track,
|
||||
"total_tracks": total_tracks,
|
||||
"parent": {
|
||||
total_tracks = getattr(self.__preferences, 'total_tracks', 0)
|
||||
current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
parent = {
|
||||
"type": "playlist",
|
||||
"name": playlist_data.get('title', 'unknown'),
|
||||
"owner": playlist_data.get('creator', {}).get('name', 'unknown'),
|
||||
"total_tracks": total_tracks,
|
||||
"url": f"https://deezer.com/playlist/{playlist_data.get('id', '')}"
|
||||
}
|
||||
elif self.__parent == "album":
|
||||
album_name = self.__song_metadata.get('album', '')
|
||||
album_artist = self.__song_metadata.get('album_artist', self.__song_metadata.get('album_artist', ''))
|
||||
total_tracks = getattr(self.__preferences, 'total_tracks', 0)
|
||||
current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
parent = {
|
||||
"type": "album",
|
||||
"title": album_name,
|
||||
"artist": album_artist,
|
||||
"total_tracks": total_tracks,
|
||||
"url": f"https://deezer.com/album/{self.__preferences.song_metadata.get('album_id', '')}"
|
||||
}
|
||||
})
|
||||
Download_JOB.report_progress(progress_data)
|
||||
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="track",
|
||||
song=self.__song_metadata['music'],
|
||||
artist=self.__song_metadata['artist'],
|
||||
status="done",
|
||||
url=url,
|
||||
parent=parent,
|
||||
current_track=current_track,
|
||||
total_tracks=total_tracks,
|
||||
convert_to=self.__convert_to
|
||||
)
|
||||
|
||||
except Exception as e: # Covers failures within download_try or download_episode_try
|
||||
item_type = "Episode" if self.__infos_dw.get('__TYPE__') == 'episode' else "Track"
|
||||
@@ -572,47 +581,48 @@ class EASY_DW:
|
||||
self.__write_track()
|
||||
|
||||
# Send immediate progress status for the track
|
||||
progress_data = {
|
||||
"type": "track",
|
||||
"song": self.__song_metadata.get("music", ""),
|
||||
"artist": self.__song_metadata.get("artist", ""),
|
||||
"status": "progress"
|
||||
}
|
||||
parent = None
|
||||
current_track = None
|
||||
total_tracks = None
|
||||
spotify_url = getattr(self.__preferences, 'spotify_url', None)
|
||||
progress_data["url"] = spotify_url if spotify_url else self.__link
|
||||
url = spotify_url if spotify_url else self.__link
|
||||
|
||||
if self.__parent == "playlist" and hasattr(self.__preferences, "json_data"):
|
||||
playlist_data = self.__preferences.json_data
|
||||
playlist_name = playlist_data.get('title', 'unknown')
|
||||
total_tracks = getattr(self.__preferences, 'total_tracks', 0)
|
||||
current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
progress_data.update({
|
||||
"current_track": current_track,
|
||||
parent = {
|
||||
"type": "playlist",
|
||||
"name": playlist_name,
|
||||
"owner": playlist_data.get('creator', {}).get('name', 'unknown'),
|
||||
"total_tracks": total_tracks,
|
||||
"parent": {
|
||||
"type": "playlist",
|
||||
"name": playlist_name,
|
||||
"owner": playlist_data.get('creator', {}).get('name', 'unknown'),
|
||||
"total_tracks": total_tracks,
|
||||
"url": f"https://deezer.com/playlist/{self.__preferences.json_data.get('id', '')}"
|
||||
}
|
||||
})
|
||||
"url": f"https://deezer.com/playlist/{self.__preferences.json_data.get('id', '')}"
|
||||
}
|
||||
elif self.__parent == "album":
|
||||
album_name = self.__song_metadata.get('album', '')
|
||||
album_artist = self.__song_metadata.get('album_artist', self.__song_metadata.get('album_artist', ''))
|
||||
total_tracks = getattr(self.__preferences, 'total_tracks', 0)
|
||||
current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
progress_data.update({
|
||||
"current_track": current_track,
|
||||
parent = {
|
||||
"type": "album",
|
||||
"title": album_name,
|
||||
"artist": album_artist,
|
||||
"total_tracks": total_tracks,
|
||||
"parent": {
|
||||
"type": "album",
|
||||
"title": album_name,
|
||||
"artist": album_artist,
|
||||
"total_tracks": total_tracks,
|
||||
"url": f"https://deezer.com/album/{self.__preferences.song_metadata.get('album_id', '')}"
|
||||
}
|
||||
})
|
||||
Download_JOB.report_progress(progress_data)
|
||||
"url": f"https://deezer.com/album/{self.__preferences.song_metadata.get('album_id', '')}"
|
||||
}
|
||||
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="track",
|
||||
song=self.__song_metadata.get("music", ""),
|
||||
artist=self.__song_metadata.get("artist", ""),
|
||||
status="progress",
|
||||
url=url,
|
||||
parent=parent,
|
||||
current_track=current_track,
|
||||
total_tracks=total_tracks,
|
||||
)
|
||||
|
||||
# Start of processing block (decryption, tagging, cover, conversion)
|
||||
register_active_download(self.__song_path)
|
||||
@@ -704,21 +714,46 @@ class EASY_DW:
|
||||
elif "404" in error_msg or "Not Found" in error_msg: error_msg = "Track not found - It might have been removed"
|
||||
|
||||
# (Error reporting code as it exists)
|
||||
error_progress_data = {
|
||||
"type": "track", "status": "error",
|
||||
"song": self.__song_metadata.get('music', ''), "artist": self.__song_metadata.get('artist', ''),
|
||||
"error": error_msg, "url": getattr(self.__preferences, 'spotify_url', None) or self.__link,
|
||||
"convert_to": self.__convert_to
|
||||
}
|
||||
parent = None
|
||||
current_track = None
|
||||
total_tracks = None
|
||||
|
||||
if self.__parent == "playlist" and hasattr(self.__preferences, "json_data"):
|
||||
playlist_data = self.__preferences.json_data; playlist_name = playlist_data.get('title', 'unknown')
|
||||
total_tracks = getattr(self.__preferences, 'total_tracks', 0); current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
error_progress_data.update({"current_track": current_track, "total_tracks": total_tracks, "parent": {"type": "playlist", "name": playlist_name, "owner": playlist_data.get('creator', {}).get('name', 'unknown'), "total_tracks": total_tracks, "url": f"https://deezer.com/playlist/{playlist_data.get('id', '')}"}})
|
||||
playlist_data = self.__preferences.json_data
|
||||
playlist_name = playlist_data.get('title', 'unknown')
|
||||
total_tracks = getattr(self.__preferences, 'total_tracks', 0)
|
||||
current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
parent = {
|
||||
"type": "playlist", "name": playlist_name,
|
||||
"owner": playlist_data.get('creator', {}).get('name', 'unknown'),
|
||||
"total_tracks": total_tracks,
|
||||
"url": f"https://deezer.com/playlist/{playlist_data.get('id', '')}"
|
||||
}
|
||||
elif self.__parent == "album":
|
||||
album_name = self.__song_metadata.get('album', ''); album_artist = self.__song_metadata.get('album_artist', self.__song_metadata.get('album_artist', ''))
|
||||
total_tracks = getattr(self.__preferences, 'total_tracks', 0); current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
error_progress_data.update({"current_track": current_track, "total_tracks": total_tracks, "parent": {"type": "album", "title": album_name, "artist": album_artist, "total_tracks": total_tracks, "url": f"https://deezer.com/album/{self.__preferences.song_metadata.get('album_id', '')}"}})
|
||||
Download_JOB.report_progress(error_progress_data)
|
||||
album_name = self.__song_metadata.get('album', '')
|
||||
album_artist = self.__song_metadata.get('album_artist', self.__song_metadata.get('album_artist', ''))
|
||||
total_tracks = getattr(self.__preferences, 'total_tracks', 0)
|
||||
current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
parent = {
|
||||
"type": "album", "title": album_name,
|
||||
"artist": album_artist,
|
||||
"total_tracks": total_tracks,
|
||||
"url": f"https://deezer.com/album/{self.__preferences.song_metadata.get('album_id', '')}"
|
||||
}
|
||||
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="track",
|
||||
status="error",
|
||||
song=self.__song_metadata.get('music', ''),
|
||||
artist=self.__song_metadata.get('artist', ''),
|
||||
error=error_msg,
|
||||
url=getattr(self.__preferences, 'spotify_url', None) or self.__link,
|
||||
convert_to=self.__convert_to,
|
||||
parent=parent,
|
||||
current_track=current_track,
|
||||
total_tracks=total_tracks
|
||||
)
|
||||
logger.error(f"Failed to process track: {error_msg}")
|
||||
|
||||
self.__c_track.success = False
|
||||
@@ -781,7 +816,7 @@ class EASY_DW:
|
||||
spotify_url = getattr(self.__preferences, 'spotify_url', None)
|
||||
progress_data["url"] = spotify_url if spotify_url else self.__link
|
||||
|
||||
Download_JOB.report_progress(progress_data)
|
||||
Download_JOB.progress_reporter.report(progress_data)
|
||||
|
||||
self.__c_track.success = True
|
||||
self.__write_episode()
|
||||
@@ -933,6 +968,29 @@ class DW_TRACK:
|
||||
logger.error(f"{error_msg} (Link: {current_link})")
|
||||
raise TrackNotFound(message=error_msg, url=current_link)
|
||||
|
||||
if track.success and not getattr(track, 'was_skipped', False):
|
||||
track_info = {
|
||||
"name": track.tags.get('music', 'Unknown Track'),
|
||||
"artist": track.tags.get('artist', 'Unknown Artist')
|
||||
}
|
||||
summary = {
|
||||
"successful_tracks": [f"{track_info['name']} - {track_info['artist']}"],
|
||||
"skipped_tracks": [],
|
||||
"failed_tracks": [],
|
||||
"total_successful": 1,
|
||||
"total_skipped": 0,
|
||||
"total_failed": 0,
|
||||
}
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="track",
|
||||
song=track_info['name'],
|
||||
artist=track_info['artist'],
|
||||
status="done",
|
||||
url=track.link,
|
||||
summary=summary
|
||||
)
|
||||
|
||||
return track
|
||||
|
||||
class DW_ALBUM:
|
||||
@@ -985,14 +1043,15 @@ class DW_ALBUM:
|
||||
total_tracks_for_report = self.__song_metadata.get('nb_tracks', 0)
|
||||
album_link_for_report = self.__preferences.link # Get album link from preferences
|
||||
|
||||
Download_JOB.report_progress({
|
||||
"type": "album",
|
||||
"artist": derived_album_artist_from_contributors,
|
||||
"status": "initializing",
|
||||
"total_tracks": total_tracks_for_report,
|
||||
"title": album_name_for_report,
|
||||
"url": album_link_for_report # Use the actual album link
|
||||
})
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="album",
|
||||
artist=derived_album_artist_from_contributors,
|
||||
status="initializing",
|
||||
total_tracks=total_tracks_for_report,
|
||||
title=album_name_for_report,
|
||||
url=album_link_for_report
|
||||
)
|
||||
|
||||
infos_dw = API_GW.get_album_data(self.__ids)['data']
|
||||
|
||||
@@ -1183,14 +1242,42 @@ class DW_ALBUM:
|
||||
album_name = self.__song_metadata.get('album', 'Unknown Album')
|
||||
total_tracks = self.__song_metadata.get('nb_tracks', 0)
|
||||
|
||||
Download_JOB.report_progress({
|
||||
"type": "album",
|
||||
"artist": derived_album_artist_from_contributors,
|
||||
"status": "done",
|
||||
"total_tracks": total_tracks,
|
||||
"title": album_name,
|
||||
"url": album_link_for_report # Use the actual album link
|
||||
})
|
||||
successful_tracks = []
|
||||
failed_tracks = []
|
||||
skipped_tracks = []
|
||||
for track in tracks:
|
||||
track_info = {
|
||||
"name": track.tags.get('music') or track.tags.get('name', 'Unknown Track'),
|
||||
"artist": track.tags.get('artist', 'Unknown Artist')
|
||||
}
|
||||
if getattr(track, 'was_skipped', False):
|
||||
skipped_tracks.append(track_info)
|
||||
elif track.success:
|
||||
successful_tracks.append(track_info)
|
||||
else:
|
||||
track_info["reason"] = getattr(track, 'error_message', 'Unknown reason')
|
||||
failed_tracks.append(track_info)
|
||||
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="album",
|
||||
artist=derived_album_artist_from_contributors,
|
||||
status="done",
|
||||
total_tracks=total_tracks,
|
||||
title=album_name,
|
||||
url=album_link_for_report, # Use the actual album link
|
||||
summary={
|
||||
"successful_tracks": [f"{t['name']} - {t['artist']}" for t in successful_tracks],
|
||||
"skipped_tracks": [f"{t['name']} - {t['artist']}" for t in skipped_tracks],
|
||||
"failed_tracks": [{
|
||||
"track": f"{t['name']} - {t['artist']}",
|
||||
"reason": t['reason']
|
||||
} for t in failed_tracks],
|
||||
"total_successful": len(successful_tracks),
|
||||
"total_skipped": len(skipped_tracks),
|
||||
"total_failed": len(failed_tracks)
|
||||
}
|
||||
)
|
||||
|
||||
return album
|
||||
|
||||
@@ -1215,14 +1302,15 @@ class DW_PLAYLIST:
|
||||
total_tracks = self.__json_data.get('nb_tracks', 0)
|
||||
|
||||
# Report playlist initializing status
|
||||
Download_JOB.report_progress({
|
||||
"type": "playlist",
|
||||
"owner": playlist_owner,
|
||||
"status": "initializing",
|
||||
"total_tracks": total_tracks,
|
||||
"name": playlist_name,
|
||||
"url": f"https://deezer.com/playlist/{self.__ids}"
|
||||
})
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="playlist",
|
||||
owner=playlist_owner,
|
||||
status="initializing",
|
||||
total_tracks=total_tracks,
|
||||
name=playlist_name,
|
||||
url=f"https://deezer.com/playlist/{self.__ids}"
|
||||
)
|
||||
|
||||
# Retrieve playlist data from API
|
||||
infos_dw = API_GW.get_playlist_data(self.__ids)['data']
|
||||
@@ -1378,14 +1466,44 @@ class DW_PLAYLIST:
|
||||
playlist_owner = self.__json_data.get('creator', {}).get('name', 'Unknown Owner')
|
||||
total_tracks = self.__json_data.get('nb_tracks', 0)
|
||||
|
||||
Download_JOB.report_progress({
|
||||
"type": "playlist",
|
||||
"owner": playlist_owner,
|
||||
"status": "done",
|
||||
"total_tracks": total_tracks,
|
||||
"name": playlist_name,
|
||||
"url": f"https://deezer.com/playlist/{self.__ids}"
|
||||
})
|
||||
successful_tracks = []
|
||||
failed_tracks = []
|
||||
skipped_tracks = []
|
||||
for track in tracks:
|
||||
track_name = track.tags.get('music') or track.tags.get('name', 'Unknown Track')
|
||||
artist_name = track.tags.get('artist', 'Unknown Artist')
|
||||
track_info = {
|
||||
"name": track_name,
|
||||
"artist": artist_name
|
||||
}
|
||||
if getattr(track, 'was_skipped', False):
|
||||
skipped_tracks.append(track_info)
|
||||
elif track.success:
|
||||
successful_tracks.append(track_info)
|
||||
else:
|
||||
track_info["reason"] = getattr(track, 'error_message', 'Unknown reason')
|
||||
failed_tracks.append(track_info)
|
||||
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="playlist",
|
||||
owner=playlist_owner,
|
||||
status="done",
|
||||
total_tracks=total_tracks,
|
||||
name=playlist_name,
|
||||
url=f"https://deezer.com/playlist/{self.__ids}",
|
||||
summary={
|
||||
"successful_tracks": [f"{t['name']} - {t['artist']}" for t in successful_tracks],
|
||||
"skipped_tracks": [f"{t['name']} - {t['artist']}" for t in skipped_tracks],
|
||||
"failed_tracks": [{
|
||||
"track": f"{t['name']} - {t['artist']}",
|
||||
"reason": t['reason']
|
||||
} for t in failed_tracks],
|
||||
"total_successful": len(successful_tracks),
|
||||
"total_skipped": len(skipped_tracks),
|
||||
"total_failed": len(failed_tracks)
|
||||
}
|
||||
)
|
||||
|
||||
return playlist
|
||||
|
||||
@@ -1435,19 +1553,20 @@ class DW_EPISODE:
|
||||
total_size = int(response.headers.get('content-length', 0))
|
||||
|
||||
# Send initial progress status
|
||||
progress_data = {
|
||||
"type": "episode",
|
||||
"song": self.__preferences.song_metadata.get('name', ''),
|
||||
"artist": self.__preferences.song_metadata.get('publisher', ''),
|
||||
"status": "progress",
|
||||
"url": f"https://www.deezer.com/episode/{self.__ids}",
|
||||
"parent": {
|
||||
"type": "show",
|
||||
"title": self.__preferences.song_metadata.get('show', ''),
|
||||
"artist": self.__preferences.song_metadata.get('publisher', '')
|
||||
}
|
||||
parent = {
|
||||
"type": "show",
|
||||
"title": self.__preferences.song_metadata.get('artist', ''),
|
||||
"artist": self.__preferences.song_metadata.get('artist', '')
|
||||
}
|
||||
Download_JOB.report_progress(progress_data)
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="episode",
|
||||
song=self.__preferences.song_metadata.get('music', ''),
|
||||
artist=self.__preferences.song_metadata.get('artist', ''),
|
||||
status="progress",
|
||||
url=f"https://www.deezer.com/episode/{self.__ids}",
|
||||
parent=parent
|
||||
)
|
||||
|
||||
with open(output_path, 'wb') as f:
|
||||
start_time = time.time()
|
||||
@@ -1464,21 +1583,22 @@ class DW_EPISODE:
|
||||
last_report_time = current_time
|
||||
percentage = round((downloaded / total_size) * 100, 2)
|
||||
|
||||
progress_data = {
|
||||
"type": "episode",
|
||||
"song": self.__preferences.song_metadata.get('name', ''),
|
||||
"artist": self.__preferences.song_metadata.get('publisher', ''),
|
||||
"status": "real-time",
|
||||
"url": f"https://www.deezer.com/episode/{self.__ids}",
|
||||
"time_elapsed": int((current_time - start_time) * 1000),
|
||||
"progress": percentage,
|
||||
"parent": {
|
||||
"type": "show",
|
||||
"title": self.__preferences.song_metadata.get('show', ''),
|
||||
"artist": self.__preferences.song_metadata.get('publisher', '')
|
||||
}
|
||||
parent = {
|
||||
"type": "show",
|
||||
"title": self.__preferences.song_metadata.get('artist', ''),
|
||||
"artist": self.__preferences.song_metadata.get('artist', '')
|
||||
}
|
||||
Download_JOB.report_progress(progress_data)
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="episode",
|
||||
song=self.__preferences.song_metadata.get('music', ''),
|
||||
artist=self.__preferences.song_metadata.get('artist', ''),
|
||||
status="real-time",
|
||||
url=f"https://www.deezer.com/episode/{self.__ids}",
|
||||
time_elapsed=int((current_time - start_time) * 1000),
|
||||
progress=percentage,
|
||||
parent=parent
|
||||
)
|
||||
|
||||
episode = Track(
|
||||
self.__preferences.song_metadata,
|
||||
@@ -1491,19 +1611,20 @@ class DW_EPISODE:
|
||||
episode.success = True
|
||||
|
||||
# Send completion status
|
||||
progress_data = {
|
||||
"type": "episode",
|
||||
"song": self.__preferences.song_metadata.get('name', ''),
|
||||
"artist": self.__preferences.song_metadata.get('publisher', ''),
|
||||
"status": "done",
|
||||
"url": f"https://www.deezer.com/episode/{self.__ids}",
|
||||
"parent": {
|
||||
"type": "show",
|
||||
"title": self.__preferences.song_metadata.get('show', ''),
|
||||
"artist": self.__preferences.song_metadata.get('publisher', '')
|
||||
}
|
||||
parent = {
|
||||
"type": "show",
|
||||
"title": self.__preferences.song_metadata.get('artist', ''),
|
||||
"artist": self.__preferences.song_metadata.get('artist', '')
|
||||
}
|
||||
Download_JOB.report_progress(progress_data)
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="episode",
|
||||
song=self.__preferences.song_metadata.get('music', ''),
|
||||
artist=self.__preferences.song_metadata.get('artist', ''),
|
||||
status="done",
|
||||
url=f"https://www.deezer.com/episode/{self.__ids}",
|
||||
parent=parent
|
||||
)
|
||||
|
||||
# Save cover image for the episode
|
||||
if self.__preferences.save_cover:
|
||||
|
||||
@@ -43,7 +43,7 @@ from deezspot.libutils.others_settings import (
|
||||
stock_save_cover,
|
||||
stock_market
|
||||
)
|
||||
from deezspot.libutils.logging_utils import ProgressReporter, logger
|
||||
from deezspot.libutils.logging_utils import ProgressReporter, logger, report_progress
|
||||
import requests
|
||||
|
||||
API()
|
||||
@@ -89,10 +89,6 @@ class DeeLogin:
|
||||
# Set the progress reporter for Download_JOB
|
||||
Download_JOB.set_progress_reporter(self.progress_reporter)
|
||||
|
||||
def report_progress(self, progress_data):
|
||||
"""Report progress using the configured reporter."""
|
||||
self.progress_reporter.report(progress_data)
|
||||
|
||||
def download_trackdee(
|
||||
self, link_track,
|
||||
output_dir=stock_output,
|
||||
@@ -125,6 +121,20 @@ class DeeLogin:
|
||||
song_metadata = API.tracking(ids, market=market)
|
||||
except MarketAvailabilityError as e:
|
||||
logger.error(f"Track {ids} is not available in market(s) '{market_str}'. Error: {e.message}")
|
||||
summary = {
|
||||
"successful_tracks": [], "skipped_tracks": [], "total_successful": 0, "total_skipped": 0, "total_failed": 1,
|
||||
"failed_tracks": [{"track": f"Track ID {ids}", "reason": str(e)}]
|
||||
}
|
||||
report_progress(
|
||||
reporter=self.progress_reporter,
|
||||
report_type="track",
|
||||
status="error",
|
||||
song="Unknown Track",
|
||||
artist="Unknown Artist",
|
||||
url=link_track,
|
||||
error=str(e),
|
||||
summary=summary
|
||||
)
|
||||
raise TrackNotFound(url=link_track, message=e.message) from e
|
||||
except NoDataApi:
|
||||
infos = self.__gw_api.get_song_data(ids)
|
||||
@@ -161,9 +171,28 @@ class DeeLogin:
|
||||
preferences.save_cover = save_cover
|
||||
preferences.market = market
|
||||
|
||||
track = DW_TRACK(preferences).dw()
|
||||
|
||||
return track
|
||||
try:
|
||||
track = DW_TRACK(preferences).dw()
|
||||
return track
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to download track: {str(e)}")
|
||||
if song_metadata:
|
||||
track_info = {"name": song_metadata.get("music", "Unknown Track"), "artist": song_metadata.get("artist", "Unknown Artist")}
|
||||
summary = {
|
||||
"successful_tracks": [], "skipped_tracks": [], "total_successful": 0, "total_skipped": 0, "total_failed": 1,
|
||||
"failed_tracks": [{"track": f"{track_info['name']} - {track_info['artist']}", "reason": str(e)}]
|
||||
}
|
||||
report_progress(
|
||||
reporter=self.progress_reporter,
|
||||
report_type="track",
|
||||
status="error",
|
||||
song=track_info['name'],
|
||||
artist=track_info['artist'],
|
||||
url=link_track,
|
||||
error=str(e),
|
||||
summary=summary
|
||||
)
|
||||
raise e
|
||||
|
||||
def download_albumdee(
|
||||
self, link_album,
|
||||
@@ -695,29 +724,26 @@ class DeeLogin:
|
||||
# Use stored credentials for API calls
|
||||
playlist_json = Spo.get_playlist(ids)
|
||||
playlist_name = playlist_json['name']
|
||||
playlist_owner = playlist_json.get('owner', {}).get('display_name', 'Unknown Owner')
|
||||
total_tracks = playlist_json['tracks']['total']
|
||||
playlist_tracks = playlist_json['tracks']['items']
|
||||
playlist = Playlist()
|
||||
tracks = playlist.tracks
|
||||
|
||||
# Initializing status - replaced print with report_progress
|
||||
self.report_progress({
|
||||
"status": "initializing",
|
||||
"type": "playlist",
|
||||
"name": playlist_name,
|
||||
"total_tracks": total_tracks
|
||||
})
|
||||
report_progress(
|
||||
reporter=self.progress_reporter,
|
||||
report_type="playlist",
|
||||
status="initializing",
|
||||
name=playlist_name,
|
||||
owner=playlist_owner,
|
||||
total_tracks=total_tracks,
|
||||
url=link_playlist
|
||||
)
|
||||
|
||||
for index, item in enumerate(playlist_tracks, 1):
|
||||
is_track = item.get('track')
|
||||
if not is_track:
|
||||
# Progress status for an invalid track item
|
||||
self.report_progress({
|
||||
"status": "progress",
|
||||
"type": "playlist",
|
||||
"track": "Unknown Track",
|
||||
"current_track": f"{index}/{total_tracks}"
|
||||
})
|
||||
continue
|
||||
|
||||
track_info = is_track
|
||||
@@ -727,24 +753,9 @@ class DeeLogin:
|
||||
|
||||
external_urls = track_info.get('external_urls', {})
|
||||
if not external_urls:
|
||||
# Progress status for unavailable track
|
||||
self.report_progress({
|
||||
"status": "progress",
|
||||
"type": "playlist",
|
||||
"track": track_name,
|
||||
"current_track": f"{index}/{total_tracks}"
|
||||
})
|
||||
logger.warning(f"The track \"{track_name}\" is not available on Spotify :(")
|
||||
continue
|
||||
|
||||
# Progress status before download attempt
|
||||
self.report_progress({
|
||||
"status": "progress",
|
||||
"type": "playlist",
|
||||
"track": track_name,
|
||||
"current_track": f"{index}/{total_tracks}"
|
||||
})
|
||||
|
||||
link_track = external_urls['spotify']
|
||||
|
||||
try:
|
||||
@@ -773,12 +784,49 @@ class DeeLogin:
|
||||
tracks.append(f"{track_name} - {artist_name}")
|
||||
|
||||
# Done status
|
||||
self.report_progress({
|
||||
"status": "done",
|
||||
"type": "playlist",
|
||||
"name": playlist_name,
|
||||
"total_tracks": total_tracks
|
||||
})
|
||||
successful_tracks_list = []
|
||||
failed_tracks_list = []
|
||||
skipped_tracks_list = []
|
||||
for track in tracks:
|
||||
if isinstance(track, Track):
|
||||
track_info = {
|
||||
"name": track.tags.get('music', 'Unknown Track'),
|
||||
"artist": track.tags.get('artist', 'Unknown Artist')
|
||||
}
|
||||
if getattr(track, 'was_skipped', False):
|
||||
skipped_tracks_list.append(f"{track_info['name']} - {track_info['artist']}")
|
||||
elif track.success:
|
||||
successful_tracks_list.append(f"{track_info['name']} - {track_info['artist']}")
|
||||
else:
|
||||
failed_tracks_list.append({
|
||||
"track": f"{track_info['name']} - {track_info['artist']}",
|
||||
"reason": getattr(track, 'error_message', 'Unknown reason')
|
||||
})
|
||||
elif isinstance(track, str): # It can be a string for failed tracks
|
||||
failed_tracks_list.append({
|
||||
"track": track,
|
||||
"reason": "Failed to download or convert."
|
||||
})
|
||||
|
||||
summary = {
|
||||
"successful_tracks": successful_tracks_list,
|
||||
"skipped_tracks": skipped_tracks_list,
|
||||
"failed_tracks": failed_tracks_list,
|
||||
"total_successful": len(successful_tracks_list),
|
||||
"total_skipped": len(skipped_tracks_list),
|
||||
"total_failed": len(failed_tracks_list),
|
||||
}
|
||||
|
||||
report_progress(
|
||||
reporter=self.progress_reporter,
|
||||
report_type="playlist",
|
||||
status="done",
|
||||
name=playlist_name,
|
||||
owner=playlist_owner,
|
||||
total_tracks=total_tracks,
|
||||
url=link_playlist,
|
||||
summary=summary
|
||||
)
|
||||
|
||||
# === New m3u File Creation Section ===
|
||||
# Create a subfolder "playlists" inside the output directory
|
||||
@@ -974,7 +1022,7 @@ class DeeLogin:
|
||||
smart.source = source
|
||||
|
||||
# Add progress reporting for the smart downloader
|
||||
self.report_progress({
|
||||
self.progress_reporter.report({
|
||||
"status": "initializing",
|
||||
"type": "smart_download",
|
||||
"link": link,
|
||||
@@ -1071,7 +1119,7 @@ class DeeLogin:
|
||||
smart.playlist = playlist
|
||||
|
||||
# Report completion
|
||||
self.report_progress({
|
||||
self.progress_reporter.report({
|
||||
"status": "done",
|
||||
"type": "smart_download",
|
||||
"source": source,
|
||||
|
||||
@@ -66,4 +66,148 @@ class ProgressReporter:
|
||||
self.callback(progress_data)
|
||||
elif not self.silent:
|
||||
# Log using JSON format
|
||||
logger.log(self.log_level, json.dumps(progress_data))
|
||||
logger.log(self.log_level, json.dumps(progress_data))
|
||||
|
||||
# --- Standardized Progress Report Format ---
|
||||
# The report_progress function generates a standardized dictionary (JSON object)
|
||||
# to provide detailed feedback about the download process.
|
||||
#
|
||||
# Base Structure:
|
||||
# {
|
||||
# "type": "track" | "album" | "playlist" | "episode",
|
||||
# "status": "initializing" | "skipped" | "retrying" | "real-time" | "error" | "done"
|
||||
# ... other fields based on type and status
|
||||
# }
|
||||
#
|
||||
# --- Field Definitions ---
|
||||
#
|
||||
# [ General Fields ]
|
||||
# - url: (str) The URL of the item being processed.
|
||||
# - convert_to: (str) Target audio format for conversion (e.g., "mp3").
|
||||
# - bitrate: (str) Target bitrate for conversion (e.g., "320").
|
||||
#
|
||||
# [ Type: "track" ]
|
||||
# - song: (str) The name of the track.
|
||||
# - artist: (str) The artist of the track.
|
||||
# - album: (str, optional) The album of the track.
|
||||
# - parent: (dict, optional) Information about the container (album/playlist).
|
||||
# { "type": "album"|"playlist", "name": str, "owner": str, "artist": str, ... }
|
||||
# - current_track: (int, optional) The track number in the context of a parent.
|
||||
# - total_tracks: (int, optional) The total tracks in the context of a parent.
|
||||
#
|
||||
# [ Status: "skipped" ]
|
||||
# - reason: (str) The reason for skipping (e.g., "Track already exists...").
|
||||
#
|
||||
# [ Status: "retrying" ]
|
||||
# - retry_count: (int) The current retry attempt number.
|
||||
# - seconds_left: (int) The time in seconds until the next retry attempt.
|
||||
# - error: (str) The error message that caused the retry.
|
||||
#
|
||||
# [ Status: "real-time" ]
|
||||
# - time_elapsed: (int) Time in milliseconds since the download started.
|
||||
# - progress: (int) Download percentage (0-100).
|
||||
#
|
||||
# [ Status: "error" ]
|
||||
# - error: (str) The detailed error message.
|
||||
#
|
||||
# [ Status: "done" (for single track downloads) ]
|
||||
# - summary: (dict) A summary of the operation.
|
||||
#
|
||||
# [ Type: "album" | "playlist" ]
|
||||
# - title / name: (str) The title of the album or name of the playlist.
|
||||
# - artist / owner: (str) The artist of the album or owner of the playlist.
|
||||
# - total_tracks: (int) The total number of tracks.
|
||||
#
|
||||
# [ Status: "done" ]
|
||||
# - summary: (dict) A detailed summary of the entire download operation.
|
||||
# {
|
||||
# "successful_tracks": [str],
|
||||
# "skipped_tracks": [str],
|
||||
# "failed_tracks": [{"track": str, "reason": str}],
|
||||
# "total_successful": int,
|
||||
# "total_skipped": int,
|
||||
# "total_failed": int
|
||||
# }
|
||||
#
|
||||
|
||||
def report_progress(
|
||||
reporter: Optional["ProgressReporter"],
|
||||
report_type: str,
|
||||
status: str,
|
||||
song: Optional[str] = None,
|
||||
artist: Optional[str] = None,
|
||||
album: Optional[str] = None,
|
||||
url: Optional[str] = None,
|
||||
convert_to: Optional[str] = None,
|
||||
bitrate: Optional[str] = None,
|
||||
parent: Optional[Dict[str, Any]] = None,
|
||||
current_track: Optional[int] = None,
|
||||
total_tracks: Optional[Union[int, str]] = None,
|
||||
reason: Optional[str] = None,
|
||||
summary: Optional[Dict[str, Any]] = None,
|
||||
error: Optional[str] = None,
|
||||
retry_count: Optional[int] = None,
|
||||
seconds_left: Optional[int] = None,
|
||||
time_elapsed: Optional[int] = None,
|
||||
progress: Optional[int] = None,
|
||||
owner: Optional[str] = None,
|
||||
name: Optional[str] = None,
|
||||
title: Optional[str] = None,
|
||||
):
|
||||
"""Builds and reports a standardized progress dictionary after validating the input."""
|
||||
|
||||
# --- Input Validation ---
|
||||
# Enforce the standardized format to ensure consistent reporting.
|
||||
if report_type == "track":
|
||||
if not all([song, artist]):
|
||||
raise ValueError("For report_type 'track', 'song' and 'artist' parameters are required.")
|
||||
if status == "skipped" and reason is None:
|
||||
raise ValueError("For a 'skipped' track, a 'reason' is required.")
|
||||
if status == "retrying" and not all(p is not None for p in [retry_count, seconds_left, error]):
|
||||
raise ValueError("For a 'retrying' track, 'retry_count', 'seconds_left', and 'error' are required.")
|
||||
if status == "real-time" and not all(p is not None for p in [time_elapsed, progress]):
|
||||
raise ValueError("For a 'real-time' track, 'time_elapsed' and 'progress' are required.")
|
||||
if status == "error" and error is None:
|
||||
raise ValueError("For an 'error' track, an 'error' message is required.")
|
||||
|
||||
elif report_type == "album":
|
||||
if not all(p is not None for p in [title, artist, total_tracks]):
|
||||
raise ValueError("For report_type 'album', 'title', 'artist', and 'total_tracks' are required.")
|
||||
if status == "done" and summary is None:
|
||||
raise ValueError("For an 'album' with status 'done', a 'summary' is required.")
|
||||
|
||||
elif report_type == "playlist":
|
||||
if not all(p is not None for p in [name, owner, total_tracks]):
|
||||
raise ValueError("For report_type 'playlist', 'name', 'owner', and 'total_tracks' are required.")
|
||||
if status == "done" and summary is None:
|
||||
raise ValueError("For a 'playlist' with status 'done', a 'summary' is required.")
|
||||
|
||||
elif report_type == "episode":
|
||||
if not all([song, artist]): # song=episode_title, artist=show_name
|
||||
raise ValueError("For report_type 'episode', 'song' and 'artist' parameters are required.")
|
||||
if status == "retrying" and not all(p is not None for p in [retry_count, seconds_left, error]):
|
||||
raise ValueError("For a 'retrying' episode, 'retry_count', 'seconds_left', and 'error' are required.")
|
||||
if status == "error" and error is None:
|
||||
raise ValueError("For an 'error' episode, an 'error' message is required.")
|
||||
|
||||
# --- Report Building ---
|
||||
report = {"type": report_type, "status": status}
|
||||
|
||||
data_fields = {
|
||||
"song": song, "artist": artist, "album": album, "url": url,
|
||||
"convert_to": convert_to, "bitrate": bitrate, "parent": parent,
|
||||
"current_track": current_track, "total_tracks": total_tracks,
|
||||
"reason": reason, "summary": summary, "error": error,
|
||||
"retry_count": retry_count, "seconds_left": seconds_left,
|
||||
"time_elapsed": time_elapsed, "progress": progress,
|
||||
"owner": owner, "name": name, "title": title
|
||||
}
|
||||
|
||||
for key, value in data_fields.items():
|
||||
if value is not None:
|
||||
report[key] = value
|
||||
|
||||
if reporter:
|
||||
reporter.report(report)
|
||||
else:
|
||||
logger.info(json.dumps(report))
|
||||
@@ -163,6 +163,13 @@ def apply_custom_format(format_str, metadata: dict, pad_tracks=True) -> str:
|
||||
else:
|
||||
# Original non-indexed placeholder logic (for %album%, %title%, %artist%, %ar_album%, etc.)
|
||||
value = metadata.get(full_key, '')
|
||||
|
||||
if full_key == 'year' and value:
|
||||
if isinstance(value, datetime):
|
||||
return str(value.year)
|
||||
# Fallback for string-based dates like "YYYY-MM-DD" or just "YYYY"
|
||||
return str(value).split('-')[0]
|
||||
|
||||
if pad_tracks and full_key in ['tracknum', 'discnum']:
|
||||
str_value = str(value)
|
||||
# Pad with leading zero if it's a single digit
|
||||
|
||||
@@ -32,7 +32,7 @@ from deezspot.libutils.utils import (
|
||||
save_cover_image,
|
||||
__get_dir as get_album_directory,
|
||||
)
|
||||
from deezspot.libutils.logging_utils import logger
|
||||
from deezspot.libutils.logging_utils import logger, report_progress
|
||||
from deezspot.libutils.cleanup_utils import (
|
||||
register_active_download,
|
||||
unregister_active_download,
|
||||
@@ -57,15 +57,6 @@ class Download_JOB:
|
||||
@classmethod
|
||||
def set_progress_reporter(cls, reporter):
|
||||
cls.progress_reporter = reporter
|
||||
|
||||
@classmethod
|
||||
def report_progress(cls, progress_data):
|
||||
"""Report progress if a reporter is configured."""
|
||||
if cls.progress_reporter:
|
||||
cls.progress_reporter.report(progress_data)
|
||||
else:
|
||||
# Fallback to logger if no reporter is configured
|
||||
logger.info(json.dumps(progress_data))
|
||||
|
||||
class EASY_DW:
|
||||
def __init__(
|
||||
@@ -336,47 +327,50 @@ class EASY_DW:
|
||||
self.__c_track.success = True # Mark as success because the desired file is available
|
||||
self.__c_track.was_skipped = True
|
||||
|
||||
progress_data = {
|
||||
"type": "track",
|
||||
"song": current_title,
|
||||
"artist": current_artist,
|
||||
"status": "skipped",
|
||||
"url": self.__link,
|
||||
"reason": f"Track already exists in desired format at {existing_file_path}",
|
||||
"convert_to": self.__preferences.convert_to, # Reflect user's conversion preference
|
||||
"bitrate": self.__preferences.bitrate # Reflect user's bitrate preference
|
||||
}
|
||||
|
||||
parent_info = None
|
||||
playlist_data = None
|
||||
total_tracks_val = None
|
||||
|
||||
if self.__parent == "playlist" and hasattr(self.__preferences, "json_data"):
|
||||
playlist_data = self.__preferences.json_data
|
||||
playlist_name = playlist_data.get('name', 'unknown')
|
||||
total_tracks = playlist_data.get('tracks', {}).get('total', 'unknown')
|
||||
current_track_num = getattr(self.__preferences, 'track_number', 0)
|
||||
progress_data.update({
|
||||
"current_track": current_track_num,
|
||||
"total_tracks": total_tracks,
|
||||
"parent": {
|
||||
"type": "playlist",
|
||||
"name": playlist_name,
|
||||
"owner": playlist_data.get('owner', {}).get('display_name', 'unknown')
|
||||
}
|
||||
})
|
||||
total_tracks_val = playlist_data.get('tracks', {}).get('total', 'unknown')
|
||||
parent_info = {
|
||||
"type": "playlist",
|
||||
"name": playlist_data.get('name', 'unknown'),
|
||||
"owner": playlist_data.get('owner', {}).get('display_name', 'unknown')
|
||||
}
|
||||
elif self.__parent == "album":
|
||||
album_name_meta = self.__song_metadata.get('album', '')
|
||||
album_artist_meta = self.__song_metadata.get('album_artist', self.__song_metadata.get('ar_album', ''))
|
||||
total_tracks_meta = self.__song_metadata.get('nb_tracks', 0)
|
||||
current_track_num = getattr(self.__preferences, 'track_number', 0)
|
||||
progress_data.update({
|
||||
"current_track": current_track_num,
|
||||
"total_tracks": total_tracks_meta,
|
||||
"parent": {
|
||||
"type": "album",
|
||||
"title": album_name_meta,
|
||||
"artist": album_artist_meta
|
||||
}
|
||||
})
|
||||
|
||||
Download_JOB.report_progress(progress_data)
|
||||
total_tracks_val = self.__song_metadata.get('nb_tracks', 0)
|
||||
parent_info = {
|
||||
"type": "album",
|
||||
"title": self.__song_metadata.get('album', ''),
|
||||
"artist": self.__song_metadata.get('album_artist', self.__song_metadata.get('ar_album', ''))
|
||||
}
|
||||
|
||||
summary_data = {
|
||||
"successful_tracks": [],
|
||||
"skipped_tracks": [f"{current_title} - {current_artist}"],
|
||||
"failed_tracks": [],
|
||||
"total_successful": 0,
|
||||
"total_skipped": 1,
|
||||
"total_failed": 0,
|
||||
} if self.__parent is None else None
|
||||
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="track",
|
||||
status="skipped",
|
||||
song=current_title,
|
||||
artist=current_artist,
|
||||
url=self.__link,
|
||||
reason=f"Track already exists in desired format at {existing_file_path}",
|
||||
convert_to=self.__preferences.convert_to,
|
||||
bitrate=self.__preferences.bitrate,
|
||||
current_track=getattr(self.__preferences, 'track_number', None),
|
||||
total_tracks=total_tracks_val,
|
||||
parent=parent_info,
|
||||
summary=summary_data
|
||||
)
|
||||
return self.__c_track
|
||||
|
||||
# If track does not exist in the desired final format, proceed with download/conversion
|
||||
@@ -432,59 +426,44 @@ class EASY_DW:
|
||||
if current_percentage > self._last_reported_percentage:
|
||||
self._last_reported_percentage = current_percentage
|
||||
|
||||
# Create real-time progress data
|
||||
progress_data = {
|
||||
"type": "track",
|
||||
"song": self.__song_metadata.get("music", ""),
|
||||
"artist": self.__song_metadata.get("artist", ""),
|
||||
"status": "real-time",
|
||||
"url": self.__link,
|
||||
"time_elapsed": int((current_time - start_time) * 1000),
|
||||
"progress": current_percentage,
|
||||
"convert_to": self.__convert_to,
|
||||
"bitrate": self.__bitrate
|
||||
}
|
||||
|
||||
# Add parent info based on parent type
|
||||
parent_info = None
|
||||
playlist_data = None
|
||||
total_tracks_val = None
|
||||
if self.__parent == "playlist" and hasattr(self.__preferences, "json_data"):
|
||||
playlist_data = self.__preferences.json_data
|
||||
playlist_name = playlist_data.get('name', 'unknown')
|
||||
total_tracks = playlist_data.get('tracks', {}).get('total', 'unknown')
|
||||
current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
playlist_owner = playlist_data.get('owner', {}).get('display_name', 'unknown')
|
||||
playlist_id = playlist_data.get('id', '')
|
||||
|
||||
progress_data.update({
|
||||
"current_track": current_track,
|
||||
"total_tracks": total_tracks,
|
||||
"parent": {
|
||||
"type": "playlist",
|
||||
"name": playlist_name,
|
||||
"owner": playlist_owner,
|
||||
"total_tracks": total_tracks,
|
||||
"url": f"https://open.spotify.com/playlist/{playlist_id}"
|
||||
}
|
||||
})
|
||||
total_tracks_val = playlist_data.get('tracks', {}).get('total', 'unknown')
|
||||
parent_info = {
|
||||
"type": "playlist",
|
||||
"name": playlist_data.get('name', 'unknown'),
|
||||
"owner": playlist_data.get('owner', {}).get('display_name', 'unknown'),
|
||||
"total_tracks": total_tracks_val,
|
||||
"url": f"https://open.spotify.com/playlist/{playlist_data.get('id', '')}"
|
||||
}
|
||||
elif self.__parent == "album":
|
||||
album_name = self.__song_metadata.get('album', '')
|
||||
album_artist = self.__song_metadata.get('album_artist', self.__song_metadata.get('ar_album', ''))
|
||||
total_tracks = self.__song_metadata.get('nb_tracks', 0)
|
||||
current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
|
||||
progress_data.update({
|
||||
"current_track": current_track,
|
||||
"total_tracks": total_tracks,
|
||||
"parent": {
|
||||
"type": "album",
|
||||
"title": album_name,
|
||||
"artist": album_artist,
|
||||
"total_tracks": total_tracks,
|
||||
"url": f"https://open.spotify.com/album/{self.__song_metadata.get('album_id', '')}"
|
||||
}
|
||||
})
|
||||
|
||||
# Report the progress
|
||||
Download_JOB.report_progress(progress_data)
|
||||
total_tracks_val = self.__song_metadata.get('nb_tracks', 0)
|
||||
parent_info = {
|
||||
"type": "album",
|
||||
"title": self.__song_metadata.get('album', ''),
|
||||
"artist": self.__song_metadata.get('album_artist', self.__song_metadata.get('ar_album', '')),
|
||||
"total_tracks": total_tracks_val,
|
||||
"url": f"https://open.spotify.com/album/{self.__song_metadata.get('album_id', '')}"
|
||||
}
|
||||
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="track",
|
||||
status="real-time",
|
||||
song=self.__song_metadata.get("music", ""),
|
||||
artist=self.__song_metadata.get("artist", ""),
|
||||
url=self.__link,
|
||||
time_elapsed=int((current_time - start_time) * 1000),
|
||||
progress=current_percentage,
|
||||
convert_to=self.__convert_to,
|
||||
bitrate=self.__bitrate,
|
||||
current_track=getattr(self.__preferences, 'track_number', None),
|
||||
total_tracks=total_tracks_val,
|
||||
parent=parent_info
|
||||
)
|
||||
|
||||
# Rate limiting (if needed)
|
||||
expected_time = bytes_written / rate_limit
|
||||
@@ -591,7 +570,24 @@ class EASY_DW:
|
||||
}
|
||||
})
|
||||
|
||||
Download_JOB.report_progress(progress_data)
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="track",
|
||||
status="retrying",
|
||||
retry_count=retries,
|
||||
seconds_left=retry_delay,
|
||||
song=self.__song_metadata.get('music', ''),
|
||||
artist=self.__song_metadata.get('artist', ''),
|
||||
album=self.__song_metadata.get('album', ''),
|
||||
error=str(e),
|
||||
url=self.__link,
|
||||
convert_to=self.__convert_to,
|
||||
bitrate=self.__bitrate,
|
||||
current_track=getattr(self.__preferences, 'track_number', None),
|
||||
total_tracks=total_tracks_val,
|
||||
parent=parent_info
|
||||
)
|
||||
|
||||
if retries >= max_retries or GLOBAL_RETRY_COUNT >= GLOBAL_MAX_RETRIES:
|
||||
# Final cleanup before giving up
|
||||
if os.path.exists(self.__song_path):
|
||||
@@ -630,59 +626,43 @@ class EASY_DW:
|
||||
else:
|
||||
error_msg = f"Audio conversion failed: {original_error_str}"
|
||||
|
||||
# Create standardized error format
|
||||
progress_data = {
|
||||
"type": "track",
|
||||
"status": "error",
|
||||
"song": self.__song_metadata.get('music', ''),
|
||||
"artist": self.__song_metadata.get('artist', ''),
|
||||
"error": error_msg,
|
||||
"url": self.__link,
|
||||
"convert_to": self.__convert_to,
|
||||
"bitrate": self.__bitrate
|
||||
}
|
||||
|
||||
# Add parent info based on parent type
|
||||
parent_info = None
|
||||
playlist_data = None
|
||||
total_tracks_val = None
|
||||
if self.__parent == "playlist" and hasattr(self.__preferences, "json_data"):
|
||||
playlist_data = self.__preferences.json_data
|
||||
playlist_name = playlist_data.get('name', 'unknown')
|
||||
total_tracks = playlist_data.get('tracks', {}).get('total', 'unknown')
|
||||
current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
playlist_owner = playlist_data.get('owner', {}).get('display_name', 'unknown')
|
||||
playlist_id = playlist_data.get('id', '')
|
||||
|
||||
progress_data.update({
|
||||
"current_track": current_track,
|
||||
"total_tracks": total_tracks,
|
||||
"parent": {
|
||||
"type": "playlist",
|
||||
"name": playlist_name,
|
||||
"owner": playlist_owner,
|
||||
"total_tracks": total_tracks,
|
||||
"url": f"https://open.spotify.com/playlist/{playlist_id}"
|
||||
}
|
||||
})
|
||||
total_tracks_val = playlist_data.get('tracks', {}).get('total', 'unknown')
|
||||
parent_info = {
|
||||
"type": "playlist",
|
||||
"name": playlist_data.get('name', 'unknown'),
|
||||
"owner": playlist_data.get('owner', {}).get('display_name', 'unknown'),
|
||||
"total_tracks": total_tracks_val,
|
||||
"url": f"https://open.spotify.com/playlist/{playlist_data.get('id', '')}"
|
||||
}
|
||||
elif self.__parent == "album":
|
||||
album_name = self.__song_metadata.get('album', '')
|
||||
album_artist = self.__song_metadata.get('album_artist', self.__song_metadata.get('ar_album', ''))
|
||||
total_tracks = self.__song_metadata.get('nb_tracks', 0)
|
||||
current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
album_id = self.__song_metadata.get('album_id', '')
|
||||
|
||||
progress_data.update({
|
||||
"current_track": current_track,
|
||||
"total_tracks": total_tracks,
|
||||
"parent": {
|
||||
"type": "album",
|
||||
"title": album_name,
|
||||
"artist": album_artist,
|
||||
"total_tracks": total_tracks,
|
||||
"url": f"https://open.spotify.com/album/{album_id}"
|
||||
}
|
||||
})
|
||||
total_tracks_val = self.__song_metadata.get('nb_tracks', 0)
|
||||
parent_info = {
|
||||
"type": "album",
|
||||
"title": self.__song_metadata.get('album', ''),
|
||||
"artist": self.__song_metadata.get('album_artist', self.__song_metadata.get('ar_album', '')),
|
||||
"total_tracks": total_tracks_val,
|
||||
"url": f"https://open.spotify.com/album/{self.__song_metadata.get('album_id', '')}"
|
||||
}
|
||||
|
||||
# Report the error
|
||||
Download_JOB.report_progress(progress_data)
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="track",
|
||||
status="error",
|
||||
song=self.__song_metadata.get('music', ''),
|
||||
artist=self.__song_metadata.get('artist', ''),
|
||||
error=error_msg,
|
||||
url=self.__link,
|
||||
convert_to=self.__convert_to,
|
||||
bitrate=self.__bitrate,
|
||||
current_track=getattr(self.__preferences, 'track_number', None),
|
||||
total_tracks=total_tracks_val,
|
||||
parent=parent_info
|
||||
)
|
||||
logger.error(f"Audio conversion error: {error_msg}")
|
||||
|
||||
# If conversion fails, clean up the .ogg file
|
||||
@@ -696,10 +676,21 @@ class EASY_DW:
|
||||
self.__convert_audio()
|
||||
except Exception as conv_e:
|
||||
# If conversion fails twice, create a final error report
|
||||
error_msg = f"Audio conversion failed after retry for '{self.__song_metadata.get('music', 'Unknown Track')}'. Original error: {str(conv_e)}"
|
||||
progress_data["error"] = error_msg
|
||||
progress_data["status"] = "error"
|
||||
Download_JOB.report_progress(progress_data)
|
||||
error_msg_2 = f"Audio conversion failed after retry for '{self.__song_metadata.get('music', 'Unknown Track')}'. Original error: {str(conv_e)}"
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="track",
|
||||
status="error",
|
||||
song=self.__song_metadata.get('music', 'Unknown Track'),
|
||||
artist=self.__song_metadata.get('artist', ''),
|
||||
error=error_msg_2,
|
||||
url=self.__link,
|
||||
convert_to=self.__convert_to,
|
||||
bitrate=self.__bitrate,
|
||||
parent=parent_info,
|
||||
current_track=getattr(self.__preferences, 'track_number', None),
|
||||
total_tracks=total_tracks_val
|
||||
)
|
||||
logger.error(error_msg)
|
||||
|
||||
if os.path.exists(self.__song_path):
|
||||
@@ -714,58 +705,63 @@ class EASY_DW:
|
||||
self.__c_track.success = True
|
||||
write_tags(self.__c_track)
|
||||
|
||||
# Create done status report using the same format as progress status
|
||||
progress_data = {
|
||||
"type": "track",
|
||||
"song": self.__song_metadata.get("music", ""),
|
||||
"artist": self.__song_metadata.get("artist", ""),
|
||||
"status": "done",
|
||||
"url": self.__link,
|
||||
"convert_to": self.__convert_to,
|
||||
"bitrate": self.__bitrate
|
||||
}
|
||||
|
||||
# Add parent info based on parent type
|
||||
# Create done status report
|
||||
song = self.__song_metadata.get("music", "")
|
||||
artist = self.__song_metadata.get("artist", "")
|
||||
parent_info = None
|
||||
total_tracks_val = None
|
||||
current_track_val = None
|
||||
summary_data = None
|
||||
|
||||
if self.__parent == "playlist" and hasattr(self.__preferences, "json_data"):
|
||||
playlist_data = self.__preferences.json_data
|
||||
playlist_name = playlist_data.get('name', 'unknown')
|
||||
total_tracks = playlist_data.get('tracks', {}).get('total', 'unknown')
|
||||
current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
|
||||
progress_data.update({
|
||||
"current_track": current_track,
|
||||
"total_tracks": total_tracks,
|
||||
"parent": {
|
||||
"type": "playlist",
|
||||
"name": playlist_name,
|
||||
"owner": playlist_data.get('owner', {}).get('display_name', 'unknown'),
|
||||
"total_tracks": total_tracks,
|
||||
"url": f"https://open.spotify.com/playlist/{playlist_data.get('id', '')}"
|
||||
}
|
||||
})
|
||||
total_tracks_val = playlist_data.get('tracks', {}).get('total', 'unknown')
|
||||
current_track_val = getattr(self.__preferences, 'track_number', 0)
|
||||
parent_info = {
|
||||
"type": "playlist",
|
||||
"name": playlist_data.get('name', 'unknown'),
|
||||
"owner": playlist_data.get('owner', {}).get('display_name', 'unknown'),
|
||||
"total_tracks": total_tracks_val,
|
||||
"url": f"https://open.spotify.com/playlist/{playlist_data.get('id', '')}"
|
||||
}
|
||||
elif self.__parent == "album":
|
||||
album_name = self.__song_metadata.get('album', '')
|
||||
album_artist = self.__song_metadata.get('album_artist', self.__song_metadata.get('ar_album', ''))
|
||||
total_tracks = self.__song_metadata.get('nb_tracks', 0)
|
||||
current_track = getattr(self.__preferences, 'track_number', 0)
|
||||
|
||||
progress_data.update({
|
||||
"current_track": current_track,
|
||||
"total_tracks": total_tracks,
|
||||
"parent": {
|
||||
"type": "album",
|
||||
"title": album_name,
|
||||
"artist": album_artist,
|
||||
"total_tracks": total_tracks,
|
||||
"url": f"https://open.spotify.com/album/{self.__song_metadata.get('album_id', '')}"
|
||||
}
|
||||
})
|
||||
|
||||
Download_JOB.report_progress(progress_data)
|
||||
total_tracks_val = self.__song_metadata.get('nb_tracks', 0)
|
||||
current_track_val = getattr(self.__preferences, 'track_number', 0)
|
||||
parent_info = {
|
||||
"type": "album",
|
||||
"title": self.__song_metadata.get('album', ''),
|
||||
"artist": self.__song_metadata.get('album_artist', self.__song_metadata.get('ar_album', '')),
|
||||
"total_tracks": total_tracks_val,
|
||||
"url": f"https://open.spotify.com/album/{self.__song_metadata.get('album_id', '')}"
|
||||
}
|
||||
|
||||
if self.__parent is None:
|
||||
summary_data = {
|
||||
"successful_tracks": [f"{song} - {artist}"],
|
||||
"skipped_tracks": [],
|
||||
"failed_tracks": [],
|
||||
"total_successful": 1,
|
||||
"total_skipped": 0,
|
||||
"total_failed": 0,
|
||||
}
|
||||
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="track",
|
||||
status="done",
|
||||
song=song,
|
||||
artist=artist,
|
||||
url=self.__link,
|
||||
convert_to=self.__convert_to,
|
||||
bitrate=self.__bitrate,
|
||||
parent=parent_info,
|
||||
current_track=current_track_val,
|
||||
total_tracks=total_tracks_val,
|
||||
summary=summary_data,
|
||||
)
|
||||
|
||||
if hasattr(self, '_EASY_DW__c_track') and self.__c_track and self.__c_track.success:
|
||||
# Unregister the final successful file path after all operations are done.
|
||||
# self.__c_track.song_path would have been updated by __convert_audio__ if conversion occurred.
|
||||
unregister_active_download(self.__c_track.song_path)
|
||||
|
||||
return self.__c_track
|
||||
@@ -806,21 +802,22 @@ class EASY_DW:
|
||||
GLOBAL_RETRY_COUNT += 1
|
||||
retries += 1
|
||||
# Log retry attempt with structured data
|
||||
print(json.dumps({
|
||||
"status": "retrying",
|
||||
"retry_count": retries,
|
||||
"seconds_left": retry_delay,
|
||||
"song": self.__song_metadata.get('music', 'Unknown Episode'),
|
||||
"artist": self.__song_metadata.get('artist', 'Unknown Show'),
|
||||
"album": self.__song_metadata.get('album', 'N/A'), # Episodes don't typically have albums
|
||||
"error": str(e),
|
||||
"convert_to": self.__convert_to,
|
||||
"bitrate": self.__bitrate
|
||||
}))
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="episode",
|
||||
status="retrying",
|
||||
retry_count=retries,
|
||||
seconds_left=retry_delay,
|
||||
song=self.__song_metadata.get('music', 'Unknown Episode'),
|
||||
artist=self.__song_metadata.get('artist', 'Unknown Show'),
|
||||
error=str(e),
|
||||
url=self.__link,
|
||||
convert_to=self.__convert_to,
|
||||
bitrate=self.__bitrate
|
||||
)
|
||||
if retries >= max_retries or GLOBAL_RETRY_COUNT >= GLOBAL_MAX_RETRIES:
|
||||
if os.path.exists(self.__song_path):
|
||||
os.remove(self.__song_path) # Clean up partial file
|
||||
unregister_active_download(self.__song_path) # Unregister it
|
||||
track_name = self.__song_metadata.get('music', 'Unknown Episode')
|
||||
artist_name = self.__song_metadata.get('artist', 'Unknown Show')
|
||||
final_error_msg = f"Maximum retry limit reached for '{track_name}' by '{artist_name}' (local: {max_retries}, global: {GLOBAL_MAX_RETRIES}). Last error: {str(e)}"
|
||||
@@ -941,23 +938,24 @@ class EASY_DW:
|
||||
# Conversion failed. __convert_audio or underlying convert_audio should have cleaned up its own temps.
|
||||
# The original downloaded file (if __convert_audio started from it) might still exist or be the self.__song_path.
|
||||
# Or self.__song_path might be a partially converted file if convert_audio failed mid-way and didn't cleanup perfectly.
|
||||
logger.error(json.dumps({
|
||||
"status": "error",
|
||||
"action": "convert_audio",
|
||||
"song": self.__song_metadata.get('music', 'Unknown Episode'),
|
||||
"artist": self.__song_metadata.get('artist', 'Unknown Show'),
|
||||
"album": self.__song_metadata.get('album', 'N/A'),
|
||||
"error": str(conv_e),
|
||||
"convert_to": self.__convert_to,
|
||||
"bitrate": self.__bitrate
|
||||
}))
|
||||
episode_title = self.__song_metadata.get('music', 'Unknown Episode')
|
||||
error_message = f"Audio conversion for episode '{episode_title}' failed. Original error: {str(conv_e)}"
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="episode",
|
||||
status="error",
|
||||
song=episode_title,
|
||||
artist=self.__song_metadata.get('artist', 'Unknown Show'),
|
||||
error=error_message,
|
||||
url=self.__link,
|
||||
convert_to=self.__convert_to,
|
||||
bitrate=self.__bitrate
|
||||
)
|
||||
# Attempt to remove self.__song_path, which is the latest known path for this episode
|
||||
if os.path.exists(self.__song_path):
|
||||
os.remove(self.__song_path)
|
||||
unregister_active_download(self.__song_path) # Unregister it as it failed/was removed
|
||||
|
||||
episode_title = self.__song_metadata.get('music', 'Unknown Episode')
|
||||
error_message = f"Audio conversion for episode '{episode_title}' failed. Original error: {str(conv_e)}"
|
||||
logger.error(error_message)
|
||||
if hasattr(self, '_EASY_DW__c_episode') and self.__c_episode:
|
||||
self.__c_episode.success = False
|
||||
@@ -1045,14 +1043,15 @@ class DW_ALBUM:
|
||||
total_tracks = self.__song_metadata.get('nb_tracks', 0)
|
||||
album_id = self.__ids
|
||||
|
||||
Download_JOB.report_progress({
|
||||
"type": "album",
|
||||
"artist": album_artist,
|
||||
"status": "initializing",
|
||||
"total_tracks": total_tracks,
|
||||
"title": album_name,
|
||||
"url": f"https://open.spotify.com/album/{album_id}"
|
||||
})
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="album",
|
||||
artist=album_artist,
|
||||
status="initializing",
|
||||
total_tracks=total_tracks,
|
||||
title=album_name,
|
||||
url=f"https://open.spotify.com/album/{album_id}",
|
||||
)
|
||||
|
||||
pic_url = self.__song_metadata['image'] # This is URL for spotify
|
||||
image_bytes = request(pic_url).content
|
||||
@@ -1095,7 +1094,7 @@ class DW_ALBUM:
|
||||
album_name_for_log = c_song_metadata.get('album', self.__song_metadata.get('album', 'Unknown Album'))
|
||||
logger.warning(
|
||||
f"In album '{album_name_for_log}', metadata list for key '{key}' is too short. "
|
||||
f"Expected at least {a + 1} elements for track {a + 1}/{total_tracks} "
|
||||
f"Expected at least {a + 1} elements for track {a + 1} "
|
||||
f"(list has {len(metadata_value_for_key)}). Assigning None to '{key}' for this track."
|
||||
)
|
||||
c_song_metadata[key] = None
|
||||
@@ -1158,14 +1157,44 @@ class DW_ALBUM:
|
||||
total_tracks = self.__song_metadata.get('nb_tracks', 0)
|
||||
album_id = self.__ids
|
||||
|
||||
Download_JOB.report_progress({
|
||||
"type": "album",
|
||||
"artist": album_artist,
|
||||
"status": "done",
|
||||
"total_tracks": total_tracks,
|
||||
"title": album_name,
|
||||
"url": f"https://open.spotify.com/album/{album_id}"
|
||||
})
|
||||
successful_tracks = []
|
||||
failed_tracks = []
|
||||
skipped_tracks = []
|
||||
for track in tracks:
|
||||
track_info = {
|
||||
"name": track.tags.get('music', 'Unknown Track'),
|
||||
"artist": track.tags.get('artist', 'Unknown Artist')
|
||||
}
|
||||
if getattr(track, 'was_skipped', False):
|
||||
skipped_tracks.append(track_info)
|
||||
elif track.success:
|
||||
successful_tracks.append(track_info)
|
||||
else:
|
||||
track_info["reason"] = getattr(track, 'error_message', 'Unknown reason')
|
||||
failed_tracks.append(track_info)
|
||||
|
||||
summary = {
|
||||
"successful_tracks": [f"{t['name']} - {t['artist']}" for t in successful_tracks],
|
||||
"skipped_tracks": [f"{t['name']} - {t['artist']}" for t in skipped_tracks],
|
||||
"failed_tracks": [{
|
||||
"track": f"{t['name']} - {t['artist']}",
|
||||
"reason": t['reason']
|
||||
} for t in failed_tracks],
|
||||
"total_successful": len(successful_tracks),
|
||||
"total_skipped": len(skipped_tracks),
|
||||
"total_failed": len(failed_tracks)
|
||||
}
|
||||
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="album",
|
||||
artist=album_artist,
|
||||
status="done",
|
||||
total_tracks=total_tracks,
|
||||
title=album_name,
|
||||
url=f"https://open.spotify.com/album/{album_id}",
|
||||
summary=summary,
|
||||
)
|
||||
|
||||
return album
|
||||
|
||||
@@ -1188,14 +1217,15 @@ class DW_PLAYLIST:
|
||||
playlist_id = self.__ids
|
||||
|
||||
# Report playlist initializing status
|
||||
Download_JOB.report_progress({
|
||||
"type": "playlist",
|
||||
"owner": playlist_owner,
|
||||
"status": "initializing",
|
||||
"total_tracks": total_tracks,
|
||||
"name": playlist_name,
|
||||
"url": f"https://open.spotify.com/playlist/{playlist_id}"
|
||||
})
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="playlist",
|
||||
owner=playlist_owner,
|
||||
status="initializing",
|
||||
total_tracks=total_tracks,
|
||||
name=playlist_name,
|
||||
url=f"https://open.spotify.com/playlist/{playlist_id}",
|
||||
)
|
||||
|
||||
# --- Prepare the m3u playlist file ---
|
||||
playlist_m3u_dir = os.path.join(self.__output_dir, "playlists")
|
||||
@@ -1344,14 +1374,43 @@ class DW_PLAYLIST:
|
||||
total_tracks = self.__json_data.get('tracks', {}).get('total', 0)
|
||||
playlist_id = self.__ids
|
||||
|
||||
Download_JOB.report_progress({
|
||||
"type": "playlist",
|
||||
"owner": playlist_owner,
|
||||
"status": "done",
|
||||
"total_tracks": total_tracks,
|
||||
"name": playlist_name,
|
||||
"url": f"https://open.spotify.com/playlist/{playlist_id}"
|
||||
})
|
||||
successful_tracks = []
|
||||
failed_tracks = []
|
||||
skipped_tracks = []
|
||||
for track in tracks:
|
||||
track_info = {
|
||||
"name": track.tags.get('music') or track.tags.get('name', 'Unknown Track'),
|
||||
"artist": track.tags.get('artist', 'Unknown Artist')
|
||||
}
|
||||
if getattr(track, 'was_skipped', False):
|
||||
skipped_tracks.append(track_info)
|
||||
elif track.success:
|
||||
successful_tracks.append(track_info)
|
||||
else:
|
||||
track_info["reason"] = getattr(track, 'error_message', 'Unknown reason')
|
||||
failed_tracks.append(track_info)
|
||||
|
||||
summary = {
|
||||
"successful_tracks": [f"{t['name']} - {t['artist']}" for t in successful_tracks],
|
||||
"skipped_tracks": [f"{t['name']} - {t['artist']}" for t in skipped_tracks],
|
||||
"failed_tracks": [{
|
||||
"track": f"{t['name']} - {t['artist']}",
|
||||
"reason": t['reason']
|
||||
} for t in failed_tracks],
|
||||
"total_successful": len(successful_tracks),
|
||||
"total_skipped": len(skipped_tracks),
|
||||
"total_failed": len(failed_tracks)
|
||||
}
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="playlist",
|
||||
owner=playlist_owner,
|
||||
status="done",
|
||||
total_tracks=total_tracks,
|
||||
name=playlist_name,
|
||||
url=f"https://open.spotify.com/playlist/{playlist_id}",
|
||||
summary=summary,
|
||||
)
|
||||
|
||||
return playlist
|
||||
|
||||
@@ -1363,36 +1422,27 @@ class DW_EPISODE:
|
||||
self.__preferences = preferences
|
||||
|
||||
def dw(self) -> Episode:
|
||||
# Using standardized episode progress format
|
||||
progress_data = {
|
||||
"type": "episode",
|
||||
"song": self.__preferences.song_metadata.get('name', 'Unknown Episode'),
|
||||
"artist": self.__preferences.song_metadata.get('show', 'Unknown Show'),
|
||||
"status": "initializing"
|
||||
}
|
||||
|
||||
# Set URL if available
|
||||
episode_id = self.__preferences.ids
|
||||
if episode_id:
|
||||
progress_data["url"] = f"https://open.spotify.com/episode/{episode_id}"
|
||||
|
||||
Download_JOB.report_progress(progress_data)
|
||||
url = f"https://open.spotify.com/episode/{episode_id}" if episode_id else None
|
||||
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="episode",
|
||||
song=self.__preferences.song_metadata.get('name', 'Unknown Episode'),
|
||||
artist=self.__preferences.song_metadata.get('show', 'Unknown Show'),
|
||||
status="initializing",
|
||||
url=url,
|
||||
)
|
||||
|
||||
episode = EASY_DW(self.__preferences).download_eps()
|
||||
|
||||
# Using standardized episode progress format
|
||||
progress_data = {
|
||||
"type": "episode",
|
||||
"song": self.__preferences.song_metadata.get('name', 'Unknown Episode'),
|
||||
"artist": self.__preferences.song_metadata.get('show', 'Unknown Show'),
|
||||
"status": "done"
|
||||
}
|
||||
|
||||
# Set URL if available
|
||||
episode_id = self.__preferences.ids
|
||||
if episode_id:
|
||||
progress_data["url"] = f"https://open.spotify.com/episode/{episode_id}"
|
||||
|
||||
Download_JOB.report_progress(progress_data)
|
||||
report_progress(
|
||||
reporter=Download_JOB.progress_reporter,
|
||||
report_type="episode",
|
||||
song=self.__preferences.song_metadata.get('name', 'Unknown Episode'),
|
||||
artist=self.__preferences.song_metadata.get('show', 'Unknown Show'),
|
||||
status="done",
|
||||
url=url,
|
||||
)
|
||||
|
||||
return episode
|
||||
|
||||
@@ -36,7 +36,7 @@ from deezspot.libutils.others_settings import (
|
||||
stock_real_time_dl,
|
||||
stock_market
|
||||
)
|
||||
from deezspot.libutils.logging_utils import logger, ProgressReporter
|
||||
from deezspot.libutils.logging_utils import logger, ProgressReporter, report_progress
|
||||
|
||||
class SpoLogin:
|
||||
def __init__(
|
||||
@@ -61,10 +61,6 @@ class SpoLogin:
|
||||
|
||||
self.__initialize_session()
|
||||
|
||||
def report_progress(self, progress_data):
|
||||
"""Report progress using the configured reporter."""
|
||||
self.progress_reporter.report(progress_data)
|
||||
|
||||
def __initialize_session(self) -> None:
|
||||
try:
|
||||
session_builder = Session.Builder()
|
||||
@@ -143,10 +139,62 @@ class SpoLogin:
|
||||
return track
|
||||
except MarketAvailabilityError as e:
|
||||
logger.error(f"Track download failed due to market availability: {str(e)}")
|
||||
if song_metadata:
|
||||
track_info = {
|
||||
"name": song_metadata.get("music", "Unknown Track"),
|
||||
"artist": song_metadata.get("artist", "Unknown Artist"),
|
||||
}
|
||||
summary = {
|
||||
"successful_tracks": [],
|
||||
"skipped_tracks": [],
|
||||
"failed_tracks": [{
|
||||
"track": f"{track_info['name']} - {track_info['artist']}",
|
||||
"reason": str(e)
|
||||
}],
|
||||
"total_successful": 0,
|
||||
"total_skipped": 0,
|
||||
"total_failed": 1
|
||||
}
|
||||
report_progress(
|
||||
reporter="ProgressReporter",
|
||||
report_type="track",
|
||||
song=track_info['name'],
|
||||
artist=track_info['artist'],
|
||||
status="failed",
|
||||
url=link_track,
|
||||
error=str(e),
|
||||
summary=summary
|
||||
)
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to download track: {str(e)}")
|
||||
traceback.print_exc()
|
||||
if song_metadata:
|
||||
track_info = {
|
||||
"name": song_metadata.get("music", "Unknown Track"),
|
||||
"artist": song_metadata.get("artist", "Unknown Artist"),
|
||||
}
|
||||
summary = {
|
||||
"successful_tracks": [],
|
||||
"skipped_tracks": [],
|
||||
"failed_tracks": [{
|
||||
"track": f"{track_info['name']} - {track_info['artist']}",
|
||||
"reason": str(e)
|
||||
}],
|
||||
"total_successful": 0,
|
||||
"total_skipped": 0,
|
||||
"total_failed": 1
|
||||
}
|
||||
report_progress(
|
||||
reporter="ProgressReporter",
|
||||
report_type="track",
|
||||
song=track_info['name'],
|
||||
artist=track_info['artist'],
|
||||
status="failed",
|
||||
url=link_track,
|
||||
error=str(e),
|
||||
summary=summary
|
||||
)
|
||||
raise e
|
||||
|
||||
def download_album(
|
||||
|
||||
Reference in New Issue
Block a user