diff --git a/app/model.py b/app/model.py index 427a604..7ad0042 100644 --- a/app/model.py +++ b/app/model.py @@ -119,6 +119,17 @@ class Playdates(Base): else: return None + @staticmethod + def remove_track(session, track_id): + """ + Remove all records of track_id + """ + + session.query(Playdates).filter( + Playdates.track_id == track_id, + ).delete() + session.commit() + class Playlists(Base): """ @@ -293,18 +304,11 @@ class PlaylistTracks(Base): session.commit() @staticmethod - def get_playlists_containing_track_id(session, track_id): + def get_track_playlists(session, track_id): + "Return all PlaylistTracks objects with this track_id" - playlists = [] - playlist_ids = session.query(PlaylistTracks.playlist_id).filter( + return session.query(PlaylistTracks).filter( PlaylistTracks.track_id == track_id).all() - for p in playlist_ids: - playlist = session.query(Playlists).filter( - Playlists.id == p[0]).first() - if playlist: - playlists.append(playlist) - - return playlists @staticmethod def move_track(session, from_playlist_id, row, to_playlist_id): @@ -492,6 +496,29 @@ class Tracks(Base): ERROR(f"get_track({id}): not found") return None + @staticmethod + def search(session, title=None, artist=None, duration=None): + """ + Return any tracks matching passed criteria + """ + + DEBUG( + f"Tracks.search({title=}, {artist=}), {duration=})" + ) + + if not title and not artist and not duration: + return None + + q = session.query(Tracks).filter(False) + if title: + q = q.filter(Tracks.title == title) + if artist: + q = q.filter(Tracks.artist == artist) + if duration: + q = q.filter(Tracks.duration == duration) + + return q.all() + @staticmethod def get_track_from_filename(session, filename): """ @@ -527,6 +554,7 @@ class Tracks(Base): try: session.query(Tracks).filter(Tracks.path == path).delete() + session.commit() except IntegrityError as exception: ERROR(f"Can't remove track with {path=} ({exception=})") diff --git a/app/songdb.py b/app/songdb.py index f611629..b1a1070 100755 --- a/app/songdb.py +++ b/app/songdb.py @@ -7,7 +7,7 @@ import tempfile from config import Config from log import DEBUG, INFO -from model import Tracks, Playdates, PlaylistTracks, Session +from model import Notes, Playdates, PlaylistTracks, Session, Tracks from mutagen.flac import FLAC from mutagen.mp3 import MP3 from pydub import AudioSegment, effects @@ -255,23 +255,26 @@ def update_db(session): db_paths = set(Tracks.get_all_paths(session)) # Remote any tracks from database whose paths don't exist for path in list(db_paths - os_paths): + # Manage tracks listed in database but where path is invalid track = Tracks.get_track_from_path(session, path) DEBUG(f"songdb.update_db(): remove from database: {path=} {track=}") - played = Playdates.last_played(session, track) - playlists = PlaylistTracks.get_playlists_containing_track_id( - session, track.id) - if played: - INFO( - f"songdb.update_db: Can't remove {track.id=} ({track.path=}) " - f"as it's in playdates.id={played.id}" - ) - elif playlists: - INFO( - f"songdb.update_db: Can't remove {track.id=} ({track.path=} " - f"as it's in playlists {[p.name for p in playlists]}" - ) - else: - Tracks.remove_path(session, path) + + # Remove references from Playdates + Playdates.remove_track(session, track.id) + + # Replace playlist entries with a note + note_txt = ( + f"File removed: {track.title=}, {track.artist=}, " + f"{track.path=}" + ) + for pt in PlaylistTracks.get_track_playlists(session, track.id): + # Create note + Notes.add_note(session, pt.playlist_id, pt.row, note_txt) + # Remove playlist entry + PlaylistTracks.remove_track(session, pt.playlist_id, pt.row) + + # Remove Track entry pointing to invalid path + Tracks.remove_path(session, path) if __name__ == '__main__' and '__file__' in globals():