Skip to content

Commit

Permalink
megarefactoring on database
Browse files Browse the repository at this point in the history
  • Loading branch information
blastbeng committed Oct 2, 2024
1 parent 9e9bcee commit d22d21d
Show file tree
Hide file tree
Showing 11 changed files with 438 additions and 267 deletions.
399 changes: 262 additions & 137 deletions spotisub/database.py

Large diffs are not rendered by default.

142 changes: 86 additions & 56 deletions spotisub/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def prechecks():
subsonic_helper.check_pysonic_connection()


def artist_top_tracks(query):
def artist_top_tracks(query, init=False):
"""artist top tracks"""
sp = spotipy_helper.get_spotipy_client()
results = sp.search(query)
Expand All @@ -39,56 +39,68 @@ def artist_top_tracks(query):
artists_uri[artist["name"]] = artist["uri"]

for artist_name in artists_uri:
artist_top = sp.artist_top_tracks(artists_uri[artist_name])
playlist_name = artist_name + " - Top Tracks"
playlist_info = {}
playlist_info["name"] = playlist_name
playlist_info["spotify_uri"] = artists_uri[artist_name]
playlist_info["type"] = constants.JOB_ATT_ID
subsonic_helper.write_playlist(sp, playlist_info, artist_top)
if init:
subsonic_helper.generate_playlist(playlist_info)
else:
logging.info('(%s) Searching top tracks for for: %s',
str(threading.current_thread().ident), artist_name)
artist_top = sp.artist_top_tracks(artists_uri[artist_name])
subsonic_helper.write_playlist(sp, playlist_info, artist_top)


def my_recommendations(count=None):
def my_recommendations(count=None, init=False):
"""my recommendations"""
sp = spotipy_helper.get_spotipy_client()
top_tracks = sp.current_user_top_tracks(limit=50, time_range='long_term')
logging.info('(%s) Loaded your custom top tracks',
str(threading.current_thread().ident))
time.sleep(2)
liked_tracks = sp.current_user_saved_tracks(limit=50)
logging.info('(%s) Loaded your top liked tracks',
str(threading.current_thread().ident))
time.sleep(2)
history = sp.current_user_recently_played(limit=50)
logging.info('(%s) Loaded your played tracks',
str(threading.current_thread().ident))
time.sleep(2)
top_tracks = None
liked_tracks = None
history = None
if not init:
top_tracks = sp.current_user_top_tracks(limit=50, time_range='long_term')
logging.info('(%s) Loaded your custom top tracks',
str(threading.current_thread().ident))
time.sleep(2)
liked_tracks = sp.current_user_saved_tracks(limit=50)
logging.info('(%s) Loaded your top liked tracks',
str(threading.current_thread().ident))
time.sleep(2)
history = sp.current_user_recently_played(limit=50)
logging.info('(%s) Loaded your played tracks',
str(threading.current_thread().ident))
time.sleep(2)
for i in range(int(os.environ.get(constants.NUM_USER_PLAYLISTS,
constants.NUM_USER_PLAYLISTS_DEFAULT_VALUE))):
if count is None or (count is not None and count == i):
logging.info(
'(%s) Searching your recommendations (playlist %s)',
str(threading.current_thread().ident), str(
i + 1))
top_track_ids = [track['id'] for track in top_tracks['items']]
liked_track_ids = [track['track']['id']
for track in liked_tracks['items']]
history_track_ids = [track['track']['id']
for track in history['items']]
seed_track_ids = top_track_ids + liked_track_ids + history_track_ids
random.shuffle(seed_track_ids)
results = sp.recommendations(seed_tracks=seed_track_ids[0:5], limit=int(
os.environ.get(constants.ITEMS_PER_PLAYLIST, constants.ITEMS_PER_PLAYLIST_DEFAULT_VALUE)))
if not init:
logging.info(
'(%s) Searching your recommendations (playlist %s)',
str(threading.current_thread().ident), str(
i + 1))
top_track_ids = [track['id'] for track in top_tracks['items']]
liked_track_ids = [track['track']['id']
for track in liked_tracks['items']]
history_track_ids = [track['track']['id']
for track in history['items']]
seed_track_ids = top_track_ids + liked_track_ids + history_track_ids
random.shuffle(seed_track_ids)
results = sp.recommendations(seed_tracks=seed_track_ids[0:5], limit=int(
os.environ.get(constants.ITEMS_PER_PLAYLIST, constants.ITEMS_PER_PLAYLIST_DEFAULT_VALUE)))
playlist_name = "My Recommendations " + str(i + 1)
playlist_info = {}
playlist_info["name"] = playlist_name
playlist_info["spotify_uri"] = None
playlist_info["type"] = constants.JOB_MR_ID
subsonic_helper.write_playlist(
sp, playlist_info, results)
if init:
subsonic_helper.generate_playlist(playlist_info)
else:
subsonic_helper.write_playlist(
sp, playlist_info, results)
if count is not None:
break
time.sleep(10)


def get_artist(name):
Expand All @@ -101,26 +113,29 @@ def get_artist(name):
return None


def show_recommendations_for_artist(name):
def show_recommendations_for_artist(name, init=False):
"""show recommendations for artist"""
sp = spotipy_helper.get_spotipy_client()
logging.info('(%s) Searching recommendations for: %s',
str(threading.current_thread().ident), name)
artist = get_artist(name)
if artist is not None:
results = sp.recommendations(
seed_artists=[
artist['id']],
limit=int(
os.environ.get(
constants.ITEMS_PER_PLAYLIST,
constants.ITEMS_PER_PLAYLIST_DEFAULT_VALUE)))
playlist_name = name + " - Recommendations"
playlist_info = {}
playlist_info["name"] = playlist_name
playlist_info["spotify_uri"] = artist["uri"]
playlist_info["type"] = constants.JOB_AR_ID
subsonic_helper.write_playlist(sp, playlist_info, results)
if init:
subsonic_helper.generate_playlist(playlist_info)
else:
logging.info('(%s) Searching recommendations for: %s',
str(threading.current_thread().ident), name)
results = sp.recommendations(
seed_artists=[
artist['id']],
limit=int(
os.environ.get(
constants.ITEMS_PER_PLAYLIST,
constants.ITEMS_PER_PLAYLIST_DEFAULT_VALUE)))
subsonic_helper.write_playlist(sp, playlist_info, results)
else:
logging.warning('(%s) Artist: %s Not found!',
str(threading.current_thread().ident), name)
Expand Down Expand Up @@ -170,7 +185,7 @@ def get_user_playlist_by_name(playlist_name, offset=0):
return name_found


def get_user_playlists(offset=0, single_execution=False, playlist_name=None):
def get_user_playlists(offset=0, single_execution=False, playlist_name=None, init=False):
"""get user playlists"""
sp = spotipy_helper.get_spotipy_client()

Expand All @@ -180,20 +195,23 @@ def get_user_playlists(offset=0, single_execution=False, playlist_name=None):
for item in playlist_result['items']:
if item['name'] is not None and item['name'].strip() != '' and (playlist_name is None or (
playlist_name is not None and item['name'].lower().strip() == playlist_name.lower().strip())):
logging.info('(%s) Importing playlist: %s',
str(threading.current_thread().ident), item['name'])
result = dict({'tracks': []})
result = get_playlist_tracks(item, result)
playlist_info = {}
playlist_info["name"] = item['name'].strip()
playlist_info["spotify_uri"] = item["uri"]
playlist_info["type"] = constants.JOB_UP_ID
subsonic_helper.write_playlist(sp, playlist_info, result)
if init:
subsonic_helper.generate_playlist(playlist_info)
else:
logging.info('(%s) Importing playlist: %s',
str(threading.current_thread().ident), item['name'])
result = dict({'tracks': []})
result = get_playlist_tracks(item, result)
subsonic_helper.write_playlist(sp, playlist_info, result)
if single_execution:
break

if not single_execution and len(playlist_result['items']) != 0:
get_user_playlists(offset=offset + 50)
get_user_playlists(offset=offset + 50, playlist_name=None, init=init)


def count_user_playlists(count, offset=0):
Expand All @@ -212,26 +230,29 @@ def all_artists_recommendations(artist_names):
if len(artist_names) > 0:
random.shuffle(artist_names)
for artist_name in artist_names:
show_recommendations_for_artist(artist_name)
show_recommendations_for_artist(artist_name, init=True)


def all_artists_top_tracks(artist_names):
"""all artists top tracks"""
if len(artist_names) > 0:
random.shuffle(artist_names)
for artist_name in artist_names:
artist_top_tracks(artist_name)
artist_top_tracks(artist_name, init=True)


def get_user_saved_tracks(result):
def get_user_saved_tracks(result, init=True):
"""get user saved tracks"""
sp = spotipy_helper.get_spotipy_client()
result = get_user_saved_tracks_playlist(result)
playlist_info = {}
playlist_info["name"] = "Saved Tracks"
playlist_info["spotify_uri"] = None
playlist_info["type"] = constants.JOB_ST_ID
subsonic_helper.write_playlist(sp, playlist_info, result)
if init:
subsonic_helper.generate_playlist(playlist_info)
else:
sp = spotipy_helper.get_spotipy_client()
result = get_user_saved_tracks_playlist(result)
subsonic_helper.write_playlist(sp, playlist_info, result)


def get_user_saved_tracks_playlist(result, offset_tracks=0):
Expand All @@ -256,3 +277,12 @@ def get_user_saved_tracks_playlist(result, offset_tracks=0):
result = get_user_saved_tracks_playlist(
result, offset_tracks=offset_tracks + 50)
return result

def scan_library():
"""Used to scan the spotify library"""
get_user_saved_tracks(None, init=True)
my_recommendations(init=True)
artist_names = subsonic_helper.get_artists_array_names()
all_artists_recommendations(artist_names)
all_artists_top_tracks(artist_names)
get_user_playlists(init=True)
45 changes: 32 additions & 13 deletions spotisub/helpers/subsonic_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,16 @@ def add_missing_values_to_track(sp, track):
return track
return None

def generate_playlist(playlist_info):
"""generate empty playlist if not exists"""
playlist_info["name"] = (os.environ.get(
constants.PLAYLIST_PREFIX,
constants.PLAYLIST_PREFIX_DEFAULT_VALUE).replace(
"\"",
"") + playlist_info["name"])
database.create_playlist(playlist_info)
logging.info('(%s) Scanning for playlist %s',
str(threading.current_thread().ident), playlist_info["name"])

def write_playlist(sp, playlist_info, results):
"""write playlist to subsonic db"""
Expand All @@ -209,8 +219,8 @@ def write_playlist(sp, playlist_info, results):
old_song_ids = get_playlist_songs_ids_by_id(playlist_id)

if playlist_id is not None:
playlist_db = database.select_playlist_info_by_subsonic_id(playlist_id)
if playlist_db is not None and playlist_db.ignored == "1":
ignored = database.select_ignore_playlist_by_name(playlist_info["name"])
if ignored is not None and ignored == 1:
logging.warning(
'(%s) Skipping playlist %s because it was marked as ignored',
playlist_info["name"])
Expand Down Expand Up @@ -443,7 +453,7 @@ def match_with_subsonic_track(
def check_ignored(insert_result, song, playlist_info):
if insert_result["song_ignored"] is True:
logging.info(
'(%s) Skipping song "%s - %s - %s" because the matching song was marked as ignored "%s"',
'(%s) Skipping song "%s - %s - %s" because the matching song is marked as ignored "%s"',
str(threading.current_thread().ident),
song["artist"],
song["title"],
Expand All @@ -452,7 +462,7 @@ def check_ignored(insert_result, song, playlist_info):
return True
elif insert_result["album_ignored"] is True:
logging.info(
'(%s) Skipping song "%s - %s - %s" because the matching album was marked as ignored "%s"',
'(%s) Skipping song "%s - %s - %s" because the matching album is marked as ignored "%s"',
str(threading.current_thread().ident),
song["artist"],
song["title"],
Expand All @@ -461,7 +471,7 @@ def check_ignored(insert_result, song, playlist_info):
return True
elif insert_result["artist_ignored"] is True:
logging.info(
'(%s) Skipping song "%s - %s - %s" because the matching artist was marked as ignored "%s"',
'(%s) Skipping song "%s - %s - %s" because the matching artist is marked as ignored "%s"',
str(threading.current_thread().ident),
song["artist"],
song["title"],
Expand All @@ -470,7 +480,16 @@ def check_ignored(insert_result, song, playlist_info):
return True
elif insert_result["ignored_pl"] is True:
logging.info(
'(%s) Skipping song "%s - %s - %s" because it was marked as ignored for playlist "%s"',
'(%s) Skipping song "%s - %s - %s" because it is marked as ignored for playlist "%s"',
str(threading.current_thread().ident),
song["artist"],
song["title"],
song["album"],
playlist_info["name"])
return True
elif insert_result["ignored_whole_pl"] is True:
logging.info(
'(%s) Skipping song "%s - %s - %s" because this playlist is marked as ignored"%s"',
str(threading.current_thread().ident),
song["artist"],
song["title"],
Expand Down Expand Up @@ -498,7 +517,7 @@ def select_all_songs(missing_only=False, page=None,

ids=[]
for playlist in playlist_songs:
if playlist.subsonic_playlist_id not in ids:
if playlist.subsonic_playlist_id is not None and playlist.subsonic_playlist_id not in ids:
ids.append(playlist.subsonic_playlist_id)

for plid in ids:
Expand Down Expand Up @@ -535,15 +554,15 @@ def select_all_playlists(spotipy_helper, page=None,

for playlist in all_playlists:
playlist["image"] = ""
if playlist["subsonic_playlist_id"] not in ids:
if "subsonic_playlist_id" in playlist and playlist["subsonic_playlist_id"] is not None and playlist["subsonic_playlist_id"] not in ids:
ids.append(playlist["subsonic_playlist_id"])
if playlist["type"] == constants.JOB_ATT_ID or playlist["type"] == constants.JOB_AR_ID:
spotify_artist = get_spotify_object_from_cache(spotipy_helper.get_spotipy_client(), playlist["spotify_playlist_uri"])
if spotify_artist is not None and "images" in spotify_artist and len(spotify_artist["images"]) > 0:
if spotify_artist is not None and "images" in spotify_artist and spotify_artist["images"] is not None and len(spotify_artist["images"]) > 0:
playlist["image"] = spotify_artist["images"][0]["url"]
elif playlist["type"] == constants.JOB_UP_ID:
spotify_playlist = get_spotify_object_from_cache(spotipy_helper.get_spotipy_client(), playlist["spotify_playlist_uri"])
if spotify_playlist is not None and "images" in spotify_playlist and len(spotify_playlist["images"]) > 0:
if spotify_playlist is not None and "images" in spotify_playlist and spotify_playlist["images"] is not None and len(spotify_playlist["images"]) > 0:
playlist["image"] = spotify_playlist["images"][0]["url"]
prefix = os.environ.get(
constants.PLAYLIST_PREFIX,
Expand Down Expand Up @@ -761,14 +780,15 @@ def load_song(uuid, spotipy_helper, page=None,

return song, songs, count

def select_playlist_info_by_subsonic_id(spotipy_helper, subsonic_playlist_id):
playlist_info_db = database.select_playlist_info_by_subsonic_id(subsonic_playlist_id)
def select_playlist_info_by_uuid(spotipy_helper, uuid):
playlist_info_db = database.select_playlist_info_by_uuid(uuid)
playlist_info = {}
prefix = os.environ.get(
constants.PLAYLIST_PREFIX,
constants.PLAYLIST_PREFIX_DEFAULT_VALUE).replace(
"\"",
"")
playlist_info["uuid"] = playlist_info_db.uuid
playlist_info["subsonic_playlist_id"] = playlist_info_db.subsonic_playlist_id
playlist_info["subsonic_playlist_name"] = playlist_info_db.subsonic_playlist_name.replace(prefix,"")
playlist_info["spotify_playlist_uri"] = playlist_info_db.spotify_playlist_uri
Expand Down Expand Up @@ -798,5 +818,4 @@ def set_ignore(type, uuid, value):
elif type == 'playlist':
database.update_ignored_playlist(uuid, value)


spotify_cache = load_spotify_cache_from_file()
Loading

0 comments on commit d22d21d

Please sign in to comment.