arimelody-web/api/track.go

182 lines
6.2 KiB
Go

package api
import (
"encoding/json"
"fmt"
"net/http"
"arimelody-web/errors"
"arimelody-web/model"
"arimelody-web/model/app"
)
type (
Track struct {
*model.Track
Releases []string `json:"releases"`
}
)
func ServeAllTracks(app *app.AppState) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
type Track struct {
ID string `json:"id"`
Title string `json:"title"`
}
var tracks = []Track{}
var dbTracks = []*model.Track{}
dbTracks, err := app.MusicService.GetAllTracks()
if err != nil {
fmt.Printf("WARN: Failed to pull tracks from DB: %s\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
for _, track := range dbTracks {
tracks = append(tracks, Track{
ID: track.ID,
Title: track.Title,
})
}
w.Header().Add("Content-Type", "application/json")
encoder := json.NewEncoder(w)
encoder.SetIndent("", "\t")
err = encoder.Encode(tracks)
if err != nil {
fmt.Printf("WARN: Failed to serve all tracks: %s\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
})
}
func ServeTrack(app *app.AppState, track *model.Track) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
dbReleases, err := app.MusicService.GetTrackReleases(track.ID)
if err != nil {
fmt.Printf("WARN: Failed to pull track releases for %s from DB: %s\n", track.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
releases := []string{}
for _, release := range dbReleases {
releases = append(releases, release.ID)
}
w.Header().Add("Content-Type", "application/json")
encoder := json.NewEncoder(w)
encoder.SetIndent("", "\t")
err = encoder.Encode(Track{ track, releases })
if err != nil {
fmt.Printf("WARN: Failed to serve track %s: %s\n", track.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
})
}
func CreateTrack(app *app.AppState) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
session := r.Context().Value("session").(*model.Session)
type CreateTrackDTO struct {
Title string `json:"title"`
Description string `json:"description"`
Lyrics string `json:"lyrics"`
}
var dto CreateTrackDTO
err := json.NewDecoder(r.Body).Decode(&dto)
if err != nil {
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
return
}
id, err := app.MusicService.CreateTrack(dto.Title, dto.Description, dto.Lyrics, "")
if err != nil {
if errors.IsValidationError(err) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
fmt.Printf("WARN: Failed to create track: %s\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
app.LogService.Info(model.LOG_MUSIC, "Track \"%s\" (%s) created by \"%s\".", dto.Title, id, session.Account.Username)
w.Header().Add("Content-Type", "text/plain")
w.WriteHeader(http.StatusCreated)
w.Write([]byte(id))
})
}
func UpdateTrack(app *app.AppState, track *model.Track) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
http.NotFound(w, r)
return
}
session := r.Context().Value("session").(*model.Session)
type UpdateTrackDTO struct {
Title string `json:"title"`
Description string `json:"description"`
Lyrics string `json:"lyrics"`
}
var dto UpdateTrackDTO
err := json.NewDecoder(r.Body).Decode(&dto)
if err != nil {
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
return
}
track.Title = dto.Title
track.Description = dto.Description
track.Lyrics = dto.Lyrics
err = app.MusicService.UpdateTrack(track)
if err != nil {
if errors.IsValidationError(err) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
fmt.Printf("WARN: Failed to update track %s: %s\n", track.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
app.LogService.Info(model.LOG_MUSIC, "Track \"%s\" (%s) updated by \"%s\".", track.Title, track.ID, session.Account.Username)
w.Header().Add("Content-Type", "application/json")
encoder := json.NewEncoder(w)
encoder.SetIndent("", "\t")
err = encoder.Encode(track)
if err != nil {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
})
}
func DeleteTrack(app *app.AppState, track *model.Track) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
http.NotFound(w, r)
return
}
session := r.Context().Value("session").(*model.Session)
var trackID = r.URL.Path[1:]
err := app.MusicService.DeleteTrack(trackID)
if err != nil {
if errors.IsNotExistError(err) {
http.NotFound(w, r)
return
}
fmt.Printf("WARN: Failed to delete track %s: %s\n", trackID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
app.LogService.Info(model.LOG_MUSIC, "Track \"%s\" (%s) deleted by \"%s\".", track.Title, track.ID, session.Account.Username)
})
}