mirror of
https://github.com/JonasunderscoreJones/turbo-octo-potato.git
synced 2025-10-28 03:29:18 +01:00
moved to spearate directory
This commit is contained in:
parent
908630443b
commit
3e4dbc012d
11 changed files with 301 additions and 8 deletions
111
spotify_scripts/discographymaker.py
Normal file
111
spotify_scripts/discographymaker.py
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
from dotenv import load_dotenv
|
||||
import spotipy
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
import top_lib
|
||||
|
||||
load_dotenv()
|
||||
|
||||
VERBOSE = True
|
||||
|
||||
artists = []
|
||||
albums = []
|
||||
|
||||
def verboseprint(message: str) -> None:
|
||||
if VERBOSE:
|
||||
print(message)
|
||||
|
||||
def remove_duplicates(input_list: list) -> list:
|
||||
return list(set(input_list))
|
||||
|
||||
def getDiscographyArtist(sp: spotipy.Spotify, first = False):
|
||||
while True:
|
||||
if first:
|
||||
user_artist_input = input("Input your first Artist (name, spotify ID or artist link). Enter other's when prompted next:\n")
|
||||
else:
|
||||
print("======================")
|
||||
user_artist_input = input("Input your next Artist (name or Spotify ID). Leave empty if all have been inputed\n")
|
||||
if user_artist_input == "": return
|
||||
|
||||
print("Looking up Artist...")
|
||||
try:
|
||||
if len(user_artist_input) == 22:
|
||||
if input("Did you Enter an ID? [ENTER for Yes, No for treating your Input as a name]: ") == "":
|
||||
return user_artist_input
|
||||
if len(user_artist_input) >= 54:
|
||||
withoutlink = user_artist_input.replace("https://open.spotify.com/artist/", "")
|
||||
if len(withoutlink) + 32 == len(user_artist_input):
|
||||
print(withoutlink[0:22])
|
||||
return withoutlink[0:22]
|
||||
search_results = sp.search(q=user_artist_input, type='artist', limit=1)
|
||||
if search_results['artists']['items'][0]['name'] != user_artist_input:
|
||||
correct_input = input(" The Artist doesn't exist on Spotify. Did you mean \"" + search_results['artists']['items'][0]['name'] + "\" [ENTER for Yes, No for retry]: ")
|
||||
if correct_input == "":
|
||||
return search_results['artists']['items'][0]['uri'].replace("spotify:artist:", "")
|
||||
else:
|
||||
print("All good, try again!")
|
||||
continue
|
||||
return search_results['artists']['items'][0]['uri'].replace("spotify:artist:", "")
|
||||
except TimeoutError:
|
||||
print("\nNetwork unreachable. Please Try again...\n")
|
||||
|
||||
def insertion_sort(data_list):
|
||||
for i in range(1, len(data_list)):
|
||||
current_album = data_list[i]
|
||||
current_date = current_album[2] # Using index 2 for the release date
|
||||
|
||||
j = i - 1
|
||||
while j >= 0 and data_list[j][2] > current_date:
|
||||
data_list[j + 1] = data_list[j]
|
||||
j -= 1
|
||||
data_list[j + 1] = current_album
|
||||
return data_list
|
||||
|
||||
def createPlaylist(sp: spotipy.Spotify, songs: list[(str, str, str, str)], userId:str, artist: str = None):
|
||||
if artist == None:
|
||||
artist = input("Primary Artist: ")
|
||||
playlist = sp.user_playlist_create(userId, artist + " Chronological Discography", description="Full Discography of " + artist + " and Solo Releases - no inst., no OSTs")
|
||||
print('New Playlist created')
|
||||
print("Name: " + playlist['name'])
|
||||
print("ID: " + playlist['id'])
|
||||
print("Description:", playlist['description'])
|
||||
print("FAILED TO SET DESCRIPTION (Spotify API Bug)\nThe playlist was created anyways") if playlist['description'] == None else None
|
||||
while len(songs) > 100:
|
||||
sp.playlist_add_items(playlist['id'], songs[:100])
|
||||
songs = songs[100:]
|
||||
sp.playlist_add_items(playlist['id'], songs)
|
||||
return playlist
|
||||
|
||||
if __name__ == "__main__":
|
||||
verboseprint("Authenticating...")
|
||||
authenticator = top_lib.Auth(verbose=VERBOSE)
|
||||
sp = authenticator.newSpotifyauth("playlist-modify-public playlist-modify-private")
|
||||
verboseprint("Authenticated!")
|
||||
|
||||
spotifyManager = top_lib.SpotifyManager(sp)
|
||||
|
||||
artist = getDiscographyArtist(sp, True)
|
||||
while artist != None:
|
||||
artists.append(artist)
|
||||
artist = getDiscographyArtist(sp)
|
||||
|
||||
def sort_key(item):
|
||||
return item[2]
|
||||
|
||||
verboseprint("Fetching Albums...")
|
||||
albums_unsorted = []
|
||||
for artist in remove_duplicates(artists):
|
||||
albums_unsorted.extend(spotifyManager.fetchArtistAlbums(artist, raise_error=False)[0])
|
||||
albums = insertion_sort(albums_unsorted)
|
||||
verboseprint("Found " + str(len(albums))+ " Albums!")
|
||||
|
||||
all_song_uris = []
|
||||
for album_id in albums:
|
||||
album_song_uris = spotifyManager.getTrackUrisFromAlbum(album_id[1])
|
||||
all_song_uris.extend(album_song_uris)
|
||||
|
||||
playlist = createPlaylist(sp, all_song_uris, authenticator.getCreds()['SPOTIFY_USER_ID'], albums[0][3] if len(artists) == 1 else None)
|
||||
|
||||
print("Playlist created! Check your Spotify!")
|
||||
34
spotify_scripts/getlastfmartists.py
Normal file
34
spotify_scripts/getlastfmartists.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import pylast, time
|
||||
|
||||
# Replace with your Last.fm API credentials
|
||||
API_KEY = ""
|
||||
API_SECRET = ""
|
||||
USERNAME = "Jonas_Jones"
|
||||
PASSWORD = "" # Leave this empty if you're not using a password
|
||||
|
||||
# Create a Last.fm network object
|
||||
network = pylast.LastFMNetwork(
|
||||
api_key=API_KEY, api_secret=API_SECRET, username=USERNAME, password_hash=PASSWORD
|
||||
)
|
||||
|
||||
def get_listened_artists():
|
||||
user = network.get_user(USERNAME)
|
||||
recent_tracks = user.get_recent_tracks(limit=None) # Fetch all recent tracks
|
||||
listened_artists = set()
|
||||
for track in recent_tracks:
|
||||
artist = track.track.artist
|
||||
if not artist in listened_artists:
|
||||
print(artist)
|
||||
listened_artists.add(artist)
|
||||
|
||||
return listened_artists
|
||||
|
||||
if __name__ == "__main__":
|
||||
start = time.time()
|
||||
listened_artists = get_listened_artists()
|
||||
end = time.time()
|
||||
print("Listened Artists:")
|
||||
for artist in listened_artists:
|
||||
print(artist)
|
||||
|
||||
print("Time elapsed: " + str(end - start) + " seconds")
|
||||
39
spotify_scripts/getlastfmartistsslower.py
Normal file
39
spotify_scripts/getlastfmartistsslower.py
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import pylast
|
||||
|
||||
# Replace with your Last.fm API credentials
|
||||
API_KEY = ""
|
||||
API_SECRET = ""
|
||||
USERNAME = "Jonas_Jones"
|
||||
PASSWORD = "" # Leave this empty if you're not using a password
|
||||
|
||||
# Create a Last.fm network object
|
||||
network = pylast.LastFMNetwork(
|
||||
api_key=API_KEY, api_secret=API_SECRET, username=USERNAME, password_hash=PASSWORD
|
||||
)
|
||||
|
||||
def get_listened_artists(limit_per_batch=100):
|
||||
user = network.get_user(USERNAME)
|
||||
|
||||
page = 1
|
||||
listened_artists = set()
|
||||
|
||||
while True:
|
||||
recent_tracks = user.get_recent_tracks(limit=limit_per_batch, page=page)
|
||||
if not recent_tracks:
|
||||
break
|
||||
|
||||
for track in recent_tracks:
|
||||
artist = track.track.artist
|
||||
listened_artists.add(artist)
|
||||
|
||||
page += 1
|
||||
|
||||
return listened_artists
|
||||
|
||||
if __name__ == "__main__":
|
||||
listened_artists = get_listened_artists()
|
||||
|
||||
print("Listened Artists:")
|
||||
for artist in listened_artists:
|
||||
print(artist)
|
||||
|
||||
38
spotify_scripts/getlasttracksp.py
Normal file
38
spotify_scripts/getlasttracksp.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
'''Get the last spotify track'''
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
import top_lib
|
||||
|
||||
# load .env file
|
||||
load_dotenv()
|
||||
|
||||
# Set up your Spotify API credentials
|
||||
SPOTIFY_CLIENT_ID = os.getenv('SPOTIFY_CLIENT_ID')
|
||||
SPOTIFY_CLIENT_SECRET = os.getenv('SPOTIFY_CLIENT_SECRET')
|
||||
SPOTIFY_REDIRECT_URI = os.getenv('SPOTIFY_REDIRECT_URI')
|
||||
PLAYLIST_ID = os.getenv('SOMEPLAYLIST_ID')
|
||||
|
||||
if not SPOTIFY_CLIENT_ID or not SPOTIFY_CLIENT_SECRET or \
|
||||
not SPOTIFY_REDIRECT_URI or not PLAYLIST_ID:
|
||||
raise ValueError("Please provide the required information in the .env file.")
|
||||
|
||||
# Create a Spotipy instance with authentication
|
||||
auth_manager = top_lib.Auth(verbose=True)
|
||||
sp = auth_manager.newSpotifyauth("playlist-read-private")
|
||||
|
||||
def get_last_track_of_playlist(playlist_id: str) -> dict:
|
||||
'''Get the last track of a playlist'''
|
||||
# Get the playlist's tracks
|
||||
playlist = sp.playlist_tracks(playlist_id)
|
||||
|
||||
# Extract the last track
|
||||
return playlist["items"][-1]["track"]
|
||||
|
||||
# Retrieve the last track of the playlist
|
||||
last_track = get_last_track_of_playlist(PLAYLIST_ID)
|
||||
|
||||
# Access information about the last track
|
||||
print("Last Track Name:", last_track["name"])
|
||||
print("Last Track Artist:", last_track["artists"][0]["name"])
|
||||
print("Last Track URI:", last_track["uri"])
|
||||
76
spotify_scripts/intro_outro_playlist_maker.py
Normal file
76
spotify_scripts/intro_outro_playlist_maker.py
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
'''Make a playlist of all the intro/outro songs from your followed artists'''
|
||||
from dotenv import load_dotenv
|
||||
import spotipy
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
import top_lib
|
||||
|
||||
# WARNING: THIS WILL RATELIMIT THE SHIT OUT OF YOUR ACCOUNT
|
||||
|
||||
load_dotenv()
|
||||
|
||||
INTROOUTROPLAYLIST_ID = os.getenv('INTROOUTROPLAYLIST_ID')
|
||||
|
||||
print(INTROOUTROPLAYLIST_ID)
|
||||
|
||||
def track_is_eligible(track_dict:dict) -> bool:
|
||||
'''Check whether or not a track is an intro/outro
|
||||
|
||||
track: track dict object from spotify api
|
||||
|
||||
Returns: whether or not the track is eligble or not'''
|
||||
if track_dict['duration_ms'] < 90000:
|
||||
return True
|
||||
if "intro" in track_dict['name'].lower() or "outro" in track_dict['name'].lower():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
API_CALL_COUNT = 0
|
||||
print("Authenticating...")
|
||||
authenticator = top_lib.Auth(verbose=True)
|
||||
sp = authenticator.newSpotifyauth(
|
||||
"user-follow-read playlist-modify-public playlist-modify-private")
|
||||
spotifyManager = top_lib.SpotifyManager(sp)
|
||||
print("Authenticated!")
|
||||
print("Fetching Artists...")
|
||||
artists = spotifyManager.fetchUserFollowedArtists()
|
||||
API_CALL_COUNT += 4
|
||||
print("Found " + str(len(artists))+ " Artists!")
|
||||
|
||||
track_uris = []
|
||||
ARTIST_NUM = len(artists)
|
||||
NOW_ARTIST = 0
|
||||
for artist in artists:
|
||||
NOW_ARTIST += 1
|
||||
try:
|
||||
print(f"[{NOW_ARTIST}/{ARTIST_NUM}]{API_CALL_COUNT}] Fetching albums for", artist[1])
|
||||
albums = spotifyManager.fetchArtistAlbums(artist[0])
|
||||
API_CALL_COUNT += 1
|
||||
except top_lib.SpotifyTooManyAlbumsError:
|
||||
print(f"[{NOW_ARTIST}/{ARTIST_NUM}]{API_CALL_COUNT}] Error fetching albums for",
|
||||
artist[1])
|
||||
continue
|
||||
for album in albums[0]:
|
||||
print(f"[{NOW_ARTIST}/{ARTIST_NUM}]{API_CALL_COUNT}] Fetching tracks for", album[0])
|
||||
album_track_uris = spotifyManager.getTrackUrisFromAlbum(album[1])
|
||||
API_CALL_COUNT += 1
|
||||
for track_uri in album_track_uris:
|
||||
track = sp.track(track_uri)
|
||||
API_CALL_COUNT += 1
|
||||
if track_is_eligible(track):
|
||||
print(f"[{NOW_ARTIST}/{ARTIST_NUM}]{API_CALL_COUNT}] " + \
|
||||
track['artists'][0]['name'], track['name'])
|
||||
track_uris.append(track_uri)
|
||||
sp.playlist_add_items(INTROOUTROPLAYLIST_ID, [track_uri])
|
||||
API_CALL_COUNT += 1
|
||||
continue
|
||||
print(f"[{NOW_ARTIST}/{ARTIST_NUM}]{API_CALL_COUNT}] Skipping",
|
||||
track['artists'][0]['name'], track['name'], end="\r")
|
||||
print(f"\n[{NOW_ARTIST}/{ARTIST_NUM}]{API_CALL_COUNT}] Done with", album[0])
|
||||
print(f"[{NOW_ARTIST}/{ARTIST_NUM}]{API_CALL_COUNT}] Done with", artist[1])
|
||||
print(f"[{NOW_ARTIST}/{ARTIST_NUM}]{API_CALL_COUNT}] Done with all artists")
|
||||
print("TOOK THIS MANY API CALLS: ", API_CALL_COUNT)
|
||||
141
spotify_scripts/kprofilesfetch.py
Normal file
141
spotify_scripts/kprofilesfetch.py
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
'''Fetch the monthly comeback/debut/release pages on kprofiles.com'''
|
||||
import datetime
|
||||
import requests
|
||||
import dotenv
|
||||
import spotipy
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
import top_lib
|
||||
|
||||
dotenv.load_dotenv()
|
||||
|
||||
WORKING_DIR = os.getenv('WORKING_DIR')
|
||||
|
||||
|
||||
def get_links():
|
||||
'''Get the links to the monthly comeback/debut/release pages on kprofiles.com
|
||||
|
||||
Returns: a list of links to the monthly comeback/debut/release pages on kprofiles.com'''
|
||||
links = []
|
||||
|
||||
# Starting month and year
|
||||
start_date = datetime.date(2020, 3, 1)
|
||||
|
||||
# End month and year
|
||||
end_date = datetime.date.today().replace(day=1)
|
||||
end_date = end_date.replace(month=end_date.month + 1) if end_date.month != 12 \
|
||||
else end_date.replace(year=end_date.year + 1, month=1)
|
||||
current_date = start_date
|
||||
while current_date <= end_date:
|
||||
# Construct the URL based on the current month and year
|
||||
links.append(f"https://kprofiles.com/{current_date.strftime('%B').lower() }" + \
|
||||
f"-{current_date.year}-comebacks-debuts-releases/")
|
||||
|
||||
# Move to the next month
|
||||
if current_date.month == 12:
|
||||
current_date = current_date.replace(year=current_date.year + 1, month=1)
|
||||
else:
|
||||
current_date = current_date.replace(month=current_date.month + 1)
|
||||
|
||||
return links
|
||||
|
||||
def check_link_extensions(link, comeback_compilation):
|
||||
'''Check if the link is valid
|
||||
|
||||
link: the link to check
|
||||
comeback_compilation: the text of the kprofiles comeback compilation page
|
||||
|
||||
Returns: the link if it is valid, None if it is not'''
|
||||
if link in comeback_compilation:
|
||||
return link
|
||||
link_base = link.copy()
|
||||
if link.replace("-debuts-releases", "") in comeback_compilation:
|
||||
link = link.replace("-debuts-releases", "")
|
||||
elif link.replace("-comebacks-debuts-releases", "") in comeback_compilation:
|
||||
link = link.replace("-comebacks-debuts-releases", "")
|
||||
elif link.replace("-comebacks-debuts-releases", "-kpop") in comeback_compilation:
|
||||
link = link.replace("-comebacks-debuts-releases", "-kpop")
|
||||
elif link[:-1] + "-2/" in comeback_compilation:
|
||||
link = link[:-1] + "-2/" # WHY IS OCTOBER 2020 THE ONLY MONTH WITH A -2
|
||||
elif link.replace("-comebacks-debuts-releases",
|
||||
"-kpop-comebacks-debuts-releases") in comeback_compilation:
|
||||
link = link.replace("-comebacks-debuts-releases", "-kpop-comebacks-debuts-releases")
|
||||
elif link.replace("-comebacks-debuts-releases", "-kpop-comebacks") in comeback_compilation:
|
||||
link = link.replace("-comebacks-debuts-releases", "-kpop-comebacks")
|
||||
if link != link_base:
|
||||
return link
|
||||
print("Link not found: " + link)
|
||||
|
||||
|
||||
def filter_valid_links(links):
|
||||
'''Filter out invalid links
|
||||
|
||||
links: the list of links to filter
|
||||
|
||||
Returns: a list of valid links'''
|
||||
valid_links = []
|
||||
compilation_link = "https://kprofiles.com/comebacks/page/"
|
||||
comeback_compilation = ""
|
||||
for i in range(1, 100):
|
||||
request = requests.get(compilation_link + str(i))
|
||||
if request.status_code == 200:
|
||||
comeback_compilation += request.text
|
||||
else:
|
||||
break
|
||||
|
||||
for link in links:
|
||||
is_valid = check_link_extensions(link, comeback_compilation)
|
||||
if is_valid:
|
||||
valid_links.append(is_valid)
|
||||
|
||||
return valid_links
|
||||
|
||||
def fetch_site(link):
|
||||
'''Fetch the site from the given link
|
||||
|
||||
link: the link to fetch
|
||||
|
||||
Returns: the text of the site'''
|
||||
#check if file already exists
|
||||
if os.path.isfile(WORKING_DIR + "/kprofiles/" + link.split("/")[-2] + ".html") \
|
||||
and not FORCE_REFRESH:
|
||||
# read from file
|
||||
with open(WORKING_DIR + "/kprofiles/" + link.split("/")[-2] + ".html", "r") as file:
|
||||
return file.read()
|
||||
request = requests.get(link)
|
||||
if request.status_code == 200:
|
||||
# save to file
|
||||
with open(WORKING_DIR + "/kprofiles/" + link.split("/")[-2] + ".html", "w") as file:
|
||||
file.write(request.text)
|
||||
return request.text
|
||||
|
||||
def fetch_handler(links):
|
||||
'''Fetch the sites from the given links
|
||||
|
||||
links: the links to fetch
|
||||
|
||||
Returns: a list of the text of the sites'''
|
||||
data = []
|
||||
progress_bar = top_lib.Progressbar(total=len(links))
|
||||
progress_bar.print(0)
|
||||
try:
|
||||
os.makedirs(WORKING_DIR + "/kprofiles/", exist_ok=True)
|
||||
except OSError:
|
||||
print(f"Creation of the directory {WORKING_DIR}/kprofiles/ failed.")
|
||||
sys.exit(1)
|
||||
for link in links:
|
||||
data.append(fetch_site(link))
|
||||
progress_bar.print(links.index(link) + 1)
|
||||
return data
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# launch args
|
||||
FORCE_REFRESH = "-f" in sys.argv
|
||||
|
||||
print("Fetching kprofiles.com... (This may take a while, kprofiles is slow...)")
|
||||
links = get_links()
|
||||
valid_links = filter_valid_links(links)
|
||||
data = fetch_handler(valid_links)
|
||||
62
spotify_scripts/lastfm-scrobble-fetch.py
Normal file
62
spotify_scripts/lastfm-scrobble-fetch.py
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import requests
|
||||
from datetime import datetime
|
||||
import json
|
||||
import urllib.parse
|
||||
import time
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# load .env file
|
||||
load_dotenv()
|
||||
|
||||
starttime = time.time()
|
||||
|
||||
LASTFM_API_KEY = os.getenv('LASTFM_API_KEY')
|
||||
LASTFM_USERNAME = os.getenv('LASTFM_USERNAME')
|
||||
|
||||
if not LASTFM_API_KEY or not LASTFM_USERNAME:
|
||||
raise ValueError("Please provide the required information in the .env file.")
|
||||
|
||||
# Get the total number of scrobbles for the user
|
||||
url = f"http://ws.audioscrobbler.com/2.0/?method=user.getinfo&user={LASTFM_USERNAME}&api_key={LASTFM_API_KEY}&format=json"
|
||||
response = requests.get(url)
|
||||
data = response.json()
|
||||
total_scrobbles = int(data['user']['playcount'])
|
||||
|
||||
# Calculate the number of pages required for pagination
|
||||
page_count = (total_scrobbles + 200 - 1) // 200
|
||||
|
||||
# Fetch all scrobbles by paginating through the API responses
|
||||
all_scrobbles = []
|
||||
for page in range(1, page_count + 1):
|
||||
url = f"http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user={LASTFM_USERNAME}&api_key={LASTFM_API_KEY}&format=json&page={page}"
|
||||
response = requests.get(url)
|
||||
data = response.json()
|
||||
tracks = data['recenttracks']['track']
|
||||
|
||||
for track in tracks:
|
||||
artist = urllib.parse.quote(track['artist']['#text'])
|
||||
song = urllib.parse.quote(track['name'])
|
||||
|
||||
track_url = f"http://ws.audioscrobbler.com/2.0/?method=track.getInfo&api_key={LASTFM_API_KEY}&artist={artist}&track={song}&format=json"
|
||||
#print(track_url)
|
||||
track_response = requests.get(track_url)
|
||||
track_data = track_response.json()
|
||||
duration = int(track_data['track']['duration'])
|
||||
track['duration'] = duration
|
||||
all_scrobbles.append(track)
|
||||
|
||||
# Save the song list to a JSON file
|
||||
output_file = "song_list.json"
|
||||
with open(output_file, "w") as file:
|
||||
json.dump(all_scrobbles, file)
|
||||
|
||||
total_duration = sum(track['duration'] for track in all_scrobbles)
|
||||
|
||||
print(total_duration)
|
||||
# Convert the total listening time to a human-readable format
|
||||
total_time = datetime.utcfromtimestamp(total_duration).strftime('%H:%M:%S')
|
||||
|
||||
print(f"Overall Listening Time: {total_time}")
|
||||
|
||||
print(f"Took: {time.time() - starttime}")
|
||||
203
spotify_scripts/likedsongsync2-oldfix.py
Normal file
203
spotify_scripts/likedsongsync2-oldfix.py
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
import pylast, spotipy, sys, os, time
|
||||
from spotipy.oauth2 import SpotifyOAuth
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
# Define your Last.fm API credentials
|
||||
LASTFM_API_KEY = os.getenv("LASTFM_API_KEY")
|
||||
LASTFM_API_SECRET = os.getenv("LASTFM_API_SECRET")
|
||||
LASTFM_USERNAME = os.getenv("LASTFM_USERNAME")
|
||||
LASTFM_PASSWORD_HASH = os.getenv("LASTFM_PASSWORD_HASH")
|
||||
|
||||
# Define your Spotify API credentials
|
||||
SPOTIPY_CLIENT_ID = os.getenv("SPOTIFY_CLIENT_ID")
|
||||
SPOTIPY_CLIENT_SECRET = os.getenv("SPOTIFY_CLIENT_SECRET")
|
||||
SPOTIPY_REDIRECT_URI = os.getenv("SPOTIFY_REDIRECT_URI")
|
||||
|
||||
# Define your playlist IDs
|
||||
LIKEDSONGPLAYLIST_ID = os.getenv("LIKEDSONGPLAYLIST_ID")
|
||||
|
||||
def progress_bar(current, total, last_time_stamp=time.time(), etastr=None):
|
||||
current = total if current > total else current
|
||||
this_timestamp = time.time()
|
||||
width = os.get_terminal_size().columns
|
||||
progress = round((current/total)*width)
|
||||
total_num_len = len(str(total))
|
||||
if width < 2* total_num_len + 15:
|
||||
return f"{current}/{total}", this_timestamp
|
||||
else:
|
||||
current_spacer = " "*(total_num_len-len(str(current)))
|
||||
if etastr:
|
||||
eta = etastr
|
||||
else:
|
||||
eta = str(round((total - current)* (this_timestamp - last_time_stamp)/60)) + "s"
|
||||
percent = str(round(current/total*100))
|
||||
percent = " "*(3-len(percent)) + percent
|
||||
progress_bar_length = width - 2*total_num_len - 13 - len(str(eta)) - len(percent)
|
||||
progress_bar_progress = round((current/total)*progress_bar_length)
|
||||
progress_bar_spacer = " "*(progress_bar_length-progress_bar_progress)
|
||||
return f"[{current_spacer}{current}/{total}|{percent}%|ETA: {eta}|{'='*progress_bar_progress}>{progress_bar_spacer}]", this_timestamp
|
||||
|
||||
def verboseprint(message, end="\n"):
|
||||
if VERBOSE_LOGGING:
|
||||
print(message, end=end)
|
||||
|
||||
def handle_playlist_part_return(playlist_part, all_songs):
|
||||
for item in playlist_part["items"]:
|
||||
track_uri = item["track"]["uri"]
|
||||
track_name = item["track"]["name"]
|
||||
artist_name = item["track"]["artists"][0]["name"]
|
||||
all_songs.append((track_uri, track_name, artist_name))
|
||||
|
||||
return all_songs
|
||||
|
||||
def get_all_songs_from_playlist(playlist_id):
|
||||
verboseprint("Fetching songs from the liked songs playlist...")
|
||||
all_songs = []
|
||||
limit = 100 # Adjust the limit based on your needs
|
||||
offset = 0
|
||||
last_time_stamp = time.time()
|
||||
|
||||
while True:
|
||||
playlist_part = sp.playlist_items(playlist_id, limit=limit, offset=offset)
|
||||
if not playlist_part["items"]:
|
||||
break
|
||||
all_songs = handle_playlist_part_return(playlist_part, all_songs)
|
||||
|
||||
progress_print, last_time_stamp = progress_bar(offset+limit, playlist_part["total"], last_time_stamp)
|
||||
verboseprint(progress_print, end="\r")
|
||||
|
||||
offset += limit
|
||||
verboseprint("")
|
||||
return all_songs
|
||||
|
||||
def get_all_liked_songs():
|
||||
verboseprint("Fetching liked songs...")
|
||||
verboseprint("This may take a while... (the API only allows for 50 songs per request for the liked songs)")
|
||||
all_liked_songs = []
|
||||
limit = 50 # Adjust the limit based on your needs
|
||||
offset = 0
|
||||
last_time_stamp = time.time()
|
||||
|
||||
while True:
|
||||
liked_songs_chunk = sp.current_user_saved_tracks(limit=limit, offset=offset)
|
||||
if not liked_songs_chunk["items"]:
|
||||
break
|
||||
all_liked_songs = handle_playlist_part_return(liked_songs_chunk, all_liked_songs)
|
||||
|
||||
progress_print, last_time_stamp = progress_bar(offset+limit, liked_songs_chunk["total"], last_time_stamp)
|
||||
verboseprint(progress_print, end="\r")
|
||||
|
||||
offset += limit
|
||||
verboseprint("")
|
||||
return all_liked_songs
|
||||
|
||||
def is_track_in_playlist(playlist_song_list, track_uri):
|
||||
playlist_tracks = playlist_song_list
|
||||
for item in playlist_tracks:
|
||||
if item[0] == track_uri:
|
||||
return True
|
||||
return False
|
||||
|
||||
def add_track_to_playlist(playlist_id, track_uri):
|
||||
sp.playlist_add_items(playlist_id, [track_uri])
|
||||
|
||||
def remove_unliked_tracks(primary_playlist_id, liked_tracks):
|
||||
verboseprint("Removing unliked tracks from the primary playlist...")
|
||||
liked_track_uris = [track_uri for track_uri, _, _ in liked_tracks]
|
||||
primary_playlist_tracks = get_all_songs_from_playlist(primary_playlist_id)
|
||||
|
||||
#tracks_to_remove = [track_uri for track_uri in primary_playlist_tracks if track_uri not in liked_track_uris]
|
||||
|
||||
tracks_to_remove = []
|
||||
for track_uri, _, _ in primary_playlist_tracks:
|
||||
if track_uri not in liked_track_uris:
|
||||
tracks_to_remove.append(track_uri)
|
||||
|
||||
if tracks_to_remove:
|
||||
sp.playlist_remove_all_occurrences_of_items(primary_playlist_id, tracks_to_remove)
|
||||
print(f"Removed {len(tracks_to_remove)} unliked track(s) from the primary playlist.")
|
||||
print(f"Track URIs: {tracks_to_remove}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# Parse command-line arguments
|
||||
VERBOSE_LOGGING = "-v" in sys.argv or "--verbose" in sys.argv
|
||||
FORCE_RESYNC_ALL = "-f" in sys.argv or "--force-all" in sys.argv
|
||||
|
||||
try:
|
||||
SKIPSONGS = int(sys.argv[sys.argv.index("--skip") + 1]) if "--skip" in sys.argv else int(sys.argv[sys.argv.index("-s") + 1]) if "-s" in sys.argv else 0
|
||||
except:
|
||||
print("[--skip/-s] Require a number to be set.")
|
||||
print("E.g.: --skip 88")
|
||||
exit()
|
||||
|
||||
verboseprint("Authenticating Spotify...")
|
||||
|
||||
# Create a Spotipy instance with authentication
|
||||
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=SPOTIPY_CLIENT_ID, client_secret=SPOTIPY_CLIENT_SECRET, redirect_uri=SPOTIPY_REDIRECT_URI, scope="user-library-read playlist-modify-public playlist-modify-private"))
|
||||
|
||||
verboseprint("Authenticating Last.fm...")
|
||||
|
||||
# Set up Last.fm network
|
||||
network = pylast.LastFMNetwork(api_key=LASTFM_API_KEY, api_secret=LASTFM_API_SECRET, username=LASTFM_USERNAME, password_hash=LASTFM_PASSWORD_HASH)
|
||||
|
||||
# Main loop for syncing liked songs
|
||||
liked_songs = get_all_liked_songs()
|
||||
|
||||
#remove_unliked_tracks(LIKEDSONGPLAYLIST_ID, liked_songs)
|
||||
|
||||
liked_songs_playlist_songs = get_all_songs_from_playlist(LIKEDSONGPLAYLIST_ID)
|
||||
|
||||
if not FORCE_RESYNC_ALL:
|
||||
verboseprint("Syncing only new songs...")
|
||||
liked_songs = [x for x in liked_songs if x not in liked_songs_playlist_songs]
|
||||
print(liked_songs)
|
||||
if len(liked_songs) == 0:
|
||||
print("Nothing to do.")
|
||||
exit()
|
||||
print(f"Number of liked tracks: {len(liked_songs)}")
|
||||
print(f"Number of playlist songs: {len(liked_songs_playlist_songs)}")
|
||||
print(f"Skipping the first {SKIPSONGS} songs...")
|
||||
tracknr = 0
|
||||
last_time_stamp = time.time()
|
||||
for track_uri, track_name, artist_name in liked_songs:
|
||||
tracknr += 1
|
||||
|
||||
def loop_do(last_time_stamp):
|
||||
track = sp.track(track_uri)
|
||||
fm_track = network.get_track(artist_name, track_name)
|
||||
fm_track.love()
|
||||
fm_track.add_tags(("awesome", "favorite"))
|
||||
|
||||
if not is_track_in_playlist(liked_songs_playlist_songs, track_uri):
|
||||
add_track_to_playlist(LIKEDSONGPLAYLIST_ID, track_uri)
|
||||
if VERBOSE_LOGGING:
|
||||
verboseprint("[" + f"%{4 + len(str(len(liked_songs)))*2}s" % (f"{tracknr}/{len(liked_songs)}|+]") + "%30.32s %s" % (track['artists'][0]['name'], track['name']))
|
||||
#verboseprint("%-10s %15s" % (f"ETA:{round((((int(len(liked_songs))-tracknr)*0.75)/60))}min", f"[{tracknr}/{int(len(liked_songs))}|+]") + "%30.32s %s" % (track['artists'][0]['name'], track['name']))
|
||||
elif VERBOSE_LOGGING:
|
||||
verboseprint("[" + f"%{2 + len(str(len(liked_songs)))*2}s" % (f"{tracknr}/{len(liked_songs)}]") + "%32.32s %s" % (track['artists'][0]['name'], track['name']))
|
||||
#verboseprint("%-10s %13s" % (f"ETA:{round((((int(len(liked_songs))-tracknr)*0.75)/60))}min", f"[{tracknr}/{int(len(liked_songs))}]") + "%32.32s %s" % (track['artists'][0]['name'], track['name']))
|
||||
verboseprint('#'* os.get_terminal_size().columns, end="\r")
|
||||
|
||||
progress_print, last_time_stamp = progress_bar(tracknr, len(liked_songs), etastr=str(round((((int(len(liked_songs))-tracknr)*0.75)/60)))+"min")
|
||||
verboseprint(progress_print, end="\r")
|
||||
return last_time_stamp
|
||||
# Loop until the API call succeeds
|
||||
while tracknr > SKIPSONGS:
|
||||
try:
|
||||
last_time_stamp = loop_do(last_time_stamp)
|
||||
break
|
||||
except KeyboardInterrupt: # Allow the user to interrupt the script
|
||||
exit()
|
||||
except spotipy.SpotifyException as e:
|
||||
if e.http_status == 429:
|
||||
time.sleep(30)
|
||||
verboseprint(" ]")
|
||||
verboseprint("WARN:RATELIMIT EXCEEDED] Waiting 30 seconds to proceed...")
|
||||
else:
|
||||
print(e.http_status)
|
||||
except e:
|
||||
continue
|
||||
260
spotify_scripts/likedsongsync2.py
Normal file
260
spotify_scripts/likedsongsync2.py
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
'''A script to sync your liked songs from Spotify to Last.fm and a Spotify
|
||||
playlist that can be made public (unlike the built-in liked songs playlist).'''
|
||||
import time
|
||||
from dotenv import load_dotenv
|
||||
import spotipy
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
import top_lib
|
||||
|
||||
# load .env file
|
||||
load_dotenv()
|
||||
|
||||
# Define your playlist IDs
|
||||
LIKEDSONGPLAYLIST_ID = os.getenv('LIKEDSONGPLAYLIST_ID')
|
||||
|
||||
def progress_bar(current, total, last_time_stamp=float, etastr=None):
|
||||
'''A function to print a progress bar to the terminal.
|
||||
current: The current progress
|
||||
total: The total progress
|
||||
last_time_stamp: The time stamp of the last call of this function
|
||||
etastr: The estimated time until completion as a string
|
||||
|
||||
Returns: A string with the progress bar'''
|
||||
current = total if current > total else current
|
||||
this_timestamp = time.time()
|
||||
width = os.get_terminal_size().columns
|
||||
#progress = round((current/total)*width)
|
||||
total_num_len = len(str(total))
|
||||
if width < 2* total_num_len + 15:
|
||||
return f"{current}/{total}", this_timestamp
|
||||
|
||||
current_spacer = " "*(total_num_len-len(str(current)))
|
||||
if etastr:
|
||||
eta = etastr
|
||||
else:
|
||||
eta = str(round((total - current) *
|
||||
(this_timestamp - last_time_stamp)/60)) + "s"
|
||||
percent = str(round(current/total*100))
|
||||
percent = " "*(3-len(percent)) + percent
|
||||
progress_bar_length = width - 2 * \
|
||||
total_num_len - 13 - len(str(eta)) - len(percent)
|
||||
progress_bar_progress = round((current/total)*progress_bar_length)
|
||||
progress_bar_spacer = " "*(progress_bar_length-progress_bar_progress)
|
||||
return f"[{current_spacer}{current}/{total}|{percent}%|ETA: {eta}|" + \
|
||||
f"{'='*progress_bar_progress}>{progress_bar_spacer}]", \
|
||||
this_timestamp
|
||||
|
||||
def verboseprint(message, end="\n"):
|
||||
'''A function to print verbose output.
|
||||
|
||||
message: The message to print
|
||||
end: The end character to use for the print function'''
|
||||
if VERBOSE_LOGGING:
|
||||
print(message, end=end)
|
||||
|
||||
def handle_playlist_part_return(playlist_part:str, all_songs:list):
|
||||
'''A function to handle parsing the playlist part and adding them to the
|
||||
list of all songs.
|
||||
|
||||
playlist_part: The playlist part to handle
|
||||
all_songs: The list of all songs to append the new songs to
|
||||
|
||||
Returns: The updated list of all songs'''
|
||||
for item in playlist_part["items"]:
|
||||
track_uri = item["track"]["uri"]
|
||||
track_name = item["track"]["name"]
|
||||
artist_name = item["track"]["artists"][0]["name"]
|
||||
all_songs.append((track_uri, track_name, artist_name))
|
||||
|
||||
return all_songs
|
||||
|
||||
def get_all_songs_from_playlist(playlist_id):
|
||||
'''A function to get all songs from a playlist.
|
||||
|
||||
playlist_id: The ID of the playlist to get the songs from
|
||||
|
||||
Returns: A list of all songs in the playlist'''
|
||||
verboseprint("Fetching songs from the liked songs playlist...")
|
||||
progressbar = top_lib.Progressbar()
|
||||
progress_bar_eta_manager = top_lib.ProgressBarEtaManager()
|
||||
all_songs = []
|
||||
limit = 100
|
||||
offset = 0
|
||||
|
||||
while True:
|
||||
playlist_part = sp.playlist_items(playlist_id,
|
||||
limit=limit,
|
||||
offset=offset)
|
||||
if not playlist_part["items"]:
|
||||
break
|
||||
all_songs = handle_playlist_part_return(playlist_part, all_songs)
|
||||
|
||||
progress_bar_eta_manager.now()
|
||||
progressbar.setTotal(playlist_part["total"])
|
||||
progress_print = progressbar.buildSnapshot(offset+limit,
|
||||
progress_bar_eta_manager
|
||||
.getAvgEta()/limit)
|
||||
verboseprint(progress_print, end="\r")
|
||||
|
||||
offset += limit
|
||||
verboseprint("")
|
||||
return all_songs
|
||||
|
||||
def get_all_liked_songs():
|
||||
'''A function to get all liked songs from Spotify.
|
||||
|
||||
Returns: A list of all liked songs'''
|
||||
verboseprint("Fetching liked songs...")
|
||||
verboseprint("This may take a while...(the API only allows for " + \
|
||||
"50 songs per request for the liked songs)")
|
||||
progressbar = top_lib.Progressbar()
|
||||
progress_bar_eta_manager = top_lib.ProgressBarEtaManager()
|
||||
all_liked_songs = []
|
||||
limit = 50
|
||||
offset = 0
|
||||
|
||||
while True:
|
||||
liked_songs_chunk = sp.current_user_saved_tracks(limit=limit,
|
||||
offset=offset)
|
||||
if not liked_songs_chunk["items"]:
|
||||
break
|
||||
all_liked_songs = handle_playlist_part_return(liked_songs_chunk,
|
||||
all_liked_songs)
|
||||
|
||||
progress_bar_eta_manager.now()
|
||||
progressbar.setTotal(liked_songs_chunk["total"])
|
||||
progress_print = progressbar.buildSnapshot(offset+limit,
|
||||
progress_bar_eta_manager
|
||||
.getAvgEta()/limit)
|
||||
verboseprint(progress_print, end="\r")
|
||||
|
||||
offset += limit
|
||||
verboseprint("")
|
||||
return all_liked_songs
|
||||
|
||||
def is_track_in_playlist(playlist_song_list, track_uri):
|
||||
'''A function to check if a track is in a playlist.
|
||||
|
||||
playlist_song_list: The list of songs in the playlist
|
||||
track_uri: The URI of the track to check
|
||||
|
||||
Returns: True if the track is in the playlist, False otherwise'''
|
||||
playlist_tracks = playlist_song_list
|
||||
for item in playlist_tracks:
|
||||
if item[0] == track_uri:
|
||||
return True
|
||||
return False
|
||||
|
||||
def add_track_to_playlist(playlist_id, track_uri):
|
||||
'''A function to add a track to a playlist.
|
||||
|
||||
playlist_id: The ID of the playlist to add the track to
|
||||
track_uri: The URI of the track to add to the playlist'''
|
||||
sp.playlist_add_items(playlist_id, [track_uri])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# Parse command-line arguments
|
||||
VERBOSE_LOGGING = "-v" in sys.argv or "--verbose" in sys.argv
|
||||
FORCE_RESYNC_ALL = "-f" in sys.argv or "--force-all" in sys.argv
|
||||
|
||||
try:
|
||||
SKIPSONGS = int(sys.argv[sys.argv.index("--skip") + 1]) if "--skip" \
|
||||
in sys.argv else int(sys.argv[sys.argv.index("-s") + 1]) \
|
||||
if "-s" in sys.argv else 0
|
||||
except ValueError:
|
||||
print("[--skip/-s] Require a number to be set.")
|
||||
print("E.g.: --skip 88")
|
||||
sys.exit(-1)
|
||||
|
||||
verboseprint("Authenticating Spotify...")
|
||||
|
||||
authenticator = top_lib.Auth(verbose=VERBOSE_LOGGING)
|
||||
|
||||
# Create a Spotipy instance with authentication
|
||||
sp = authenticator.newSpotifyauth(
|
||||
scope="user-library-read playlist-modify-public playlist-modify-private")
|
||||
|
||||
verboseprint("Authenticating Last.fm...")
|
||||
|
||||
# Set up Last.fm network
|
||||
network = authenticator.newLastfmauth()
|
||||
|
||||
# Main loop for syncing liked songs
|
||||
liked_songs = get_all_liked_songs()
|
||||
|
||||
liked_songs_playlist_songs = get_all_songs_from_playlist(LIKEDSONGPLAYLIST_ID)
|
||||
|
||||
if not FORCE_RESYNC_ALL:
|
||||
verboseprint("Syncing only new songs...")
|
||||
liked_songs = [x for x in liked_songs if x not in liked_songs_playlist_songs]
|
||||
if len(liked_songs) == 0:
|
||||
print("Nothing to do.")
|
||||
sys.exit(0)
|
||||
verboseprint(f"Number of playlist songs: {len(liked_songs_playlist_songs)}")
|
||||
verboseprint(f"Skipping the first {SKIPSONGS} songs...")
|
||||
TRACK_NR = 0
|
||||
last_time_stamp = time.time()
|
||||
progressbar = top_lib.Progressbar()
|
||||
progressbar.setTotal(len(liked_songs))
|
||||
progressBarEtaManager = top_lib.ProgressBarEtaManager()
|
||||
for track_uri, track_name, artist_name in liked_songs[::-1]:
|
||||
TRACK_NR += 1
|
||||
|
||||
def loop_do(last_time_stamp):
|
||||
'''A function to loop until the API call succeeds.
|
||||
|
||||
last_time_stamp: The time stamp of the last call of this function
|
||||
|
||||
Returns: The time stamp of the last call of this function'''
|
||||
track = sp.track(track_uri)
|
||||
fm_track = network.get_track(artist_name, track_name)
|
||||
fm_track.love()
|
||||
fm_track.add_tags(("awesome", "favorite"))
|
||||
verboseprint(' '* os.get_terminal_size().columns, end="\r")
|
||||
if not is_track_in_playlist(liked_songs_playlist_songs, track_uri):
|
||||
verboseprint("[" + f"%{4 + len(str(len(liked_songs)))*2}s" %
|
||||
(f"{TRACK_NR}/{len(liked_songs)}|+]") +
|
||||
"%30.32s %s" % (track['artists'][0]['name'],
|
||||
track['name']))
|
||||
|
||||
else:
|
||||
verboseprint("[" + f"%{2 + len(str(len(liked_songs)))*2}s" %
|
||||
(f"{TRACK_NR}/{len(liked_songs)}]") +
|
||||
"%32.32s %s" % (track['artists'][0]['name'],
|
||||
track['name']))
|
||||
|
||||
progressBarEtaManager.now()
|
||||
#print(progressBarEtaManager.getDurations())
|
||||
#print(tracknr)
|
||||
progress_print = progressbar.buildSnapshot(TRACK_NR,
|
||||
progressBarEtaManager
|
||||
.getAvgEta())
|
||||
#print(progressBarEtaManager.getDurations())
|
||||
verboseprint(progress_print, end="\r")
|
||||
if not is_track_in_playlist(liked_songs_playlist_songs, track_uri):
|
||||
add_track_to_playlist(LIKEDSONGPLAYLIST_ID, track_uri)
|
||||
|
||||
return last_time_stamp
|
||||
# Loop until the API call succeeds
|
||||
while TRACK_NR > SKIPSONGS:
|
||||
try:
|
||||
last_time_stamp = loop_do(last_time_stamp)
|
||||
break
|
||||
except KeyboardInterrupt: # Allow the user to interrupt the script
|
||||
print("Interrupted by user.")
|
||||
sys.exit(0)
|
||||
except spotipy.SpotifyException as e:
|
||||
if e.http_status == 429:
|
||||
time.sleep(30)
|
||||
verboseprint(" ]")
|
||||
verboseprint("WARN:RATELIMIT EXCEEDED] Waiting 30 seconds to proceed...")
|
||||
else:
|
||||
verboseprint(e.http_status)
|
||||
except Exception:
|
||||
#except e:
|
||||
continue
|
||||
65
spotify_scripts/playlist_description_update.py
Normal file
65
spotify_scripts/playlist_description_update.py
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import spotipy
|
||||
from spotipy.oauth2 import SpotifyOAuth
|
||||
import hashlib
|
||||
from dotenv import load_dotenv
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
import top_lib
|
||||
|
||||
def encrypt_playlist_name(name):
|
||||
# Using SHA-256 hash function, but you can choose others like MD5 or SHA-512
|
||||
hash_object = hashlib.sha256(name.encode())
|
||||
encrypted_id = hash_object.hexdigest()
|
||||
return encrypted_id
|
||||
|
||||
def get_playlists_with_name(sp, name):
|
||||
playlists = sp.current_user_playlists()
|
||||
matching_playlists = [playlist for playlist in playlists['items'] if name in playlist['name']]
|
||||
return matching_playlists
|
||||
|
||||
def main():
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
# Set up Spotify API credentials
|
||||
SPOTIPY_CLIENT_ID = os.getenv('SPOTIPY_CLIENT_ID')
|
||||
SPOTIPY_CLIENT_SECRET = os.getenv('SPOTIPY_CLIENT_SECRET')
|
||||
SPOTIPY_REDIRECT_URI = os.getenv('SPOTIPY_REDIRECT_URI')
|
||||
|
||||
# Set up Spotify authentication
|
||||
authenticator = top_lib.Auth(verbose=True)
|
||||
sp = authenticator.newSpotifyauth(scope="user-library-read playlist-modify-public playlist-modify-private")
|
||||
|
||||
# Specify the target name in playlist
|
||||
target_name = "Chronological Discography"
|
||||
|
||||
# Get playlists with the specified name
|
||||
matching_playlists = get_playlists_with_name(sp, target_name)
|
||||
|
||||
counter = 0
|
||||
|
||||
# Print and hash the playlist names
|
||||
for playlist in matching_playlists:
|
||||
playlist_name = playlist['name']
|
||||
encrypted_id = encrypt_playlist_name(playlist_name)
|
||||
|
||||
# Print the original name and encrypted ID
|
||||
print(f"Playlist Name: {playlist_name}")
|
||||
print(f"Encrypted ID: {encrypted_id}")
|
||||
|
||||
# Update the playlist description with the encrypted ID
|
||||
new_description = f"ID: {encrypted_id} - {playlist['description']}"
|
||||
|
||||
print(f"New Description: {new_description}")
|
||||
# Uncomment the following line to actually update the playlist description
|
||||
sp.playlist_change_details(playlist['id'], description=new_description)
|
||||
|
||||
counter += 1
|
||||
print(f"Updated {counter} playlists")
|
||||
|
||||
print()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue