diff --git a/app/api/search.py b/app/api/search.py index 4d2aca3..2278416 100644 --- a/app/api/search.py +++ b/app/api/search.py @@ -19,7 +19,10 @@ def query_in_quotes(query: str) -> bool: """ Returns True if the query is in quotes """ - return query.startswith('"') and query.endswith('"') + try: + return query.startswith('"') and query.endswith('"') + except AttributeError: + return False class Search: @@ -51,9 +54,13 @@ class Search: self.query, albums_only=True, in_quotes=in_quotes ) - def get_top_results(self, in_quotes=False): + def get_top_results( + self, + limit: int, + in_quotes=False, + ): finder = searchlib.TopResults() - return finder.search(self.query, in_quotes=in_quotes) + return finder.search(self.query, in_quotes=in_quotes, limit=limit) @api.route("/search/tracks", methods=["GET"]) @@ -122,12 +129,15 @@ def get_top_results(): """ query = request.args.get("q") + limit = request.args.get("limit", "6") + limit = int(limit) + in_quotes = query_in_quotes(query) if not query: return {"error": "No query provided"}, 400 - return Search(query).get_top_results(in_quotes=in_quotes) + return Search(query).get_top_results(in_quotes=in_quotes, limit=limit) @api.route("/search/loadmore") diff --git a/app/lib/searchlib.py b/app/lib/searchlib.py index f8ed947..a655013 100644 --- a/app/lib/searchlib.py +++ b/app/lib/searchlib.py @@ -274,13 +274,19 @@ class TopResults: return albums[:limit] @staticmethod - def search(query: str, albums_only=False, tracks_only=False, in_quotes=False): + def search( + query: str, + limit: int = None, + albums_only=False, + tracks_only=False, + in_quotes=False, + ): items, titles = TopResults.collect_all() results = TopResults.get_results(titles, query) - tracks_limit = Limit.tracks if tracks_only else 5 - albums_limit = Limit.albums if albums_only else 6 - artists_limit = 3 + tracks_limit = Limit.tracks if tracks_only else 4 + albums_limit = Limit.albums if albums_only else limit + artists_limit = limit # map results to their respective items try: diff --git a/app/models/track.py b/app/models/track.py index a13d0ed..42b2a98 100644 --- a/app/models/track.py +++ b/app/models/track.py @@ -2,9 +2,13 @@ from dataclasses import dataclass from app.settings import ParserFlags, get_flag from app.utils.hashing import create_hash -from app.utils.parsers import (clean_title, get_base_title_and_versions, - parse_feat_from_title, remove_prod, - split_artists) +from app.utils.parsers import ( + clean_title, + get_base_title_and_versions, + parse_feat_from_title, + remove_prod, + split_artists, +) from .artist import ArtistMinimal @@ -51,8 +55,10 @@ class Track: if get_flag(ParserFlags.EXTRACT_FEAT): featured, new_title = parse_feat_from_title(self.title) - original_lower = "-".join([a.lower() for a in artists]) - artists.extend([a for a in featured if a.lower() not in original_lower]) + original_lower = "-".join([create_hash(a) for a in artists]) + artists.extend( + [a for a in featured if create_hash(a) not in original_lower] + ) if get_flag(ParserFlags.REMOVE_PROD): new_title = remove_prod(new_title) @@ -121,7 +127,7 @@ class Track: def add_artists(self, artists: list[str], new_album_title: str): for artist in artists: - if create_hash(artist) not in self.artist_hashes: + if create_hash(artist, decode=True) not in self.artist_hashes: self.artists.append(ArtistMinimal(artist)) self.recreate_artists_hash() diff --git a/app/utils/hashing.py b/app/utils/hashing.py index 6492784..b501a4e 100644 --- a/app/utils/hashing.py +++ b/app/utils/hashing.py @@ -1,4 +1,5 @@ import hashlib +import re from unidecode import unidecode @@ -14,6 +15,7 @@ def create_hash(*args: str, decode=False, limit=10) -> str: str_ = str_.lower().strip().replace(" ", "") str_ = "".join(t for t in str_ if t.isalnum()) + str_ = re.sub(r"[^a-zA-Z0-9\s]", "", str_) str_ = str_.encode("utf-8") str_ = hashlib.sha256(str_).hexdigest() return str_[-limit:] diff --git a/app/utils/parsers.py b/app/utils/parsers.py index 7bc498e..44cf19e 100644 --- a/app/utils/parsers.py +++ b/app/utils/parsers.py @@ -133,6 +133,8 @@ def get_album_info(bracket_text: str | None) -> list[str]: if not bracket_text: return [] + # replace all non-alphanumeric characters with an empty string + bracket_text = re.sub(r"[^a-zA-Z0-9\s]", "", bracket_text) versions = [] for version_keywords in AlbumVersionEnum: