package api import ( "encoding/json" "fmt" "net/http" "arimelody.me/arimelody.me/global" "arimelody.me/arimelody.me/music/model" controller "arimelody.me/arimelody.me/music/controller" ) 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) { w.Header().Add("Content-Type", "application/json") err := json.NewEncoder(w).Encode(global.Artists) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } }) } func ServeArtist() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/" { ServeAllArtists().ServeHTTP(w, r) return } type ( creditJSON struct { Role string `json:"role"` Primary bool `json:"primary"` } artistJSON struct { model.Artist Credits map[string]creditJSON `json:"credits"` } ) var artist = artistJSON{} artist.ID = r.URL.Path[1:] var a = global.GetArtist(artist.ID) if a == nil { http.NotFound(w, r) return } artist.Name = a.Name artist.Website = a.Website artist.Credits = make(map[string]creditJSON) for _, release := range global.Releases { for _, credit := range release.Credits { if credit.Artist.ID != artist.ID { continue } artist.Credits[release.ID] = creditJSON{ Role: credit.Role, Primary: credit.Primary, } } } w.Header().Add("Content-Type", "application/json") err := json.NewEncoder(w).Encode(artist) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } }) } func CreateArtist() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.NotFound(w, r) return } var data artistJSON err := json.NewDecoder(r.Body).Decode(&data) if err != nil { fmt.Printf("Failed to create artist: %s\n", err) 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 } if global.GetArtist(data.ID) != nil { http.Error(w, fmt.Sprintf("Artist %s already exists\n", data.ID), http.StatusBadRequest) return } var artist = model.Artist{ ID: data.ID, Name: *data.Name, Website: *data.Website, Avatar: *data.Avatar, } err = controller.CreateArtistDB(global.DB, &artist) if err != nil { fmt.Printf("Failed to create artist %s: %s\n", artist.ID, err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } global.Artists = append(global.Artists, &artist) w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) err = json.NewEncoder(w).Encode(artist) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } }) } func UpdateArtist() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPut { http.NotFound(w, r) return } if r.URL.Path == "/" { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } var data artistJSON err := json.NewDecoder(r.Body).Decode(&data) if err != nil { fmt.Printf("Failed to update artist: %s\n", err) http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } var artistID = r.URL.Path[1:] var artist = global.GetArtist(artistID) if artist == nil { http.Error(w, fmt.Sprintf("Artist %s does not exist\n", artistID), http.StatusBadRequest) return } var update = *artist if data.ID != "" { update.ID = data.ID } if data.Name != nil { update.Name = *data.Name } if data.Website != nil { update.Website = *data.Website } if data.Avatar != nil { update.Avatar = *data.Avatar } err = controller.UpdateArtistDB(global.DB, &update) if err != nil { fmt.Printf("Failed to update artist %s: %s\n", artist.ID, err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } artist.ID = update.ID artist.Name = update.Name artist.Website = update.Website artist.Avatar = update.Avatar w.Header().Add("Content-Type", "application/json") err = json.NewEncoder(w).Encode(artist) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } }) } func DeleteArtist() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodDelete { http.NotFound(w, r) return } if r.URL.Path == "/" { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } var artistID = r.URL.Path[1:] var artist = global.GetArtist(artistID) if artist == nil { http.Error(w, fmt.Sprintf("Artist %s does not exist\n", artistID), http.StatusBadRequest) return } err := controller.DeleteArtistDB(global.DB, artist) if err != nil { fmt.Printf("Failed to delete artist %s: %s\n", artist.ID, err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } global.Artists = func () []*model.Artist { var artists = []*model.Artist{} for _, a := range global.Artists { if a.ID == artist.ID { continue } artists = append(artists, a) } return artists }() w.WriteHeader(http.StatusOK) w.Write([]byte(fmt.Sprintf("Artist %s has been deleted\n", artist.ID))) }) }