""" Contains all the search routes. """ from typing import List from app import helpers from app.lib import searchlib from flask import Blueprint from flask import request from server.app import instances, models search_bp = Blueprint("search", __name__, url_prefix="/") SEARCH_RESULTS = { "tracks": [], "albums": [], "artists": [], } class SearchResults: """ Holds all the search results. """ query: str = "" tracks: list[models.Track] albums: list[models.Album] playlists: list[models.Playlist] artists: list[models.Artist] class DoSearch: """Class containing the methods that perform searching.""" def __init__(self, query: str) -> None: """ :param :str:`query`: the search query. """ self.query = query SearchResults.query = query def search_tracks(self): """Calls :class:`SearchTracks` which returns the tracks that fuzzily match the search terms. Then adds them to the `SearchResults` store. """ self.tracks = helpers.Get.get_all_tracks() tracks = searchlib.SearchTracks(self.tracks, self.query)() SearchResults.tracks = tracks return tracks def search_artists(self): """Calls :class:`SearchArtists` which returns the artists that fuzzily match the search term. Then adds them to the `SearchResults` store. """ self.artists = helpers.Get.get_all_artists() artists = searchlib.SearchArtists(self.artists, self.query)() SearchResults.artists = artists return artists def search_albums(self): """Calls :class:`SearchAlbums` which returns the albums that fuzzily match the search term. Then adds them to the `SearchResults` store. """ self.albums = helpers.Get.get_all_albums() albums = searchlib.SearchAlbums(self.albums, self.query)() SearchResults.albums = albums return albums def search_playlists(self): """Calls :class:`SearchPlaylists` which returns the playlists that fuzzily match the search term. Then adds them to the `SearchResults` store. """ self.playlists = helpers.Get.get_all_playlists() playlists = searchlib.SearchPlaylists(self.playlists, self.query) SearchResults.playlists = playlists return playlists def search_all(self): """Calls all the search methods.""" self.search_tracks() self.search_albums() self.search_artists() self.search_playlists() @search_bp.route("/search/tracks", methods=["GET"]) def search_tracks(): """ Searches for tracks that match the search query. """ query = request.args.get("q") if not query: return {"error": "No query provided"}, 400 if SearchResults.query == query and len(SearchResults.tracks) > 0: return { "tracks": SearchResults.tracks[:5], "more": len(SearchResults.tracks) > 5, }, 200 tracks = DoSearch(query).search_tracks() return { "tracks": tracks[:5], "more": len(tracks) > 5, }, 200 @search_bp.route("/search/albums", methods=["GET"]) def search_albums(): """ Searches for albums. """ query = request.args.get("q") if not query: return {"error": "No query provided"}, 400 if SearchResults.query == query and len(SearchResults.albums) > 0: return { "albums": SearchResults.albums[:6], "more": len(SearchResults.albums) > 6, }, 200 tracks = DoSearch(query).search_albums() return { "albums": tracks[:6], "more": len(tracks) > 6, }, 200 @search_bp.route("/search/artists", methods=["GET"]) def search_artists(): """ Searches for artists. """ query = request.args.get("q") if not query: return {"error": "No query provided"}, 400 if SearchResults.query == query and len(SearchResults.artists) > 0: return { "artists": SearchResults.artists[:6], "more": len(SearchResults.artists) > 6, }, 200 artists = DoSearch(query).search_artists() return { "artists": artists[:6], "more": len(artists) > 6, }, 200 @search_bp.route("/search/top", methods=["GET"]) def get_top_results(): """ Returns the top results for the search query. """ query = request.args.get("q") if not query: return {"error": "No query provided"}, 400 DoSearch(query).search_all() max = 2 return { "tracks": SearchResults.tracks[:max], "albums": SearchResults.albums[:max], "artists": SearchResults.artists[:max], "playlists": SearchResults.playlists[:max], } @search_bp.route("/search") def search(): """ Returns a list of songs, albums and artists that match the search query. """ query = request.args.get("q") or "Mexican girl" albums = searchlib.SearchAlbums(query)() artists_dicts = searchlib.SearchArtists(query)() tracks = searchlib.SearchTracks(query)() top_artist = artists_dicts[0]["name"] _tracks = searchlib.GetTopArtistTracks(top_artist)() tracks = [*tracks, *[t for t in _tracks if t not in tracks]] SEARCH_RESULTS.clear() SEARCH_RESULTS["tracks"] = tracks SEARCH_RESULTS["albums"] = albums SEARCH_RESULTS["artists"] = artists_dicts 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}, ] } @search_bp.route("/search/loadmore") def search_load_more(): """ Returns more songs, albums or artists from a search query. """ type = request.args.get("type") index = int(request.args.get("index")) if type == "tracks": return { "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], "more": len(SEARCH_RESULTS["albums"]) > index + 6, } elif type == "artists": return { "artists": SEARCH_RESULTS["artists"][index : index + 6], "more": len(SEARCH_RESULTS["artists"]) > index + 6, }