From d22d21de2bdf9a9ac3c2a5fce77484d77501fb66 Mon Sep 17 00:00:00 2001 From: blast Date: Wed, 2 Oct 2024 17:16:25 +0200 Subject: [PATCH] megarefactoring on database --- spotisub/database.py | 399 +++++++++++++++-------- spotisub/generator.py | 142 ++++---- spotisub/helpers/subsonic_helper.py | 45 ++- spotisub/routes.py | 41 ++- spotisub/templates/album.html | 14 +- spotisub/templates/artist.html | 14 +- spotisub/templates/overview.html | 8 +- spotisub/templates/overview_content.html | 4 +- spotisub/templates/playlists.html | 14 +- spotisub/templates/song.html | 14 +- spotisub/templates/toolbar.html | 10 +- 11 files changed, 438 insertions(+), 267 deletions(-) diff --git a/spotisub/database.py b/spotisub/database.py index d75504a..3fe6941 100644 --- a/spotisub/database.py +++ b/spotisub/database.py @@ -20,8 +20,8 @@ from sqlalchemy import or_ from sqlalchemy import collate -VERSION = "0.3.2" -VERSIONS = ["0.3.0-alpha-01", "0.3.1", "0.3.2"] +VERSION = "0.3.2-alpha1" +VERSIONS = ["0.3.0-alpha-01", "0.3.1", "0.3.2-alpha1"] SQLITE = 'sqlite' USER = 'user' @@ -77,11 +77,9 @@ def __init__(self, dbtype, dbname=''): Column( 'subsonic_artist_id', String(36), nullable=True), Column( - 'subsonic_playlist_id', String(36), nullable=False), + 'spotify_song_uuid', String(36), nullable=True), Column( - 'subsonic_playlist_name', String(500), nullable=False), - Column( - 'spotify_song_uuid', String(36), nullable=False), + 'playlist_info_uuid', String(36), nullable=False), Column( 'ignored', Integer, nullable=False, default=0) ) @@ -89,12 +87,14 @@ def __init__(self, dbtype, dbname=''): playlist_info = Table(PLAYLIST_INFO, metadata, Column( 'uuid', String(36), primary_key=True, nullable=False), + Column( + 'subsonic_playlist_id', String(36), unique=True, nullable=True), + Column( + 'subsonic_playlist_name', String(500), unique=True, nullable=False), Column( 'spotify_playlist_uri', String(36), nullable=True), Column( 'type', String(36), nullable=False), - Column( - 'subsonic_playlist_id', String(36), nullable=False), Column( 'ignored', Integer, nullable=False, default=0) ) @@ -209,12 +209,18 @@ def upgrade(): fconfig = select_config_by_name(conn, 'VERSION') if fconfig is None or fconfig.value not in VERSIONS: # FIRST RELEASE 3.0.0 DROPPING ENTIRE DATABASE - backup_table(conn, SPOTIFY_SONG) - backup_table(conn, SPOTIFY_ALBUM) - backup_table(conn, SPOTIFY_ARTIST) - backup_table(conn, SPOTIFY_SONG_ARTIST_RELATION) - backup_table(conn, SUBSONIC_SPOTIFY_RELATION) - backup_table(conn, PLAYLIST_INFO) + #backup_table(conn, SPOTIFY_SONG) + #backup_table(conn, SPOTIFY_ALBUM) + #backup_table(conn, SPOTIFY_ARTIST) + #backup_table(conn, SPOTIFY_SONG_ARTIST_RELATION) + #backup_table(conn, SUBSONIC_SPOTIFY_RELATION) + #backup_table(conn, PLAYLIST_INFO) + drop_table(conn, SPOTIFY_SONG) + drop_table(conn, SPOTIFY_ALBUM) + drop_table(conn, SPOTIFY_ARTIST) + drop_table(conn, SPOTIFY_SONG_ARTIST_RELATION) + drop_table(conn, SUBSONIC_SPOTIFY_RELATION) + drop_table(conn, PLAYLIST_INFO) upgraded = True if fconfig is None or fconfig.value != VERSION: insert_or_update_config(conn, 'VERSION', VERSION) @@ -223,15 +229,15 @@ def upgrade(): conn.close() if upgraded: dbms.metadata.create_all(dbms.db_engine) - with dbms.db_engine.connect() as conn: - clone_table_from_bak(conn, SPOTIFY_SONG) - clone_table_from_bak(conn, SPOTIFY_ALBUM) - clone_table_from_bak(conn, SPOTIFY_ARTIST) - clone_table_from_bak(conn, SPOTIFY_SONG_ARTIST_RELATION) - clone_table_from_bak(conn, SUBSONIC_SPOTIFY_RELATION) - clone_table_from_bak(conn, PLAYLIST_INFO) - conn.commit() - conn.close() + #with dbms.db_engine.connect() as conn: + # clone_table_from_bak(conn, SPOTIFY_SONG) + # clone_table_from_bak(conn, SPOTIFY_ALBUM) + # clone_table_from_bak(conn, SPOTIFY_ARTIST) + # clone_table_from_bak(conn, SPOTIFY_SONG_ARTIST_RELATION) + # clone_table_from_bak(conn, SUBSONIC_SPOTIFY_RELATION) + # clone_table_from_bak(conn, PLAYLIST_INFO) + # conn.commit() + # conn.close() def drop_table(conn, table_name): @@ -278,46 +284,62 @@ def user_exists(): return False - def insert_song(playlist_info, subsonic_track, artist_spotify, track_spotify): - """insert song into database""" + """Create empty playlist into database""" return_dict = None with dbms.db_engine.connect() as conn: - return_dict = insert_spotify_song( - conn, artist_spotify, track_spotify) - if return_dict["song_uuid"] is not None: - pl_relation = None - if subsonic_track is None: - pl_relation = insert_playlist_relation( - conn, None, None, playlist_info, return_dict["song_uuid"]) - else: - track_id = None - artist_id = None - if "id" in subsonic_track: - track_id = subsonic_track["id"] - if "artistId" in subsonic_track: - artist_id = subsonic_track["artistId"] - pl_relation = insert_playlist_relation( - conn, - track_id, - artist_id, - playlist_info, - return_dict["song_uuid"]) - if pl_relation is not None: - insert_playlist_type( - conn, playlist_info) - return_dict["ignored_pl"] = (pl_relation.ignored==1) + pl_info = insert_playlist_type( + conn, playlist_info) + if pl_info is not None: + return_dict = insert_spotify_song( + conn, artist_spotify, track_spotify) + if return_dict["song_uuid"] is not None: + pl_relation = None + if subsonic_track is None: + pl_relation = insert_playlist_relation( + conn, None, None, playlist_info, return_dict["song_uuid"], pl_info.uuid) + else: + track_id = None + artist_id = None + if "id" in subsonic_track: + track_id = subsonic_track["id"] + if "artistId" in subsonic_track: + artist_id = subsonic_track["artistId"] + pl_relation = insert_playlist_relation( + conn, + track_id, + artist_id, + playlist_info, + return_dict["song_uuid"], + pl_info.uuid) + + if pl_relation is not None: + return_dict["uuid"] = pl_relation.uuid + return_dict["ignored_pl"] = (pl_relation.ignored==1) + return_dict["ignored_whole_pl"] = (pl_info.ignored==1) conn.commit() else: conn.rollback() - return_dict = None conn.close() return return_dict +def create_playlist(playlist_info): + """Create empty playlist into database""" + return_dict = None + with dbms.db_engine.connect() as conn: + pl_info = insert_playlist_type( + conn, playlist_info) + if pl_info is not None: + conn.commit() + else: + conn.rollback() + conn.close() + def insert_playlist_type(conn, playlist_info): """insert playlist into database""" - playlist_info_db = select_playlist_info_by_uri_sub_id(conn, playlist_info) + playlist_info_db = select_playlist_info_by_name(conn, playlist_info["name"]) + subsonic_playlist_id_info = playlist_info["subsonic_playlist_id"] if "subsonic_playlist_id" in playlist_info else None if playlist_info_db is None: stmt = insert( dbms.playlist_info).values( @@ -325,18 +347,53 @@ def insert_playlist_type(conn, playlist_info): uuid.uuid4().hex), spotify_playlist_uri=playlist_info["spotify_uri"], type=playlist_info["type"], - subsonic_playlist_id=playlist_info["subsonic_playlist_id"]).prefix_with('OR IGNORE') + subsonic_playlist_id=subsonic_playlist_id_info, + subsonic_playlist_name=playlist_info["name"]) stmt.compile() conn.execute(stmt) + return select_playlist_info_by_name(conn, playlist_info["name"]) + else: + stmt = update( + dbms.playlist_info).where( + dbms.playlist_info.c.uuid == playlist_info_db.uuid).values( + spotify_playlist_uri=playlist_info["spotify_uri"], + type=playlist_info["type"], + subsonic_playlist_id=subsonic_playlist_id_info, + subsonic_playlist_name=playlist_info["name"]) + stmt.compile() + conn.execute(stmt) + return select_playlist_info_by_name(conn, playlist_info["name"]) + -def select_playlist_info_by_uri_sub_id(conn, playlist_info): +def select_ignore_playlist_by_name(name): + """select spotify artists by uuid""" + value = None + with dbms.db_engine.connect() as conn: + stmt = select( + dbms.playlist_info.c.ignored).where( + dbms.playlist_info.c.subsonic_playlist_name == name) + stmt.compile() + cursor = conn.execute(stmt) + records = cursor.fetchall() + + for row in records: + value = row.ignored + cursor.close() + + return value + +def select_playlist_info_by_name(conn, name): """select spotify artists by uuid""" value = None stmt = select( - dbms.playlist_info.c.uuid).where( - dbms.playlist_info.c.spotify_playlist_uri == playlist_info["spotify_uri"], - dbms.playlist_info.c.subsonic_playlist_id == playlist_info["subsonic_playlist_id"]) + dbms.playlist_info.c.uuid, + dbms.playlist_info.c.subsonic_playlist_id, + dbms.playlist_info.c.subsonic_playlist_name, + dbms.playlist_info.c.spotify_playlist_uri, + dbms.playlist_info.c.ignored, + dbms.playlist_info.c.type).where( + dbms.playlist_info.c.subsonic_playlist_name == name) stmt.compile() cursor = conn.execute(stmt) records = cursor.fetchall() @@ -347,18 +404,42 @@ def select_playlist_info_by_uri_sub_id(conn, playlist_info): return value +def select_playlist_info_by_uuid(uuid): + """select spotify artists by uuid""" + with dbms.db_engine.connect() as conn: + value = None + stmt = select( + dbms.playlist_info.c.uuid, + dbms.playlist_info.c.subsonic_playlist_id, + dbms.playlist_info.c.subsonic_playlist_name, + dbms.playlist_info.c.spotify_playlist_uri, + dbms.playlist_info.c.ignored, + dbms.playlist_info.c.type).where( + dbms.playlist_info.c.uuid == uuid) + stmt.compile() + cursor = conn.execute(stmt) + records = cursor.fetchall() + + for row in records: + value = row + cursor.close() + conn.close() + return value + def delete_playlist_relation_by_id(playlist_id: str): """delete playlist from database""" with dbms.db_engine.connect() as conn: - stmt1 = delete(dbms.subsonic_spotify_relation).where( - dbms.subsonic_spotify_relation.c.subsonic_playlist_id == playlist_id) - stmt1.compile() - stmt2 = delete(dbms.playlist_info).where( - dbms.playlist_info.c.subsonic_playlist_id == playlist_id) - stmt2.compile() - conn.execute(stmt1) - conn.execute(stmt2) - conn.commit() + pl_info = select_playlist_info_by_subsonic_id(playlist_id, conn_ext=conn) + if pl_info is not None: + stmt1 = delete(dbms.subsonic_spotify_relation).where( + dbms.subsonic_spotify_relation.c.playlist_info_uuid == pl_info) + stmt1.compile() + stmt2 = delete(dbms.playlist_info).where( + dbms.playlist_info.c.subsonic_playlist_id == playlist_id) + stmt2.compile() + conn.execute(stmt1) + conn.execute(stmt2) + conn.commit() conn.close() @@ -385,43 +466,46 @@ def delete_song_relation(playlist_id: str, subsonic_track): def insert_playlist_relation(conn, subsonic_song_id, - subsonic_artist_id, playlist_info, spotify_song_uuid): + subsonic_artist_id, playlist_info, spotify_song_uuid, pl_info_uuid): """insert playlist into database""" old_relation = select_playlist_relation(conn, subsonic_song_id, - subsonic_artist_id, playlist_info, spotify_song_uuid) + subsonic_artist_id, spotify_song_uuid, pl_info_uuid) if old_relation is None: + new_uuid = str(uuid.uuid4().hex) stmt = insert( dbms.subsonic_spotify_relation).values( - - uuid=str( - uuid.uuid4().hex), + uuid=new_uuid, subsonic_song_id=subsonic_song_id, subsonic_artist_id=subsonic_artist_id, - subsonic_playlist_id=playlist_info["subsonic_playlist_id"], - subsonic_playlist_name=playlist_info["name"], - spotify_song_uuid=spotify_song_uuid) + spotify_song_uuid=spotify_song_uuid, + playlist_info_uuid=pl_info_uuid) stmt.compile() conn.execute(stmt) - return select_playlist_relation(conn, subsonic_song_id, - subsonic_artist_id, playlist_info, spotify_song_uuid) + return select_playlist_relation_by_uuid(conn, new_uuid) else: - return old_relation + stmt = update( + dbms.subsonic_spotify_relation).where( + dbms.subsonic_spotify_relation.c.uuid == old_relation.uuid, + dbms.subsonic_spotify_relation.c.playlist_info_uuid == pl_info_uuid).values( + subsonic_song_id=subsonic_song_id, + subsonic_artist_id=subsonic_artist_id, + spotify_song_uuid=spotify_song_uuid) + stmt.compile() + conn.execute(stmt) + return select_playlist_relation_by_uuid(conn, old_relation.uuid) -def select_playlist_info_by_subsonic_id(subsonic_playlist_id): +def select_playlist_info_by_subsonic_id(subsonic_playlist_uuid, conn_ext=None): """select spotify artists by uuid""" value = None - with dbms.db_engine.connect() as conn: + with conn_ext if conn_ext is not None else dbms.db_engine.connect() as conn: stmt = select( dbms.playlist_info.c.uuid, dbms.playlist_info.c.subsonic_playlist_id, - dbms.subsonic_spotify_relation.c.subsonic_playlist_name, + dbms.playlist_info.c.subsonic_playlist_name, dbms.playlist_info.c.spotify_playlist_uri, dbms.playlist_info.c.ignored, - dbms.playlist_info.c.type) - stmt = stmt.join( - dbms.subsonic_spotify_relation, - dbms.playlist_info.c.subsonic_playlist_id == dbms.subsonic_spotify_relation.c.subsonic_playlist_id).where( - dbms.playlist_info.c.subsonic_playlist_id == subsonic_playlist_id) + dbms.playlist_info.c.type).where( + dbms.playlist_info.c.subsonic_playlist_id == subsonic_playlist_uuid) stmt = stmt.group_by( dbms.playlist_info.c.uuid) @@ -433,31 +517,51 @@ def select_playlist_info_by_subsonic_id(subsonic_playlist_id): for row in records: value = row cursor.close() - conn.close() + if conn_ext is None: + conn.close() return value def select_playlist_relation(conn, subsonic_song_id, - subsonic_artist_id, playlist_info, spotify_song_uuid): + subsonic_artist_id, spotify_song_uuid, pl_info_uuid): value = None """select playlist relation""" stmt = select(dbms.subsonic_spotify_relation.c.uuid, dbms.subsonic_spotify_relation.c.subsonic_song_id, dbms.subsonic_spotify_relation.c.subsonic_artist_id, - dbms.subsonic_spotify_relation.c.subsonic_playlist_id, - dbms.subsonic_spotify_relation.c.subsonic_playlist_name, dbms.subsonic_spotify_relation.c.spotify_song_uuid, dbms.subsonic_spotify_relation.c.ignored).where( dbms.subsonic_spotify_relation.c.subsonic_song_id==subsonic_song_id, dbms.subsonic_spotify_relation.c.subsonic_artist_id==subsonic_artist_id, - dbms.subsonic_spotify_relation.c.subsonic_playlist_id==playlist_info["subsonic_playlist_id"], - dbms.subsonic_spotify_relation.c.subsonic_playlist_name==playlist_info["name"], + dbms.subsonic_spotify_relation.c.playlist_info_uuid==pl_info_uuid, dbms.subsonic_spotify_relation.c.spotify_song_uuid==spotify_song_uuid) stmt.compile() + cursor = conn.execute(stmt) + records = cursor.fetchall() + + for row in records: + value = row + cursor.close() + + return value + + +def select_playlist_relation_by_uuid(conn, uuid): + value = None + """select playlist relation""" + stmt = select(dbms.subsonic_spotify_relation.c.uuid, + dbms.subsonic_spotify_relation.c.subsonic_song_id, + dbms.subsonic_spotify_relation.c.subsonic_artist_id, + dbms.subsonic_spotify_relation.c.spotify_song_uuid, + dbms.subsonic_spotify_relation.c.ignored).where( + dbms.subsonic_spotify_relation.c.uuid==uuid) + stmt.compile() + + cursor = conn.execute(stmt) records = cursor.fetchall() @@ -474,11 +578,12 @@ def select_all_songs(conn_ext=None, missing_only=False, page=None, stmt = None with conn_ext if conn_ext is not None else dbms.db_engine.connect() as conn: stmt = select( - dbms.subsonic_spotify_relation.c.uuid, + dbms.playlist_info.c.uuid, dbms.subsonic_spotify_relation.c.subsonic_song_id, + dbms.subsonic_spotify_relation.c.uuid.label('relation_uuid'), dbms.subsonic_spotify_relation.c.subsonic_artist_id, - dbms.subsonic_spotify_relation.c.subsonic_playlist_id, - dbms.subsonic_spotify_relation.c.subsonic_playlist_name, + dbms.playlist_info.c.subsonic_playlist_id, + dbms.playlist_info.c.subsonic_playlist_name, dbms.subsonic_spotify_relation.c.spotify_song_uuid, dbms.playlist_info.c.type, dbms.playlist_info.c.ignored.label('ignored_whole_pl'), @@ -497,6 +602,9 @@ def select_all_songs(conn_ext=None, missing_only=False, page=None, func.group_concat(dbms.spotify_artist.c.ignored).label( 'spotify_artist_ignored'), dbms.spotify_song.c.tms_insert) + stmt = stmt.join( + dbms.playlist_info, + dbms.playlist_info.c.uuid == dbms.subsonic_spotify_relation.c.playlist_info_uuid) stmt = stmt.join( dbms.spotify_song, dbms.subsonic_spotify_relation.c.spotify_song_uuid == dbms.spotify_song.c.uuid) @@ -509,9 +617,6 @@ def select_all_songs(conn_ext=None, missing_only=False, page=None, stmt = stmt.join( dbms.spotify_artist, dbms.spotify_song_artist_relation.c.artist_uuid == dbms.spotify_artist.c.uuid) - stmt = stmt.join( - dbms.playlist_info, - dbms.playlist_info.c.subsonic_playlist_id == dbms.subsonic_spotify_relation.c.subsonic_playlist_id) if missing_only: stmt = stmt.where( dbms.subsonic_spotify_relation.c.subsonic_song_id == None, @@ -524,21 +629,21 @@ def select_all_songs(conn_ext=None, missing_only=False, page=None, dbms.subsonic_spotify_relation.c.subsonic_song_id == subsonic_song_id) if playlist_uuid is not None: stmt = stmt.where( - dbms.subsonic_spotify_relation.c.subsonic_playlist_id == playlist_uuid) + dbms.playlist_info.c.uuid == playlist_uuid) if search is not None: stmt = stmt.filter(or_(dbms.spotify_song.c.title.ilike(f'%{search}%'), dbms.spotify_album.c.name.ilike( f'%{search}%'), dbms.spotify_artist.c.name.ilike( f'%{search}%'), - dbms.subsonic_spotify_relation.c.subsonic_playlist_name.ilike(f'%{search}%'))) + dbms.playlist_info.c.subsonic_playlist_name.ilike(f'%{search}%'))) stmt = limit_and_order_stmt( stmt, page=page, limit=limit, order=order, asc=asc) stmt = stmt.group_by( dbms.subsonic_spotify_relation.c.spotify_song_uuid, - dbms.subsonic_spotify_relation.c.subsonic_playlist_id) + dbms.playlist_info.c.subsonic_playlist_name) stmt.compile() cursor = conn.execute(stmt) records = cursor.fetchall() @@ -557,11 +662,11 @@ def count_songs(conn, missing_only=False, search=None, song_uuid=None, playlist_ count = 0 query = """SELECT COUNT(*) FROM - (SELECT subsonic_spotify_relation.uuid, + (SELECT playlist_info.uuid, subsonic_spotify_relation.subsonic_song_id, subsonic_spotify_relation.subsonic_artist_id, - subsonic_spotify_relation.subsonic_playlist_id, - subsonic_spotify_relation.subsonic_playlist_name, + playlist_info.subsonic_playlist_id, + playlist_info.subsonic_playlist_name, subsonic_spotify_relation.spotify_song_uuid, spotify_song.title AS spotify_song_title, spotify_song.spotify_uri AS spotify_song_uri, @@ -570,7 +675,8 @@ def count_songs(conn, missing_only=False, search=None, song_uuid=None, playlist_ spotify_album.name AS spotify_album_name, group_concat(spotify_artist.name) AS spotify_artist_names, group_concat(spotify_artist.uuid) AS spotify_artist_uuids, - spotify_song.tms_insert FROM subsonic_spotify_relation + spotify_song.tms_insert FROM playlist_info + JOIN subsonic_spotify_relation ON playlist_info.uuid = subsonic_spotify_relation.playlist_info_uuid JOIN spotify_song ON subsonic_spotify_relation.spotify_song_uuid = spotify_song.uuid JOIN spotify_album ON spotify_song.album_uuid = spotify_album.uuid JOIN spotify_song_artist_relation ON spotify_song.uuid = spotify_song_artist_relation.song_uuid @@ -585,19 +691,19 @@ def count_songs(conn, missing_only=False, search=None, song_uuid=None, playlist_ where = where + """ (lower(spotify_song.title) LIKE lower('""" + search + """') OR lower(spotify_album.name) LIKE lower('""" + search + """') OR lower(spotify_artist.name) LIKE lower('""" + search + """') - OR lower(subsonic_spotify_relation.subsonic_playlist_name) LIKE lower('""" + search + """') """ + OR lower(playlist_info.subsonic_playlist_name) LIKE lower('""" + search + """') """ where = where + """ OR lower(spotify_song.title) LIKE lower('%""" + search + """') OR lower(spotify_album.name) LIKE lower('%""" + search + """') OR lower(spotify_artist.name) LIKE lower('%""" + search + """') - OR lower(subsonic_spotify_relation.subsonic_playlist_name) LIKE lower('%""" + search + """') """ + OR lower(playlist_info.subsonic_playlist_name) LIKE lower('%""" + search + """') """ where = where + """ OR lower(spotify_song.title) LIKE lower('""" + search + """%') OR lower(spotify_album.name) LIKE lower('""" + search + """%') OR lower(spotify_artist.name) LIKE lower('""" + search + """%') - OR lower(subsonic_spotify_relation.subsonic_playlist_name) LIKE lower('""" + search + """%') """ + OR lower(playlist_info.subsonic_playlist_name) LIKE lower('""" + search + """%') """ where = where + """ OR lower(spotify_song.title) LIKE lower('%""" + search + """%') OR lower(spotify_album.name) LIKE lower('%""" + search + """%') OR lower(spotify_artist.name) LIKE lower('%""" + search + """%') - OR lower(subsonic_spotify_relation.subsonic_playlist_name) LIKE lower('%""" + search + """%')) """ + OR lower(playlist_info.subsonic_playlist_name) LIKE lower('%""" + search + """%')) """ if song_uuid is not None: if where != "": where = where + " and " @@ -605,13 +711,13 @@ def count_songs(conn, missing_only=False, search=None, song_uuid=None, playlist_ if playlist_id is not None: if where != "": where = where + " and " - where = where + " subsonic_spotify_relation.subsonic_playlist_id = '" + playlist_id + "' " + where = where + " playlist_info.uuid = '" + playlist_id + "' " if where != "": query = query + " where " + where query = query + """group by subsonic_spotify_relation.spotify_song_uuid, - subsonic_spotify_relation.subsonic_playlist_id);""" + playlist_info.subsonic_playlist_name);""" count = conn.execute(text(query)).scalar() @@ -978,9 +1084,11 @@ def select_songs_by_artist_uuid( dbms.spotify_album.c.ignored.label('spotify_album_ignored'), dbms.subsonic_spotify_relation.c.uuid.label('subsonic_spotify_relation_uuid'), dbms.subsonic_spotify_relation.c.subsonic_song_id, - dbms.subsonic_spotify_relation.c.subsonic_playlist_name, - dbms.subsonic_spotify_relation.c.subsonic_playlist_id, + dbms.playlist_info.c.subsonic_playlist_name, + dbms.playlist_info.c.subsonic_playlist_id, + dbms.playlist_info.c.uuid.label('playlist_info_uuid'), dbms.subsonic_spotify_relation.c.ignored.label('ignored_pl'), + dbms.subsonic_spotify_relation.c.uuid.label('relation_uuid'), func.group_concat(dbms.spotify_artist.c.name).label( 'spotify_artist_names'), func.group_concat(dbms.spotify_artist.c.uuid).label('spotify_artist_uuids'), @@ -989,8 +1097,8 @@ def select_songs_by_artist_uuid( dbms.spotify_album, dbms.spotify_song.c.album_uuid == dbms.spotify_album.c.uuid).join( dbms.spotify_artist, dbms.spotify_artist.c.uuid == dbms.spotify_song_artist_relation.c.artist_uuid).join( dbms.spotify_song_artist_relation, dbms.spotify_song.c.uuid == dbms.spotify_song_artist_relation.c.song_uuid).join( - dbms.playlist_info, - dbms.playlist_info.c.subsonic_playlist_id == dbms.subsonic_spotify_relation.c.subsonic_playlist_id).where( + dbms.playlist_info, + dbms.playlist_info.c.uuid == dbms.subsonic_spotify_relation.c.playlist_info_uuid).where( dbms.spotify_song_artist_relation.c.artist_uuid == artist_uuid) stmt = limit_and_order_stmt( @@ -1002,7 +1110,7 @@ def select_songs_by_artist_uuid( stmt = stmt.group_by( dbms.subsonic_spotify_relation.c.spotify_song_uuid, - dbms.subsonic_spotify_relation.c.subsonic_playlist_id) + dbms.playlist_info.c.subsonic_playlist_name) stmt.compile() cursor = conn.execute(stmt) records = cursor.fetchall() @@ -1013,7 +1121,15 @@ def select_songs_by_artist_uuid( def select_count_songs_by_artist_uuid(conn, artist_uuid): - query = """select count(*) from (SELECT spotify_song_artist_relation.song_uuid, spotify_song.uuid, spotify_song.spotify_uri, spotify_song.title, spotify_song.album_uuid, spotify_album.name AS album_name, subsonic_spotify_relation.subsonic_song_id, subsonic_spotify_relation.subsonic_playlist_name, subsonic_spotify_relation.subsonic_playlist_id, group_concat(spotify_artist.name) AS spotify_artist_names, group_concat(spotify_artist.uuid) AS spotify_artist_uuids FROM spotify_song JOIN subsonic_spotify_relation ON subsonic_spotify_relation.spotify_song_uuid = spotify_song.uuid JOIN spotify_album ON spotify_song.album_uuid = spotify_album.uuid JOIN spotify_artist ON spotify_artist.uuid = spotify_song_artist_relation.artist_uuid JOIN spotify_song_artist_relation ON spotify_song.uuid = spotify_song_artist_relation.song_uuid WHERE spotify_song_artist_relation.artist_uuid = '""" + artist_uuid + """' GROUP BY subsonic_spotify_relation.spotify_song_uuid, subsonic_spotify_relation.subsonic_playlist_id)""" + query = """select count(*) from (SELECT spotify_song_artist_relation.song_uuid, spotify_song.uuid, spotify_song.spotify_uri, + spotify_song.title, spotify_song.album_uuid, spotify_album.name AS album_name, subsonic_spotify_relation.subsonic_song_id, + playlist_info.subsonic_playlist_name, playlist_info.subsonic_playlist_id, group_concat(spotify_artist.name) + AS spotify_artist_names, group_concat(spotify_artist.uuid) AS spotify_artist_uuids + FROM spotify_song JOIN subsonic_spotify_relation ON subsonic_spotify_relation.spotify_song_uuid = spotify_song.uuid + JOIN playlist_info ON subsonic_spotify_relation.playlist_info_uuid = playlist_info.uuid + JOIN spotify_album ON spotify_song.album_uuid = spotify_album.uuid JOIN spotify_artist ON spotify_artist.uuid = spotify_song_artist_relation.artist_uuid + JOIN spotify_song_artist_relation ON spotify_song.uuid = spotify_song_artist_relation.song_uuid + WHERE spotify_song_artist_relation.artist_uuid = '""" + artist_uuid + """' GROUP BY subsonic_spotify_relation.spotify_song_uuid, playlist_info.subsonic_playlist_name)""" count = conn.execute(text(query)).scalar() conn.close() @@ -1036,9 +1152,10 @@ def select_songs_by_album_uuid( dbms.spotify_album.c.ignored.label('spotify_album_ignored'), dbms.subsonic_spotify_relation.c.subsonic_song_id, dbms.subsonic_spotify_relation.c.ignored.label('ignored_pl'), - dbms.subsonic_spotify_relation.c.subsonic_playlist_name, - dbms.subsonic_spotify_relation.c.subsonic_playlist_id, - dbms.subsonic_spotify_relation.c.uuid.label('subsonic_spotify_relation_uuid'), + dbms.playlist_info.c.subsonic_playlist_name, + dbms.playlist_info.c.subsonic_playlist_id, + dbms.playlist_info.c.uuid.label('playlist_info_uuid'), + dbms.subsonic_spotify_relation.c.uuid.label('relation_uuid'), func.group_concat(dbms.spotify_artist.c.name).label( 'spotify_artist_names'), func.group_concat(dbms.spotify_artist.c.uuid).label('spotify_artist_uuids'), @@ -1047,8 +1164,8 @@ def select_songs_by_album_uuid( dbms.spotify_album, dbms.spotify_song.c.album_uuid == dbms.spotify_album.c.uuid).join( dbms.spotify_song_artist_relation, dbms.spotify_song.c.uuid == dbms.spotify_song_artist_relation.c.song_uuid).join( dbms.spotify_artist, dbms.spotify_artist.c.uuid == dbms.spotify_song_artist_relation.c.artist_uuid).join( - dbms.playlist_info, - dbms.playlist_info.c.subsonic_playlist_id == dbms.subsonic_spotify_relation.c.subsonic_playlist_id).where( + dbms.playlist_info, + dbms.playlist_info.c.uuid == dbms.subsonic_spotify_relation.c.playlist_info_uuid).where( dbms.spotify_song.c.album_uuid == album_uuid) stmt = limit_and_order_stmt( @@ -1060,7 +1177,7 @@ def select_songs_by_album_uuid( stmt = stmt.group_by( dbms.subsonic_spotify_relation.c.spotify_song_uuid, - dbms.subsonic_spotify_relation.c.subsonic_playlist_id) + dbms.playlist_info.c.subsonic_playlist_name) stmt.compile() cursor = conn.execute(stmt) records = cursor.fetchall() @@ -1071,7 +1188,17 @@ def select_songs_by_album_uuid( def select_count_songs_by_album_uuid(conn, album_uuid): - query = """select count(*) from (SELECT spotify_song_artist_relation.song_uuid, spotify_song.uuid, spotify_song.spotify_uri, spotify_song.title, spotify_song.album_uuid, spotify_album.name AS album_name, subsonic_spotify_relation.subsonic_song_id, subsonic_spotify_relation.subsonic_playlist_name, subsonic_spotify_relation.subsonic_playlist_id, group_concat(spotify_artist.name) AS spotify_artist_names, group_concat(spotify_artist.uuid) AS spotify_artist_uuids FROM spotify_song JOIN subsonic_spotify_relation ON subsonic_spotify_relation.spotify_song_uuid = spotify_song.uuid JOIN spotify_album ON spotify_song.album_uuid = spotify_album.uuid JOIN spotify_song_artist_relation ON spotify_song.uuid = spotify_song_artist_relation.song_uuid JOIN spotify_artist ON spotify_artist.uuid = spotify_song_artist_relation.artist_uuid WHERE spotify_song.album_uuid = '""" + album_uuid + """' GROUP BY subsonic_spotify_relation.spotify_song_uuid, subsonic_spotify_relation.subsonic_playlist_id)""" + query = """select count(*) from (SELECT spotify_song_artist_relation.song_uuid, spotify_song.uuid, + spotify_song.spotify_uri, spotify_song.title, spotify_song.album_uuid, spotify_album.name AS album_name, + subsonic_spotify_relation.subsonic_song_id, playlist_info.subsonic_playlist_name, playlist_info.subsonic_playlist_id, + group_concat(spotify_artist.name) AS spotify_artist_names, group_concat(spotify_artist.uuid) AS spotify_artist_uuids + FROM spotify_song + JOIN subsonic_spotify_relation ON subsonic_spotify_relation.spotify_song_uuid = spotify_song.uuid + JOIN playlist_info ON subsonic_spotify_relation.playlist_info_uuid = playlist_info.uuid + JOIN spotify_album ON spotify_song.album_uuid = spotify_album.uuid + JOIN spotify_song_artist_relation ON spotify_song.uuid = spotify_song_artist_relation.song_uuid + JOIN spotify_artist ON spotify_artist.uuid = spotify_song_artist_relation.artist_uuid + WHERE spotify_song.album_uuid = '""" + album_uuid + """' GROUP BY subsonic_spotify_relation.spotify_song_uuid, playlist_info.subsonic_playlist_name)""" count = conn.execute(text(query)).scalar() conn.close() @@ -1086,27 +1213,25 @@ def select_all_playlists(conn_ext=None, page=None, limit=None, order=None, asc=N with conn_ext if conn_ext is not None else dbms.db_engine.connect() as conn: stmt = select( dbms.playlist_info.c.subsonic_playlist_id, - dbms.subsonic_spotify_relation.c.subsonic_playlist_name, - dbms.subsonic_spotify_relation.c.uuid, + dbms.playlist_info.c.subsonic_playlist_name, + dbms.playlist_info.c.uuid, dbms.playlist_info.c.spotify_playlist_uri, dbms.playlist_info.c.type, - dbms.playlist_info.c.ignored).join( - dbms.subsonic_spotify_relation, - dbms.playlist_info.c.subsonic_playlist_id == dbms.subsonic_spotify_relation.c.subsonic_playlist_id) + dbms.playlist_info.c.ignored) stmt = limit_and_order_stmt( stmt, page=page, limit=limit, order=order, asc=asc) stmt = stmt.group_by( - dbms.playlist_info.c.subsonic_playlist_id) + dbms.playlist_info.c.subsonic_playlist_name) stmt.compile() cursor = conn.execute(stmt) rows = cursor.fetchall() for row in rows: - total, matched, missing = get_playlist_counts(conn, row.subsonic_playlist_id) + total, matched, missing = get_playlist_counts(conn, row.uuid) record = {} record["uuid"] = row.uuid record["subsonic_playlist_id"] = row.subsonic_playlist_id @@ -1119,7 +1244,7 @@ def select_all_playlists(conn_ext=None, page=None, limit=None, order=None, asc=N record["total"] = total record["matched"] = matched record["missing"] = missing - record["percentage"] = int((matched/total)*100) + record["percentage"] = int((matched/total)*100) if total != 0 else 0 records.append(record) @@ -1137,22 +1262,22 @@ def count_playlists(conn): """select playlists from database""" count = 0 - query = """select count(*) from (SELECT playlist_info.subsonic_playlist_id, subsonic_spotify_relation.subsonic_playlist_name, playlist_info.spotify_playlist_uri, playlist_info.type FROM playlist_info JOIN subsonic_spotify_relation ON playlist_info.subsonic_playlist_id = subsonic_spotify_relation.subsonic_playlist_id GROUP BY playlist_info.subsonic_playlist_id);""" + query = """select count(*) from (SELECT playlist_info.subsonic_playlist_id, playlist_info.subsonic_playlist_name, playlist_info.spotify_playlist_uri, playlist_info.type FROM playlist_info GROUP BY playlist_info.subsonic_playlist_name);""" count = conn.execute(text(query)).scalar() return count -def get_playlist_counts(conn, subsonic_playlist_id): +def get_playlist_counts(conn, pl_info_uuid): """select count songs from database""" total = 0 missing = 0 matched = 0 - total_query = "SELECT COUNT(*) FROM (SELECT subsonic_spotify_relation.uuid from subsonic_spotify_relation where subsonic_spotify_relation.subsonic_playlist_id = '" + subsonic_playlist_id + "');" - matched_query = "SELECT COUNT(*) FROM (SELECT subsonic_spotify_relation.uuid from subsonic_spotify_relation where subsonic_spotify_relation.subsonic_playlist_id = '" + subsonic_playlist_id + "' and subsonic_spotify_relation.subsonic_song_id is not null);" - missing_query = "SELECT COUNT(*) FROM (SELECT subsonic_spotify_relation.uuid from subsonic_spotify_relation where subsonic_spotify_relation.subsonic_playlist_id = '" + subsonic_playlist_id + "' and subsonic_spotify_relation.subsonic_song_id is null);" + total_query = "SELECT COUNT(*) FROM (SELECT subsonic_spotify_relation.uuid from subsonic_spotify_relation where subsonic_spotify_relation.playlist_info_uuid = '" + pl_info_uuid + "' and subsonic_spotify_relation.spotify_song_uuid is not null);" + matched_query = "SELECT COUNT(*) FROM (SELECT subsonic_spotify_relation.uuid from subsonic_spotify_relation where subsonic_spotify_relation.playlist_info_uuid = '" + pl_info_uuid + "' and subsonic_spotify_relation.subsonic_song_id is not null and subsonic_spotify_relation.spotify_song_uuid is not null);" + missing_query = "SELECT COUNT(*) FROM (SELECT subsonic_spotify_relation.uuid from subsonic_spotify_relation where subsonic_spotify_relation.playlist_info_uuid = '" + pl_info_uuid + "' and subsonic_spotify_relation.subsonic_song_id is null and subsonic_spotify_relation.spotify_song_uuid is not null);" total = conn.execute(text(total_query)).scalar() matched = conn.execute(text(matched_query)).scalar() @@ -1209,11 +1334,11 @@ def update_ignored_song_pl(uuid, value): conn.commit() conn.close() -def update_ignored_playlist(subsonic_playlist_id, value): +def update_ignored_playlist(uuid, value): with dbms.db_engine.connect() as conn: stmt = update( dbms.playlist_info).where( - dbms.playlist_info.c.subsonic_playlist_id == subsonic_playlist_id).values( + dbms.playlist_info.c.uuid == uuid).values( ignored=value) stmt.compile() diff --git a/spotisub/generator.py b/spotisub/generator.py index cbd3c87..ff0b243 100644 --- a/spotisub/generator.py +++ b/spotisub/generator.py @@ -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) @@ -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): @@ -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) @@ -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() @@ -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): @@ -212,7 +230,7 @@ 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): @@ -220,18 +238,21 @@ def all_artists_top_tracks(artist_names): 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): @@ -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) \ No newline at end of file diff --git a/spotisub/helpers/subsonic_helper.py b/spotisub/helpers/subsonic_helper.py index 55b616f..7ae1f02 100644 --- a/spotisub/helpers/subsonic_helper.py +++ b/spotisub/helpers/subsonic_helper.py @@ -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""" @@ -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"]) @@ -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"], @@ -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"], @@ -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"], @@ -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"], @@ -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: @@ -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, @@ -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 @@ -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() \ No newline at end of file diff --git a/spotisub/routes.py b/spotisub/routes.py index e034873..f30591c 100644 --- a/spotisub/routes.py +++ b/spotisub/routes.py @@ -57,6 +57,7 @@ def after_request(response): @spotisub.errorhandler(Exception) def all_exception_handler(error): + utils.write_exception() return render_template('errors/404.html', title='Error!', errors=[repr(error)]) @@ -90,7 +91,7 @@ def get_json_message(message, is_ok): @spotisub.route('/overview////') @spotisub.route('/overview/////') @login_required -def overview(page=1, limit=100, order='subsonic_spotify_relation.subsonic_playlist_name', asc=1): +def overview(page=1, limit=100, order='playlist_info.subsonic_playlist_name', asc=1): title = 'Overview' spotipy_helper.get_secrets() all_playlists, song_count = subsonic_helper.select_all_playlists(spotipy_helper, @@ -99,7 +100,7 @@ def overview(page=1, limit=100, order='subsonic_spotify_relation.subsonic_playli pagination_array, prev_page, next_page = utils.get_pagination( page, total_pages) sorting_dict = {} - sorting_dict["Playlist Name"] = "subsonic_spotify_relation.subsonic_playlist_name" + sorting_dict["Playlist Name"] = "playlist_info.subsonic_playlist_name" sorting_dict["Type"] = "playlist_info.type" return render_template('overview.html', title=title, @@ -123,12 +124,12 @@ def overview(page=1, limit=100, order='subsonic_spotify_relation.subsonic_playli @spotisub.route('/overview_content////') @spotisub.route('/overview_content/////') @login_required -def overview_content(page=1, limit=25, order='subsonic_spotify_relation.subsonic_playlist_name', asc=1): +def overview_content(page=1, limit=25, order='playlist_info.subsonic_playlist_name', asc=1): spotipy_helper.get_secrets() all_playlists, song_count = subsonic_helper.select_all_playlists(spotipy_helper, page=page - 1, limit=limit, order=order, asc=(asc == 1)) sorting_dict = {} - sorting_dict["Playlist Name"] = "subsonic_spotify_relation.subsonic_playlist_name" + sorting_dict["Playlist Name"] = "playlist_info.subsonic_playlist_name" sorting_dict["Type"] = "playlist_info.type" return render_template('overview_content.html', playlists=all_playlists, @@ -155,14 +156,14 @@ def playlist(uuid=None, page=1, limit=25, pagination_array, prev_page, next_page = utils.get_pagination( page, total_pages) - playlist_info = subsonic_helper.select_playlist_info_by_subsonic_id(spotipy_helper, uuid) + playlist_info = subsonic_helper.select_playlist_info_by_uuid(spotipy_helper, uuid) sorting_dict = {} sorting_dict["Status"] = "subsonic_spotify_relation.subsonic_song_id" sorting_dict["Spotify Song Title"] = "spotify_song.title" sorting_dict["Spotify Artist"] = "spotify_artist.name" sorting_dict["Spotify Album"] = "spotify_album.name" - sorting_dict["Playlist Name"] = "subsonic_spotify_relation.subsonic_playlist_name" + sorting_dict["Playlist Name"] = "playlist_info.subsonic_playlist_name" return render_template('playlists.html', title=title, @@ -204,7 +205,7 @@ def playlists(missing_only=0, page=1, limit=25, sorting_dict["Spotify Song Title"] = "spotify_song.title" sorting_dict["Spotify Artist"] = "spotify_artist.name" sorting_dict["Spotify Album"] = "spotify_album.name" - sorting_dict["Playlist Name"] = "subsonic_spotify_relation.subsonic_playlist_name" + sorting_dict["Playlist Name"] = "playlist_info.subsonic_playlist_name" return render_template('playlists.html', @@ -244,7 +245,7 @@ def song(uuid=None, page=1, limit=25, order='spotify_song.title', asc=1): sorting_dict["Spotify Song Title"] = "spotify_song.title" sorting_dict["Spotify Artist"] = "spotify_artist.name" sorting_dict["Spotify Album"] = "spotify_album.name" - sorting_dict["Playlist Name"] = "subsonic_spotify_relation.subsonic_playlist_name" + sorting_dict["Playlist Name"] = "playlist_info.subsonic_playlist_name" return render_template('song.html', title=title, @@ -281,7 +282,7 @@ def album(uuid=None, page=1, limit=25, order='spotify_song.title', asc=1): sorting_dict["Spotify Song Title"] = "spotify_song.title" sorting_dict["Spotify Artist"] = "spotify_artist.name" sorting_dict["Spotify Album"] = "spotify_album.name" - sorting_dict["Playlist Name"] = "subsonic_spotify_relation.subsonic_playlist_name" + sorting_dict["Playlist Name"] = "playlist_info.subsonic_playlist_name" return render_template('album.html', title=title, album=album1, @@ -318,7 +319,7 @@ def artist(uuid=None, page=1, limit=25, order='spotify_song.title', asc=1): sorting_dict["Spotify Song Title"] = "spotify_song.title" sorting_dict["Spotify Artist"] = "spotify_artist.name" sorting_dict["Spotify Album"] = "spotify_album.name" - sorting_dict["Playlist Name"] = "subsonic_spotify_relation.subsonic_playlist_name" + sorting_dict["Playlist Name"] = "playlist_info.subsonic_playlist_name" return render_template('artist.html', title=title, artist=artist1, @@ -340,16 +341,6 @@ def artist(uuid=None, page=1, limit=25, order='spotify_song.title', asc=1): def ignore(type=None, uuid=None, value = None): """Set ignored value to an object""" subsonic_helper.set_ignore(type,uuid,value) - if type == 'song': - database.update_ignored_song(uuid,value) - elif type == 'artist': - database.update_ignored_artist(uuid,value) - elif type == 'album': - database.update_ignored_album(uuid,value) - elif type == 'song_pl': - database.update_ignored_song_pl(uuid,value) - elif type == 'playlist': - database.update_ignored_playlist(uuid,value) return get_response_json(get_json_message( "Setting ignored to " +str(value)+ " to object with uuid " + uuid +", type: " + type, True), 200) @@ -583,6 +574,12 @@ def remove_subsonic_deleted_playlist(): subsonic_helper.remove_subsonic_deleted_playlist() +@scheduler.task('interval', id='scan_library', hours=1) +def scan_library(): + """remove_subsonic_deleted_playlist task""" + generator.scan_library() + + scheduler.init_app(spotisub) scheduler.start(paused=(os.environ.get(constants.SCHEDULER_ENABLED, constants.SCHEDULER_ENABLED_DEFAULT_VALUE) != "1")) @@ -590,6 +587,6 @@ def remove_subsonic_deleted_playlist(): # Used to initialize cache for the first 100 playlists try: - subsonic_helper.select_all_playlists(spotipy_helper, page=0, limit=100, order='subsonic_spotify_relation.subsonic_playlist_name', asc=True) + subsonic_helper.select_all_playlists(spotipy_helper, page=0, limit=100, order='playlist_info.subsonic_playlist_name', asc=True) except: - pass \ No newline at end of file + pass diff --git a/spotisub/templates/album.html b/spotisub/templates/album.html index b54683f..9deb790 100644 --- a/spotisub/templates/album.html +++ b/spotisub/templates/album.html @@ -82,14 +82,14 @@ {% endif %} - {% if order == 'subsonic_spotify_relation.subsonic_playlist_name' %} + {% if order == 'playlist_info.subsonic_playlist_name' %} {% if asc == 1 %} - Playlist Name + Playlist Name {% else %} - Playlist Name + Playlist Name {% endif %} {% else %} - Playlist Name + Playlist Name {% endif %} @@ -140,15 +140,15 @@ {% if song.ignored_whole_pl == 1 %} {% endif %} - {{ song.subsonic_playlist_name }} + {{ song.subsonic_playlist_name }} {% if song.ignored_pl == 1 %} - + {% else %} - + {% endif %} diff --git a/spotisub/templates/artist.html b/spotisub/templates/artist.html index 8e6fac9..915195c 100644 --- a/spotisub/templates/artist.html +++ b/spotisub/templates/artist.html @@ -91,14 +91,14 @@ {% endif %} - {% if order == 'subsonic_spotify_relation.subsonic_playlist_name' %} + {% if order == 'playlist_info.subsonic_playlist_name' %} {% if asc == 1 %} - Playlist Name + Playlist Name {% else %} - Playlist Name + Playlist Name {% endif %} {% else %} - Playlist Name + Playlist Name {% endif %} @@ -146,15 +146,15 @@ {% if song.ignored_whole_pl == 1 %} {% endif %} - {{ song.subsonic_playlist_name }} + {{ song.subsonic_playlist_name }} {% if song.ignored_pl == 1 %} - + {% else %} - + {% endif %} diff --git a/spotisub/templates/overview.html b/spotisub/templates/overview.html index 5904c57..52aced2 100644 --- a/spotisub/templates/overview.html +++ b/spotisub/templates/overview.html @@ -19,14 +19,14 @@ - {% if order == 'subsonic_spotify_relation.subsonic_playlist_name' %} + {% if order == 'playlist_info.subsonic_playlist_name' %} {% if asc == 1 %} - Playlist Name + Playlist Name {% else %} - Playlist Name + Playlist Name {% endif %} {% else %} - Playlist Name + Playlist Name {% endif %} {% if order == 'playlist_info.type' %} diff --git a/spotisub/templates/overview_content.html b/spotisub/templates/overview_content.html index d06ea3f..b2d04a6 100644 --- a/spotisub/templates/overview_content.html +++ b/spotisub/templates/overview_content.html @@ -1,10 +1,10 @@ {% for playlist in playlists %} - {{ playlist[ -{{ playlist["subsonic_playlist_name"] }} +{{ playlist["subsonic_playlist_name"] }} {{ playlist["type_desc"] }} {% if playlist["type"] == "user_playlists" %} diff --git a/spotisub/templates/playlists.html b/spotisub/templates/playlists.html index 91ed991..fa525b2 100644 --- a/spotisub/templates/playlists.html +++ b/spotisub/templates/playlists.html @@ -79,14 +79,14 @@ {% endif %} - {% if order == 'subsonic_spotify_relation.subsonic_playlist_name' %} + {% if order == 'playlist_info.subsonic_playlist_name' %} {% if asc == 1 %} - Playlist Name + Playlist Name {% else %} - Playlist Name + Playlist Name {% endif %} {% else %} - Playlist Name + Playlist Name {% endif %} @@ -137,15 +137,15 @@ {% if playlist.ignored_whole_pl == 1 %} {% endif %} - {{ playlist.subsonic_playlist_name }} + {{ playlist.subsonic_playlist_name }} {% if playlist.ignored_pl == 1 %} - + {% else %} - + {% endif %} diff --git a/spotisub/templates/song.html b/spotisub/templates/song.html index baa122e..89d4e19 100644 --- a/spotisub/templates/song.html +++ b/spotisub/templates/song.html @@ -90,14 +90,14 @@ {% endif %} - {% if order == 'subsonic_spotify_relation.subsonic_playlist_name' %} + {% if order == 'playlist_info.subsonic_playlist_name' %} {% if asc == 1 %} - Playlist Name + Playlist Name {% else %} - Playlist Name + Playlist Name {% endif %} {% else %} - Playlist Name + Playlist Name {% endif %} @@ -144,15 +144,15 @@ {% if song.ignored_whole_pl == 1 %} {% endif %} - {{ song.subsonic_playlist_name }} + {{ song.subsonic_playlist_name }} {% if song.ignored_pl == 1 %} - + {% else %} - + {% endif %} diff --git a/spotisub/templates/toolbar.html b/spotisub/templates/toolbar.html index debd06a..b1e45c8 100644 --- a/spotisub/templates/toolbar.html +++ b/spotisub/templates/toolbar.html @@ -1,23 +1,22 @@
- -
{% if title == 'Playlist' %} {% if playlist_info["ignored"] == 1 %} - {% else %} - {% endif %} {% endif %} +