From fb8046cc804e0d49a2c30cc0fe62390d86284ba7 Mon Sep 17 00:00:00 2001 From: bloedboemmel Date: Sun, 13 Nov 2022 17:24:12 +0100 Subject: [PATCH 1/2] Sleeping only for missing songs, edit error for Album not found Closes #1018 --- TIDALDL-PY/tidal_dl/download.py | 37 +++++++++++++++++++++++---------- TIDALDL-PY/tidal_dl/paths.py | 14 +++++++------ TIDALDL-PY/tidal_dl/tidal.py | 6 ------ 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/TIDALDL-PY/tidal_dl/download.py b/TIDALDL-PY/tidal_dl/download.py index 0f4ef8ad..07eda7b4 100644 --- a/TIDALDL-PY/tidal_dl/download.py +++ b/TIDALDL-PY/tidal_dl/download.py @@ -110,14 +110,20 @@ def downloadAlbumInfo(album, tracks): aigpy.file.write(path, infos, "w+") -def downloadVideo(video: Video, album: Album = None, playlist: Playlist = None): +def downloadVideo(video: Video, path, stream, album: Album = None, playlist: Playlist = None): try: - stream = TIDAL_API.getVideoStreamUrl(video.id, SETTINGS.videoQuality) - path = getVideoPath(video, album, playlist) + if __isSkip__(path, stream.m3u8Url): + Printf.success(aigpy.path.getFileName(path) + " (skip:already exists!)") + return True, '' Printf.video(video, stream) logging.info("[DL Video] name=" + aigpy.path.getFileName(path) + "\nurl=" + stream.m3u8Url) + # Sleep for human behaviour + if SETTINGS.downloadDelay is not False: + sleep_time = random.randint(500, 5000) / 1000 + print(f"Sleeping for {sleep_time} seconds, to mimic human behaviour and prevent too many requests error") + time.sleep(sleep_time) m3u8content = requests.get(stream.m3u8Url).content if m3u8content is None: Printf.err(f"DL Video[{video.title}] getM3u8 failed.{str(e)}") @@ -140,11 +146,8 @@ def downloadVideo(video: Video, album: Album = None, playlist: Playlist = None): return False, str(e) -def downloadTrack(track: Track, album=None, playlist=None, userProgress=None, partSize=1048576): +def downloadTrack(track: Track, album=None, path=None, stream=None, userProgress=None, partSize=1048576): try: - stream = TIDAL_API.getStreamUrl(track.id, SETTINGS.audioQuality) - path = getTrackPath(track, stream, album, playlist) - if SETTINGS.showTrackInfo and not SETTINGS.multiThread: Printf.track(track, stream) @@ -156,6 +159,12 @@ def downloadTrack(track: Track, album=None, playlist=None, userProgress=None, pa Printf.success(aigpy.path.getFileName(path) + " (skip:already exists!)") return True, '' + #Sleep for human behaviour + if SETTINGS.downloadDelay is not False: + sleep_time = random.randint(500, 5000) / 1000 + print(f"Sleeping for {sleep_time} seconds, to mimic human behaviour and prevent too many requests error") + time.sleep(sleep_time) + # download logging.info("[DL Track] name=" + aigpy.path.getFileName(path) + "\nurl=" + stream.url) @@ -206,7 +215,9 @@ def __getAlbum__(item: Track): if itemAlbum is None: itemAlbum = __getAlbum__(item) item.trackNumberOnPlaylist = index + 1 - downloadTrack(item, itemAlbum, playlist) + stream = TIDAL_API.getStreamUrl(item.id, SETTINGS.audioQuality) + path = getTrackPath(item, stream, album, playlist) + downloadTrack(item, path=path, stream=stream, album=itemAlbum) else: thread_pool = ThreadPoolExecutor(max_workers=5) for index, item in enumerate(tracks): @@ -214,10 +225,14 @@ def __getAlbum__(item: Track): if itemAlbum is None: itemAlbum = __getAlbum__(item) item.trackNumberOnPlaylist = index + 1 - thread_pool.submit(downloadTrack, item, itemAlbum, playlist) + stream = TIDAL_API.getStreamUrl(item.id, SETTINGS.audioQuality) + path = getTrackPath(item, stream, album, playlist) + thread_pool.submit(downloadTrack, item, path=path, stream=stream, album=itemAlbum) thread_pool.shutdown(wait=True) def downloadVideos(videos, album: Album, playlist=None): - for item in videos: - downloadVideo(item, album, playlist) + for video in videos: + stream = TIDAL_API.getVideoStreamUrl(video.id, SETTINGS.videoQuality) + path = getVideoPath(video, album, playlist) + downloadVideo(video, path, stream, album, playlist) diff --git a/TIDALDL-PY/tidal_dl/paths.py b/TIDALDL-PY/tidal_dl/paths.py index c63295ef..17c8b61c 100644 --- a/TIDALDL-PY/tidal_dl/paths.py +++ b/TIDALDL-PY/tidal_dl/paths.py @@ -116,10 +116,6 @@ def getTrackPath(track, stream, album=None, playlist=None): # explicit explicit = "(Explicit)" if track.explicit else '' - # album and addyear - albumName = __fixPath__(album.title) - year = __getYear__(album.releaseDate) - # extension extension = __getExtension__(stream) @@ -131,8 +127,14 @@ def getTrackPath(track, stream, album=None, playlist=None): retpath = retpath.replace(R"{ArtistsName}", artists) retpath = retpath.replace(R"{TrackTitle}", title) retpath = retpath.replace(R"{ExplicitFlag}", explicit) - retpath = retpath.replace(R"{AlbumYear}", year) - retpath = retpath.replace(R"{AlbumTitle}", albumName) + + if album is not None: + # album and addyear + albumName = __fixPath__(album.title) + year = __getYear__(album.releaseDate) + retpath = retpath.replace(R"{AlbumYear}", year) + retpath = retpath.replace(R"{AlbumTitle}", albumName) + retpath = retpath.replace(R"{AudioQuality}", track.audioQuality) retpath = retpath.replace(R"{DurationSeconds}", str(track.duration)) retpath = retpath.replace(R"{Duration}", __getDurationStr__(track.duration)) diff --git a/TIDALDL-PY/tidal_dl/tidal.py b/TIDALDL-PY/tidal_dl/tidal.py index cf99a757..b00e06bd 100644 --- a/TIDALDL-PY/tidal_dl/tidal.py +++ b/TIDALDL-PY/tidal_dl/tidal.py @@ -38,12 +38,6 @@ def __get__(self, path, params={}, urlpre='https://api.tidalhifi.com/v1/'): for index in range(0, 3): try: respond = requests.get(urlpre + path, headers=header, params=params) - if respond.url.find("playbackinfopostpaywall") != -1 and SETTINGS.downloadDelay is not False: - # random sleep between 0.5 and 5 seconds and print it - sleep_time = random.randint(500, 5000) / 1000 - print(f"Sleeping for {sleep_time} seconds, to mimic human behaviour and prevent too many requests error") - time.sleep(sleep_time) - if respond.status_code == 429: print('Too many requests, waiting for 20 seconds...') # Loop countdown 20 seconds and print the remaining time From 422a03bb3e70c8e98417a076c31f08cadaed9008 Mon Sep 17 00:00:00 2001 From: bloedboemmel Date: Mon, 28 Nov 2022 10:00:15 +0100 Subject: [PATCH 2/2] Fixes Tidal 429 Error by avoiding to many calls --- TIDALDL-PY/tidal_dl/download.py | 28 +++++++++++++++++----------- TIDALDL-PY/tidal_dl/paths.py | 18 ++++++------------ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/TIDALDL-PY/tidal_dl/download.py b/TIDALDL-PY/tidal_dl/download.py index 07eda7b4..8467c14f 100644 --- a/TIDALDL-PY/tidal_dl/download.py +++ b/TIDALDL-PY/tidal_dl/download.py @@ -110,8 +110,11 @@ def downloadAlbumInfo(album, tracks): aigpy.file.write(path, infos, "w+") -def downloadVideo(video: Video, path, stream, album: Album = None, playlist: Playlist = None): +def downloadVideo(video: Video, album: Album = None, playlist: Playlist = None): try: + stream = TIDAL_API.getVideoStreamUrl(video.id, SETTINGS.videoQuality) + path = getVideoPath(video, album, playlist) + if __isSkip__(path, stream.m3u8Url): Printf.success(aigpy.path.getFileName(path) + " (skip:already exists!)") return True, '' @@ -146,8 +149,13 @@ def downloadVideo(video: Video, path, stream, album: Album = None, playlist: Pla return False, str(e) -def downloadTrack(track: Track, album=None, path=None, stream=None, userProgress=None, partSize=1048576): +def downloadTrack(track: Track, album=None, playlist=None, userProgress=None, partSize=1048576): try: + path = getTrackPath(track, album, playlist) + if os.path.exists(path): + Printf.success(aigpy.path.getFileName(path) + " (skip:already exists!)") + return True, '' + stream = TIDAL_API.getStreamUrl(track.id, SETTINGS.audioQuality) if SETTINGS.showTrackInfo and not SETTINGS.multiThread: Printf.track(track, stream) @@ -215,9 +223,9 @@ def __getAlbum__(item: Track): if itemAlbum is None: itemAlbum = __getAlbum__(item) item.trackNumberOnPlaylist = index + 1 - stream = TIDAL_API.getStreamUrl(item.id, SETTINGS.audioQuality) - path = getTrackPath(item, stream, album, playlist) - downloadTrack(item, path=path, stream=stream, album=itemAlbum) + + downloadTrack(item, playlist=playlist, album=itemAlbum) + else: thread_pool = ThreadPoolExecutor(max_workers=5) for index, item in enumerate(tracks): @@ -225,14 +233,12 @@ def __getAlbum__(item: Track): if itemAlbum is None: itemAlbum = __getAlbum__(item) item.trackNumberOnPlaylist = index + 1 - stream = TIDAL_API.getStreamUrl(item.id, SETTINGS.audioQuality) - path = getTrackPath(item, stream, album, playlist) - thread_pool.submit(downloadTrack, item, path=path, stream=stream, album=itemAlbum) + + thread_pool.submit(downloadTrack, item, playlist=playlist, album=itemAlbum) + thread_pool.shutdown(wait=True) def downloadVideos(videos, album: Album, playlist=None): for video in videos: - stream = TIDAL_API.getVideoStreamUrl(video.id, SETTINGS.videoQuality) - path = getVideoPath(video, album, playlist) - downloadVideo(video, path, stream, album, playlist) + downloadVideo(video, album, playlist) diff --git a/TIDALDL-PY/tidal_dl/paths.py b/TIDALDL-PY/tidal_dl/paths.py index 17c8b61c..426bf282 100644 --- a/TIDALDL-PY/tidal_dl/paths.py +++ b/TIDALDL-PY/tidal_dl/paths.py @@ -32,16 +32,10 @@ def __getDurationStr__(seconds): time_string = time_string[2:] return time_string - -def __getExtension__(stream: StreamUrl): - if '.flac' in stream.url: - return '.flac' - if '.mp4' in stream.url: - if 'ac4' in stream.codec or 'mha1' in stream.codec: - return '.mp4' - return '.m4a' - return '.m4a' - +def __getExtension__(track): + if track.audioQuality == "LOSSLESS" or track.audioQuality == "HI_RES": + return ".flac" + return ".m4a" def getAlbumPath(album): artistName = __fixPath__(TIDAL_API.getArtistsName(album.artists)) @@ -92,7 +86,7 @@ def getPlaylistPath(playlist): return f"{SETTINGS.downloadPath}/{retpath}" -def getTrackPath(track, stream, album=None, playlist=None): +def getTrackPath(track, album=None, playlist=None): base = './' number = str(track.trackNumber).rjust(2, '0') if album is not None: @@ -117,7 +111,7 @@ def getTrackPath(track, stream, album=None, playlist=None): explicit = "(Explicit)" if track.explicit else '' # extension - extension = __getExtension__(stream) + extension = __getExtension__(track) retpath = SETTINGS.trackFileFormat if retpath is None or len(retpath) <= 0: