[jsonapi] Support /api/search?type=genre like type=composers is supported

Ref. #1735
This commit is contained in:
ejurgensen 2024-03-30 22:18:18 +01:00
parent 39f5df8ade
commit 3e7e03b4c1
2 changed files with 78 additions and 8 deletions

View File

@ -2037,12 +2037,12 @@ curl -X PUT "http://localhost:3689/api/library/backup"
| Method | Endpoint | Description |
| --------- | ----------------------------------------------------------- | ------------------------------------ |
| GET | [/api/search](#search-by-search-term) | Search for playlists, artists, albums, tracks, composers by a simple search term |
| GET | [/api/search](#search-by-search-term) | Search for playlists, artists, albums, tracks, genres, composers by a simple search term |
| GET | [/api/search](#search-by-query-language) | Search by complex query expression |
### Search by search term
Search for playlists, artists, albums, tracks, composers that include the given query in their title (case insensitive matching).
Search for playlists, artists, albums, tracks, genres, composers that include the given query in their title (case insensitive matching).
**Endpoint**
@ -2055,7 +2055,7 @@ GET /api/search
| Parameter | Value |
| --------------- | ----------------------------------------------------------- |
| query | The search keyword |
| type | Comma separated list of the result types (`playlist`, `artist`, `album`, `track`, `composers`) |
| type | Comma separated list of the result types (`playlist`, `artist`, `album`, `track`, `genres`, `composers`) |
| media_kind | *(Optional)* Filter results by media kind (`music`, `movie`, `podcast`, `audiobook`, `musicvideo`, `tvshow`). Filter only applies to artist, album and track result types. |
| offset | *(Optional)* Offset of the first item to return for each type |
| limit | *(Optional)* Maximum number of items to return for each type |
@ -2064,11 +2064,12 @@ GET /api/search
| Key | Type | Value |
| --------------- | -------- | ----------------------------------------- |
| tracks | object | [`paging`](#paging-object) object containing [`track`](#track-object) objects that matches the `query` |
| artists | object | [`paging`](#paging-object) object containing [`artist`](#artist-object) objects that matches the `query` |
| albums | object | [`paging`](#paging-object) object containing [`album`](#album-object) objects that matches the `query` |
| playlists | object | [`paging`](#paging-object) object containing [`playlist`](#playlist-object) objects that matches the `query` |
| composers | object | [`paging`](#paging-object) object containing `composers` objects that matches the `query` |
| tracks | object | [`paging`](#paging-object) object containing [`track`](#track-object) objects that match the `query` |
| artists | object | [`paging`](#paging-object) object containing [`artist`](#artist-object) objects that match the `query` |
| albums | object | [`paging`](#paging-object) object containing [`album`](#album-object) objects that match the `query` |
| playlists | object | [`paging`](#paging-object) object containing [`playlist`](#playlist-object) objects that match the `query` |
| genres | object | [`paging`](#paging-object) object containing [`browse-info`](#browse-info-object) objects that match the `query` |
| composers | object | [`paging`](#paging-object) object containing [`browse-info`](#browse-info-object) objects that match the `query` |
**Example**

View File

@ -4326,6 +4326,68 @@ search_composers(json_object *reply, struct httpd_request *hreq, const char *par
return ret;
}
static int
search_genres(json_object *reply, struct httpd_request *hreq, const char *param_query, struct smartpl *smartpl_expression, enum media_kind media_kind)
{
json_object *type;
json_object *items;
struct query_params query_params;
int total;
int ret;
memset(&query_params, 0, sizeof(struct query_params));
ret = query_params_limit_set(&query_params, hreq);
if (ret < 0)
goto out;
type = json_object_new_object();
json_object_object_add(reply, "genres", type);
items = json_object_new_array();
json_object_object_add(type, "items", items);
query_params.type = Q_BROWSE_GENRES;
query_params.sort = S_GENRE;
ret = query_params_limit_set(&query_params, hreq);
if (ret < 0)
goto out;
if (param_query)
{
if (media_kind)
query_params.filter = db_mprintf("(f.genre LIKE '%%%q%%' AND f.media_kind = %d)", param_query, media_kind);
else
query_params.filter = db_mprintf("(f.genre LIKE '%%%q%%')", param_query);
}
else
{
query_params.filter = strdup(smartpl_expression->query_where);
query_params.having = safe_strdup(smartpl_expression->having);
query_params.order = safe_strdup(smartpl_expression->order);
if (smartpl_expression->limit > 0)
{
query_params.idx_type = I_SUB;
query_params.limit = smartpl_expression->limit;
query_params.offset = 0;
}
}
ret = fetch_browse_info(&query_params, items, &total);
if (ret < 0)
goto out;
json_object_object_add(type, "total", json_object_new_int(total));
json_object_object_add(type, "offset", json_object_new_int(query_params.offset));
json_object_object_add(type, "limit", json_object_new_int(query_params.limit));
out:
free_query_params(&query_params, 1);
return ret;
}
static int
search_playlists(json_object *reply, struct httpd_request *hreq, const char *param_query)
{
@ -4448,6 +4510,13 @@ jsonapi_reply_search(struct httpd_request *hreq)
goto error;
}
if (strstr(param_type, "genre"))
{
ret = search_genres(reply, hreq, param_query, &smartpl_expression, media_kind);
if (ret < 0)
goto error;
}
if (strstr(param_type, "playlist") && param_query)
{
ret = search_playlists(reply, hreq, param_query);