add docs for search endpoints

This commit is contained in:
mungai-njoroge
2024-03-10 17:40:35 +03:00
committed by Mungai Njoroge
parent 766eb388b2
commit 4edb3a5e7a
5 changed files with 51 additions and 59 deletions
+2 -25
View File
@@ -1,29 +1,6 @@
# What's New? # What's New?
- New opt-in alternate (no sidebar) layout - Hovering on recent favorite item will show how long ago it was ♥ed
- Added search bar to the top bar (all layouts)
- Move browse options to homepage bottom
- Move to a stronger WSGI server ([waitress](https://docs.pylonsproject.org/projects/waitress/en/stable/))
- Proper ARM64 and other platforms support
- A Proper timezone fix. Thanks to @tcsenpai on #170
- Hovering over a recently played/added item on the homepage will reveal how long ago
- Recently added items will not have a cutoff
- The exhaustive list of web client stuff can be found on [commit 4211ccc](https://github.com/swing-opensource/swingmusic-client/commit/4211ccc685e3d33dbf008cbb6c77542baf0130dc) in the client repo.
# Bug fixes & Enhancements
- Lyrics plugin now works when Swing Music is auto started (tested on Ubuntu)
- Track not being removed from queue
- Playlist list page moving out of bounds
- Save queue as playlist not working
- Keyboard shortcuts not working in first try
- Fix recently added items not filling row
- Fix recently added items order
# Development # Development
- API documentation on /openapi
- WIP code base documentation to `.github/docs`. Contributions are welcome!
- Bump watchdog to v4
> [!TIP]
> Plans for a mobile are underway. The development will be led by @EricGacoki
+1 -1
View File
@@ -67,7 +67,7 @@ def create_api():
app.register_api(album.api) app.register_api(album.api)
app.register_api(artist.api) app.register_api(artist.api)
app.register_api(send_file.api) app.register_api(send_file.api)
app.register_blueprint(search.api) app.register_api(search.api)
app.register_blueprint(folder.api) app.register_blueprint(folder.api)
app.register_blueprint(playlist.api) app.register_blueprint(playlist.api)
app.register_blueprint(favorites.api) app.register_blueprint(favorites.api)
+46 -32
View File
@@ -2,14 +2,19 @@
Contains all the search routes. Contains all the search routes.
""" """
from flask import Blueprint, request from flask import request
from pydantic import BaseModel, Field
from unidecode import unidecode from unidecode import unidecode
from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from app import models from app import models
from app.lib import searchlib from app.lib import searchlib
from app.settings import Defaults
from app.store.tracks import TrackStore from app.store.tracks import TrackStore
api = Blueprint("search", __name__, url_prefix="/") tag = Tag(name="Search", description="Search for tracks, albums and artists")
api = APIBlueprint("search", __name__, url_prefix="/search", abp_tags=[tag])
SEARCH_COUNT = 30 SEARCH_COUNT = 30
"""The max amount of items to return per request""" """The max amount of items to return per request"""
@@ -63,18 +68,19 @@ class Search:
return finder.search(self.query, in_quotes=in_quotes, limit=limit) return finder.search(self.query, in_quotes=in_quotes, limit=limit)
@api.route("/search/tracks", methods=["GET"]) class SearchQuery(BaseModel):
def search_tracks(): q: str = Field(description="The search query", example=Defaults.API_ARTISTNAME)
@api.get("/tracks")
def search_tracks(query: SearchQuery):
""" """
Searches for tracks that match the search query. Searches for tracks
""" """
query = request.args.get("q") query = query.q
in_quotes = query_in_quotes(query) in_quotes = query_in_quotes(query)
if not query:
return {"error": "No query provided"}, 400
tracks = Search(query).search_tracks(in_quotes) tracks = Search(query).search_tracks(in_quotes)
return { return {
@@ -83,18 +89,15 @@ def search_tracks():
} }
@api.route("/search/albums", methods=["GET"]) @api.get("/albums")
def search_albums(): def search_albums(query: SearchQuery):
""" """
Searches for albums. Searches for albums.
""" """
query = request.args.get("q") query = query.q
in_quotes = query_in_quotes(query) in_quotes = query_in_quotes(query)
if not query:
return {"error": "No query provided"}, 400
albums = Search(query).search_albums(in_quotes) albums = Search(query).search_albums(in_quotes)
return { return {
@@ -103,13 +106,13 @@ def search_albums():
} }
@api.route("/search/artists", methods=["GET"]) @api.get("/artists")
def search_artists(): def search_artists(query: SearchQuery):
""" """
Searches for artists. Searches for artists.
""" """
query = request.args.get("q") query = query.q
if not query: if not query:
return {"error": "No query provided"}, 400 return {"error": "No query provided"}, 400
@@ -122,15 +125,20 @@ def search_artists():
} }
@api.route("/search/top", methods=["GET"]) class TopResultsQuery(SearchQuery):
def get_top_results(): limit: int = Field(
description="The number of items to return", default=Defaults.API_CARD_LIMIT
)
@api.get("/top")
def get_top_results(query: TopResultsQuery):
""" """
Returns the top results for the search query. Returns the top results for the search query.
""" """
query = request.args.get("q") query = query.q
limit = request.args.get("limit", "6") limit = query.limit
limit = int(limit)
in_quotes = query_in_quotes(query) in_quotes = query_in_quotes(query)
@@ -140,32 +148,38 @@ def get_top_results():
return Search(query).get_top_results(in_quotes=in_quotes, limit=limit) return Search(query).get_top_results(in_quotes=in_quotes, limit=limit)
@api.route("/search/loadmore") class SearchLoadMoreQuery(SearchQuery):
def search_load_more(): type: str = Field(description="The type of search", example="tracks")
index: int = Field(description="The index to start from", default=0)
@api.get("/loadmore")
def search_load_more(query: SearchLoadMoreQuery):
""" """
Returns more songs, albums or artists from a search query. Returns more songs, albums or artists from a search query.
NOTE: You must first initiate a search using the `/search` endpoint.
""" """
query = request.args.get("q") query = query.q
item_type = query.type
index = query.index
in_quotes = query_in_quotes(query) in_quotes = query_in_quotes(query)
s_type = request.args.get("type") if item_type == "tracks":
index = int(request.args.get("index") or 0)
if s_type == "tracks":
t = Search(query).search_tracks(in_quotes) t = Search(query).search_tracks(in_quotes)
return { return {
"tracks": t[index : index + SEARCH_COUNT], "tracks": t[index : index + SEARCH_COUNT],
"more": len(t) > index + SEARCH_COUNT, "more": len(t) > index + SEARCH_COUNT,
} }
elif s_type == "albums": elif item_type == "albums":
a = Search(query).search_albums(in_quotes) a = Search(query).search_albums(in_quotes)
return { return {
"albums": a[index : index + SEARCH_COUNT], "albums": a[index : index + SEARCH_COUNT],
"more": len(a) > index + SEARCH_COUNT, "more": len(a) > index + SEARCH_COUNT,
} }
elif s_type == "artists": elif item_type == "artists":
a = Search(query).search_artists() a = Search(query).search_artists()
return { return {
"artists": a[index : index + SEARCH_COUNT], "artists": a[index : index + SEARCH_COUNT],
+1 -1
View File
@@ -12,7 +12,7 @@ from app.lib.trackslib import get_silence_paddings
from app.store.tracks import TrackStore from app.store.tracks import TrackStore
bp_tag = Tag(name="File", description="Single artist") bp_tag = Tag(name="File", description="Audio files")
api = APIBlueprint("track", __name__, url_prefix="/file", abp_tags=[bp_tag]) api = APIBlueprint("track", __name__, url_prefix="/file", abp_tags=[bp_tag])
+1
View File
@@ -102,6 +102,7 @@ class Defaults:
API_ARTISTHASH = "fc6f0acac5" API_ARTISTHASH = "fc6f0acac5"
API_TRACKHASH = "0853280a12" API_TRACKHASH = "0853280a12"
API_ALBUMNAME = "Rumours" API_ALBUMNAME = "Rumours"
API_ARTISTNAME = "girl in red"
API_CARD_LIMIT = 6 API_CARD_LIMIT = 6