Giter Site home page Giter Site logo

spotify_to_tidal's Introduction

A command line tool for importing your Spotify playlists into Tidal

Installation

Clone this git repository and then run:

python3 -m pip install -r requirements.txt

Setup

  1. Rename the file example_config.yml to config.yml
  2. Go here and register a new app on developer.spotify.com.
  3. Copy and paste your client ID and client secret to the Spotify part of the config file
  4. Copy and paste the value in 'redirect_uri' of the config file to Redirect URIs at developer.spotify.com and press ADD
  5. Enter your Spotify username to the config file

Usage

To synchronize all of your Spotify playlists with your Tidal account run the following

python3 sync.py

This will take a long time because the Tidal API is really slow.

You can also just synchronize a specific playlist by doing the following:

python3 sync.py --uri 1ABCDEqsABCD6EaABCDa0a

See example_config.yml for more configuration options, and sync.py --help for more options.

spotify_to_tidal's People

Contributors

big-mak avatar theedgeofrage avatar timrae avatar vaosilva avatar vkolotov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

spotify_to_tidal's Issues

Failed to get all playlists.

image

I tried to get all the playlists, but no text appears and it ends.
I import normally if I use the uri option.
Please help me get all the playlists.

No URL for authorization?

Hi there,

seems that I am doing something wrong. On a headless Ubuntu 20 I run:

python3 sync.py

but nothing happens. I have to abort with ctrl-c to get back to the command line, where it then says:

Traceback (most recent call last):
File "/home/meiko/spotify_to_tidal/sync.py", line 297, in
spotify_session = open_spotify_session(config['spotify'])
File "/home/meiko/spotify_to_tidal/auth.py", line 16, in open_spotify_session
credentials_manager.get_access_token(as_dict=False)
File "/home/meiko/miniconda3/lib/python3.10/site-packages/spotipy/oauth2.py", line 535, in get_access_token
"code": code or self.get_auth_response(),
File "/home/meiko/miniconda3/lib/python3.10/site-packages/spotipy/oauth2.py", line 490, in get_auth_response
return self._get_auth_response_local_server(redirect_port)
File "/home/meiko/miniconda3/lib/python3.10/site-packages/spotipy/oauth2.py", line 459, in _get_auth_response_local_server
server.handle_request()
File "/home/meiko/miniconda3/lib/python3.10/socketserver.py", line 294, in handle_request
ready = selector.select(timeout)
File "/home/meiko/miniconda3/lib/python3.10/selectors.py", line 416, in select
fd_event_list = self._selector.poll(timeout)
KeyboardInterrupt

If I understand everything right, I should have get an URL for authorization, haven't I?

Thanks
meiko

Tidal client error

Hi,

When running sync.py, after entering the url that I was redirected to, I get this error message:

Login failed: {"status":401,"error":"invalid_client","error_description":"Client with token 8SEZWa4J1NVC5U5Y not found","sub_status":1005}
Traceback (most recent call last):
  File "/Users/davidkatchouni/Downloads/spotify_to_tidal-master/sync.py", line 288, in <module>
    tidal_session = open_tidal_session()
  File "/Users/davidkatchouni/Downloads/spotify_to_tidal-master/auth.py", line 40, in open_tidal_session
    login, future = session.login_oauth_simple()
  File "/usr/local/lib/python3.9/site-packages/tidalapi/__init__.py", line 213, in login_oauth_simple
    login, future = self.login_oauth()
  File "/usr/local/lib/python3.9/site-packages/tidalapi/__init__.py", line 226, in login_oauth
    login, future = self._login_with_link()
  File "/usr/local/lib/python3.9/site-packages/tidalapi/__init__.py", line 240, in _login_with_link
    request.raise_for_status()
  File "/usr/local/lib/python3.9/site-packages/requests/models.py", line 960, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: https://auth.tidal.com/v1/oauth2/device_authorization

KeyError: 'picture'

I've followed all instructions, however getting this error when running the script. No ideas how to solve it...

  File "sync.py", line 298, in <module>
    tidal_session = open_tidal_session()
  File "/Users/gediminas/WEB/learning/spotify_to_tidal/auth.py", line 48, in open_tidal_session
    future.result()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/concurrent/futures/_base.py", line 435, in result
    return self.__get_result()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/concurrent/futures/_base.py", line 384, in __get_result
    raise self._exception
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tidalapi/session.py", line 364, in _process_link_login
    self.user = tidalapi.User(self, user_id=json['userId']).factory()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tidalapi/user.py", line 48, in factory
    return self.request.map_request('users/%s' % self.id, parse=self.parse)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tidalapi/request.py", line 118, in map_request
    return self.map_json(json_obj, parse=parse)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tidalapi/request.py", line 125, in map_json
    return parse(json_obj)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tidalapi/user.py", line 65, in parse
    return user.parse(json_obj)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tidalapi/user.py", line 104, in parse
    super(LoggedInUser, self).parse(json_obj)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tidalapi/user.py", line 77, in parse
    self.picture_id = json_obj['picture']
KeyError: 'picture'

Connection aborted RemoteDisconnected

After I fixed an error that the http exception does not have a method json ( I just removed the part from the print) I get another HTTPException after too many timeouts. Its probably the api hard limiting I guess?

multiprocessing.pool.RemoteTraceback: 
"""
Traceback (most recent call last):
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 703, in urlopen
    httplib_response = self._make_request(
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 449, in _make_request
    six.raise_from(e, None)
  File "<string>", line 3, in raise_from
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 444, in _make_request
    httplib_response = conn.getresponse()
  File "/opt/homebrew/Cellar/[email protected]/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10/http/client.py", line 1374, in getresponse
    response.begin()
  File "/opt/homebrew/Cellar/[email protected]/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10/http/client.py", line 318, in begin
    version, status, reason = self._read_status()
  File "/opt/homebrew/Cellar/[email protected]/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10/http/client.py", line 287, in _read_status
    raise RemoteDisconnected("Remote end closed connection without"
http.client.RemoteDisconnected: Remote end closed connection without response

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/requests/adapters.py", line 489, in send
    resp = conn.urlopen(
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 787, in urlopen
    retries = retries.increment(
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/urllib3/util/retry.py", line 550, in increment
    raise six.reraise(type(error), error, _stacktrace)
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/urllib3/packages/six.py", line 769, in reraise
    raise value.with_traceback(tb)
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 703, in urlopen
    httplib_response = self._make_request(
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 449, in _make_request
    six.raise_from(e, None)
  File "<string>", line 3, in raise_from
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 444, in _make_request
    httplib_response = conn.getresponse()
  File "/opt/homebrew/Cellar/[email protected]/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10/http/client.py", line 1374, in getresponse
    response.begin()
  File "/opt/homebrew/Cellar/[email protected]/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10/http/client.py", line 318, in begin
    version, status, reason = self._read_status()
  File "/opt/homebrew/Cellar/[email protected]/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10/http/client.py", line 287, in _read_status
    raise RemoteDisconnected("Remote end closed connection without"
urllib3.exceptions.ProtocolError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/homebrew/Cellar/[email protected]/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10/multiprocessing/pool.py", line 125, in worker
    result = (True, func(*args, **kwds))
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/sync.py", line 126, in _enumerate_wrapper
    return (index, repeat_on_http_error(function, value, **kwargs))
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/sync.py", line 121, in repeat_on_http_error
    return repeat_on_http_error(function, *args, remaining=remaining-1, **kwargs)
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/sync.py", line 121, in repeat_on_http_error
    return repeat_on_http_error(function, *args, remaining=remaining-1, **kwargs)
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/sync.py", line 121, in repeat_on_http_error
    return repeat_on_http_error(function, *args, remaining=remaining-1, **kwargs)
  [Previous line repeated 1 more time]
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/sync.py", line 110, in repeat_on_http_error
    return function(*args, **kwargs)
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/sync.py", line 87, in tidal_search
    album_result = tidal_session.search(simple(spotify_track['album']['name']) + " " + simple(spotify_track['album']['artists'][0]['name']), models=[tidalapi.album.Album])
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/tidalapi/session.py", line 446, in search
    json_obj = self.request.request('GET', 'search', params=params).json()
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/tidalapi/request.py", line 97, in request
    request = self.basic_request(method, path, params, data, headers)
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/tidalapi/request.py", line 62, in basic_request
    request = self.session.request_session.request(method, url, params=request_params, data=data, headers=headers)
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/requests/sessions.py", line 587, in request
    resp = self.send(prep, **send_kwargs)
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/requests/sessions.py", line 701, in send
    r = adapter.send(request, **kwargs)
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/requests/adapters.py", line 547, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/./sync.py", line 292, in <module>
    sync_list(spotify_session, tidal_session, get_user_playlist_mappings(spotify_session, tidal_session, config), config)
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/./sync.py", line 228, in sync_list
    repeat_on_http_error(sync_playlist, spotify_session, tidal_session, spotify_id, tidal_id, config)
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/./sync.py", line 110, in repeat_on_http_error
    return function(*args, **kwargs)
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/./sync.py", line 210, in sync_playlist
    tidal_tracks = call_async_with_progress(tidal_search, spotify_tracks, task_description, config.get('subprocesses', 50), tidal_session=tidal_session)
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/./sync.py", line 131, in call_async_with_progress
    for index, result in tqdm(process_pool.imap_unordered(partial(_enumerate_wrapper, function=function, **kwargs),
  File "/Users/secretunicorn/Downloads/spotify_to_tidal/venv/lib/python3.10/site-packages/tqdm/std.py", line 1195, in __iter__
    for obj in iterable:
  File "/opt/homebrew/Cellar/[email protected]/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10/multiprocessing/pool.py", line 873, in next
    raise value
requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))

Create file with all songs that could not be synced

Maybe this could create a csv with the columns title, artist, spotifyId, playlist maybe album.
To either help find the titles if they are just named slightly different or to at least know which songs you lost, without having create such a file from the console output.

KeyError: 'picture'

Traceback (most recent call last):
  File "/Users/koraysels/PycharmProjects/spotify_to_tidal/sync.py", line 299, in <module>
    tidal_session = open_tidal_session()
                    ^^^^^^^^^^^^^^^^^^^^
  File "/Users/koraysels/PycharmProjects/spotify_to_tidal/auth.py", line 48, in open_tidal_session
    future.result()
  File "/Users/koraysels/.pyenv/versions/3.11.1/lib/python3.11/concurrent/futures/_base.py", line 456, in result
    return self.__get_result()
           ^^^^^^^^^^^^^^^^^^^
  File "/Users/koraysels/.pyenv/versions/3.11.1/lib/python3.11/concurrent/futures/_base.py", line 401, in __get_result
    raise self._exception
  File "/Users/koraysels/.pyenv/versions/3.11.1/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/koraysels/.pyenv/versions/3.11.1/lib/python3.11/site-packages/tidalapi/session.py", line 364, in _process_link_login
    self.user = tidalapi.User(self, user_id=json['userId']).factory()
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/koraysels/.pyenv/versions/3.11.1/lib/python3.11/site-packages/tidalapi/user.py", line 48, in factory
    return self.request.map_request('users/%s' % self.id, parse=self.parse)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/koraysels/.pyenv/versions/3.11.1/lib/python3.11/site-packages/tidalapi/request.py", line 118, in map_request
    return self.map_json(json_obj, parse=parse)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/koraysels/.pyenv/versions/3.11.1/lib/python3.11/site-packages/tidalapi/request.py", line 125, in map_json
    return parse(json_obj)
           ^^^^^^^^^^^^^^^
  File "/Users/koraysels/.pyenv/versions/3.11.1/lib/python3.11/site-packages/tidalapi/user.py", line 65, in parse
    return user.parse(json_obj)
           ^^^^^^^^^^^^^^^^^^^^
  File "/Users/koraysels/.pyenv/versions/3.11.1/lib/python3.11/site-packages/tidalapi/user.py", line 104, in parse
    super(LoggedInUser, self).parse(json_obj)
  File "/Users/koraysels/.pyenv/versions/3.11.1/lib/python3.11/site-packages/tidalapi/user.py", line 77, in parse
    self.picture_id = json_obj['picture']
                      ~~~~~~~~^^^^^^^^^^^
KeyError: 'picture'

cannot seem to get it working..

Add new items without deleting tidal playlist

Hi,

first of all its an awesome project.

Could you please add an parameter for appending the tidal playlist?
It would be awesome if I could add more music to the tidal playlist without them getting removed by the script.

Thanks mate :)

Maintain chronological order in Tidal playlist

Current Behavior: Syncing a playlist correctly syncs the tracks to a new playlist. However, when sorting the Tidal playlist, we actually get the inverse order as the Spotify playlist. For example, Tidal's playlist has to be in descending date order to match Spotify's ascending date order.

Desired Behavior: When sorting by the "Date Added" column, the Spotify and Tidal playlists should have an identical order.

Fix: Reverse the Tidal tracks before appending them to the playlist.

Not all playlist are sync

Hi, I tried today the script, and after finish and check there were no errors I see on my tidal account, only the playlist created by me are sync, but not others playlist saved on my account.

Is there an error, or something I have to config?

Thank you anyway!

tidal credentials ?

had a tidal login problem but it turns out that Tidal changed the secret values so tidalapi barfed.
I ended up hardcoding the secrets from here in tidalapi_init_.py and bob is my uncle

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.