arimelody-web/admin/music/releasehttp.go
ari melody 21912d4ec2
refactor mux path routes
legend has it that if you refactor your code enough times, one day you
will finally be happy
2025-11-07 17:48:06 +00:00

251 lines
9.5 KiB
Go

package music
import (
"fmt"
"net/http"
"os"
"strings"
"arimelody-web/admin/core"
"arimelody-web/admin/templates"
"arimelody-web/controller"
"arimelody-web/model"
)
func serveReleases(app *model.AppState) http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/{id}/", func(w http.ResponseWriter, r *http.Request) {
releaseID := r.PathValue("id")
release, err := controller.GetRelease(app.DB, releaseID, true)
if err != nil {
if strings.Contains(err.Error(), "no rows") {
http.NotFound(w, r)
return
}
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch full release data for %s: %s\n", releaseID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
mux := http.NewServeMux()
mux.Handle("/{id}/editcredits", serveEditCredits(release))
mux.Handle("/{id}/addcredit", serveAddCredit(app, release))
mux.Handle("/{id}/newcredit", serveNewCredit(app))
mux.Handle("/{id}/editlinks", serveEditLinks(release))
mux.Handle("/{id}/edittracks", serveEditTracks(release))
mux.Handle("/{id}/addtrack", serveAddTrack(app, release))
mux.Handle("/{id}/newtrack", serveNewTrack(app))
mux.ServeHTTP(w, r)
})
mux.HandleFunc("/{id}", func(w http.ResponseWriter, r *http.Request) {
serveRelease(app, r.PathValue("id")).ServeHTTP(w, r)
})
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
session := r.Context().Value("session").(*model.Session)
type ReleasesData struct {
core.AdminPageData
Releases []*model.Release
}
releases, err := controller.GetAllReleases(app.DB, false, 0, true)
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch releases: %s\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
err = templates.ReleasesTemplate.Execute(w, ReleasesData{
AdminPageData: core.AdminPageData{
Path: r.URL.Path,
Session: session,
},
Releases: releases,
})
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to serve releases page: %s\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
})
return mux
}
func serveRelease(app *model.AppState, releaseID string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
session := r.Context().Value("session").(*model.Session)
release, err := controller.GetRelease(app.DB, releaseID, true)
if err != nil {
if strings.Contains(err.Error(), "no rows") {
http.NotFound(w, r)
return
}
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch full release data for %s: %s\n", releaseID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
type ReleaseResponse struct {
core.AdminPageData
Release *model.Release
}
for i, track := range release.Tracks { track.Number = i + 1 }
err = templates.EditReleaseTemplate.Execute(w, ReleaseResponse{
AdminPageData: core.AdminPageData{ Path: r.URL.Path, Session: session },
Release: release,
})
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to serve admin release page for %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
})
}
func serveEditCredits(release *model.Release) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
err := templates.EditCreditsTemplate.Execute(w, release)
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to serve edit credits component for %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
})
}
func serveAddCredit(app *model.AppState, release *model.Release) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
artists, err := controller.GetArtistsNotOnRelease(app.DB, release.ID)
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch artists not on %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
type response struct {
ReleaseID string;
Artists []*model.Artist
}
w.Header().Set("Content-Type", "text/html")
err = templates.AddCreditTemplate.Execute(w, response{
ReleaseID: release.ID,
Artists: artists,
})
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to serve add credits component for %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
})
}
func serveNewCredit(app *model.AppState) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
split := strings.Split(r.URL.Path, "/")
artistID := split[len(split) - 1]
artist, err := controller.GetArtist(app.DB, artistID)
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch artist %s: %s\n", artistID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
if artist == nil {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", "text/html")
err = templates.NewCreditTemplate.Execute(w, artist)
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to serve new credit component for %s: %s\n", artist.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
})
}
func serveEditLinks(release *model.Release) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
err := templates.EditLinksTemplate.Execute(w, release)
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to serve edit links component for %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
})
}
func serveEditTracks(release *model.Release) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
type editTracksData struct { Release *model.Release }
for i, track := range release.Tracks { track.Number = i + 1 }
err := templates.EditTracksTemplate.Execute(w, editTracksData{ Release: release })
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to serve edit tracks component for %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
})
}
func serveAddTrack(app *model.AppState, release *model.Release) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
tracks, err := controller.GetTracksNotOnRelease(app.DB, release.ID)
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch tracks not on %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
type response struct {
ReleaseID string;
Tracks []*model.Track
}
w.Header().Set("Content-Type", "text/html")
err = templates.AddTrackTemplate.Execute(w, response{
ReleaseID: release.ID,
Tracks: tracks,
})
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to add tracks component for %s: %s\n", release.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
})
}
func serveNewTrack(app *model.AppState) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
split := strings.Split(r.URL.Path, "/")
trackID := split[len(split) - 1]
track, err := controller.GetTrack(app.DB, trackID)
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch track %s: %s\n", trackID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
if track == nil {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", "text/html")
err = templates.NewTrackTemplate.Execute(w, track)
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to serve new track component for %s: %s\n", track.ID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
})
}