Cleanup API responses and add better comments
This commit is contained in:
parent
05cb03ac52
commit
d56b21a3d1
3 changed files with 51 additions and 22 deletions
14
auth.go
14
auth.go
|
@ -5,7 +5,6 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
@ -48,21 +47,14 @@ func getSpotifyToken(clientID string, clientSecret string) (SpotifyToken, error)
|
|||
slog.Error("[GOMUSIC] Failed to authenticate with spotify", "Error", resp.Status)
|
||||
return SpotifyToken{}, fmt.Errorf("Failed to authenticate with spotify: %s", resp.Status)
|
||||
}
|
||||
respData, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
slog.Error("[GOMUSIC] Failed to read response body data from spotify", "Error", err)
|
||||
return SpotifyToken{}, fmt.Errorf("Failed to authenticate with spotify")
|
||||
}
|
||||
// Close this immediately since it's unused now
|
||||
resp.Body.Close()
|
||||
|
||||
var spotifyToken SpotifyToken
|
||||
err = json.Unmarshal(respData, &spotifyToken)
|
||||
err = json.NewDecoder(resp.Body).Decode(&spotifyToken)
|
||||
if err != nil {
|
||||
slog.Error("[GOMUSIC] Failed to parse spotify authentication response", "Error", err)
|
||||
return SpotifyToken{}, fmt.Errorf("Failed to parse spotify JSON response: %w", err)
|
||||
}
|
||||
|
||||
resp.Body.Close()
|
||||
return spotifyToken, nil
|
||||
}
|
||||
|
||||
|
@ -93,8 +85,6 @@ func spotifyAuth(clientID string, clientSecret string) gin.HandlerFunc {
|
|||
|
||||
// Pass the authorization header into context
|
||||
c.Set("spotifyAuthToken", fmt.Sprintf("Bearer %s", spotifyToken.AccessToken))
|
||||
|
||||
// Process the request
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
|
45
database.go
45
database.go
|
@ -3,8 +3,10 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
"gorm.io/driver/sqlite"
|
||||
"encoding/json"
|
||||
"gorm.io/gorm"
|
||||
"log/slog"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ArtistProfile struct {
|
||||
|
@ -22,14 +24,13 @@ type Genre struct {
|
|||
|
||||
func setupTestDatabase(name string) *gorm.DB {
|
||||
slog.Info("[GOMUSIC] Setting up new test database in memory")
|
||||
// Open a named DB instance so each test has a clean environment
|
||||
// Open a named DB instance in memory so each test has a clean environment
|
||||
dbName := fmt.Sprintf("file:%s?mode=memory&cache=shared", name)
|
||||
db, err := gorm.Open(sqlite.Open(dbName), &gorm.Config{})
|
||||
if err != nil {
|
||||
panic("Failed to open database")
|
||||
}
|
||||
|
||||
// Run model migrations here to keep DB consistent
|
||||
db.AutoMigrate(&ArtistProfile{}, &Genre{})
|
||||
return db
|
||||
}
|
||||
|
@ -41,7 +42,45 @@ func setupDatabase() *gorm.DB {
|
|||
panic("Failed to open database")
|
||||
}
|
||||
|
||||
// Run model migrations here to keep DB consistent
|
||||
db.AutoMigrate(&ArtistProfile{}, &Genre{})
|
||||
return 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
|
||||
Popularity int
|
||||
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,
|
||||
Popularity: p.Popularity,
|
||||
Genres: artistGenres,
|
||||
}
|
||||
return json.Marshal(&t)
|
||||
}
|
||||
|
||||
func (g *Genre) MarshalJSON() ([]byte, error) {
|
||||
type CleanedGenre struct {
|
||||
Name string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
t := CleanedGenre{
|
||||
Name: g.Name,
|
||||
CreatedAt: g.CreatedAt,
|
||||
}
|
||||
|
||||
return json.Marshal(&t)
|
||||
}
|
||||
|
|
14
routes.go
14
routes.go
|
@ -23,6 +23,8 @@ func (env *Env) getArtistByID(c *gin.Context) {
|
|||
|
||||
spotifyResponse, err := getSpotifyArtistData(artistID, spotifyAuthToken)
|
||||
if err != nil {
|
||||
// cast the error back into our custom type
|
||||
// so we can get context on why things failed
|
||||
statusCode := err.(*ResponseError).StatusCode
|
||||
switch statusCode {
|
||||
case 404:
|
||||
|
@ -43,16 +45,13 @@ func (env *Env) getArtistByID(c *gin.Context) {
|
|||
genreList = append(genreList, Genre{Name: val})
|
||||
}
|
||||
|
||||
artistProfile := ArtistProfile{
|
||||
artistProfile := &ArtistProfile{
|
||||
SpotifyID: spotifyResponse.ID,
|
||||
Name: spotifyResponse.Name,
|
||||
Popularity: spotifyResponse.Popularity,
|
||||
Genres: genreList,
|
||||
}
|
||||
|
||||
// Create new record
|
||||
// Otherwise update values when artist with this SpotifyID already exists
|
||||
// Basically upsert
|
||||
dbResult := env.db.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "spotify_id"}},
|
||||
UpdateAll: true,
|
||||
|
@ -62,8 +61,7 @@ func (env *Env) getArtistByID(c *gin.Context) {
|
|||
slog.Error("[GOMUSIC] Failed to store response in local database", "Error", err)
|
||||
}
|
||||
|
||||
// Send back our response data
|
||||
c.JSON(http.StatusOK, spotifyResponse)
|
||||
c.JSON(http.StatusOK, artistProfile)
|
||||
}
|
||||
|
||||
func (env *Env) getArtistByName(c *gin.Context) {
|
||||
|
@ -74,12 +72,14 @@ func (env *Env) getArtistByName(c *gin.Context) {
|
|||
}
|
||||
|
||||
// Lookup this name in the DB and return any ArtistProfile objects
|
||||
// This is case insensitive on sqlite
|
||||
var artistProfiles []ArtistProfile
|
||||
dbResult := env.db.Where("name LIKE ?", fmt.Sprintf("%%%s%%", artistName)).Find(&artistProfiles)
|
||||
dbResult := env.db.Where("name LIKE ?", fmt.Sprintf("%%%s%%", artistName)).Preload("Genres").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"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, artistProfiles)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue