Skip to content

Instantly share code, notes, and snippets.

@j0e1in
Created June 27, 2020 20:06
Show Gist options
  • Save j0e1in/ccfa48d3e65959e1c760db7552f4f758 to your computer and use it in GitHub Desktop.
Save j0e1in/ccfa48d3e65959e1c760db7552f4f758 to your computer and use it in GitHub Desktop.
Download all albums/tracks of all of your favorite artists on TIDAL.
""" Download all albums/tracks of all of your favorite artists on TIDAL.
# Usage
- Install dependency: `pip install -U tidal-dl`
- Create tidal-dl.ini with following content and then fill your username and password
```
username = <username>
password = <password>
countrycode = US
outputdir = ./
quality = HI_RES
resolution = 1080
threadnum = 3
onlym4a = False
showprogress = True
addhyphen = True
addyear = False
```
Note: This configuration requires TIDAL HIFI subscription. If you have premium subscription,
change quality to either LOSSLESS or HIGH. See https://yaronzz.top/post/tidal_dl_installation/
- Execute `tidal-dl` command once to fill access token in tidal-dl.ini
- Execute this file at the same directory where tidal-dl.ini is located
```
python download_tidal_favorite_artists.py
```
"""
from tidal_dl.download import Download
from tidal_dl import tidal
from threading import Thread, Lock
import json
import os
import random
import time
FAV_ARTISTS_FILE = "favorite_artists.json"
FORCE_RESTART = False
def fetchFavoriteArtists():
config = tidal.TidalConfig()
tool = tidal.TidalTool()
artists = []
offset = 0
limit = 100
total = 1
while offset < total:
fav_artists_url = (
f"users/{config.userid}/favorites/artists?limit={limit}&offset={offset}"
)
print(f"Fetching << {fav_artists_url} >>")
data = tool._get(fav_artists_url)
offset = data["offset"] + len(data["items"])
total = data["totalNumberOfItems"]
for artist in data["items"]:
artists.append(
dict(
name=artist["item"]["name"],
url=artist["item"]["url"],
downloaded=False,
)
)
return artists
def saveFavoriteArtists(artists):
with open(FAV_ARTISTS_FILE, "w") as f:
json.dump(artists, f)
def loadFavoriteArtists():
if not os.path.exists(FAV_ARTISTS_FILE):
return []
with open(FAV_ARTISTS_FILE, "r") as f:
return json.load(f)
def setArtistDownloadStatus(artist, status):
artists = loadFavoriteArtists()
for art in artists:
if art["url"] == artist["url"]:
art["downloaded"] = status
saveFavoriteArtists(artists)
def restoreStatus(src_artists, dest_artists):
artist_index_by_url = {art["url"]: idx for idx, art in enumerate(dest_artists)}
for art in src_artists:
if art["url"] in artist_index_by_url:
idx = artist_index_by_url[art["url"]]
dest_artists[idx]["downloaded"] = art.get("downloaded", False)
def downlaodArtist(artist):
print(f"Start downloading {artist['name']}...")
downloader = Download()
downloader.downloadUrl(artist["url"])
setArtistDownloadStatus(artist, True)
print(f"Finished downloading {artist['name']}...sleep for 100 seconds")
time.sleep(100)
if __name__ == "__main__":
fetched_artists = fetchFavoriteArtists()
if not FORCE_RESTART: # restore download status if not to force restart
loaded_artists = loadFavoriteArtists()
restoreStatus(loaded_artists, fetched_artists)
saveFavoriteArtists(fetched_artists)
not_downloaded_artists = [
art for art in fetched_artists if art["downloaded"] is False
]
total = len(fetched_artists)
n_downloaded = total - len(not_downloaded_artists)
for art in not_downloaded_artists:
print(
f"Total artists: {total} | Downloaded: {n_downloaded} | Remaining: {total - n_downloaded}"
)
try:
downlaodArtist(art)
except Exception as err:
# Some tracks may have session invalid issue, and causing
# "local variable 'url' referenced before assignment" exception,
# need to download them manually
print(f"<{art['name']}> Exception: {err}")
time.sleep(10)
n_downloaded += 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment