diff --git a/database.go b/database.go index 1144273..cd6e442 100644 --- a/database.go +++ b/database.go @@ -1,9 +1,9 @@ package main import ( + "encoding/json" "fmt" "gorm.io/driver/sqlite" - "encoding/json" "gorm.io/gorm" "log/slog" "time" @@ -48,37 +48,37 @@ func setupDatabase() *gorm.DB { // Some functions to control JSON marshalling of DB structs func (p *ArtistProfile) MarshalJSON() ([]byte, error) { - type CleanedProfile struct { - UpdatedAt time.Time - SpotifyID string - Name string + type CleanedProfile struct { + UpdatedAt time.Time + SpotifyID string + Name string Popularity int - Genres []string - } + Genres []string + } artistGenres := make([]string, 0, len(p.Genres)) for _, val := range p.Genres { artistGenres = append(artistGenres, val.Name) } - t := CleanedProfile{ - UpdatedAt: p.UpdatedAt, - SpotifyID: p.SpotifyID, - Name: p.Name, + t := CleanedProfile{ + UpdatedAt: p.UpdatedAt, + SpotifyID: p.SpotifyID, + Name: p.Name, Popularity: p.Popularity, - Genres: artistGenres, - } - return json.Marshal(&t) + Genres: artistGenres, + } + return json.Marshal(&t) } func (g *Genre) MarshalJSON() ([]byte, error) { type CleanedGenre struct { - Name string + Name string CreatedAt time.Time } t := CleanedGenre{ - Name: g.Name, + Name: g.Name, CreatedAt: g.CreatedAt, } diff --git a/main.go b/main.go index 52cf55e..ddd289e 100644 --- a/main.go +++ b/main.go @@ -27,6 +27,8 @@ func setupRouter(env *Env, spotifyID string, spotifySecret string) *gin.Engine { r.GET("/artists/:artistID", env.getArtistByID) r.GET("/artists", env.getArtistByName) r.GET("/genres", env.getGenres) + + // POST create endpoint r.POST("/genres", env.createGenre) return r } diff --git a/routes.go b/routes.go index 58236b6..10c0152 100644 --- a/routes.go +++ b/routes.go @@ -17,7 +17,7 @@ func paginator() gin.HandlerFunc { queryPageSize := c.DefaultQuery("page_size", "10") // add some defaults here if user gives us empty values - if queryPage == ""{ + if queryPage == "" { queryPage = "1" } if queryPageSize == "" { @@ -38,8 +38,12 @@ func paginator() gin.HandlerFunc { return } - if page < 1 || pageSize < 1 { - page, pageSize = 1, 10 + if page < 1 { + page = 1 + } + + if pageSize < 10 { + pageSize = 10 } // Calculate the correct SQL offset for this page @@ -123,7 +127,8 @@ func (env *Env) getArtistByName(c *gin.Context) { // NOTE: However unicode is treated case sensitive due to very difficult conversions for some languages/characters // NOTE: In future better DBs with unicode support such as postgres should be used var artistProfiles []ArtistProfile - dbResult := env.db.Where("name LIKE ?", fmt.Sprintf("%%%s%%", artistName)).Preload("Genres").Offset(pageOffset).Limit(pageSize).Find(&artistProfiles) + searchString := fmt.Sprintf("%%%s%%"), artistName) + dbResult := env.db.Where("name LIKE ?", searchString).Preload("Genres").Offset(pageOffset).Limit(pageSize).Find(&artistProfiles) if dbResult.Error != nil { slog.Error("[GOMUSIC] Failed to query local database for artist name", "Name", artistName) c.JSON(http.StatusInternalServerError, gin.H{"Error": "Failed to lookup name"}) @@ -156,12 +161,12 @@ func (env *Env) getGenres(c *gin.Context) { c.JSON(http.StatusOK, genreList) } -func (env *Env) createGenre(c * gin.Context) { +func (env *Env) createGenre(c *gin.Context) { var userGenre Genre if c.ShouldBind(&userGenre) == nil { // If we didn't get the correct data abort early if userGenre.Name == "" { - c.JSON(http.StatusBadRequest, gin.H{"Error":"Could not find genre name"}) + c.JSON(http.StatusBadRequest, gin.H{"Error": "Could not find genre name"}) return } dbResult := env.db.Clauses(clause.OnConflict{ @@ -175,5 +180,5 @@ func (env *Env) createGenre(c * gin.Context) { c.String(http.StatusOK, "Success") return } - c.JSON(http.StatusInternalServerError, gin.H{"Error":"Failed to parse input data"}) + c.JSON(http.StatusInternalServerError, gin.H{"Error": "Failed to parse input data"}) } diff --git a/routes_test.go b/routes_test.go index f51a7ba..abfb125 100644 --- a/routes_test.go +++ b/routes_test.go @@ -6,16 +6,16 @@ import ( "github.com/stretchr/testify/assert" "net/http" "net/http/httptest" - "testing" "strings" + "testing" ) // Define some custom types to make response parsing easier type SearchResponse struct { - SpotifyID string - Name string + SpotifyID string + Name string Popularity int - Genres []string + Genres []string } type SearchResponseList []SearchResponse @@ -213,10 +213,10 @@ func TestGetPaginatedArtistByName(t *testing.T) { for i := 0; i < 100; i++ { testName := fmt.Sprintf("test%d", i) testArtist := ArtistProfile{ - Name: testName, - SpotifyID: testName, + Name: testName, + SpotifyID: testName, Popularity: i, - Genres: []Genre{ Genre{Name: testName} }, + Genres: []Genre{Genre{Name: testName}}, } testData = append(testData, testArtist) }