mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-05 04:53:01 +00:00
Restyle Save complete albums to the db for faster startup (#38)
This commit is contained in:
@@ -3,16 +3,18 @@ This module contains all the Flask Blueprints and API routes. It also contains a
|
|||||||
that are used through-out the app. It handles the initialization of the watchdog,
|
that are used through-out the app. It handles the initialization of the watchdog,
|
||||||
checking and creating config dirs and starting the re-indexing process using a background thread.
|
checking and creating config dirs and starting the re-indexing process using a background thread.
|
||||||
"""
|
"""
|
||||||
|
from typing import List
|
||||||
|
from typing import Set
|
||||||
|
|
||||||
from typing import List, Set
|
from app import functions
|
||||||
|
from app import helpers
|
||||||
from app import models, instances
|
from app import instances
|
||||||
from app import functions, helpers, prep
|
from app import models
|
||||||
|
from app import prep
|
||||||
from app.lib import albumslib
|
from app.lib import albumslib
|
||||||
from app.lib import folderslib
|
from app.lib import folderslib
|
||||||
from app.lib import playlistlib
|
from app.lib import playlistlib
|
||||||
|
|
||||||
|
|
||||||
DB_TRACKS = instances.tracks_instance.get_all_tracks()
|
DB_TRACKS = instances.tracks_instance.get_all_tracks()
|
||||||
VALID_FOLDERS: Set[str] = set()
|
VALID_FOLDERS: Set[str] = set()
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
"""
|
"""
|
||||||
Contains all the artist(s) routes.
|
Contains all the artist(s) routes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
from flask import Blueprint
|
|
||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
from app import instances
|
from app import cache
|
||||||
from app import helpers
|
from app import helpers
|
||||||
|
from app import instances
|
||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
artist_bp = Blueprint("artist", __name__, url_prefix="/")
|
artist_bp = Blueprint("artist", __name__, url_prefix="/")
|
||||||
from app import cache
|
|
||||||
|
|
||||||
|
|
||||||
@artist_bp.route("/artist/<artist>")
|
@artist_bp.route("/artist/<artist>")
|
||||||
@@ -53,4 +51,8 @@ def get_artist_data(artist: str):
|
|||||||
|
|
||||||
return albums_with_count
|
return albums_with_count
|
||||||
|
|
||||||
return {"artist": artist_obj, "songs": songs, "albums": get_artist_albums()}
|
return {
|
||||||
|
"artist": artist_obj,
|
||||||
|
"songs": songs,
|
||||||
|
"albums": get_artist_albums()
|
||||||
|
}
|
||||||
|
|||||||
@@ -32,4 +32,4 @@ def get_sample_track():
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
return instances.tracks_instance.get_song_by_album("Legends Never Die",
|
return instances.tracks_instance.get_song_by_album("Legends Never Die",
|
||||||
"Juice WRLD")
|
"Juice WRLD")
|
||||||
|
|||||||
@@ -3,9 +3,8 @@ This file contains the Album class for interacting with
|
|||||||
album documents in MongoDB.
|
album documents in MongoDB.
|
||||||
"""
|
"""
|
||||||
from app import db
|
from app import db
|
||||||
from bson import ObjectId
|
|
||||||
|
|
||||||
from app.models import Album
|
from app.models import Album
|
||||||
|
from bson import ObjectId
|
||||||
|
|
||||||
convert_many = db.convert_many
|
convert_many = db.convert_many
|
||||||
convert_one = db.convert_one
|
convert_one = db.convert_one
|
||||||
|
|||||||
+13
-16
@@ -1,11 +1,11 @@
|
|||||||
"""
|
"""
|
||||||
This module contains functions for the server
|
This module contains functions for the server
|
||||||
"""
|
"""
|
||||||
from dataclasses import asdict
|
|
||||||
import datetime
|
import datetime
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
|
from dataclasses import asdict
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
@@ -18,12 +18,12 @@ from app import settings
|
|||||||
from app.lib import albumslib
|
from app.lib import albumslib
|
||||||
from app.lib import folderslib
|
from app.lib import folderslib
|
||||||
from app.lib import watchdoge
|
from app.lib import watchdoge
|
||||||
|
from app.lib.taglib import get_tags
|
||||||
|
from app.lib.taglib import return_album_art
|
||||||
|
from app.logger import Log
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from progress.bar import Bar
|
from progress.bar import Bar
|
||||||
|
|
||||||
from app.logger import Log
|
|
||||||
from app.lib.taglib import get_tags, return_album_art
|
|
||||||
|
|
||||||
|
|
||||||
@helpers.background
|
@helpers.background
|
||||||
def reindex_tracks():
|
def reindex_tracks():
|
||||||
@@ -60,7 +60,8 @@ def populate():
|
|||||||
albums = []
|
albums = []
|
||||||
folders = set()
|
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))
|
_bar = Bar("Checking files", max=len(files))
|
||||||
for track in db_tracks:
|
for track in db_tracks:
|
||||||
@@ -128,11 +129,8 @@ def populate():
|
|||||||
end = time.time()
|
end = time.time()
|
||||||
|
|
||||||
print(
|
print(
|
||||||
str(datetime.timedelta(seconds=round(end - start)))
|
str(datetime.timedelta(seconds=round(end - start))) + " elapsed for " +
|
||||||
+ " elapsed for "
|
str(len(files)) + " files")
|
||||||
+ str(len(files))
|
|
||||||
+ " files"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def fetch_image_path(artist: str) -> str or None:
|
def fetch_image_path(artist: str) -> str or None:
|
||||||
@@ -167,9 +165,8 @@ 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 = (
|
file_path = (helpers.app_dir + "/images/artists/" +
|
||||||
helpers.app_dir + "/images/artists/" + artist.replace("/", "::") + ".webp"
|
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)
|
||||||
@@ -191,8 +188,7 @@ 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)
|
||||||
@@ -201,7 +197,8 @@ def fetch_album_bio(title: str, albumartist: str):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
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:
|
except KeyError:
|
||||||
bio = None
|
bio = None
|
||||||
|
|
||||||
|
|||||||
+14
-12
@@ -1,15 +1,16 @@
|
|||||||
"""
|
"""
|
||||||
This module contains mimi functions for the server.
|
This module contains mimi functions for the server.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import threading
|
import threading
|
||||||
from typing import Dict, List
|
|
||||||
import time
|
import time
|
||||||
|
from typing import Dict
|
||||||
|
from typing import List
|
||||||
|
|
||||||
from app import models, settings
|
from app import models
|
||||||
|
from app import settings
|
||||||
|
|
||||||
app_dir = settings.APP_DIR
|
app_dir = settings.APP_DIR
|
||||||
|
|
||||||
@@ -26,7 +27,9 @@ def background(func):
|
|||||||
return background_func
|
return background_func
|
||||||
|
|
||||||
|
|
||||||
def run_fast_scandir(__dir: str, ext: list, full=False) -> Dict[List[str], List[str]]:
|
def run_fast_scandir(__dir: str,
|
||||||
|
ext: list,
|
||||||
|
full=False) -> Dict[List[str], List[str]]:
|
||||||
"""
|
"""
|
||||||
Scans a directory for files with a specific extension. Returns a list of files and folders in the directory.
|
Scans a directory for files with a specific extension. Returns a list of files and folders in the directory.
|
||||||
"""
|
"""
|
||||||
@@ -59,12 +62,10 @@ def remove_duplicates(tracklist: List[models.Track]) -> List[models.Track]:
|
|||||||
|
|
||||||
while song_num < len(tracklist) - 1:
|
while song_num < len(tracklist) - 1:
|
||||||
for index, song in enumerate(tracklist):
|
for index, song in enumerate(tracklist):
|
||||||
if (
|
if (tracklist[song_num].title == song.title
|
||||||
tracklist[song_num].title == song.title
|
and tracklist[song_num].album == song.album
|
||||||
and tracklist[song_num].album == song.album
|
and tracklist[song_num].artists == song.artists
|
||||||
and tracklist[song_num].artists == song.artists
|
and index != song_num):
|
||||||
and index != song_num
|
|
||||||
):
|
|
||||||
tracklist.remove(song)
|
tracklist.remove(song)
|
||||||
|
|
||||||
song_num += 1
|
song_num += 1
|
||||||
@@ -107,10 +108,11 @@ def check_artist_image(image: str) -> str:
|
|||||||
"""
|
"""
|
||||||
img_name = image.replace("/", "::") + ".webp"
|
img_name = image.replace("/", "::") + ".webp"
|
||||||
|
|
||||||
if not os.path.exists(os.path.join(app_dir, "images", "artists", img_name)):
|
if not os.path.exists(os.path.join(app_dir, "images", "artists",
|
||||||
|
img_name)):
|
||||||
return use_memoji()
|
return use_memoji()
|
||||||
else:
|
else:
|
||||||
return (settings.IMG_ARTIST_URI + img_name,)
|
return (settings.IMG_ARTIST_URI + img_name, )
|
||||||
|
|
||||||
|
|
||||||
class Timer:
|
class Timer:
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
"""
|
"""
|
||||||
All the MongoDB instances are created here.
|
All the MongoDB instances are created here.
|
||||||
"""
|
"""
|
||||||
|
from app.db import albums
|
||||||
from app.db import artists, albums, trackcolors, tracks, playlists
|
from app.db import artists
|
||||||
|
from app.db import playlists
|
||||||
|
from app.db import trackcolors
|
||||||
|
from app.db import tracks
|
||||||
|
|
||||||
tracks_instance = tracks.AllSongs()
|
tracks_instance = tracks.AllSongs()
|
||||||
artist_instance = artists.Artists()
|
artist_instance = artists.Artists()
|
||||||
track_color_instance = trackcolors.TrackColors()
|
track_color_instance = trackcolors.TrackColors()
|
||||||
album_instance = albums.Albums()
|
album_instance = albums.Albums()
|
||||||
playlist_instance = playlists.Playlists()
|
playlist_instance = playlists.Playlists()
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ import random
|
|||||||
import urllib
|
import urllib
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from typing import List
|
from typing import List
|
||||||
from progress.bar import Bar
|
|
||||||
|
|
||||||
from app import api
|
from app import api
|
||||||
from app import functions
|
from app import functions
|
||||||
|
from app import instances
|
||||||
from app import models
|
from app import models
|
||||||
from app.lib import trackslib
|
from app.lib import trackslib
|
||||||
from app import instances
|
from progress.bar import Bar
|
||||||
|
|
||||||
|
|
||||||
def get_all_albums() -> List[models.Album]:
|
def get_all_albums() -> List[models.Album]:
|
||||||
@@ -63,7 +63,8 @@ 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[mid].artist == artist:
|
if api.ALBUMS[mid].title == albumtitle and api.ALBUMS[
|
||||||
|
mid].artist == artist:
|
||||||
return mid
|
return mid
|
||||||
|
|
||||||
if api.ALBUMS[mid].title < albumtitle:
|
if api.ALBUMS[mid].title < albumtitle:
|
||||||
@@ -101,7 +102,8 @@ def get_album_image(album: list) -> str:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
for track in album:
|
for track in album:
|
||||||
img_p = (track["album"] + track["albumartist"] + ".webp").replace("/", "::")
|
img_p = (track["album"] + track["albumartist"] + ".webp").replace(
|
||||||
|
"/", "::")
|
||||||
img = functions.extract_thumb(track["filepath"], webp_path=img_p)
|
img = functions.extract_thumb(track["filepath"], webp_path=img_p)
|
||||||
|
|
||||||
if img is not None:
|
if img is not None:
|
||||||
@@ -140,8 +142,7 @@ 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,10 +1,11 @@
|
|||||||
import colorgram
|
|
||||||
from progress.bar import Bar
|
|
||||||
from PIL import Image
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from app import api, instances
|
import colorgram
|
||||||
|
from app import api
|
||||||
|
from app import instances
|
||||||
from app.lib.taglib import return_album_art
|
from app.lib.taglib import return_album_art
|
||||||
|
from PIL import Image
|
||||||
|
from progress.bar import Bar
|
||||||
|
|
||||||
|
|
||||||
def get_image_colors(image) -> list:
|
def get_image_colors(image) -> list:
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import time
|
import time
|
||||||
from typing import List, Set
|
from typing import List
|
||||||
|
from typing import Set
|
||||||
|
|
||||||
from app import api
|
from app import api
|
||||||
from app import helpers
|
from app import helpers
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import os
|
import os
|
||||||
from mutagen.flac import FLAC
|
|
||||||
from mutagen.id3 import ID3
|
|
||||||
from mutagen.flac import MutagenError
|
|
||||||
import mutagen
|
|
||||||
import urllib
|
import urllib
|
||||||
from PIL import Image
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
|
import mutagen
|
||||||
from app import settings
|
from app import settings
|
||||||
|
from mutagen.flac import FLAC
|
||||||
|
from mutagen.flac import MutagenError
|
||||||
|
from mutagen.id3 import ID3
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
def return_album_art(filepath: str):
|
def return_album_art(filepath: str):
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
"""
|
"""
|
||||||
This library contains the classes and functions related to the watchdog file watcher.
|
This library contains the classes and functions related to the watchdog file watcher.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import time
|
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
from watchdog.observers import Observer
|
from app import api
|
||||||
from watchdog.events import PatternMatchingEventHandler
|
|
||||||
|
|
||||||
from app import instances
|
from app import instances
|
||||||
from app import models
|
from app import models
|
||||||
from app import api
|
|
||||||
from app.lib import folderslib
|
from app.lib import folderslib
|
||||||
from app.lib.taglib import get_tags
|
|
||||||
from app.lib.albumslib import create_album
|
from app.lib.albumslib import create_album
|
||||||
|
from app.lib.taglib import get_tags
|
||||||
|
from watchdog.events import PatternMatchingEventHandler
|
||||||
|
from watchdog.observers import Observer
|
||||||
|
|
||||||
|
|
||||||
class OnMyWatch:
|
class OnMyWatch:
|
||||||
@@ -76,7 +74,8 @@ def remove_track(filepath: str) -> None:
|
|||||||
fpath = filepath.replace(fname, "")
|
fpath = filepath.replace(fname, "")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
trackid = instances.tracks_instance.get_song_by_path(filepath)["_id"]["$oid"]
|
trackid = instances.tracks_instance.get_song_by_path(
|
||||||
|
filepath)["_id"]["$oid"]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
print(f"💙 Watchdog Error: Error removing track {filepath} TypeError")
|
print(f"💙 Watchdog Error: Error removing track {filepath} TypeError")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from app.settings import logger
|
|||||||
|
|
||||||
|
|
||||||
class Log:
|
class Log:
|
||||||
|
|
||||||
def __init__(self, msg):
|
def __init__(self, msg):
|
||||||
if logger.enable:
|
if logger.enable:
|
||||||
print("\n🦋 " + msg + "\n")
|
print("\n🦋 " + msg + "\n")
|
||||||
|
|||||||
@@ -73,11 +73,9 @@ class Album:
|
|||||||
|
|
||||||
def get_p_track(ptrack):
|
def get_p_track(ptrack):
|
||||||
for track in api.TRACKS:
|
for track in api.TRACKS:
|
||||||
if (
|
if (track.title == ptrack["title"]
|
||||||
track.title == ptrack["title"]
|
and track.artists == ptrack["artists"]
|
||||||
and track.artists == ptrack["artists"]
|
and ptrack["album"] == track.album):
|
||||||
and ptrack["album"] == track.album
|
|
||||||
):
|
|
||||||
return track
|
return track
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"""
|
"""
|
||||||
Contains default configs
|
Contains default configs
|
||||||
"""
|
"""
|
||||||
from dataclasses import dataclass
|
|
||||||
import os
|
import os
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
# paths
|
# paths
|
||||||
CONFIG_FOLDER = ".alice"
|
CONFIG_FOLDER = ".alice"
|
||||||
@@ -36,4 +36,4 @@ P_COLORS = [
|
|||||||
|
|
||||||
|
|
||||||
class logger:
|
class logger:
|
||||||
enable = True
|
enable = True
|
||||||
|
|||||||
Reference in New Issue
Block a user