diff --git a/server/app/api/album.py b/server/app/api/album.py index 3b4347d1..e37c185b 100644 --- a/server/app/api/album.py +++ b/server/app/api/album.py @@ -49,7 +49,7 @@ def get_album(): album = instances.album_instance.find_album_by_hash(albumhash) if not album: - return {"error": "Album not found."}, 404 + return {"error": "Album not created yet."}, 204 album = models.Album(album) diff --git a/server/app/helpers.py b/server/app/helpers.py index 12fe7d73..6cdd9dec 100644 --- a/server/app/helpers.py +++ b/server/app/helpers.py @@ -2,7 +2,6 @@ This module contains mini functions for the server. """ import os -import random import threading from datetime import datetime from typing import Dict, Set @@ -11,8 +10,8 @@ from typing import List import requests from app import models -from app import settings from app import instances +from app.lib.albumslib import Thumbnail def background(func): @@ -85,12 +84,15 @@ def is_valid_file(filename: str) -> bool: return False +ill_chars = '/\\:*?"<>|#&' + + def create_album_hash(title: str, artist: str) -> str: """ Creates a simple hash for an album """ lower = (title + artist).replace(" ", "").lower() - hash = "".join([i for i in lower if i not in '/\\:*?"<>|&']) + hash = "".join([i for i in lower if i not in ill_chars]) return hash @@ -104,7 +106,7 @@ def create_safe_name(name: str) -> str: """ Creates a url-safe name from a name. """ - return "".join([i for i in name if i not in '/\\:*?"<>|#']) + return "".join([i for i in name if i not in ill_chars]) class UseBisection: @@ -116,21 +118,20 @@ class UseBisection: """ def __init__(self, source: List, search_from: str, queries: List[str]) -> None: - self.list = source - self.queries = queries - self.search_from = search_from - self.list.sort(key=lambda x: getattr(x, search_from)) + self.source_list = source + self.queries_list = queries + self.attr = search_from + self.source_list.sort(key=lambda x: getattr(x, search_from)) def find(self, query: str): left = 0 - right = len(self.list) - 1 + right = len(self.source_list) - 1 while left <= right: mid = (left + right) // 2 - - if self.list[mid].__getattribute__(self.search_from) == query: - return self.list[mid] - elif self.list[mid].__getattribute__(self.search_from) > query: + if self.source_list[mid].__getattribute__(self.attr) == query: + return self.source_list[mid] + elif self.source_list[mid].__getattribute__(self.attr) > query: right = mid - 1 else: left = mid + 1 @@ -138,7 +139,11 @@ class UseBisection: return None def __call__(self) -> List: - return [self.find(query) for query in self.queries] + if len(self.source_list) == 0: + print("🚀🚀🚀🚀🚀🚀🚀") + return [None] + + return [self.find(query) for query in self.queries_list] class Get: diff --git a/server/app/lib/albumslib.py b/server/app/lib/albumslib.py index eedccb03..dcb70438 100644 --- a/server/app/lib/albumslib.py +++ b/server/app/lib/albumslib.py @@ -2,6 +2,7 @@ This library contains all the functions related to albums. """ from concurrent.futures import ThreadPoolExecutor +from multiprocessing import Manager from dataclasses import dataclass import os import random @@ -13,7 +14,7 @@ from tqdm import tqdm from app.settings import THUMBS_PATH from app import instances - +from app.logger import logg # def get_all_albums() -> List[models.Album]: # """ @@ -67,7 +68,8 @@ class ValidateThumbs: for entry in tqdm(entries, desc="Validating thumbnails"): e = helpers.UseBisection(thumbs, "filename", [entry.name])() - if e is not None: + + if e is None: os.remove(entry.path) @staticmethod @@ -76,7 +78,7 @@ class ValidateThumbs: Re-rip lost album thumbnails """ entries = os.scandir(THUMBS_PATH) - entries = [Thumbnail(entry) for entry in entries if entry.is_file()] + entries = [Thumbnail(entry.name) for entry in entries if entry.is_file()] albums = helpers.Get.get_all_albums() thumbs = [(album.hash + ".webp") for album in albums] @@ -85,13 +87,18 @@ class ValidateThumbs: e = helpers.UseBisection(entries, "filename", [t_hash])()[0] if e is None: - hash = t_hash.split(".")[0] + hash = t_hash.replace(".webp", "") RipAlbumImage(hash) - return e + logg.info("Ripping lost album thumbnails...") + # with ThreadPoolExecutor() as pool: + # i = pool.map(rip_image, thumbs) + # [a for a in i] + # ⚠️ empty lists are sent to the useBisection function as the source list. + for thumb in thumbs: + rip_image(thumb) - with ThreadPoolExecutor() as pool: - pool.map(rip_image, thumbs) + logg.info("Ripping lost album thumbnails...done") def __init__(self) -> None: self.remove_obsolete() diff --git a/server/app/logger.py b/server/app/logger.py index e67d184a..1c4c5785 100644 --- a/server/app/logger.py +++ b/server/app/logger.py @@ -13,7 +13,7 @@ class CustomFormatter(logging.Formatter): # format = ( # "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" # ) - format = "%(levelname)s: @%(name)s: >>> %(message)s (%(filename)s:%(lineno)d)" + format = "[%(asctime)s] [%(levelname)s] [@%(name)s] >>> %(message)s [%(filename)s:%(lineno)d]" FORMATS = { logging.DEBUG: grey + format + reset, @@ -25,7 +25,7 @@ class CustomFormatter(logging.Formatter): def format(self, record): log_fmt = self.FORMATS.get(record.levelno) - formatter = logging.Formatter(log_fmt) + formatter = logging.Formatter(log_fmt, "%H:%M:%S") return formatter.format(record) diff --git a/server/app/settings.py b/server/app/settings.py index f6eb0ff7..ccb2bace 100644 --- a/server/app/settings.py +++ b/server/app/settings.py @@ -26,19 +26,6 @@ DEFAULT_ARTIST_IMG = IMG_ARTIST_URI + "0.webp" LAST_FM_API_KEY = "762db7a44a9e6fb5585661f5f2bdf23a" -P_COLORS = [ - "rgb(4, 40, 196)", - "rgb(196, 4, 68)", - "rgb(4, 99, 59)", - "rgb(161, 87, 1)", - "rgb(1, 161, 22)", - "rgb(116, 1, 161)", - "rgb(0, 0, 0)", - "rgb(95, 95, 95)", - "rgb(141, 132, 2)", - "rgb(141, 11, 2)", -] - CPU_COUNT = multiprocessing.cpu_count() diff --git a/src/composables/pages/album.ts b/src/composables/pages/album.ts index bdd32702..3739f426 100644 --- a/src/composables/pages/album.ts +++ b/src/composables/pages/album.ts @@ -1,9 +1,13 @@ -import axios, { AxiosError } from "axios"; import state from "../state"; import { AlbumInfo, Track } from "../../interfaces"; import useAxios from "../useAxios"; +import { NotifType, useNotifStore } from "@/stores/notification"; -const getAlbumTracks = async (album: string, artist: string) => { +const getAlbumData = async ( + album: string, + artist: string, + ToastStore: typeof useNotifStore +) => { const url = state.settings.uri + "/album"; interface AlbumData { @@ -19,9 +23,13 @@ const getAlbumTracks = async (album: string, artist: string) => { }, }); - if (status == 404) { + if (status == 204) { + ToastStore().showNotification("Album not created yet!", NotifType.Error); return { - info: {}, + info: { + album: album, + artist: artist, + }, tracks: [], }; } @@ -63,4 +71,4 @@ const getAlbumBio = async (album: string, albumartist: string) => { } }; -export { getAlbumTracks, getAlbumArtists, getAlbumBio }; +export { getAlbumData as getAlbumTracks, getAlbumArtists, getAlbumBio }; diff --git a/src/stores/pages/album.ts b/src/stores/pages/album.ts index aa391c81..f1af23ae 100644 --- a/src/stores/pages/album.ts +++ b/src/stores/pages/album.ts @@ -1,4 +1,5 @@ import { defineStore } from "pinia"; +import { useNotifStore } from "../notification"; import { Track, Artist, AlbumInfo } from "../../interfaces"; import { getAlbumTracks, @@ -21,7 +22,7 @@ export default defineStore("album", { * @param albumartist artist of the album */ async fetchTracksAndArtists(title: string, albumartist: string) { - const tracks = await getAlbumTracks(title, albumartist); + const tracks = await getAlbumTracks(title, albumartist, useNotifStore); const artists = await getAlbumArtists(title, albumartist); this.tracks = tracks.tracks;