package api import ( "encoding/json" "fmt" "net/http" "strings" "arimelody.me/arimelody.me/global" "arimelody.me/arimelody.me/music/model" ) type artistJSON struct { ID string `json:"id"` Name *string `json:"name"` Website *string `json:"website"` Avatar *string `json:"avatar"` } func ServeAllArtists() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var artists = []*model.Artist{} err := global.DB.Select(&artists, "SELECT * FROM artist") if err != nil { fmt.Printf("FATAL: Failed to serve all artists: %s\n", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json") err = json.NewEncoder(w).Encode(artists) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } }) } func ServeArtist(artist model.Artist) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { type ( creditJSON struct { Release string `json:"release"` Role string `json:"role"` Primary bool `json:"primary"` } artistJSON struct { model.Artist Credits map[string]creditJSON `json:"credits"` } ) var credits = map[string]creditJSON{} err := global.DB.Select(&credits, "SELECT release,role,is_primary FROM musiccredit WHERE id=$1", artist.ID) if err != nil { fmt.Printf("FATAL: Failed to retrieve artist credits for %s: %s\n", artist.ID, err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json") err = json.NewEncoder(w).Encode(artistJSON{ Artist: artist, Credits: credits, }) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } }) } func CreateArtist() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var data artistJSON err := json.NewDecoder(r.Body).Decode(&data) if err != nil { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } if data.ID == "" { http.Error(w, "Artist ID cannot be blank\n", http.StatusBadRequest) return } if data.Name == nil || *data.Name == "" { http.Error(w, "Artist name cannot be blank\n", http.StatusBadRequest) return } var artist = model.Artist{ ID: data.ID, Name: *data.Name, Website: *data.Website, Avatar: *data.Avatar, } _, err = global.DB.Exec( "INSERT INTO artist (id, name, website, avatar) "+ "VALUES ($1, $2, $3, $4)", artist.ID, artist.Name, artist.Website, artist.Avatar) if err != nil { if strings.Contains(err.Error(), "duplicate key") { http.Error(w, fmt.Sprintf("Artist %s already exists\n", data.ID), http.StatusBadRequest) return } fmt.Printf("FATAL: Failed to create artist %s: %s\n", artist.ID, err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.WriteHeader(http.StatusCreated) }) } func UpdateArtist(artist model.Artist) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var data artistJSON err := json.NewDecoder(r.Body).Decode(&data) if err != nil { fmt.Printf("FATAL: Failed to update artist: %s\n", err) http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } if data.ID != "" { artist.ID = data.ID } if data.Name != nil { artist.Name = *data.Name } if data.Website != nil { artist.Website = *data.Website } if data.Avatar != nil { artist.Avatar = *data.Avatar } _, err = global.DB.Exec( "UPDATE artist "+ "SET name=$2, website=$3, avatar=$4 "+ "WHERE id=$1", artist.ID, artist.Name, artist.Website, artist.Avatar) if err != nil { fmt.Printf("FATAL: Failed to update artist %s: %s\n", artist.ID, err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } }) } func DeleteArtist(artist model.Artist) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, err := global.DB.Exec( "DELETE FROM artist "+ "WHERE id=$1", artist.ID) if err != nil { fmt.Printf("FATAL: Failed to delete artist %s: %s\n", artist.ID, err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } }) }