swingmusic/server/app/api/search.py
2022-07-06 17:38:33 +03:00

217 lines
5.3 KiB
Python

"""
Contains all the search routes.
"""
from pprint import pprint
from typing import List
from app import helpers
from app import models
from app import serializer
from app.lib import searchlib
from flask import Blueprint
from flask import request
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)()
tracks = helpers.RemoveDuplicates(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 = 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.
"""
albums = helpers.Get.get_all_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 = helpers.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()
@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
tracks = DoSearch(query).search_tracks()
return {
"tracks": tracks[:6],
"more": len(tracks) > 6,
}, 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
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
artists = DoSearch(query).search_artists()
return {
"artists": artists[:6],
"more": len(artists) > 6,
}, 200
@search_bp.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[:6],
"more": len(playlists) > 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/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":
t = SearchResults.tracks
return {
"tracks": t[index:index + 5],
"more": len(t) > index + 5,
}
elif type == "albums":
a = SearchResults.albums
return {
"albums": a[index:index + 6],
"more": len(a) > index + 6,
}
elif type == "artists":
a = SearchResults.artists
return {
"artists": a[index:index + 6],
"more": len(a) > index + 6,
}