From 2afbf31ed6bed0c7ef502ab98ee6e7d0fec3009d Mon Sep 17 00:00:00 2001 From: juli0n21 Date: Thu, 6 Feb 2025 00:58:49 +0100 Subject: [PATCH] add count to artist songs --- go-backend/database.go | 15 ++-- go-backend/docs/docs.go | 65 +++++++++++++++-- go-backend/docs/swagger.json | 65 +++++++++++++++-- go-backend/docs/swagger.yaml | 44 +++++++++++- go-backend/handlers.go | 136 ++++++++++++++++++++--------------- go-backend/models.go | 7 ++ 6 files changed, 256 insertions(+), 76 deletions(-) diff --git a/go-backend/database.go b/go-backend/database.go index 023aeb7..7f9dda1 100644 --- a/go-backend/database.go +++ b/go-backend/database.go @@ -351,21 +351,22 @@ func getSearch(db *sql.DB, q string, limit, offset int) (ActiveSearch, error) { return ActiveSearch{}, nil } -func getArtists(db *sql.DB, q string, limit, offset int) ([]string, error) { - rows, err := db.Query("SELECT Artist FROM Beatmap WHERE Artist LIKE ? OR Title LIKE ? GROUP BY Artist LIMIT ? OFFSET ?", "%"+q+"%", "%"+q+"%", limit, offset) +func getArtists(db *sql.DB, q string, limit, offset int) ([]Artist, error) { + rows, err := db.Query("SELECT Artist, COUNT(Artist) FROM Beatmap WHERE Artist LIKE ? OR Title LIKE ? GROUP BY Artist LIMIT ? OFFSET ?", "%"+q+"%", "%"+q+"%", limit, offset) if err != nil { - return []string{}, err + return []Artist{}, err } defer rows.Close() - var artist []string + artist := []Artist{} for rows.Next() { var a string - err := rows.Scan(&a) + var c int + err := rows.Scan(&a, &c) if err != nil { - return []string{}, err + return []Artist{}, err } - artist = append(artist, a) + artist = append(artist, Artist{Artist: a, Count: c}) } return artist, nil diff --git a/go-backend/docs/docs.go b/go-backend/docs/docs.go index 64bfec7..92743d0 100644 --- a/go-backend/docs/docs.go +++ b/go-backend/docs/docs.go @@ -287,10 +287,7 @@ const docTemplate = `{ "200": { "description": "List of artists", "schema": { - "type": "array", - "items": { - "type": "string" - } + "$ref": "#/definitions/main.Artist" } }, "400": { @@ -413,6 +410,52 @@ const docTemplate = `{ } } }, + "/songs/artist": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "songs" + ], + "summary": "Returns all the Songs of a specific Artist", + "parameters": [ + { + "type": "string", + "description": "Artist Name", + "name": "artist", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/main.Song" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, "/songs/favorites": { "get": { "description": "Retrieves favorite songs filtered by a query with pagination support.", @@ -540,6 +583,20 @@ const docTemplate = `{ } } }, + "main.Artist": { + "description": "Artist holds search results for a given artist", + "type": "object", + "properties": { + "artist": { + "type": "string", + "example": "Miku" + }, + "count": { + "type": "integer", + "example": 21 + } + } + }, "main.Collection": { "description": "Collection holds a list of songs", "type": "object", diff --git a/go-backend/docs/swagger.json b/go-backend/docs/swagger.json index 134c5ee..6da7744 100644 --- a/go-backend/docs/swagger.json +++ b/go-backend/docs/swagger.json @@ -281,10 +281,7 @@ "200": { "description": "List of artists", "schema": { - "type": "array", - "items": { - "type": "string" - } + "$ref": "#/definitions/main.Artist" } }, "400": { @@ -407,6 +404,52 @@ } } }, + "/songs/artist": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "songs" + ], + "summary": "Returns all the Songs of a specific Artist", + "parameters": [ + { + "type": "string", + "description": "Artist Name", + "name": "artist", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/main.Song" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, "/songs/favorites": { "get": { "description": "Retrieves favorite songs filtered by a query with pagination support.", @@ -534,6 +577,20 @@ } } }, + "main.Artist": { + "description": "Artist holds search results for a given artist", + "type": "object", + "properties": { + "artist": { + "type": "string", + "example": "Miku" + }, + "count": { + "type": "integer", + "example": 21 + } + } + }, "main.Collection": { "description": "Collection holds a list of songs", "type": "object", diff --git a/go-backend/docs/swagger.yaml b/go-backend/docs/swagger.yaml index 9e2b806..5eb557f 100644 --- a/go-backend/docs/swagger.yaml +++ b/go-backend/docs/swagger.yaml @@ -11,6 +11,16 @@ definitions: $ref: '#/definitions/main.Song' type: array type: object + main.Artist: + description: Artist holds search results for a given artist + properties: + artist: + example: Miku + type: string + count: + example: 21 + type: integer + type: object main.Collection: description: Collection holds a list of songs properties: @@ -248,9 +258,7 @@ paths: "200": description: List of artists schema: - items: - type: string - type: array + $ref: '#/definitions/main.Artist' "400": description: Bad Request schema: @@ -332,6 +340,36 @@ paths: summary: Get a song by its hash tags: - songs + /songs/artist: + get: + consumes: + - application/json + parameters: + - description: Artist Name + in: query + name: artist + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/main.Song' + type: array + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + summary: Returns all the Songs of a specific Artist + tags: + - songs /songs/favorites: get: consumes: diff --git a/go-backend/handlers.go b/go-backend/handlers.go index 5d0779d..5eb53da 100644 --- a/go-backend/handlers.go +++ b/go-backend/handlers.go @@ -36,6 +36,7 @@ func (s *Server) registerRoutes() { http.HandleFunc("/api/v1/song/{hash}/", s.song) http.HandleFunc("/api/v1/songs/recents", s.recents) http.HandleFunc("/api/v1/songs/favorites", s.favorites) + http.HandleFunc("/api/v1/songs/artist", s.aristsSongs) http.HandleFunc("/api/v1/collection", s.collection) http.HandleFunc("/api/v1/search/collections", s.collectionSearch) @@ -169,8 +170,8 @@ func (s *Server) favorites(w http.ResponseWriter, r *http.Request) { // @Tags songs // @Accept json // @Produce json -// @Param index query int false "Index" -// @Param name query string false "Index" +// @Param index query int false "Index" +// @Param name query string false "Index" // @Success 200 {array} Song // @Failure 400 {string} string "Invalid parameter" // @Failure 500 {string} string "Internal server error" @@ -204,18 +205,18 @@ func (s *Server) collection(w http.ResponseWriter, r *http.Request) { } -// @Summary Searches collections based on a query -// @Description Searches collections in the database based on the query parameter -// @Tags search -// @Accept json -// @Produce json -// @Param query query string true "Search query" -// @Param limit query int false "Limit the number of results" default(10) -// @Param offset query int false "Offset for pagination" default(0) -// @Success 200 {array} Collection "List of collections" -// @Failure 400 {object} string "Bad Request" -// @Failure 500 {object} string "Internal Server Error" -// @Router /search/collections [get] +// @Summary Searches collections based on a query +// @Description Searches collections in the database based on the query parameter +// @Tags search +// @Accept json +// @Produce json +// @Param query query string true "Search query" +// @Param limit query int false "Limit the number of results" default(10) +// @Param offset query int false "Offset for pagination" default(0) +// @Success 200 {array} Collection "List of collections" +// @Failure 400 {object} string "Bad Request" +// @Failure 500 {object} string "Internal Server Error" +// @Router /search/collections [get] func (s *Server) collectionSearch(w http.ResponseWriter, r *http.Request) { q := r.URL.Query().Get("query") @@ -230,18 +231,37 @@ func (s *Server) collectionSearch(w http.ResponseWriter, r *http.Request) { writeJSON(w, preview, http.StatusOK) } -// @Summary Searches active records based on a query -// @Description Searches active records in the database based on the query parameter -// @Tags search -// @Accept json -// @Produce json -// @Param query query string true "Search query" -// @Param limit query int false "Limit the number of results" default(10) -// @Param offset query int false "Offset for pagination" default(0) -// @Success 200 {object} ActiveSearch "Active search result" -// @Failure 400 {object} string "Bad Request" -// @Failure 500 {object} string "Internal Server Error" -// @Router /search/active [get] +// @Summary Returns all the Songs of a specific Artist +// @Tags songs +// @Accept json +// @Produce json +// @Param artist query string true "Artist Name" +// @Success 200 {array} Song +// @Failure 400 {object} string "Bad Request" +// @Failure 500 {object} string "Internal Server Error" +// @Router /songs/artist [get] +func (s *Server) aristsSongs(w http.ResponseWriter, r *http.Request) { + artist := r.URL.Query().Get("artist") + if artist == "" { + http.Error(w, ErrRequiredParameterNotPresent.Error(), http.StatusBadRequest) + return + } + + writeJSON(w, []Song{}, http.StatusOK) +} + +// @Summary Searches active records based on a query +// @Description Searches active records in the database based on the query parameter +// @Tags search +// @Accept json +// @Produce json +// @Param query query string true "Search query" +// @Param limit query int false "Limit the number of results" default(10) +// @Param offset query int false "Offset for pagination" default(0) +// @Success 200 {object} ActiveSearch "Active search result" +// @Failure 400 {object} string "Bad Request" +// @Failure 500 {object} string "Internal Server Error" +// @Router /search/active [get] func (s *Server) activeSearch(w http.ResponseWriter, r *http.Request) { q := r.URL.Query().Get("query") if q == "" { @@ -261,18 +281,18 @@ func (s *Server) activeSearch(w http.ResponseWriter, r *http.Request) { writeJSON(w, recent, http.StatusOK) } -// @Summary Searches for artists based on a query -// @Description Searches for artists in the database based on the query parameter -// @Tags search -// @Accept json -// @Produce json -// @Param query query string true "Search query" -// @Param limit query int false "Limit the number of results" default(10) -// @Param offset query int false "Offset for pagination" default(0) -// @Success 200 {array} string "List of artists" -// @Failure 400 {object} string "Bad Request" -// @Failure 500 {object} string "Internal Server Error" -// @Router /search/artist [get] +// @Summary Searches for artists based on a query +// @Description Searches for artists in the database based on the query parameter +// @Tags search +// @Accept json +// @Produce json +// @Param query query string true "Search query" +// @Param limit query int false "Limit the number of results" default(10) +// @Param offset query int false "Offset for pagination" default(0) +// @Success 200 {object} Artist "List of artists" +// @Failure 400 {object} string "Bad Request" +// @Failure 500 {object} string "Internal Server Error" +// @Router /search/artist [get] func (s *Server) artistSearch(w http.ResponseWriter, r *http.Request) { q := r.URL.Query().Get("query") if q == "" { @@ -292,16 +312,16 @@ func (s *Server) artistSearch(w http.ResponseWriter, r *http.Request) { writeJSON(w, a, http.StatusOK) } -// @Summary Retrieves a song file by its encoded path -// @Description Retrieves a song file from the server based on the provided encoded filepath -// @Tags files -// @Accept json -// @Produce json -// @Param filepath path string true "Base64 encoded file path" -// @Success 200 {file} File "The requested song file" -// @Failure 400 {object} string "Bad Request" -// @Failure 404 {object} string "File Not Found" -// @Router /audio/{filepath} [get] +// @Summary Retrieves a song file by its encoded path +// @Description Retrieves a song file from the server based on the provided encoded filepath +// @Tags files +// @Accept json +// @Produce json +// @Param filepath path string true "Base64 encoded file path" +// @Success 200 {file} File "The requested song file" +// @Failure 400 {object} string "Bad Request" +// @Failure 404 {object} string "File Not Found" +// @Router /audio/{filepath} [get] func (s *Server) songFile(w http.ResponseWriter, r *http.Request) { f := r.PathValue("filepath") if f == "" { @@ -334,16 +354,16 @@ func (s *Server) songFile(w http.ResponseWriter, r *http.Request) { http.ServeContent(w, r, stat.Name(), stat.ModTime(), file) } -// @Summary Retrieves an image file by its encoded path -// @Description Retrieves an image file from the server based on the provided encoded filepath -// @Tags files -// @Accept json -// @Produce json -// @Param filepath path string true "Base64 encoded file path" -// @Success 200 {file} File "The requested image file" -// @Failure 400 {object} string "Bad Request" -// @Failure 404 {object} string "File Not Found" -// @Router /image/{filepath} [get] +// @Summary Retrieves an image file by its encoded path +// @Description Retrieves an image file from the server based on the provided encoded filepath +// @Tags files +// @Accept json +// @Produce json +// @Param filepath path string true "Base64 encoded file path" +// @Success 200 {file} File "The requested image file" +// @Failure 400 {object} string "Bad Request" +// @Failure 404 {object} string "File Not Found" +// @Router /image/{filepath} [get] func (s *Server) imageFile(w http.ResponseWriter, r *http.Request) { f := r.PathValue("filepath") if f == "" { diff --git a/go-backend/models.go b/go-backend/models.go index 02d2ad3..41fb4a9 100644 --- a/go-backend/models.go +++ b/go-backend/models.go @@ -37,3 +37,10 @@ type ActiveSearch struct { Artist string `json:"artist" example:"Ed Sheeran"` Songs []Song `json:"songs"` } + +// Artist represents an active song search query +// @Description Artist holds search results for a given artist +type Artist struct { + Artist string `json:"artist" example:"Miku"` + Count int `json:"count" example:"21"` +}