create albums from pre-albums instead of individual tracks

This commit is contained in:
geoffrey45
2022-04-25 11:59:36 +03:00
parent c6e3bd9f94
commit 6527b3abc5
6 changed files with 106 additions and 45 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ VALID_FOLDERS: Set[str] = set()
ALBUMS: List[models.Album] = []
TRACKS: List[models.Track] = []
PLAYLISTS: List[models.Playlist] = []
FOLDERS: Set[models.Folder] = set()
FOLDERS: List[models.Folder] = List
@helpers.background
+14 -7
View File
@@ -15,11 +15,17 @@ def send_track_file(trackid):
Returns an audio file that matches the passed id to the client.
"""
try:
filepath = [
file["filepath"] for file in api.DB_TRACKS
if file["_id"]["$oid"] == trackid
][0]
except (FileNotFoundError, IndexError) as e:
files = []
for f in api.DB_TRACKS:
try:
if f["_id"]["$oid"] == trackid:
files.append(f["filepath"])
except KeyError:
# Bug: some albums are not found although they exist in `api.ALBUMS`. It has something to do with the bisection method used or sorting. Not sure yet.
pass
filepath = files[0]
except IndexError:
return "File not found", 404
return send_file(filepath, mimetype="audio/mp3")
@@ -31,5 +37,6 @@ def get_sample_track():
Returns a sample track object.
"""
return instances.tracks_instance.get_song_by_album("Legends Never Die",
"Juice WRLD")
return instances.tracks_instance.get_song_by_album(
"Legends Never Die", "Juice WRLD"
)
+59 -20
View File
@@ -3,11 +3,12 @@ This module contains functions for the server
"""
import datetime
import os
from pprint import pprint
import random
import time
from dataclasses import asdict
from io import BytesIO
from typing import List
from typing import List, Type
import requests
from app import api
@@ -60,8 +61,7 @@ def populate():
albums = []
folders = set()
files = helpers.run_fast_scandir(settings.HOME_DIR, [".flac", ".mp3"],
full=True)[1]
files = helpers.run_fast_scandir(settings.HOME_DIR, [".flac", ".mp3"], full=True)[1]
_bar = Bar("Checking files", max=len(files))
for track in db_tracks:
@@ -88,24 +88,59 @@ def populate():
Log(f"Tagged {len(tagged_tracks)} tracks")
_bar = Bar("Creating stuff", max=len(tagged_tracks))
for track in tagged_tracks:
albumindex = albumslib.find_album(track["album"], track["albumartist"])
album = None
pre_albums = []
for t in tagged_tracks:
a = {
"title": t["album"],
"artist": t["albumartist"],
}
if a not in pre_albums:
pre_albums.append(a)
exist_count = 0
_bar = Bar("Creating albums", max=len(pre_albums))
for aa in pre_albums:
albumindex = albumslib.find_album(aa["title"], aa["artist"])
if albumindex is None:
track = [
track
for track in tagged_tracks
if track["album"] == aa["title"]
and track["albumartist"] == aa["artist"]
][0]
album = albumslib.create_album(track)
api.ALBUMS.append(album)
albums.append(album)
instances.album_instance.insert_album(asdict(album))
else:
album = api.ALBUMS[albumindex]
exist_count += 1
track["image"] = album.image
upsert_id = instances.tracks_instance.insert_song(track)
_bar.next()
track["_id"] = {"$oid": str(upsert_id)}
api.TRACKS.append(models.Track(track))
_bar.finish()
Log(f"{exist_count} of {len(albums)} were already in the database")
_bar = Bar("Creating tracks", max=len(tagged_tracks))
for track in tagged_tracks:
try:
album_index = albumslib.find_album(track["album"], track["albumartist"])
album = api.ALBUMS[album_index]
track["image"] = album.image
upsert_id = instances.tracks_instance.insert_song(track)
track["_id"] = {"$oid": str(upsert_id)}
api.TRACKS.append(models.Track(track))
except TypeError:
# Bug: some albums are not found although they exist in `api.ALBUMS`. It has something to do with the bisection method used or sorting. Not sure yet.
pass
_bar.next()
@@ -118,7 +153,7 @@ def populate():
if folder not in api.VALID_FOLDERS:
api.VALID_FOLDERS.add(folder)
fff = folderslib.create_folder(folder)
api.FOLDERS.add(fff)
api.FOLDERS.append(fff)
_bar.next()
@@ -129,8 +164,11 @@ def populate():
end = time.time()
print(
str(datetime.timedelta(seconds=round(end - start))) + " elapsed for " +
str(len(files)) + " files")
str(datetime.timedelta(seconds=round(end - start)))
+ " elapsed for "
+ str(len(files))
+ " files"
)
def fetch_image_path(artist: str) -> str or None:
@@ -165,8 +203,9 @@ def fetch_artist_images():
_bar = Bar("Processing images", max=len(artists))
for artist in artists:
file_path = (helpers.app_dir + "/images/artists/" +
artist.replace("/", "::") + ".webp")
file_path = (
helpers.app_dir + "/images/artists/" + artist.replace("/", "::") + ".webp"
)
if not os.path.exists(file_path):
img_path = fetch_image_path(artist)
@@ -188,7 +227,8 @@ def fetch_album_bio(title: str, albumartist: str):
Returns the album bio for a given album.
"""
last_fm_url = "http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key={}&artist={}&album={}&format=json".format(
settings.LAST_FM_API_KEY, albumartist, title)
settings.LAST_FM_API_KEY, albumartist, title
)
try:
response = requests.get(last_fm_url)
@@ -197,8 +237,7 @@ def fetch_album_bio(title: str, albumartist: str):
return None
try:
bio = data["album"]["wiki"]["summary"].split(
'<a href="https://www.last.fm/')[0]
bio = data["album"]["wiki"]["summary"].split('<a href="https://www.last.fm/')[0]
except KeyError:
bio = None
+26 -10
View File
@@ -13,6 +13,9 @@ from app import models
from app.lib import trackslib
from progress.bar import Bar
from app.lib import taglib
from app import settings
def get_all_albums() -> List[models.Album]:
"""
@@ -51,7 +54,7 @@ def create_everything() -> List[models.Track]:
api.TRACKS.sort(key=lambda x: x.title)
def find_album(albumtitle: str, artist: str) -> models.Album:
def find_album(albumtitle: str, artist: str) -> int or None:
"""
Finds an album by album title and artist.
"""
@@ -63,8 +66,7 @@ def find_album(albumtitle: str, artist: str) -> models.Album:
iter += 1
mid = (left + right) // 2
if api.ALBUMS[mid].title == albumtitle and api.ALBUMS[
mid].artist == artist:
if api.ALBUMS[mid].title == albumtitle and api.ALBUMS[mid].artist == artist:
return mid
if api.ALBUMS[mid].title < albumtitle:
@@ -96,20 +98,33 @@ def use_defaults() -> str:
return path
def gen_random_path() -> str:
"""
Generates a random image file path for an album image.
"""
choices = "abcdefghijklmnopqrstuvwxyz0123456789"
path = "".join(random.choice(choices) for i in range(20))
path += ".webp"
return path
def get_album_image(album: list) -> str:
"""
Gets the image of an album.
"""
uri = settings.IMG_THUMB_URI
for track in album:
img_p = (track["album"] + track["albumartist"] + ".webp").replace(
"/", "::")
img = functions.extract_thumb(track["filepath"], webp_path=img_p)
img_p = gen_random_path()
if img is not None:
return img
exists = taglib.extract_thumb(track["filepath"], webp_path=img_p)
return use_defaults()
if exists:
return uri + img_p
return uri + use_defaults()
def get_album_tracks(album: str, artist: str) -> List:
@@ -142,7 +157,8 @@ def create_album(track) -> models.Album:
album["date"] = album_tracks[0]["date"]
album["artistimage"] = urllib.parse.quote_plus(
album_tracks[0]["albumartist"] + ".webp")
album_tracks[0]["albumartist"] + ".webp"
)
album["image"] = get_album_image(album_tracks)
+5 -6
View File
@@ -1,5 +1,4 @@
import os
import urllib
from io import BytesIO
import mutagen
@@ -29,14 +28,14 @@ def return_album_art(filepath: str):
return None
def extract_thumb(audio_file_path: str, webp_path: str) -> str:
def extract_thumb(audio_file_path: str, webp_path: str) -> bool:
"""
Extracts the thumbnail from an audio file. Returns the path to the thumbnail.
"""
img_path = os.path.join(settings.THUMBS_PATH, webp_path)
if os.path.exists(img_path):
return urllib.parse.quote(webp_path)
return True
album_art = return_album_art(audio_file_path)
@@ -52,11 +51,11 @@ def extract_thumb(audio_file_path: str, webp_path: str) -> str:
small_img = png.resize((250, 250), Image.ANTIALIAS)
small_img.save(webp_path, format="webp")
except:
return None
return False
return urllib.parse.quote(webp_path)
return True
else:
return None
return False
def parse_artist_tag(audio):
+1 -1
View File
@@ -63,7 +63,7 @@ def add_track(filepath: str) -> None:
if folder not in api.VALID_FOLDERS:
api.VALID_FOLDERS.add(folder)
f = folderslib.create_folder(folder)
api.FOLDERS.add(f)
api.FOLDERS.append(f)
def remove_track(filepath: str) -> None: