diff --git a/server/app/api/album.py b/server/app/api/album.py index ada2555f..fbdf73d4 100644 --- a/server/app/api/album.py +++ b/server/app/api/album.py @@ -36,7 +36,7 @@ def get_albums(): @album_bp.route("/album/tracks", methods=["POST"]) -def get_album_tracks(): +def get_album(): """Returns all the tracks in the given album.""" data = request.get_json() @@ -46,11 +46,19 @@ def get_album_tracks(): songs = trackslib.get_album_tracks(album, artist) albumhash = helpers.create_album_hash(album, artist) index = albumslib.find_album(api.ALBUMS, albumhash) - album = api.ALBUMS[index] + album: models.Album = api.ALBUMS[index] album.count = len(songs) album.duration = albumslib.get_album_duration(songs) + if ( + album.count == 1 + and songs[0].title == album.title + and songs[0].tracknumber == 1 + and songs[0].disknumber == 1 + ): + album.is_single = True + return {"songs": songs, "info": album} diff --git a/server/app/lib/taglib.py b/server/app/lib/taglib.py index bee344ff..0106b2c3 100644 --- a/server/app/lib/taglib.py +++ b/server/app/lib/taglib.py @@ -28,7 +28,7 @@ def return_album_art(filepath: str): return None -def extract_thumb(audio_file_path: str, webp_path: str) -> bool: +def extract_thumb(filepath: str, webp_path: str) -> bool: """ Extracts the thumbnail from an audio file. Returns the path to the thumbnail. """ @@ -37,7 +37,7 @@ def extract_thumb(audio_file_path: str, webp_path: str) -> bool: if os.path.exists(img_path): return True - album_art = return_album_art(audio_file_path) + album_art = return_album_art(filepath) if album_art is not None: img = Image.open(BytesIO(album_art)) @@ -58,98 +58,98 @@ def extract_thumb(audio_file_path: str, webp_path: str) -> bool: return False -def parse_artist_tag(audio): +def parse_artist_tag(tags): """ Parses the artist tag from an audio file. """ try: - artists = audio["artist"][0] + artists = tags["artist"][0] except (KeyError, IndexError): artists = "Unknown" return artists -def parse_title_tag(audio, full_path: str): +def parse_title_tag(tags, full_path: str): """ Parses the title tag from an audio file. """ try: - title = audio["title"][0] + title = tags["title"][0] except (KeyError, IndexError): title = full_path.split("/")[-1] return title -def parse_album_artist_tag(audio): +def parse_album_artist_tag(tags): """ Parses the album artist tag from an audio file. """ try: - albumartist = audio["albumartist"][0] + albumartist = tags["albumartist"][0] except (KeyError, IndexError): albumartist = "Unknown" return albumartist -def parse_album_tag(audio, full_path: str): +def parse_album_tag(tags, full_path: str): """ Parses the album tag from an audio file. """ try: - album = audio["album"][0] + album = tags["album"][0] except (KeyError, IndexError): album = full_path.split("/")[-1] return album -def parse_genre_tag(audio): +def parse_genre_tag(tags): """ Parses the genre tag from an audio file. """ try: - genre = audio["genre"][0] + genre = tags["genre"][0] except (KeyError, IndexError): genre = "Unknown" return genre -def parse_date_tag(audio): +def parse_date_tag(tags): """ Parses the date tag from an audio file. """ try: - date = audio["date"][0] + date = tags["date"][0] except (KeyError, IndexError): date = "Unknown" return date -def parse_track_number(audio): +def parse_track_number(tags): """ Parses the track number from an audio file. """ try: - track_number = audio["tracknumber"][0] + track_number = tags["tracknumber"][0] except (KeyError, IndexError): - track_number = "Unknown" + track_number = 1 return track_number -def parse_disk_number(audio): +def parse_disk_number(tags): """ Parses the disk number from an audio file. """ try: - disk_number = audio["discnumber"][0] + disk_number = tags["disknumber"][0] except (KeyError, IndexError): - disk_number = "Unknown" + disk_number = 1 return disk_number @@ -159,21 +159,21 @@ def get_tags(fullpath: str) -> dict | None: Returns a dictionary of tags for a given file. """ try: - audio = mutagen.File(fullpath, easy=True) + tags = mutagen.File(fullpath, easy=True) except MutagenError: return None tags = { - "artists": parse_artist_tag(audio), - "title": parse_title_tag(audio, fullpath), - "albumartist": parse_album_artist_tag(audio), - "album": parse_album_tag(audio, fullpath), - "genre": parse_genre_tag(audio), - "date": parse_date_tag(audio)[:4], - "tracknumber": parse_track_number(audio), - "discnumber": parse_disk_number(audio), - "length": round(audio.info.length), - "bitrate": round(int(audio.info.bitrate) / 1000), + "artists": parse_artist_tag(tags), + "title": parse_title_tag(tags, fullpath), + "albumartist": parse_album_artist_tag(tags), + "album": parse_album_tag(tags, fullpath), + "genre": parse_genre_tag(tags), + "date": parse_date_tag(tags)[:4], + "tracknumber": parse_track_number(tags), + "disknumber": parse_disk_number(tags), + "length": round(tags.info.length), + "bitrate": round(int(tags.info.bitrate) / 1000), "filepath": fullpath, "folder": os.path.dirname(fullpath), } diff --git a/server/app/models.py b/server/app/models.py index fc15bbd0..47e5c452 100644 --- a/server/app/models.py +++ b/server/app/models.py @@ -1,12 +1,10 @@ """ Contains all the models for objects generation and typing. """ -from dataclasses import dataclass -from dataclasses import field +from dataclasses import dataclass, field from typing import List -from app import api -from app import helpers +from app import api, helpers from app.exceptions import TrackExistsInPlaylist @@ -28,7 +26,7 @@ class Track: bitrate: int image: str tracknumber: int - discnumber: int + disknumber: int albumhash: str def __init__(self, tags): @@ -43,18 +41,21 @@ class Track: self.album = tags["album"] self.folder = tags["folder"] self.filepath = tags["filepath"] - self.length = tags["length"] self.genre = tags["genre"] - self.bitrate = tags["bitrate"] + self.bitrate = int(tags["bitrate"]) + self.length = int(tags["length"]) + self.disknumber = int(tags["disknumber"]) + self.albumhash = tags["albumhash"] try: self.image = tags["image"] except KeyError: print(tags) - self.tracknumber = tags["tracknumber"] - self.discnumber = tags["discnumber"] - self.albumhash = tags["albumhash"] + try: + self.tracknumber = int(tags["tracknumber"]) + except ValueError: + self.tracknumber = 1 @dataclass(slots=True) @@ -88,6 +89,7 @@ class Album: duration: int = 0 is_soundtrack: bool = False is_compilation: bool = False + is_single: bool = False def __init__(self, tags): self.title = tags["title"] diff --git a/src/components/AlbumView/Header.vue b/src/components/AlbumView/Header.vue index f30b362d..166beb8f 100644 --- a/src/components/AlbumView/Header.vue +++ b/src/components/AlbumView/Header.vue @@ -15,6 +15,7 @@