mirror of
https://github.com/JuLi0n21/pwa-player.git
synced 2026-04-19 23:40:05 +00:00
add count to artist songs
This commit is contained in:
@@ -351,21 +351,22 @@ func getSearch(db *sql.DB, q string, limit, offset int) (ActiveSearch, error) {
|
|||||||
return ActiveSearch{}, nil
|
return ActiveSearch{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getArtists(db *sql.DB, q string, limit, offset int) ([]string, error) {
|
func getArtists(db *sql.DB, q string, limit, offset int) ([]Artist, error) {
|
||||||
rows, err := db.Query("SELECT Artist FROM Beatmap WHERE Artist LIKE ? OR Title LIKE ? GROUP BY Artist LIMIT ? OFFSET ?", "%"+q+"%", "%"+q+"%", limit, offset)
|
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 {
|
if err != nil {
|
||||||
return []string{}, err
|
return []Artist{}, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
var artist []string
|
artist := []Artist{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var a string
|
var a string
|
||||||
err := rows.Scan(&a)
|
var c int
|
||||||
|
err := rows.Scan(&a, &c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []string{}, err
|
return []Artist{}, err
|
||||||
}
|
}
|
||||||
artist = append(artist, a)
|
artist = append(artist, Artist{Artist: a, Count: c})
|
||||||
}
|
}
|
||||||
|
|
||||||
return artist, nil
|
return artist, nil
|
||||||
|
|||||||
@@ -287,10 +287,7 @@ const docTemplate = `{
|
|||||||
"200": {
|
"200": {
|
||||||
"description": "List of artists",
|
"description": "List of artists",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "array",
|
"$ref": "#/definitions/main.Artist"
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"400": {
|
"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": {
|
"/songs/favorites": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "Retrieves favorite songs filtered by a query with pagination support.",
|
"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": {
|
"main.Collection": {
|
||||||
"description": "Collection holds a list of songs",
|
"description": "Collection holds a list of songs",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|||||||
@@ -281,10 +281,7 @@
|
|||||||
"200": {
|
"200": {
|
||||||
"description": "List of artists",
|
"description": "List of artists",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "array",
|
"$ref": "#/definitions/main.Artist"
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"400": {
|
"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": {
|
"/songs/favorites": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "Retrieves favorite songs filtered by a query with pagination support.",
|
"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": {
|
"main.Collection": {
|
||||||
"description": "Collection holds a list of songs",
|
"description": "Collection holds a list of songs",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|||||||
@@ -11,6 +11,16 @@ definitions:
|
|||||||
$ref: '#/definitions/main.Song'
|
$ref: '#/definitions/main.Song'
|
||||||
type: array
|
type: array
|
||||||
type: object
|
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:
|
main.Collection:
|
||||||
description: Collection holds a list of songs
|
description: Collection holds a list of songs
|
||||||
properties:
|
properties:
|
||||||
@@ -248,9 +258,7 @@ paths:
|
|||||||
"200":
|
"200":
|
||||||
description: List of artists
|
description: List of artists
|
||||||
schema:
|
schema:
|
||||||
items:
|
$ref: '#/definitions/main.Artist'
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
"400":
|
"400":
|
||||||
description: Bad Request
|
description: Bad Request
|
||||||
schema:
|
schema:
|
||||||
@@ -332,6 +340,36 @@ paths:
|
|||||||
summary: Get a song by its hash
|
summary: Get a song by its hash
|
||||||
tags:
|
tags:
|
||||||
- songs
|
- 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:
|
/songs/favorites:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ func (s *Server) registerRoutes() {
|
|||||||
http.HandleFunc("/api/v1/song/{hash}/", s.song)
|
http.HandleFunc("/api/v1/song/{hash}/", s.song)
|
||||||
http.HandleFunc("/api/v1/songs/recents", s.recents)
|
http.HandleFunc("/api/v1/songs/recents", s.recents)
|
||||||
http.HandleFunc("/api/v1/songs/favorites", s.favorites)
|
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/collection", s.collection)
|
||||||
http.HandleFunc("/api/v1/search/collections", s.collectionSearch)
|
http.HandleFunc("/api/v1/search/collections", s.collectionSearch)
|
||||||
@@ -169,8 +170,8 @@ func (s *Server) favorites(w http.ResponseWriter, r *http.Request) {
|
|||||||
// @Tags songs
|
// @Tags songs
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param index query int false "Index"
|
// @Param index query int false "Index"
|
||||||
// @Param name query string false "Index"
|
// @Param name query string false "Index"
|
||||||
// @Success 200 {array} Song
|
// @Success 200 {array} Song
|
||||||
// @Failure 400 {string} string "Invalid parameter"
|
// @Failure 400 {string} string "Invalid parameter"
|
||||||
// @Failure 500 {string} string "Internal server error"
|
// @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
|
// @Summary Searches collections based on a query
|
||||||
// @Description Searches collections in the database based on the query parameter
|
// @Description Searches collections in the database based on the query parameter
|
||||||
// @Tags search
|
// @Tags search
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param query query string true "Search query"
|
// @Param query query string true "Search query"
|
||||||
// @Param limit query int false "Limit the number of results" default(10)
|
// @Param limit query int false "Limit the number of results" default(10)
|
||||||
// @Param offset query int false "Offset for pagination" default(0)
|
// @Param offset query int false "Offset for pagination" default(0)
|
||||||
// @Success 200 {array} Collection "List of collections"
|
// @Success 200 {array} Collection "List of collections"
|
||||||
// @Failure 400 {object} string "Bad Request"
|
// @Failure 400 {object} string "Bad Request"
|
||||||
// @Failure 500 {object} string "Internal Server Error"
|
// @Failure 500 {object} string "Internal Server Error"
|
||||||
// @Router /search/collections [get]
|
// @Router /search/collections [get]
|
||||||
func (s *Server) collectionSearch(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) collectionSearch(w http.ResponseWriter, r *http.Request) {
|
||||||
q := r.URL.Query().Get("query")
|
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)
|
writeJSON(w, preview, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Searches active records based on a query
|
// @Summary Returns all the Songs of a specific Artist
|
||||||
// @Description Searches active records in the database based on the query parameter
|
// @Tags songs
|
||||||
// @Tags search
|
// @Accept json
|
||||||
// @Accept json
|
// @Produce json
|
||||||
// @Produce json
|
// @Param artist query string true "Artist Name"
|
||||||
// @Param query query string true "Search query"
|
// @Success 200 {array} Song
|
||||||
// @Param limit query int false "Limit the number of results" default(10)
|
// @Failure 400 {object} string "Bad Request"
|
||||||
// @Param offset query int false "Offset for pagination" default(0)
|
// @Failure 500 {object} string "Internal Server Error"
|
||||||
// @Success 200 {object} ActiveSearch "Active search result"
|
// @Router /songs/artist [get]
|
||||||
// @Failure 400 {object} string "Bad Request"
|
func (s *Server) aristsSongs(w http.ResponseWriter, r *http.Request) {
|
||||||
// @Failure 500 {object} string "Internal Server Error"
|
artist := r.URL.Query().Get("artist")
|
||||||
// @Router /search/active [get]
|
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) {
|
func (s *Server) activeSearch(w http.ResponseWriter, r *http.Request) {
|
||||||
q := r.URL.Query().Get("query")
|
q := r.URL.Query().Get("query")
|
||||||
if q == "" {
|
if q == "" {
|
||||||
@@ -261,18 +281,18 @@ func (s *Server) activeSearch(w http.ResponseWriter, r *http.Request) {
|
|||||||
writeJSON(w, recent, http.StatusOK)
|
writeJSON(w, recent, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Searches for artists based on a query
|
// @Summary Searches for artists based on a query
|
||||||
// @Description Searches for artists in the database based on the query parameter
|
// @Description Searches for artists in the database based on the query parameter
|
||||||
// @Tags search
|
// @Tags search
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param query query string true "Search query"
|
// @Param query query string true "Search query"
|
||||||
// @Param limit query int false "Limit the number of results" default(10)
|
// @Param limit query int false "Limit the number of results" default(10)
|
||||||
// @Param offset query int false "Offset for pagination" default(0)
|
// @Param offset query int false "Offset for pagination" default(0)
|
||||||
// @Success 200 {array} string "List of artists"
|
// @Success 200 {object} Artist "List of artists"
|
||||||
// @Failure 400 {object} string "Bad Request"
|
// @Failure 400 {object} string "Bad Request"
|
||||||
// @Failure 500 {object} string "Internal Server Error"
|
// @Failure 500 {object} string "Internal Server Error"
|
||||||
// @Router /search/artist [get]
|
// @Router /search/artist [get]
|
||||||
func (s *Server) artistSearch(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) artistSearch(w http.ResponseWriter, r *http.Request) {
|
||||||
q := r.URL.Query().Get("query")
|
q := r.URL.Query().Get("query")
|
||||||
if q == "" {
|
if q == "" {
|
||||||
@@ -292,16 +312,16 @@ func (s *Server) artistSearch(w http.ResponseWriter, r *http.Request) {
|
|||||||
writeJSON(w, a, http.StatusOK)
|
writeJSON(w, a, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Retrieves a song file by its encoded path
|
// @Summary Retrieves a song file by its encoded path
|
||||||
// @Description Retrieves a song file from the server based on the provided encoded filepath
|
// @Description Retrieves a song file from the server based on the provided encoded filepath
|
||||||
// @Tags files
|
// @Tags files
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param filepath path string true "Base64 encoded file path"
|
// @Param filepath path string true "Base64 encoded file path"
|
||||||
// @Success 200 {file} File "The requested song file"
|
// @Success 200 {file} File "The requested song file"
|
||||||
// @Failure 400 {object} string "Bad Request"
|
// @Failure 400 {object} string "Bad Request"
|
||||||
// @Failure 404 {object} string "File Not Found"
|
// @Failure 404 {object} string "File Not Found"
|
||||||
// @Router /audio/{filepath} [get]
|
// @Router /audio/{filepath} [get]
|
||||||
func (s *Server) songFile(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) songFile(w http.ResponseWriter, r *http.Request) {
|
||||||
f := r.PathValue("filepath")
|
f := r.PathValue("filepath")
|
||||||
if f == "" {
|
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)
|
http.ServeContent(w, r, stat.Name(), stat.ModTime(), file)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Retrieves an image file by its encoded path
|
// @Summary Retrieves an image file by its encoded path
|
||||||
// @Description Retrieves an image file from the server based on the provided encoded filepath
|
// @Description Retrieves an image file from the server based on the provided encoded filepath
|
||||||
// @Tags files
|
// @Tags files
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param filepath path string true "Base64 encoded file path"
|
// @Param filepath path string true "Base64 encoded file path"
|
||||||
// @Success 200 {file} File "The requested image file"
|
// @Success 200 {file} File "The requested image file"
|
||||||
// @Failure 400 {object} string "Bad Request"
|
// @Failure 400 {object} string "Bad Request"
|
||||||
// @Failure 404 {object} string "File Not Found"
|
// @Failure 404 {object} string "File Not Found"
|
||||||
// @Router /image/{filepath} [get]
|
// @Router /image/{filepath} [get]
|
||||||
func (s *Server) imageFile(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) imageFile(w http.ResponseWriter, r *http.Request) {
|
||||||
f := r.PathValue("filepath")
|
f := r.PathValue("filepath")
|
||||||
if f == "" {
|
if f == "" {
|
||||||
|
|||||||
@@ -37,3 +37,10 @@ type ActiveSearch struct {
|
|||||||
Artist string `json:"artist" example:"Ed Sheeran"`
|
Artist string `json:"artist" example:"Ed Sheeran"`
|
||||||
Songs []Song `json:"songs"`
|
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"`
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user