swingmusic/app/api/search.py
Mungai Njoroge 198957bcae
Move server code to this repo (#95)
move server code to this repo
2023-01-13 20:01:52 +03:00

219 lines
5.6 KiB
Python

"""
Contains all the search routes.
"""
from flask import Blueprint, request
from app import models, utils
from app.db.store import Store
from app.lib import searchlib
searchbp = Blueprint("search", __name__, url_prefix="/")
SEARCH_COUNT = 12
"""The max amount of items to return per request"""
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.tracks: list[models.Track] = []
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 = Store.tracks
tracks = searchlib.SearchTracks(self.tracks, self.query)()
if len(tracks) == 0:
return []
tracks = utils.remove_duplicates(tracks)
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 = utils.Get.get_all_artists()
artists = [a.name for a in Store.artists]
artists = searchlib.SearchArtists(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.
"""
# albums = utils.Get.get_all_albums()
albums = Store.albums
albums = searchlib.SearchAlbums(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.
# """
# playlists = utils.Get.get_all_playlists()
# playlists = [serializer.Playlist(playlist) for playlist in playlists]
# playlists = searchlib.SearchPlaylists(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()
@searchbp.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
tracks = DoSearch(query).search_tracks()
return {
"tracks": tracks[:SEARCH_COUNT],
"more": len(tracks) > SEARCH_COUNT,
}
@searchbp.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
tracks = DoSearch(query).search_albums()
return {
"albums": tracks[:SEARCH_COUNT],
"more": len(tracks) > SEARCH_COUNT,
}
@searchbp.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
artists = DoSearch(query).search_artists()
return {
"artists": artists[:SEARCH_COUNT],
"more": len(artists) > SEARCH_COUNT,
}
# @searchbp.route("/search/playlists", methods=["GET"])
# def search_playlists():
# """
# Searches for playlists.
# """
# query = request.args.get("q")
# if not query:
# return {"error": "No query provided"}, 400
# playlists = DoSearch(query).search_playlists()
# return {
# "playlists": playlists[:SEARCH_COUNT],
# "more": len(playlists) > SEARCH_COUNT,
# }
@searchbp.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],
}
@searchbp.route("/search/loadmore")
def search_load_more():
"""
Returns more songs, albums or artists from a search query.
"""
s_type = request.args.get("type")
index = int(request.args.get("index") or 0)
if s_type == "tracks":
t = SearchResults.tracks
return {
"tracks": t[index : index + SEARCH_COUNT],
"more": len(t) > index + SEARCH_COUNT,
}
elif s_type == "albums":
a = SearchResults.albums
return {
"albums": a[index : index + SEARCH_COUNT],
"more": len(a) > index + SEARCH_COUNT,
}
elif s_type == "artists":
a = SearchResults.artists
return {
"artists": a[index : index + SEARCH_COUNT],
"more": len(a) > index + SEARCH_COUNT,
}