check if track exists in db before sending file

This commit is contained in:
mungai-njoroge 2023-06-19 21:49:13 +03:00
parent a201303bd9
commit cc6552cb94
17 changed files with 96 additions and 31 deletions

1
.gitignore vendored
View File

@ -22,3 +22,4 @@ encoderx.py
dist dist
build build
client client
.gitignore

View File

@ -185,20 +185,13 @@ def get_all_favorites():
artists = remove_none(artists) artists = remove_none(artists)
recents = [] recents = []
first_n = favs[:album_limit] # first_n = favs
for fav in first_n: for fav in favs:
if fav[2] == FavType.track: if len(recents) >= largest:
try: break
track = [t for t in tracks if t.trackhash == fav[1]][0]
recents.append({
"type": "track",
"item": recent_fav_track_serializer(track)
})
except IndexError:
pass
elif fav[2] == FavType.album: if fav[2] == FavType.album:
try: try:
album = [a for a in albums if a.albumhash == fav[1]][0] album = [a for a in albums if a.albumhash == fav[1]][0]
recents.append({ recents.append({
@ -206,8 +199,9 @@ def get_all_favorites():
"item": recent_fav_album_serializer(album) "item": recent_fav_album_serializer(album)
}) })
except IndexError: except IndexError:
pass continue
elif fav[2] == FavType.artist:
if fav[2] == FavType.artist:
try: try:
artist = [a for a in artists if a.artisthash == fav[1]][0] artist = [a for a in artists if a.artisthash == fav[1]][0]
recents.append({ recents.append({
@ -215,7 +209,7 @@ def get_all_favorites():
"item": recent_fav_artist_serializer(artist) "item": recent_fav_artist_serializer(artist)
}) })
except IndexError: except IndexError:
pass continue
return { return {
"recents": recents[:album_limit], "recents": recents[:album_limit],

View File

@ -24,9 +24,17 @@ def send_track_file(trackhash: str):
filepath = request.args.get("filepath") filepath = request.args.get("filepath")
if filepath is not None and os.path.exists(filepath): if filepath is not None:
audio_type = get_mime(filepath) try:
return send_file(filepath, mimetype=audio_type) track = TrackStore.get_tracks_by_filepaths([filepath])[0]
except IndexError:
track = None
track_exists = track is not None and os.path.exists(track.filepath)
if track_exists:
audio_type = get_mime(filepath)
return send_file(filepath, mimetype=audio_type)
if trackhash is None: if trackhash is None:
return msg, 404 return msg, 404

View File

@ -151,7 +151,9 @@ class HandleArgs:
@staticmethod @staticmethod
def handle_periodic_scan_interval(): def handle_periodic_scan_interval():
if any((a in ARGS for a in ALLARGS.periodic_scan_interval.value)): if any((a in ARGS for a in ALLARGS.periodic_scan_interval.value)):
index = [ARGS.index(a) for a in ALLARGS.periodic_scan_interval.value if a in ARGS][0] index = [
ARGS.index(a) for a in ALLARGS.periodic_scan_interval.value if a in ARGS
][0]
try: try:
interval = ARGS[index + 1] interval = ARGS[index + 1]

View File

@ -17,13 +17,17 @@ class SQLiteAlbumMethods:
""" """
cur.execute(sql, (albumhash, colors)) cur.execute(sql, (albumhash, colors))
return cur.lastrowid lastrowid = cur.lastrowid
cur.close()
return lastrowid
@classmethod @classmethod
def get_all_albums(cls): def get_all_albums(cls):
with SQLiteManager() as cur: with SQLiteManager() as cur:
cur.execute("SELECT * FROM albums") cur.execute("SELECT * FROM albums")
albums = cur.fetchall() albums = cur.fetchall()
cur.close()
if albums is not None: if albums is not None:
return albums return albums
@ -35,6 +39,7 @@ class SQLiteAlbumMethods:
with SQLiteManager() as cur: with SQLiteManager() as cur:
cur.execute("SELECT * FROM albums WHERE albumartist=?", (albumartist,)) cur.execute("SELECT * FROM albums WHERE albumartist=?", (albumartist,))
albums = cur.fetchall() albums = cur.fetchall()
cur.close()
if albums is not None: if albums is not None:
return tuples_to_albums(albums) return tuples_to_albums(albums)

View File

@ -21,6 +21,7 @@ class SQLiteArtistMethods:
""" """
colors = json.dumps(colors) colors = json.dumps(colors)
cur.execute(sql, (artisthash, colors)) cur.execute(sql, (artisthash, colors))
cur.close()
@staticmethod @staticmethod
def get_all_artists(): def get_all_artists():
@ -34,3 +35,5 @@ class SQLiteArtistMethods:
for artist in cur.fetchall(): for artist in cur.fetchall():
yield artist yield artist
cur.close()

View File

@ -14,6 +14,7 @@ class SQLiteFavoriteMethods:
with SQLiteManager(userdata_db=True) as cur: with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (itemhash, fav_type)) cur.execute(sql, (itemhash, fav_type))
items = cur.fetchall() items = cur.fetchall()
cur.close()
return len(items) > 0 return len(items) > 0
@classmethod @classmethod
@ -28,6 +29,7 @@ class SQLiteFavoriteMethods:
sql = """INSERT INTO favorites(type, hash) VALUES(?,?)""" sql = """INSERT INTO favorites(type, hash) VALUES(?,?)"""
with SQLiteManager(userdata_db=True) as cur: with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (fav_type, fav_hash)) cur.execute(sql, (fav_type, fav_hash))
cur.close()
@classmethod @classmethod
def get_all(cls) -> list[tuple]: def get_all(cls) -> list[tuple]:
@ -38,6 +40,7 @@ class SQLiteFavoriteMethods:
with SQLiteManager(userdata_db=True) as cur: with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql) cur.execute(sql)
favs = cur.fetchall() favs = cur.fetchall()
cur.close()
return [fav for fav in favs if fav[1] != ""] return [fav for fav in favs if fav[1] != ""]
@classmethod @classmethod
@ -48,7 +51,9 @@ class SQLiteFavoriteMethods:
sql = """SELECT * FROM favorites WHERE type = ?""" sql = """SELECT * FROM favorites WHERE type = ?"""
with SQLiteManager(userdata_db=True) as cur: with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (fav_type,)) cur.execute(sql, (fav_type,))
return cur.fetchall() all_favs = cur.fetchall()
cur.close()
return all_favs
@classmethod @classmethod
def get_fav_tracks(cls) -> list[tuple]: def get_fav_tracks(cls) -> list[tuple]:
@ -80,3 +85,4 @@ class SQLiteFavoriteMethods:
with SQLiteManager(userdata_db=True) as cur: with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (fav_hash, fav_type)) cur.execute(sql, (fav_hash, fav_type))
cur.close()

View File

@ -21,7 +21,10 @@ class MigrationManager:
""" """
with SQLiteManager() as cur: with SQLiteManager() as cur:
cur.execute(cls.all_get_sql) cur.execute(cls.all_get_sql)
return int(cur.fetchone()[1]) ver = int(cur.fetchone()[1])
cur.close()
return ver
@classmethod @classmethod
def get_maindb_postinit_version(cls) -> int: def get_maindb_postinit_version(cls) -> int:
@ -30,7 +33,10 @@ class MigrationManager:
""" """
with SQLiteManager() as cur: with SQLiteManager() as cur:
cur.execute(cls.all_get_sql) cur.execute(cls.all_get_sql)
return int(cur.fetchone()[2]) ver = int(cur.fetchone()[2])
cur.close()
return ver
@classmethod @classmethod
def get_userdatadb_postinit_version(cls) -> int: def get_userdatadb_postinit_version(cls) -> int:
@ -39,7 +45,10 @@ class MigrationManager:
""" """
with SQLiteManager(userdata_db=True) as cur: with SQLiteManager(userdata_db=True) as cur:
cur.execute(cls.all_get_sql) cur.execute(cls.all_get_sql)
return cur.fetchone()[2] ver = cur.fetchone()[2]
cur.close()
return ver
# 👇 Setters 👇 # 👇 Setters 👇
@classmethod @classmethod
@ -49,6 +58,7 @@ class MigrationManager:
""" """
with SQLiteManager() as cur: with SQLiteManager() as cur:
cur.execute(cls.pre_init_set_sql, (version,)) cur.execute(cls.pre_init_set_sql, (version,))
cur.close()
@classmethod @classmethod
def set_maindb_postinit_version(cls, version: int): def set_maindb_postinit_version(cls, version: int):

View File

@ -31,6 +31,7 @@ class SQLitePlaylistMethods:
with SQLiteManager(userdata_db=True) as cur: with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, playlist) cur.execute(sql, playlist)
pid = cur.lastrowid pid = cur.lastrowid
cur.close()
p_tuple = (pid, *playlist.values()) p_tuple = (pid, *playlist.values())
return tuple_to_playlist(p_tuple) return tuple_to_playlist(p_tuple)
@ -43,6 +44,7 @@ class SQLitePlaylistMethods:
cur.execute(sql, (name,)) cur.execute(sql, (name,))
data = cur.fetchone() data = cur.fetchone()
cur.close()
if data is not None: if data is not None:
return tuple_to_playlist(data) return tuple_to_playlist(data)
@ -57,6 +59,7 @@ class SQLitePlaylistMethods:
cur.execute(sql, (name,)) cur.execute(sql, (name,))
data = cur.fetchone() data = cur.fetchone()
cur.close()
return int(data[0]) return int(data[0])
@ -65,6 +68,7 @@ class SQLitePlaylistMethods:
with SQLiteManager(userdata_db=True) as cur: with SQLiteManager(userdata_db=True) as cur:
cur.execute("SELECT * FROM playlists") cur.execute("SELECT * FROM playlists")
playlists = cur.fetchall() playlists = cur.fetchall()
cur.close()
if playlists is not None: if playlists is not None:
return tuples_to_playlists(playlists) return tuples_to_playlists(playlists)
@ -79,6 +83,7 @@ class SQLitePlaylistMethods:
cur.execute(sql, (playlist_id,)) cur.execute(sql, (playlist_id,))
data = cur.fetchone() data = cur.fetchone()
cur.close()
if data is not None: if data is not None:
return tuple_to_playlist(data) return tuple_to_playlist(data)

View File

@ -18,6 +18,7 @@ class SettingsSQLMethods:
with SQLiteManager(userdata_db=True) as cur: with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql) cur.execute(sql)
dirs = cur.fetchall() dirs = cur.fetchall()
cur.close()
dirs = [_dir[0] for _dir in dirs] dirs = [_dir[0] for _dir in dirs]
return [win_replace_slash(d) for d in dirs] return [win_replace_slash(d) for d in dirs]

View File

@ -32,7 +32,7 @@ def get_folders(paths: list[str]):
for track in TrackStore.tracks: for track in TrackStore.tracks:
for path in paths: for path in paths:
if track.filepath.startswith(path): if track.folder.startswith(path):
count_dict[path] += 1 count_dict[path] += 1
folders = [{"path": path, "count": count_dict[path]} for path in paths] folders = [{"path": path, "count": count_dict[path]} for path in paths]

View File

@ -131,6 +131,11 @@ def add_track(filepath: str) -> None:
Then creates the folder, album and artist objects for the added track and adds them to the store. Then creates the folder, album and artist objects for the added track and adds them to the store.
""" """
# remove the track if it already exists
TrackStore.remove_track_by_filepath(filepath)
db.remove_track_by_filepath(filepath)
# add the track to the database and store.
tags = get_tags(filepath) tags = get_tags(filepath)
if tags is None: if tags is None:
@ -253,7 +258,11 @@ class Handler(PatternMatchingEventHandler):
if os.path.getsize(event.src_path) > 0: if os.path.getsize(event.src_path) > 0:
path = self.get_abs_path(event.src_path) path = self.get_abs_path(event.src_path)
add_track(path) add_track(path)
except FileNotFoundError:
# file was closed and deleted.
pass
except ValueError: except ValueError:
# file was removed from the list by another event handler.
pass pass
def on_modified(self, event): def on_modified(self, event):

View File

@ -42,7 +42,7 @@ class Track:
self.og_album = self.album self.og_album = self.album
if self.artist is not None: if self.artist is not None:
artists = split_artists(self.artist) artists = split_artists(self.artist, with_and=True)
new_title = self.title new_title = self.title
if get_flag(ParserFlags.EXTRACT_FEAT): if get_flag(ParserFlags.EXTRACT_FEAT):
@ -71,7 +71,7 @@ class Track:
self.artist_hashes = "-".join(create_hash(a, decode=True) for a in artists) self.artist_hashes = "-".join(create_hash(a, decode=True) for a in artists)
self.artist = [ArtistMinimal(a) for a in artists] self.artist = [ArtistMinimal(a) for a in artists]
albumartists = split_artists(self.albumartist) albumartists = split_artists(self.albumartist, with_and=True)
self.albumartist = [ArtistMinimal(a) for a in albumartists] self.albumartist = [ArtistMinimal(a) for a in albumartists]
self.filetype = self.filepath.rsplit(".", maxsplit=1)[-1] self.filetype = self.filepath.rsplit(".", maxsplit=1)[-1]

View File

@ -5,6 +5,8 @@ args = ALLARGS
HELP_MESSAGE = f""" HELP_MESSAGE = f"""
Usage: swingmusic [options] Usage: swingmusic [options]
Swing Music is a beautiful, self-hosted music player for your local audio files. Like a cooler Spotify ... but bring your own music.
Options: Options:
{', '.join(args.help.value)}: Show this help message {', '.join(args.help.value)}: Show this help message
{', '.join(args.version.value)}: Show the app version {', '.join(args.version.value)}: Show the app version

View File

@ -1,4 +1,4 @@
from app.models import Track, Album, Artist from app.models import Album, Artist, Track
def recent_fav_track_serializer(track: Track) -> dict: def recent_fav_track_serializer(track: Track) -> dict:
@ -21,8 +21,9 @@ def recent_fav_album_serializer(album: Album) -> dict:
""" """
return { return {
"image": album.image, "image": album.image,
"title": album.title, "title": album.og_title,
"albumhash": album.albumhash, "albumhash": album.albumhash,
"artist": album.albumartists[0].name,
"colors": album.colors, "colors": album.colors,
} }

View File

@ -8,7 +8,7 @@ join = os.path.join
class Release: class Release:
APP_VERSION = "v1.2.1" APP_VERSION = "1.3.0.beta"
class Paths: class Paths:

View File

@ -6,7 +6,7 @@ def split_artists(src: str, with_and: bool = False):
""" """
Splits a string of artists into a list of artists. Splits a string of artists into a list of artists.
""" """
exp = r"\s*(?: and |&|,|;)\s*" if with_and else r"\s*[,;]\s*" exp = r"\s*(?: and |&|,|;|/)\s*" if with_and else r"\s*[,;]\s*"
artists = re.split(exp, src) artists = re.split(exp, src)
return [a.strip() for a in artists] return [a.strip() for a in artists]
@ -245,3 +245,21 @@ def clean_title(title: str) -> str:
# #
# if "-" in title: # if "-" in title:
# return remove_hyphen_remasters(title) # return remove_hyphen_remasters(title)
# Traceback (most recent call last):
# File "/usr/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
# self.run()
# File "/usr/lib/python3.10/threading.py", line 953, in run
# self._target(*self._args, **self._kwargs)
# File "/home/cwilvx/code/swingmusic/app/periodic_scan.py", line 29, in run_periodic_scans
# Populate(key=get_random_str())
# File "/home/cwilvx/code/swingmusic/app/lib/populate.py", line 74, in __init__
# self.tag_untagged(untagged, key)
# File "/home/cwilvx/code/swingmusic/app/lib/populate.py", line 123, in tag_untagged
# insert_many_tracks(tagged_tracks)
# File "/home/cwilvx/code/swingmusic/app/db/sqlite/tracks.py", line 54, in insert_many_tracks
# cls.insert_one_track(track, cur)
# File "/home/cwilvx/code/swingmusic/app/db/sqlite/tracks.py", line 45, in insert_one_track
# cur.execute(sql, track)
# sqlite3.IntegrityError: UNIQUE constraint failed: tracks.filepath