From 034419b9a545305e886d115fc91a340d5ea1fe80 Mon Sep 17 00:00:00 2001 From: Jonas_Jones <91549607+J-onasJones@users.noreply.github.com> Date: Thu, 31 Aug 2023 12:58:45 +0200 Subject: [PATCH] first dump I could find from my laptop --- discographymaker.py | 136 +++++++++++++++++++++++++++++++++++++++ lastfm-scrobble-fetch.py | 54 ++++++++++++++++ likedsongsync.py | 79 +++++++++++++++++++++++ linesum.py | 38 +++++++++++ trackduration-sum.py | 3 + 5 files changed, 310 insertions(+) create mode 100644 discographymaker.py create mode 100644 lastfm-scrobble-fetch.py create mode 100644 likedsongsync.py create mode 100644 linesum.py create mode 100644 trackduration-sum.py diff --git a/discographymaker.py b/discographymaker.py new file mode 100644 index 0000000..de205b4 --- /dev/null +++ b/discographymaker.py @@ -0,0 +1,136 @@ +SPOTIFY_KEY = "" +SPOTIFY_SECRET = "" +SPOTIFY_USER_ID = "" + +VERBOSE = True + +import spotipy +from spotipy.oauth2 import SpotifyOAuth + +artists = [] +albums = [] + +def verboseprint(message: str) -> None: + if VERBOSE: + print(message) + +def remove_duplicates(input_list: list) -> list: + return list(set(input_list)) + +def spotifyauth() -> spotipy.Spotify: + return spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=SPOTIFY_KEY, + client_secret=SPOTIFY_SECRET, + redirect_uri="http://localhost:6969", + scope="playlist-modify-public playlist-modify-private")) + +def getDiscographyArtist(sp: spotipy.Spotify, first = False): + while True: + if first: + user_artist_input = input("Input your first Artist (name or spotify ID). 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 + 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 ArtistAlbumGarbageHandler(apiresponse: list): + this_artist_album_part = [] + for i in apiresponse['items']: + this_artist_album_part.append((i['name'], i['id'], i['release_date'], i['artists'][0]['name'])) + verboseprint("Found " + str(len(this_artist_album_part)) + " Albums for " + apiresponse['items'][0]['artists'][0]['name']) + return this_artist_album_part + + +def getArtistAlbum(sp: spotipy.Spotify, artists: list[str]) -> list[(str, str, str, str)]: + albums = [] + for artist in artists: + try: + this_artist_albums = [] + this_artist_album_part_garbage = sp.artist_albums(artist_id=artist, album_type="album,single,compilation", limit=50) + this_artist_albums = ArtistAlbumGarbageHandler(this_artist_album_part_garbage) + if this_artist_album_part_garbage['total'] > 50: + print("There currently is a bug in the Spotify API that prevents fetching anything after the first 50 Albums. Given that your artist " + this_artist_album_part_garbage['items'][0]['artists'][0]['name'] + " has more than 50 Albums, you'll need to manually add the missing ones.") + if input("Alternatively, you can end the script here since albums will be out of order [(E/e) to end] ") in ["E", "e", "end", "End"]: + exit() + + albums.append(this_artist_albums) + + except TimeoutError: + print("\nNetwork unreachable. THIS IS NOT RECOVERABLE. Please restart the process") + exit() + return albums + +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)], artist: str = None): + if artist == None: + artist = input("Primary Artist: ") + playlist = sp.user_playlist_create(SPOTIFY_USER_ID, 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 + +def get_song_uris(album_id): + album_tracks = sp.album_tracks(album_id) + song_uris = [track['uri'] for track in album_tracks['items']] + return song_uris + +verboseprint("Authenticating...") +sp = spotifyauth() +verboseprint("Authenticated!") + +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 = [item for sublist in getArtistAlbum(sp, remove_duplicates(artists)) for item in sublist] +albums = insertion_sort(albums_unsorted) +verboseprint("Found " + str(len(albums))+ " Albums!") + +all_song_uris = [] +for album_id in albums: + album_song_uris = get_song_uris(album_id[1]) + all_song_uris.extend(album_song_uris) + +playlist = createPlaylist(sp, all_song_uris, albums[0][3] if len(artists) == 1 else None) + +print("Playlist created! Check your Spotify!") diff --git a/lastfm-scrobble-fetch.py b/lastfm-scrobble-fetch.py new file mode 100644 index 0000000..cc61f90 --- /dev/null +++ b/lastfm-scrobble-fetch.py @@ -0,0 +1,54 @@ +import requests +from datetime import datetime +import json +import urllib.parse +import time + +starttime = time.time() + +API_KEY = "" +USERNAME = "" + +# Get the total number of scrobbles for the user +url = f"http://ws.audioscrobbler.com/2.0/?method=user.getinfo&user={USERNAME}&api_key={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={USERNAME}&api_key={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={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}") \ No newline at end of file diff --git a/likedsongsync.py b/likedsongsync.py new file mode 100644 index 0000000..8e3634e --- /dev/null +++ b/likedsongsync.py @@ -0,0 +1,79 @@ +LASTFM_KEY = "" +LASTFM_SECRET = "" +SPOTIFY_KEY = "" +SPOTIFY_SECRET = "" + +VERBOSE = True + +import pylast, os, spotipy +from spotipy.oauth2 import SpotifyOAuth + +def verboseprint(message): + if VERBOSE: + print(message) + +#last.fm auth +def lastfmauth(): + SESSION_KEY_FILE = os.path.join(os.path.expanduser("~"), ".session_key") + network = pylast.LastFMNetwork(LASTFM_KEY, LASTFM_SECRET) + if not os.path.exists(SESSION_KEY_FILE): + skg = pylast.SessionKeyGenerator(network) + url = skg.get_web_auth_url() + + print(f"Please authorize this script to access your account: {url}\n") + import time + import webbrowser + + webbrowser.open(url) + + while True: + try: + session_key = skg.get_web_auth_session_key(url) + with open(SESSION_KEY_FILE, "w") as f: + f.write(session_key) + break + except pylast.WSError: + time.sleep(1) + else: + session_key = open(SESSION_KEY_FILE).read() + + network.session_key = session_key + return network + +#spotify +def spotifyauth(): + return spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=SPOTIFY_KEY, + client_secret=SPOTIFY_SECRET, + redirect_uri="http://localhost:42010", + scope="user-library-read")) +def show_tracks(results): + tracknr = results['offset'] + for item in results['items']: + track = item['track'] + tracknr+=1 + verboseprint("%-10s %13s" % (f"ETA:{round((((int(results['total'])-tracknr)*0.25)/60))}min", f"[{tracknr}/{int(results['total'])}]") + "%32.32s %s" % (track['artists'][0]['name'], track['name'])) + #TODO: Fix this abomination + try: + track = network.get_track(track['artists'][0]['name'], track['name']) + track.love() + except pylast.NetworkError: + try: + sleep(1) + track = network.get_track(track['artists'][0]['name'], track['name']) + track.love() + except pylast.NetworkError: + verboseprint("Network error. Skipping..." + "%32.32s %s" % (track['artists'][0]['name'], track['name'])) + + +verboseprint("Authenticating Spotify...") +sp = spotifyauth() +verboseprint("Done\nAuthenticating Last.fm") +network = lastfmauth() +verboseprint("Done!\nStarting...") + +results = sp.current_user_saved_tracks() +show_tracks(results) + +while results['next']: + results = sp.next(results) + show_tracks(results) diff --git a/linesum.py b/linesum.py new file mode 100644 index 0000000..74fdcda --- /dev/null +++ b/linesum.py @@ -0,0 +1,38 @@ +def convert_time_to_seconds(time_str): + # Split the time string into hours, minutes, and seconds + time_parts = time_str.split(':') + print(time_parts) + # Convert each part to an integer + minutes = int(time_parts[0]) + seconds = int(time_parts[1]) + + # Calculate the total time in seconds + total_seconds = minutes * 60 + seconds + + return total_seconds + + +input_file = 'data.txt' +total_product = 0 + +with open(input_file, 'r') as file: + for line in file: + line_parts = line.strip().split(':::') + print(line_parts) + + # Extract the relevant information + avg_track_length = line_parts[6] + play_count = int(line_parts[3]) + + if avg_track_length == 'NaN:NaN': + # Use 3 minutes and 30 seconds (3:30) as the default track length + track_length_seconds = convert_time_to_seconds('0:03:30') + else: + # Convert average track length to seconds + track_length_seconds = convert_time_to_seconds(avg_track_length) + + # Calculate the product and add it to the total + product = track_length_seconds * play_count + total_product += product + +print(f"Sum of (Average Track Length * Play Count): {total_product}") \ No newline at end of file diff --git a/trackduration-sum.py b/trackduration-sum.py new file mode 100644 index 0000000..caee695 --- /dev/null +++ b/trackduration-sum.py @@ -0,0 +1,3 @@ + + +total_duration = sum(track['duration'] for track in all_scrobbles)