Plan
Premium
Country
Belgium
Device
laptop
Operating System
Windows
My Question or Issue
i want to make an app to easily manage playlists and i would like to extract removed and unavailable songs and be able to make a new playlist and add those songs.
this is my current code but it only makes a new playlist
import base64
import json
import requests
import re
import webbrowser
# Set up the API endpoint, client ID, and client secret
endpoint = "https://api.spotify.com/v1/"
client_id = "f"
client_secret = ""
redirect_uri = "http://localhost:8000"
# Set up the OAuth2 authorization parameters
auth_url = "https://accounts.spotify.com/authorize"
scope = "playlist-read-private playlist-modify-private playlist-modify-public"
state = "abc123"
# Encode the client ID and client secret using base64
client_creds = f"{client_id}:{client_secret}"
client_creds_b64 = base64.b64encode(client_creds.encode()).decode()
# Obtain the authorization code
auth_query_params = {
"response_type": "code",
"redirect_uri": redirect_uri,
"scope": scope,
"client_id": client_id
}
auth_url_query = auth_url + "?" + "&".join([f"{k}={v}" for k, v in auth_query_params.items()])
# Open the authorization URL in the default web browser
webbrowser.open(auth_url_query)
# Wait for the user to enter the authorization code
redirect_url = input("Enter the URL you were redirected to: ").strip()
auth_code = redirect_url.split("?code=")[1].split("&state=")[0]
# Exchange the authorization code for an access token
token_url = "https://accounts.spotify.com/api/token"
token_data = {
"grant_type": "authorization_code",
"code": auth_code,
"redirect_uri": redirect_uri,
"client_id": client_id,
"client_secret": client_secret
}
token_headers = {
"Authorization": f"Basic {client_creds_b64}"
}
response = requests.post(token_url, data=token_data, headers=token_headers)
if response.status_code not in range(200, 299):
print(f"Failed to retrieve access token. {response.status_code} - {response.text}")
exit()
response_data = response.json()
access_token = response_data["access_token"]
refresh_token = response_data["refresh_token"]
expires_in = response_data["expires_in"]
# Set up headers for API requests
api_headers = {
"Authorization": f"Bearer {access_token}"
}
# Create a new playlist or choose an existing playlist
while True:
user_profile_url = endpoint + "me"
user_profile_response = requests.get(user_profile_url, headers=api_headers)
if user_profile_response.status_code != 200:
print(f"Failed to get user profile. {user_profile_response.status_code} - {user_profile_response.text}")
continue
user_profile_data = user_profile_response.json()
user_id = user_profile_data["id"]
# Filter out unavailable and removed songs from a playlist
playlist_url = input("Enter a Spotify playlist link to filter out unavailable and removed songs: ").strip()
playlist_id_match = re.search(r"playlist/(\w+)", playlist_url)
if not playlist_id_match:
print("Invalid playlist link. Please enter a valid Spotify playlist link.")
continue
playlist_id = playlist_id_match.group(1)
# Get playlist tracks
playlist_tracks_url = endpoint + f"playlists/{playlist_id}/tracks?market=from_token"
playlist_tracks_response = requests.get(playlist_tracks_url, headers=api_headers)
if playlist_tracks_response.status_code != 200:
print(f"Failed to get playlist tracks. {playlist_tracks_response.status_code} - {playlist_tracks_response.text}")
continue
playlist_tracks_data = playlist_tracks_response.json()
playlist_tracks = playlist_tracks_data["items"]
# Create a new playlist with the filtered tracks
new_playlist_name = input("Enter a name for the new playlist: ")
new_playlist_description = input("Enter a description for the new playlist: ")
new_playlist_url = endpoint + f"users/{user_id}/playlists"
new_playlist_payload = {
"name": new_playlist_name,
"description": new_playlist_description,
"public": False
}
new_playlist_response = requests.post(
new_playlist_url,
headers=api_headers,
json=new_playlist_payload
)
if new_playlist_response.status_code != 201:
print(f"Failed to create new playlist. {new_playlist_response.status_code} - {new_playlist_response.text}")
exit()
new_playlist_data = new_playlist_response.json()
new_playlist_id = new_playlist_data["id"]
# Filter out unavailable and removed tracks
filtered_tracks = []
for track in playlist_tracks:
# Check if the track is removed or unavailable
if not track.get("is_playable", True) or track.get("is_local"):
print(f"Skipping track {track['track']['name']}. Reason: unavailable or local.")
filtered_tracks.append(track)
# Add filtered tracks to new playlist
add_tracks_url = endpoint + f"playlists/{new_playlist_id}/tracks"
track_uris = [f"spotify:track:{track['track']['id']}" for track in filtered_tracks]
add_tracks_data = {
"uris": track_uris
}
add_tracks_response = requests.post(add_tracks_url, headers=api_headers, json=add_tracks_data)
if add_tracks_response.status_code != 201:
print(f"Failed to add tracks to new playlist. {add_tracks_response.status_code} - {add_tracks_response.text}")
else:
print(f"Added {len(filtered_tracks)} tracks to new playlist.")
# Set the initial offset and limit
offset = 0
limit = 100
# Loop through all the tracks in the playlist
while True:
# Set the query parameters
params = {
"offset": offset,
"limit": limit,
"fields": "items(track(name, id, uri, is_local, available_markets))"
}
# Make the request to the API
response = requests.get(url, headers=headers, params=params)
# Check if the response was successful
if response.status_code != 200:
print(f"Error: {response.status_code} - {response.text}")
break
# Parse the response JSON
data = json.loads(response.text)
# Loop through the tracks in the response
for item in data["items"]:
track = item["track"]
track_name = track["name"]
track_id = track["id"]
track_uri = track["uri"]
is_local = track["is_local"]
available_markets = track["available_markets"]
# Do something with the track information here
print(f"Track Name: {track_name}")
print(f"Track ID: {track_id}")
print(f"Track URI: {track_uri}")
print(f"Is Local: {is_local}")
print(f"Available Markets: {available_markets}")
# Check if there are more tracks to retrieve
if data["next"] is None:
break
# Update the offset
offset += limit
""" playlist_url = endpoint + f"users/{user_id}/playlists"
playlist_data = {
"name": playlist_name,
"public": False
}
playlist_response = requests.post(playlist_url, json=playlist_data, headers=api_headers)
if playlist_response.status_code != 201:
print(f"Failed to create playlist. {playlist_response.status_code} - {playlist_response.text}")
playlist_data = playlist_response.json()
playlist_id = playlist_data["id"]
print(f"Playlist '{playlist_name}' created with ID '{playlist_id}'")
break
elif choice == "existing":
# Choose an existing playlist
playlist_id = input("Enter the ID of the existing playlist: ").strip()
playlist_url = endpoint + f"playlists/{playlist_id}"
playlist_response = requests.get(playlist_url, headers=api_headers)
if playlist_response.status_code != 200:
print(f"Failed to get playlist. {playlist_response.status_code} - {playlist_response.text}")
continue
playlist_data = playlist_response.json()
playlist_name = playlist_data["name"]
print(f"Playlist '{playlist_name}' chosen with ID '{playlist_id}'")
break
else:
print("Invalid choice. Please enter 'new' or 'existing'.")
"""