Skip to content
This repository was archived by the owner on Apr 5, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions ElectricShuffle.code-workspace

This file was deleted.

18 changes: 12 additions & 6 deletions ElectricShuffle.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,25 @@
out_file.write(json.dumps(session_dict))

### Now that session is handled, get playlists
playlists = session.user.playlists()

playlists_no_e = session.user.playlists()
for playlist in playlists_no_e:
if("- Electrified" in playlist.name):
playlists_no_e.remove(playlist)
print("Please select the playlist you wish to shuffle by intering it's number below")
for idx, playlist in enumerate(playlists):
for idx, playlist in enumerate(playlists_no_e):
print(f" [{idx+1}] {playlist.name}")

# Get playlists on user account
playlist_num = int(input("Playlist Number: ")) - 1

selected_playlist = playlists[playlist_num]
selected_playlist = playlists_no_e[playlist_num]
print(f"Electric shuffle {selected_playlist.name}?")
should_continue = bool(input("Continue (Yes/No): "))

### Allow bailing
if not should_continue:
exit(1)


### Do the thing
tracklist = selected_playlist.tracks()
track_ids = []
Expand All @@ -67,9 +69,12 @@

### Signify that this is a copy for the user
shuffled_name = f"{selected_playlist.name} - Electrified"

# Get all playlists including - Electrified
playlists = session.user.playlists()
for playlist in playlists:
### Delete an existing version of this playlist if we are re-rolling
if playlist.name is shuffled_name:
if playlist.name == shuffled_name:
playlist.delete()

## Create (or re create) the electric playlist
Expand All @@ -78,3 +83,4 @@
## Add the beautiful music after a quick shuffle
random.shuffle(track_ids)
new_playlist.add(track_ids)
print("Shuffling complete")
107 changes: 107 additions & 0 deletions ElectricShuffleAll.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/bin/env python3

import datetime
import json
import os
from os import path
import random
from select import select
import tidalapi


def token_refresh(session, refresh_token):
"""
Retrieves a new access token using the specified parameters, updating the current access token

:param refresh_token: The refresh token retrieved when using the OAuth login.
:return: True if we believe the token was successfully refreshed, otherwise False
"""
url = 'https://auth.tidal.com/v1/oauth2/token'
params = {
'grant_type': 'refresh_token',
'refresh_token': refresh_token,
'client_id': session.config.client_id,
'client_secret': session.config.client_secret
}

request = session.request_session.post(url, params)
json = request.json()
if not request.ok:
log.warning("The refresh token has expired, a new login is required.")
return json
session.access_token = json['access_token']
session.expiry_time = datetime.datetime.now() + datetime.timedelta(seconds=json['expires_in'])
session.token_type = json['token_type']
return json

dir = path.dirname(path.realpath(__file__))
credential_file = path.join(dir, '.credentials.json')

need_oauth = True
print("Creating Session")
session = tidalapi.Session()

# Check if the credentials are still valid
if os.path.exists(credential_file):
with open(credential_file, "r") as open_file:
token_json = json.load(open_file)

token_refresh(session, token_json["refresh_token"])

# Check tokens with tidal
session.load_oauth_session(
token_json["token_type"],
token_json["access_token"],
token_json["refresh_token"],
datetime.datetime.fromisoformat(token_json["expiry_time"])
)

new_token_json = token_refresh(session, token_json["refresh_token"])
session_dict = {
"token_type": session.token_type,
"access_token": session.access_token,
"refresh_token": session.refresh_token,
"expiry_time": session.expiry_time.isoformat()
}
with open(credential_file, "w") as out_file:
out_file.write(json.dumps(session_dict))

if not session.check_login():
# Have user go log in and when this completes, we will auto continue
session.login_oauth_simple()

session_dict = {
"token_type": session.token_type,
"access_token": session.access_token,
"refresh_token": session.refresh_token,
"expiry_time": session.expiry_time.isoformat()
}
with open(credential_file, "w") as out_file:
out_file.write(json.dumps(session_dict))

### Now that session is handled, get playlists
print("Getting Playlists")
playlists = session.user.playlists()

for playlist in playlists:
### Signify that this is a copy for the user
shuffled_name = f"{playlist.name} - Electrified"

if "- Electrified" in playlist.name:
playlist.delete()
else:
print("Shuffling playlist " + playlist.name)

### Do the thing
tracklist = playlist.tracks()
track_ids = []

for track in tracklist:
track_ids.append(track.id)

## Create (or re create) the electric playlist
new_playlist = session.user.create_playlist(shuffled_name, playlist.description)

## Add the beautiful music after a quick shuffle
random.shuffle(track_ids)
new_playlist.add(track_ids)
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,29 @@ This is a (terrible) app to shuffle your Tidal playlists since there are not (cu

I'm not responsible for bricked devices, dead SD cards, thermonuclear war, or you getting fired because your entire playlist got deleted and you are now too sad to work. This _shouldn't happen_ but the app is very lightly tested.

### Running The Program
### Setting up Environment

1. Clone this repo to your computer
1. Create a venv to install packages by running `python3 -m venv .venv`
1. Start using the virtual env by running `source .venv/bin/activate`
1. Install required packages by running `pip3 install -r requirements.txt`

### Running ElectricShuffle
1. Run the program `./ElectricShuffle.py`
1. Log in by clicking the link (or copying it to your browser). Once logged in return to the terminal.
1. Pick a playlist to shuffle
1. Confirm that is the playlist you want
1. Go enjoy some tunes! Notice your new playlist which is a copy of your current one but with an " - Electrified" suffix. This is the shuffled one.

### Running ElectricShuffleAll
This script requires no human intervention beyond the initial login. Run it one time manually to login, then automate to your heart's content.

**Note:** On linux VMs there is an issue where the tidalapi package sends requests too fast for the tidal servers. Adding time.sleep(1) to the tidalapi playlist.py \__init__ resolves the issue.

1. Run the program `./ElectricShuffleAll.py`
1. Log in by clicking the link (or copying it to your browser). Once logged in return to the terminal. (Once per environment)
1. Shuffles all playlists

### Contributing

Contributions are welcome, this is just a little hobby script I wrote to make my life easier. Feel free to change it and send a pull request.
Expand Down
34 changes: 2 additions & 32 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,32 +1,2 @@
attr==0.3.2
brotli==1.0.9
brotlicffi==1.0.9.2
ConfigParser==5.3.0
cryptography==38.0.1
Cython==0.29.32
dl==0.1.0
docutils==0.19
HTMLParser==0.0.2
ipython==8.5.0
ipywidgets==8.0.2
Jinja2==3.1.2
jnius==1.1.0
lockfile==0.12.2
mock==4.0.3
numpy==1.23.2
Pillow==9.2.0
pluggy==1.0.0
protobuf==4.21.5
pyOpenSSL==22.0.0
pytest==7.1.3
railroad==0.5.0
secretstorage==3.3.3
simplejson==3.17.6
Sphinx==5.1.1
toml==0.10.2
tornado==6.2
trove_classifiers==2022.8.31
truststore==0.5.0
unicodedata2==14.0.0
urllib3_secure_extra==0.1.0
xmlrpclib==1.0.1
tidalapi==0.7.0