diff --git a/README.md b/README.md index 053be0e..6c5918f 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,6 @@ random scripts (the repo name was recommended by github) *These scripts where once used to automate silly tasks* -# DOCUMENTATION -Visit [docs.jonasjones.dev/turbo-octo-potato](https://docs.jonasjones.dev/turbo-octo-potato) for the documentation to these scripts - # Use at your own risk! These are mostly undocumented and potentially unsafe/hacky/silly scripts that I can't bother to keep around in my Downloads folder. diff --git a/spotify_scripts/discographymaker.py b/discographymaker.py similarity index 97% rename from spotify_scripts/discographymaker.py rename to discographymaker.py index 9349c59..fa4fd85 100644 --- a/spotify_scripts/discographymaker.py +++ b/discographymaker.py @@ -1,9 +1,5 @@ -from dotenv import load_dotenv import spotipy -import sys -import os - -sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from dotenv import load_dotenv import top_lib load_dotenv() diff --git a/spotify_scripts/getlasttracksp.py b/getlasttracksp.py similarity index 100% rename from spotify_scripts/getlasttracksp.py rename to getlasttracksp.py diff --git a/spotify_scripts/intro_outro_playlist_maker.py b/intro_outro_playlist_maker.py similarity index 96% rename from spotify_scripts/intro_outro_playlist_maker.py rename to intro_outro_playlist_maker.py index 267be2c..b715b47 100644 --- a/spotify_scripts/intro_outro_playlist_maker.py +++ b/intro_outro_playlist_maker.py @@ -1,10 +1,7 @@ '''Make a playlist of all the intro/outro songs from your followed artists''' -from dotenv import load_dotenv -import spotipy -import sys import os +from dotenv import load_dotenv -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 diff --git a/spotify_scripts/kprofilesfetch.py b/kprofilesfetch.py similarity index 98% rename from spotify_scripts/kprofilesfetch.py rename to kprofilesfetch.py index c5d73f4..ac27856 100644 --- a/spotify_scripts/kprofilesfetch.py +++ b/kprofilesfetch.py @@ -1,12 +1,10 @@ '''Fetch the monthly comeback/debut/release pages on kprofiles.com''' +import os +import sys 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() diff --git a/spotify_scripts/lastfm-scrobble-fetch.py b/lastfm-scrobble-fetch.py similarity index 100% rename from spotify_scripts/lastfm-scrobble-fetch.py rename to lastfm-scrobble-fetch.py diff --git a/spotify_scripts/likedsongsync2.py b/likedsongsync2.py similarity index 99% rename from spotify_scripts/likedsongsync2.py rename to likedsongsync2.py index e63c180..b816bdc 100644 --- a/spotify_scripts/likedsongsync2.py +++ b/likedsongsync2.py @@ -1,12 +1,11 @@ '''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 +import time +import spotipy +from dotenv import load_dotenv -sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import top_lib # load .env file diff --git a/spotify_scripts/playlist_description_update.py b/playlist_description_update.py similarity index 94% rename from spotify_scripts/playlist_description_update.py rename to playlist_description_update.py index d985d0f..02130c5 100644 --- a/spotify_scripts/playlist_description_update.py +++ b/playlist_description_update.py @@ -1,11 +1,7 @@ import spotipy from spotipy.oauth2 import SpotifyOAuth -import hashlib +import hashlib, os 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): diff --git a/spotify_scripts/getlastfmartists.py b/spotify_scripts/getlastfmartists.py deleted file mode 100644 index 3d6538f..0000000 --- a/spotify_scripts/getlastfmartists.py +++ /dev/null @@ -1,34 +0,0 @@ -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") diff --git a/spotify_scripts/getlastfmartistsslower.py b/spotify_scripts/getlastfmartistsslower.py deleted file mode 100644 index 843bd7d..0000000 --- a/spotify_scripts/getlastfmartistsslower.py +++ /dev/null @@ -1,39 +0,0 @@ -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) - diff --git a/spotify_scripts/likedsongsync2-oldfix.py b/spotify_scripts/likedsongsync2-oldfix.py deleted file mode 100644 index da28890..0000000 --- a/spotify_scripts/likedsongsync2-oldfix.py +++ /dev/null @@ -1,203 +0,0 @@ -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 diff --git a/tabletop_achievements/README.md b/tabletop_achievements/README.md deleted file mode 100644 index 97fee45..0000000 --- a/tabletop_achievements/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Tabletop Simulator Achievement Scripts - -You can find the documentation for these scripts and how to use them at [docs.jonasjones.dev/tabletop_achievement_scripts](https://docs.jonasjones.dev/tabletop_achievement_scripts) \ No newline at end of file diff --git a/tabletop_achievements/tabletop_fliptable_loop.py b/tabletop_achievements/tabletop_fliptable_loop.py deleted file mode 100644 index eeec09c..0000000 --- a/tabletop_achievements/tabletop_fliptable_loop.py +++ /dev/null @@ -1,38 +0,0 @@ -import pyautogui -import time - -# The position of the "Flip" button at the top of the screen -FIRSTCLICK_X = 2300 -FIRSTCLICK_Y = 70 - -# The timeout for UI elements to load (in seconds) -INBETWEENSLEEPTIME = 0.2 - -# The position of the "Yes" button of the "FLip table?" prompt -SECONDCLICK_X = 1760 -SECONDCLICK_Y = 1140 - -# The timeout set by the game until the "Flip" button becomes clickable again (in seconds) -TIMEOUTSLEEPTIME = 2 - -# The amount of iterations depending on the achievement -ITERATIONS = 100 - -# initialize the counter -count = 0 - -time.sleep(3) # delay to focus the game after launching the script - -while count < ITERATIONS: - # Click the "Flip" button - pyautogui.click(FIRSTCLICK_X, FIRSTCLICK_Y) - time.sleep(INBETWEENSLEEPTIME) - - # Click the confirmation button - pyautogui.click(SECONDCLICK_X, SECONDCLICK_Y) - - # update the counter and display it - count += 1 - print(count, end="\r") - - time.sleep(TIMEOUTSLEEPTIME) # Wait for 3 seconds before repeating diff --git a/tabletop_achievements/tabletop_savetochest_loop.py b/tabletop_achievements/tabletop_savetochest_loop.py deleted file mode 100644 index 689b8fd..0000000 --- a/tabletop_achievements/tabletop_savetochest_loop.py +++ /dev/null @@ -1,56 +0,0 @@ -import pyautogui -import time -import os - -# The position of the right click to open the context menu for the object -RIGHTCLICK_X = 1870 -RIGHTCLICK_Y = 675 - -# The position of the "Save Object" option in the context menu -SAVECONTEXTMENUCLICK_X = 2030 -SAVECONTEXTMENUCLICK_Y = 875 - -# The position of the name input field in the "Save Object" poup -NAMEFIELDCLICK_X = 1700 -NAMEFIELDCLICK_Y = 1110 - -# The position of the save button in the "Save Object" popup -SAVECLICK_X = 1770 -SAVECLICK_Y = 1200 - -# The timeout for UI elements to load (in seconds) -TIMEOUTTIME = 0.15 - -# initialize the counter -count = 0 - - -time.sleep(3) # delay to focus the game after launching the script - -while count < 100: - # Right click for context menu - pyautogui.moveTo(RIGHTCLICK_X, RIGHTCLICK_Y) - pyautogui.click(RIGHTCLICK_X, RIGHTCLICK_Y, button='right') - time.sleep(TIMEOUTTIME) - - # Click on the "Save Object" option in the context menu - pyautogui.click(SAVECONTEXTMENUCLICK_X, SAVECONTEXTMENUCLICK_Y) - time.sleep(TIMEOUTTIME) - - # Click on the name input field to focus it - pyautogui.click(NAMEFIELDCLICK_X, NAMEFIELDCLICK_Y) - time.sleep(TIMEOUTTIME) - - # Get the current Unix timestamp - timestamp = str(int(time.time())) - - # Enter the timestamp as key presses - pyautogui.write(timestamp) - - # Click on the save button - pyautogui.click(SAVECLICK_X, SAVECLICK_Y) - time.sleep(TIMEOUTTIME) - - # update the counter and display it - count += 1 - print(count, end='\r') diff --git a/tabletop_achievements/tabletop_tint_loop.py b/tabletop_achievements/tabletop_tint_loop.py deleted file mode 100644 index fe24913..0000000 --- a/tabletop_achievements/tabletop_tint_loop.py +++ /dev/null @@ -1,52 +0,0 @@ -import pyautogui -import time -import random - -# The position of the right-click to open the context menu on an object -RIGHTCLICK_X = 1890 -RIGHTCLICK_Y = 970 - -# The position of the "Color Tint" button in the context menu -FIRSTCLICK_X = 2055 -FIRSTCLICK_Y = 1225 - -# The position of the upper left corner of the color-selector square -SECONDCLICK_XMIN = 600 -SECONDCLICK_YMIN = 600 - -# The position of the lower right corner of the color-selector square -SECONDCLICK_XMAX = 1100 -SECONDCLICK_YMAX = 1100 - -# The position of the "Apply" button of the color selector -CONFIRMCLICK_X = 760 -CONFIRMCLICK_Y = 1550 - -# The timeout for UI elements to load (in seconds) -SLEEPTIME = 0.15 - -# initialize the counter -count = 0 - -time.sleep(3) # delay to focus the game after launching the script - -# Move to and rightclick on the object -pyautogui.moveTo(RIGHTCLICK_X, RIGHTCLICK_Y) -pyautogui.click(RIGHTCLICK_X, RIGHTCLICK_Y, button='right') - -while count < 1000: - # Click on the "Color Tint" option - pyautogui.click(FIRSTCLICK_X, FIRSTCLICK_Y) - time.sleep(SLEEPTIME) - - # Generate random x and y coordinates - x = random.randint(SECONDCLICK_XMIN, SECONDCLICK_XMAX) - y = random.randint(SECONDCLICK_YMIN, SECONDCLICK_YMAX) - - # Click at the random coordinates - pyautogui.click(x, y) - time.sleep(SLEEPTIME) - - # Click on the "Apply" button - pyautogui.click(CONFIRMCLICK_X, CONFIRMCLICK_Y) - time.sleep(SLEEPTIME)