Restyle Implement Fuzzy search using rapidfuzz (#60)

This commit is contained in:
restyled-io[bot] 2022-05-26 19:12:04 +03:00 committed by GitHub
parent 1a3a196d7a
commit 2b33fb87a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 90 additions and 74 deletions

View File

@ -1,11 +1,10 @@
"""
Contains all the search routes.
"""
from flask import Blueprint, request
from app.lib import searchlib
from app import helpers
from app.lib import searchlib
from flask import Blueprint
from flask import request
search_bp = Blueprint("search", __name__, url_prefix="/")
@ -96,9 +95,18 @@ def search():
return {
"data": [
{"tracks": tracks[:5], "more": len(tracks) > 5},
{"albums": albums[:6], "more": len(albums) > 6},
{"artists": artists_dicts[:6], "more": len(artists_dicts) > 6},
{
"tracks": tracks[:5],
"more": len(tracks) > 5
},
{
"albums": albums[:6],
"more": len(albums) > 6
},
{
"artists": artists_dicts[:6],
"more": len(artists_dicts) > 6
},
]
}
@ -116,18 +124,18 @@ def search_load_more():
if type == "tracks":
return {
"tracks": SEARCH_RESULTS["tracks"][index : index + 5],
"tracks": SEARCH_RESULTS["tracks"][index:index + 5],
"more": len(SEARCH_RESULTS["tracks"]) > index + 5,
}
elif type == "albums":
return {
"albums": SEARCH_RESULTS["albums"][index : index + 6],
"albums": SEARCH_RESULTS["albums"][index:index + 6],
"more": len(SEARCH_RESULTS["albums"]) > index + 6,
}
elif type == "artists":
return {
"artists": SEARCH_RESULTS["artists"][index : index + 6],
"artists": SEARCH_RESULTS["artists"][index:index + 6],
"more": len(SEARCH_RESULTS["artists"]) > index + 6,
}

View File

@ -6,9 +6,11 @@ import random
import threading
import time
from datetime import datetime
from typing import Dict, List
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
@ -25,7 +27,9 @@ def 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.
"""
@ -58,12 +62,10 @@ def remove_duplicates(tracklist: List[models.Track]) -> List[models.Track]:
while song_num < len(tracklist) - 1:
for index, song in enumerate(tracklist):
if (
tracklist[song_num].title == song.title
and tracklist[song_num].album == song.album
and tracklist[song_num].artists == song.artists
and index != song_num
):
if (tracklist[song_num].title == song.title
and tracklist[song_num].album == song.album
and tracklist[song_num].artists == song.artists
and index != song_num):
tracklist.remove(song)
song_num += 1
@ -106,7 +108,8 @@ def check_artist_image(image: str) -> str:
"""
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()
else:
return img_name

View File

@ -6,13 +6,13 @@ import urllib
from typing import List
from app import api
from app import helpers
from app import instances
from app import models
from app.lib import taglib
from app.lib import trackslib
from progress.bar import Bar
from tqdm import tqdm
from app import helpers
def get_all_albums() -> List[models.Album]:

View File

@ -1,26 +1,26 @@
from concurrent.futures import ThreadPoolExecutor
from multiprocessing import Pool
from copy import deepcopy
import os
from os import path
import time
from concurrent.futures import ThreadPoolExecutor
from copy import deepcopy
from multiprocessing import Pool
from os import path
from typing import List
from tqdm import tqdm
from app import api
from app import settings
from app.helpers import create_album_hash, run_fast_scandir
from app.helpers import create_album_hash
from app.helpers import run_fast_scandir
from app.instances import album_instance
from app.instances import tracks_instance
from app.lib import folderslib
from app.lib.albumslib import create_album
from app.lib.albumslib import find_album
from app.lib.taglib import get_tags
from app.logger import Log
from app.models import Album, Track
from app.lib.trackslib import find_track
from app.logger import Log
from app.models import Album
from app.models import Track
from tqdm import tqdm
class Populate:
@ -95,7 +95,8 @@ class Populate:
folder = tags["folder"]
self.folders.add(folder)
tags["albumhash"] = create_album_hash(tags["album"], tags["albumartist"])
tags["albumhash"] = create_album_hash(tags["album"],
tags["albumartist"])
self.tagged_tracks.append(tags)
api.DB_TRACKS.append(tags)
@ -168,9 +169,8 @@ class Populate:
for album in tqdm(self.pre_albums, desc="Building albums"):
self.create_album(album)
Log(
f"{self.exist_count} of {len(self.pre_albums)} albums were already in the database"
)
Log(f"{self.exist_count} of {len(self.pre_albums)} albums were already in the database"
)
def create_track(self, track: dict):
"""
@ -205,9 +205,8 @@ class Populate:
with ThreadPoolExecutor() as executor:
executor.map(self.create_track, self.tagged_tracks)
Log(
f"Added {len(self.tagged_tracks)} new tracks and {len(self.albums)} new albums"
)
Log(f"Added {len(self.tagged_tracks)} new tracks and {len(self.albums)} new albums"
)
def save_albums(self):
"""

View File

@ -1,13 +1,14 @@
"""
This library contains all the functions related to the search functionality.
"""
from typing import List
from app import api, helpers, models
from app import api
from app import helpers
from app import models
from app.lib import albumslib
from rapidfuzz import fuzz, process
from rapidfuzz import fuzz
from rapidfuzz import process
ratio = fuzz.ratio
wratio = fuzz.WRatio
@ -34,6 +35,7 @@ class Limit:
class SearchTracks:
def __init__(self, query) -> None:
self.query = query
@ -55,6 +57,7 @@ class SearchTracks:
class SearchArtists:
def __init__(self, query) -> None:
self.query = query
@ -100,6 +103,7 @@ class SearchArtists:
class SearchAlbums:
def __init__(self, query) -> None:
self.query = query
@ -137,6 +141,7 @@ class SearchAlbums:
class GetTopArtistTracks:
def __init__(self, artist: str) -> None:
self.artist = artist
@ -160,5 +165,6 @@ def get_artists(artist: str) -> List[models.Track]:
Gets all songs with a given artist.
"""
return [
track for track in api.TRACKS if artist.lower() in str(track.artists).lower()
track for track in api.TRACKS
if artist.lower() in str(track.artists).lower()
]

View File

@ -7,14 +7,14 @@ import time
from app import api
from app import instances
from app import models
from app.helpers import create_album_hash
from app.lib import folderslib
from app.lib.albumslib import create_album, find_album
from app.lib.albumslib import create_album
from app.lib.albumslib import find_album
from app.lib.taglib import get_tags
from watchdog.events import PatternMatchingEventHandler
from watchdog.observers import Observer
from app.helpers import create_album_hash
class OnMyWatch:
"""
@ -87,7 +87,8 @@ def remove_track(filepath: str) -> None:
fpath = filepath.replace(fname, "")
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:
print(f"💙 Watchdog Error: Error removing track {filepath} TypeError")
return

View File

@ -6,8 +6,8 @@ from dataclasses import field
from typing import List
from app import api
from app.exceptions import TrackExistsInPlaylist
from app import helpers
from app.exceptions import TrackExistsInPlaylist
@dataclass(slots=True)
@ -97,11 +97,9 @@ class Album:
def get_p_track(ptrack):
for track in api.TRACKS:
if (
track.title == ptrack["title"]
and track.artists == ptrack["artists"]
and ptrack["album"] == track.album
):
if (track.title == ptrack["title"]
and track.artists == ptrack["artists"]
and ptrack["album"] == track.album):
return track

View File

@ -8,17 +8,15 @@ gpath=$(poetry run which gunicorn)
while getopts ':s' opt; do
case $opt in
s)
echo "🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴"
cd "./app"
"$gpath" -b 0.0.0.0:9877 -w 4 --threads=2 "imgserver:app" &
cd ../
;;
echo "🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴"
cd "./app"
"$gpath" -b 0.0.0.0:9877 -w 4 --threads=2 "imgserver:app" &
cd ../
;;
\?)
echo "Invalid option: -$OPTARG" >&2
;;
echo "Invalid option: -$OPTARG" >&2
;;
esac
done
"$gpath" -b 0.0.0.0:9876 -w 1 --threads=4 "manage:create_app()"

View File

@ -7,7 +7,7 @@
display: grid;
height: 100%;
padding-right: $small;
@include phone-only {
grid-template-columns: 1fr 9.2rem;
}

View File

@ -15,7 +15,7 @@
<div
class="h"
v-if="props.album.artist.toLowerCase() == 'various artists'"
>
Compilation
</div>

View File

@ -9,7 +9,7 @@
class="nav-button"
id="home-button"
v-motion-slide-from-left-100
>
<div class="in">
<div class="nav-icon image" :id="`${menu.name}-icon`"></div>

View File

@ -43,7 +43,7 @@ function updateQueue(track: Track) {
padding: $small;
height: 100% !important;
overflow: hidden;
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;

View File

@ -64,7 +64,7 @@ export default function (queue: any) {
if (!key_down_fired) {
if (!ctrlKey) return;
e.preventDefault();
key_down_fired = true;
}

View File

@ -3,7 +3,8 @@ import { getElem } from "./perks";
export default (mouseX, mouseY) => {
const scope = getElem("app", "id");
const contextMenu = getElem("context-menu", "class");
// ? compute what is the mouse position relative to the container element (scope)
// ? compute what is the mouse position relative to the container element
// (scope)
let { left: scopeOffsetX, top: scopeOffsetY } = scope.getBoundingClientRect();
scopeOffsetX = scopeOffsetX < 0 ? 0 : scopeOffsetX;

View File

@ -1,12 +1,14 @@
import { createApp } from "vue";
import App from "./App.vue";
import "./registerServiceWorker";
import router from "./router";
import { createPinia } from "pinia";
import { MotionPlugin } from "@vueuse/motion";
import useCustomTransitions from "./transitions";
import "../src/assets/css/global.scss";
import { MotionPlugin } from "@vueuse/motion";
import { createPinia } from "pinia";
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import useCustomTransitions from "./transitions";
const app = createApp(App);
app.use(createPinia());