mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-05 04:53:01 +00:00
create albums from pre-albums instead of individual tracks
This commit is contained in:
@@ -21,7 +21,7 @@ VALID_FOLDERS: Set[str] = set()
|
|||||||
ALBUMS: List[models.Album] = []
|
ALBUMS: List[models.Album] = []
|
||||||
TRACKS: List[models.Track] = []
|
TRACKS: List[models.Track] = []
|
||||||
PLAYLISTS: List[models.Playlist] = []
|
PLAYLISTS: List[models.Playlist] = []
|
||||||
FOLDERS: Set[models.Folder] = set()
|
FOLDERS: List[models.Folder] = List
|
||||||
|
|
||||||
|
|
||||||
@helpers.background
|
@helpers.background
|
||||||
|
|||||||
+14
-7
@@ -15,11 +15,17 @@ def send_track_file(trackid):
|
|||||||
Returns an audio file that matches the passed id to the client.
|
Returns an audio file that matches the passed id to the client.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
filepath = [
|
files = []
|
||||||
file["filepath"] for file in api.DB_TRACKS
|
for f in api.DB_TRACKS:
|
||||||
if file["_id"]["$oid"] == trackid
|
try:
|
||||||
][0]
|
if f["_id"]["$oid"] == trackid:
|
||||||
except (FileNotFoundError, IndexError) as e:
|
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 "File not found", 404
|
||||||
|
|
||||||
return send_file(filepath, mimetype="audio/mp3")
|
return send_file(filepath, mimetype="audio/mp3")
|
||||||
@@ -31,5 +37,6 @@ def get_sample_track():
|
|||||||
Returns a sample track object.
|
Returns a sample track object.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return instances.tracks_instance.get_song_by_album("Legends Never Die",
|
return instances.tracks_instance.get_song_by_album(
|
||||||
"Juice WRLD")
|
"Legends Never Die", "Juice WRLD"
|
||||||
|
)
|
||||||
|
|||||||
+55
-16
@@ -3,11 +3,12 @@ This module contains functions for the server
|
|||||||
"""
|
"""
|
||||||
import datetime
|
import datetime
|
||||||
import os
|
import os
|
||||||
|
from pprint import pprint
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import List
|
from typing import List, Type
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from app import api
|
from app import api
|
||||||
@@ -60,8 +61,7 @@ def populate():
|
|||||||
albums = []
|
albums = []
|
||||||
folders = set()
|
folders = set()
|
||||||
|
|
||||||
files = helpers.run_fast_scandir(settings.HOME_DIR, [".flac", ".mp3"],
|
files = helpers.run_fast_scandir(settings.HOME_DIR, [".flac", ".mp3"], full=True)[1]
|
||||||
full=True)[1]
|
|
||||||
|
|
||||||
_bar = Bar("Checking files", max=len(files))
|
_bar = Bar("Checking files", max=len(files))
|
||||||
for track in db_tracks:
|
for track in db_tracks:
|
||||||
@@ -88,24 +88,59 @@ def populate():
|
|||||||
|
|
||||||
Log(f"Tagged {len(tagged_tracks)} tracks")
|
Log(f"Tagged {len(tagged_tracks)} tracks")
|
||||||
|
|
||||||
_bar = Bar("Creating stuff", max=len(tagged_tracks))
|
pre_albums = []
|
||||||
for track in tagged_tracks:
|
|
||||||
albumindex = albumslib.find_album(track["album"], track["albumartist"])
|
for t in tagged_tracks:
|
||||||
album = None
|
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:
|
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)
|
album = albumslib.create_album(track)
|
||||||
api.ALBUMS.append(album)
|
api.ALBUMS.append(album)
|
||||||
albums.append(album)
|
albums.append(album)
|
||||||
|
|
||||||
instances.album_instance.insert_album(asdict(album))
|
instances.album_instance.insert_album(asdict(album))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
album = api.ALBUMS[albumindex]
|
exist_count += 1
|
||||||
|
|
||||||
|
_bar.next()
|
||||||
|
|
||||||
|
_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
|
track["image"] = album.image
|
||||||
upsert_id = instances.tracks_instance.insert_song(track)
|
upsert_id = instances.tracks_instance.insert_song(track)
|
||||||
|
|
||||||
track["_id"] = {"$oid": str(upsert_id)}
|
track["_id"] = {"$oid": str(upsert_id)}
|
||||||
api.TRACKS.append(models.Track(track))
|
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()
|
_bar.next()
|
||||||
|
|
||||||
@@ -118,7 +153,7 @@ def populate():
|
|||||||
if folder not in api.VALID_FOLDERS:
|
if folder not in api.VALID_FOLDERS:
|
||||||
api.VALID_FOLDERS.add(folder)
|
api.VALID_FOLDERS.add(folder)
|
||||||
fff = folderslib.create_folder(folder)
|
fff = folderslib.create_folder(folder)
|
||||||
api.FOLDERS.add(fff)
|
api.FOLDERS.append(fff)
|
||||||
|
|
||||||
_bar.next()
|
_bar.next()
|
||||||
|
|
||||||
@@ -129,8 +164,11 @@ def populate():
|
|||||||
end = time.time()
|
end = time.time()
|
||||||
|
|
||||||
print(
|
print(
|
||||||
str(datetime.timedelta(seconds=round(end - start))) + " elapsed for " +
|
str(datetime.timedelta(seconds=round(end - start)))
|
||||||
str(len(files)) + " files")
|
+ " elapsed for "
|
||||||
|
+ str(len(files))
|
||||||
|
+ " files"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def fetch_image_path(artist: str) -> str or None:
|
def fetch_image_path(artist: str) -> str or None:
|
||||||
@@ -165,8 +203,9 @@ def fetch_artist_images():
|
|||||||
|
|
||||||
_bar = Bar("Processing images", max=len(artists))
|
_bar = Bar("Processing images", max=len(artists))
|
||||||
for artist in artists:
|
for artist in artists:
|
||||||
file_path = (helpers.app_dir + "/images/artists/" +
|
file_path = (
|
||||||
artist.replace("/", "::") + ".webp")
|
helpers.app_dir + "/images/artists/" + artist.replace("/", "::") + ".webp"
|
||||||
|
)
|
||||||
|
|
||||||
if not os.path.exists(file_path):
|
if not os.path.exists(file_path):
|
||||||
img_path = fetch_image_path(artist)
|
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.
|
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(
|
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:
|
try:
|
||||||
response = requests.get(last_fm_url)
|
response = requests.get(last_fm_url)
|
||||||
@@ -197,8 +237,7 @@ def fetch_album_bio(title: str, albumartist: str):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bio = data["album"]["wiki"]["summary"].split(
|
bio = data["album"]["wiki"]["summary"].split('<a href="https://www.last.fm/')[0]
|
||||||
'<a href="https://www.last.fm/')[0]
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
bio = None
|
bio = None
|
||||||
|
|
||||||
|
|||||||
+26
-10
@@ -13,6 +13,9 @@ from app import models
|
|||||||
from app.lib import trackslib
|
from app.lib import trackslib
|
||||||
from progress.bar import Bar
|
from progress.bar import Bar
|
||||||
|
|
||||||
|
from app.lib import taglib
|
||||||
|
from app import settings
|
||||||
|
|
||||||
|
|
||||||
def get_all_albums() -> List[models.Album]:
|
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)
|
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.
|
Finds an album by album title and artist.
|
||||||
"""
|
"""
|
||||||
@@ -63,8 +66,7 @@ def find_album(albumtitle: str, artist: str) -> models.Album:
|
|||||||
iter += 1
|
iter += 1
|
||||||
mid = (left + right) // 2
|
mid = (left + right) // 2
|
||||||
|
|
||||||
if api.ALBUMS[mid].title == albumtitle and api.ALBUMS[
|
if api.ALBUMS[mid].title == albumtitle and api.ALBUMS[mid].artist == artist:
|
||||||
mid].artist == artist:
|
|
||||||
return mid
|
return mid
|
||||||
|
|
||||||
if api.ALBUMS[mid].title < albumtitle:
|
if api.ALBUMS[mid].title < albumtitle:
|
||||||
@@ -96,20 +98,33 @@ def use_defaults() -> str:
|
|||||||
return path
|
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:
|
def get_album_image(album: list) -> str:
|
||||||
"""
|
"""
|
||||||
Gets the image of an album.
|
Gets the image of an album.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
uri = settings.IMG_THUMB_URI
|
||||||
|
|
||||||
for track in album:
|
for track in album:
|
||||||
img_p = (track["album"] + track["albumartist"] + ".webp").replace(
|
img_p = gen_random_path()
|
||||||
"/", "::")
|
|
||||||
img = functions.extract_thumb(track["filepath"], webp_path=img_p)
|
|
||||||
|
|
||||||
if img is not None:
|
exists = taglib.extract_thumb(track["filepath"], webp_path=img_p)
|
||||||
return img
|
|
||||||
|
|
||||||
return use_defaults()
|
if exists:
|
||||||
|
return uri + img_p
|
||||||
|
|
||||||
|
return uri + use_defaults()
|
||||||
|
|
||||||
|
|
||||||
def get_album_tracks(album: str, artist: str) -> List:
|
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["date"] = album_tracks[0]["date"]
|
||||||
|
|
||||||
album["artistimage"] = urllib.parse.quote_plus(
|
album["artistimage"] = urllib.parse.quote_plus(
|
||||||
album_tracks[0]["albumartist"] + ".webp")
|
album_tracks[0]["albumartist"] + ".webp"
|
||||||
|
)
|
||||||
|
|
||||||
album["image"] = get_album_image(album_tracks)
|
album["image"] = get_album_image(album_tracks)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import os
|
import os
|
||||||
import urllib
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
import mutagen
|
import mutagen
|
||||||
@@ -29,14 +28,14 @@ def return_album_art(filepath: str):
|
|||||||
return None
|
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.
|
Extracts the thumbnail from an audio file. Returns the path to the thumbnail.
|
||||||
"""
|
"""
|
||||||
img_path = os.path.join(settings.THUMBS_PATH, webp_path)
|
img_path = os.path.join(settings.THUMBS_PATH, webp_path)
|
||||||
|
|
||||||
if os.path.exists(img_path):
|
if os.path.exists(img_path):
|
||||||
return urllib.parse.quote(webp_path)
|
return True
|
||||||
|
|
||||||
album_art = return_album_art(audio_file_path)
|
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 = png.resize((250, 250), Image.ANTIALIAS)
|
||||||
small_img.save(webp_path, format="webp")
|
small_img.save(webp_path, format="webp")
|
||||||
except:
|
except:
|
||||||
return None
|
return False
|
||||||
|
|
||||||
return urllib.parse.quote(webp_path)
|
return True
|
||||||
else:
|
else:
|
||||||
return None
|
return False
|
||||||
|
|
||||||
|
|
||||||
def parse_artist_tag(audio):
|
def parse_artist_tag(audio):
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ def add_track(filepath: str) -> None:
|
|||||||
if folder not in api.VALID_FOLDERS:
|
if folder not in api.VALID_FOLDERS:
|
||||||
api.VALID_FOLDERS.add(folder)
|
api.VALID_FOLDERS.add(folder)
|
||||||
f = folderslib.create_folder(folder)
|
f = folderslib.create_folder(folder)
|
||||||
api.FOLDERS.add(f)
|
api.FOLDERS.append(f)
|
||||||
|
|
||||||
|
|
||||||
def remove_track(filepath: str) -> None:
|
def remove_track(filepath: str) -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user