From 4edb3a5e7aa1328ebcce1bce2a160017de276e4a Mon Sep 17 00:00:00 2001 From: mungai-njoroge Date: Sun, 10 Mar 2024 17:40:35 +0300 Subject: [PATCH] add docs for search endpoints --- .github/changelog.md | 27 ++------------- app/api/__init__.py | 2 +- app/api/search.py | 78 ++++++++++++++++++++++++++------------------ app/api/send_file.py | 2 +- app/settings.py | 1 + 5 files changed, 51 insertions(+), 59 deletions(-) diff --git a/.github/changelog.md b/.github/changelog.md index d424a67d..1d087f45 100644 --- a/.github/changelog.md +++ b/.github/changelog.md @@ -1,29 +1,6 @@ # What's New? -- New opt-in alternate (no sidebar) layout -- 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 +- Hovering on recent favorite item will show how long ago it was ♥ed # Development - -- 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 \ No newline at end of file +- API documentation on /openapi \ No newline at end of file diff --git a/app/api/__init__.py b/app/api/__init__.py index b72c0ec0..9cc6db1f 100644 --- a/app/api/__init__.py +++ b/app/api/__init__.py @@ -67,7 +67,7 @@ def create_api(): app.register_api(album.api) app.register_api(artist.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(playlist.api) app.register_blueprint(favorites.api) diff --git a/app/api/search.py b/app/api/search.py index f554c549..3b55a82b 100644 --- a/app/api/search.py +++ b/app/api/search.py @@ -2,14 +2,19 @@ Contains all the search routes. """ -from flask import Blueprint, request +from flask import request +from pydantic import BaseModel, Field from unidecode import unidecode +from flask_openapi3 import Tag +from flask_openapi3 import APIBlueprint from app import models from app.lib import searchlib +from app.settings import Defaults 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 """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) -@api.route("/search/tracks", methods=["GET"]) -def search_tracks(): +class SearchQuery(BaseModel): + 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) - if not query: - return {"error": "No query provided"}, 400 - tracks = Search(query).search_tracks(in_quotes) return { @@ -83,18 +89,15 @@ def search_tracks(): } -@api.route("/search/albums", methods=["GET"]) -def search_albums(): +@api.get("/albums") +def search_albums(query: SearchQuery): """ Searches for albums. """ - query = request.args.get("q") + query = query.q in_quotes = query_in_quotes(query) - if not query: - return {"error": "No query provided"}, 400 - albums = Search(query).search_albums(in_quotes) return { @@ -103,13 +106,13 @@ def search_albums(): } -@api.route("/search/artists", methods=["GET"]) -def search_artists(): +@api.get("/artists") +def search_artists(query: SearchQuery): """ Searches for artists. """ - query = request.args.get("q") + query = query.q if not query: return {"error": "No query provided"}, 400 @@ -122,15 +125,20 @@ def search_artists(): } -@api.route("/search/top", methods=["GET"]) -def get_top_results(): +class TopResultsQuery(SearchQuery): + 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. """ - query = request.args.get("q") - limit = request.args.get("limit", "6") - limit = int(limit) + query = query.q + limit = query.limit 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) -@api.route("/search/loadmore") -def search_load_more(): +class SearchLoadMoreQuery(SearchQuery): + 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. + + 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) - s_type = request.args.get("type") - index = int(request.args.get("index") or 0) - - if s_type == "tracks": + if item_type == "tracks": t = Search(query).search_tracks(in_quotes) return { "tracks": t[index : index + SEARCH_COUNT], "more": len(t) > index + SEARCH_COUNT, } - elif s_type == "albums": + elif item_type == "albums": a = Search(query).search_albums(in_quotes) return { "albums": a[index : index + SEARCH_COUNT], "more": len(a) > index + SEARCH_COUNT, } - elif s_type == "artists": + elif item_type == "artists": a = Search(query).search_artists() return { "artists": a[index : index + SEARCH_COUNT], diff --git a/app/api/send_file.py b/app/api/send_file.py index e07f32a7..bbcd7c05 100644 --- a/app/api/send_file.py +++ b/app/api/send_file.py @@ -12,7 +12,7 @@ from app.lib.trackslib import get_silence_paddings 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]) diff --git a/app/settings.py b/app/settings.py index e141576f..5021e62d 100644 --- a/app/settings.py +++ b/app/settings.py @@ -102,6 +102,7 @@ class Defaults: API_ARTISTHASH = "fc6f0acac5" API_TRACKHASH = "0853280a12" API_ALBUMNAME = "Rumours" + API_ARTISTNAME = "girl in red" API_CARD_LIMIT = 6