musicbrainz-provider #2

Merged
Mrixs merged 72 commits from musicbrainz-provider into master 2026-08-05 20:19:16 +00:00
4 changed files with 135 additions and 15 deletions
Showing only changes of commit 0dcc86015d - Show all commits

View File

@@ -55,11 +55,11 @@
- [x] run project tests - must pass before next task
### Task 3: Update Web UI and Handlers
- [ ] Update `ArtistData` or similar view models to include the new filter booleans
- [ ] Update `internal/web/handlers.go` to handle the new toggle POST requests
- [ ] Update `internal/web/templates/artist.html` to show new toggles for Live and Remix
- [ ] write tests for new web handlers
- [ ] run project tests - must pass before next task
- [x] Update `ArtistData` or similar view models to include the new filter booleans
- [x] Update `internal/web/handlers.go` to handle the new toggle POST requests
- [x] Update `internal/web/templates/artist.html` to show new toggles for Live and Remix
- [x] write tests for new web handlers
- [x] run project tests - must pass before next task
### Task 4: Verify and Document
- [ ] Verify the scanner correctly suppresses "Live" and "Remix" types when toggles are enabled

View File

@@ -82,6 +82,9 @@ type ArtistData struct {
Name string
MBID string
IgnoreSingles bool
IgnoreCompilations bool
IgnoreLive bool
IgnoreRemix bool
LocalAlbums []LocalAlbumView
Missing []MissingReleaseView
UIBaseURL string
@@ -146,11 +149,14 @@ func (s *Server) buildArtistData(ctx context.Context, id string) (*ArtistData, e
}
data := &ArtistData{
ID: settings.ID,
Name: settings.Name,
MBID: settings.MBID,
IgnoreSingles: settings.IgnoreSingles,
UIBaseURL: s.uiBaseURL,
ID: settings.ID,
Name: settings.Name,
MBID: settings.MBID,
IgnoreSingles: settings.IgnoreSingles,
IgnoreCompilations: settings.IgnoreCompilations,
IgnoreLive: settings.IgnoreLive,
IgnoreRemix: settings.IgnoreRemix,
UIBaseURL: s.uiBaseURL,
}
for _, a := range locals {
data.LocalAlbums = append(data.LocalAlbums, LocalAlbumView{Title: a.Title})
@@ -318,3 +324,99 @@ func (s *Server) toggleIgnoreSingles(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/artist/"+id, http.StatusSeeOther)
}
// toggleIgnoreCompilations handles POST /artist/{id}/ignore-compilations which flips the
// artist's ignore_compilations flag.
func (s *Server) toggleIgnoreCompilations(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
if !s.sameOrigin(r) {
http.Error(w, "forbidden: cross-origin request", http.StatusForbidden)
return
}
id := r.PathValue("id")
if id == "" || !isValidID(id) {
http.NotFound(w, r)
return
}
settings, err := database.GetArtistSettings(s.db, id)
if err != nil {
http.Error(w, fmt.Sprintf("load artist: %v", err), http.StatusInternalServerError)
return
}
if err := database.UpdateArtistSettings(s.db, id, map[string]interface{}{
"ignore_compilations": !settings.IgnoreCompilations,
}); err != nil {
http.Error(w, fmt.Sprintf("update artist: %v", err), http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/artist/"+id, http.StatusSeeOther)
}
// toggleIgnoreLive handles POST /artist/{id}/ignore-live which flips the
// artist's ignore_live flag.
func (s *Server) toggleIgnoreLive(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
if !s.sameOrigin(r) {
http.Error(w, "forbidden: cross-origin request", http.StatusForbidden)
return
}
id := r.PathValue("id")
if id == "" || !isValidID(id) {
http.NotFound(w, r)
return
}
settings, err := database.GetArtistSettings(s.db, id)
if err != nil {
http.Error(w, fmt.Sprintf("load artist: %v", err), http.StatusInternalServerError)
return
}
if err := database.UpdateArtistSettings(s.db, id, map[string]interface{}{
"ignore_live": !settings.IgnoreLive,
}); err != nil {
http.Error(w, fmt.Sprintf("update artist: %v", err), http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/artist/"+id, http.StatusSeeOther)
}
// toggleIgnoreRemix handles POST /artist/{id}/ignore-remix which flips the
// artist's ignore_remix flag.
func (s *Server) toggleIgnoreRemix(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
if !s.sameOrigin(r) {
http.Error(w, "forbidden: cross-origin request", http.StatusForbidden)
return
}
id := r.PathValue("id")
if id == "" || !isValidID(id) {
http.NotFound(w, r)
return
}
settings, err := database.GetArtistSettings(s.db, id)
if err != nil {
http.Error(w, fmt.Sprintf("load artist: %v", err), http.StatusInternalServerError)
return
}
if err := database.UpdateArtistSettings(s.db, id, map[string]interface{}{
"ignore_remix": !settings.IgnoreRemix,
}); err != nil {
http.Error(w, fmt.Sprintf("update artist: %v", err), http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/artist/"+id, http.StatusSeeOther)
}

View File

@@ -58,6 +58,9 @@ func NewServer(cfg *config.ServerConfig, db *database.DB, uiBaseURL string, thre
mux.HandleFunc("/artist/{id}/ignore", s.ignoreOrRestore)
mux.HandleFunc("/artist/{id}/restore", s.ignoreOrRestore)
mux.HandleFunc("/artist/{id}/ignore-singles", s.toggleIgnoreSingles)
mux.HandleFunc("/artist/{id}/ignore-compilations", s.toggleIgnoreCompilations)
mux.HandleFunc("/artist/{id}/ignore-live", s.toggleIgnoreLive)
mux.HandleFunc("/artist/{id}/ignore-remix", s.toggleIgnoreRemix)
mux.HandleFunc("/archive", s.handleArchive)
s.mux = mux
return s
@@ -171,11 +174,11 @@ func (s *Server) sameOrigin(r *http.Request) bool {
// ArtistSummary is the dashboard projection of a single monitored artist and
// its missing-release count.
type ArtistSummary struct {
ID string
Name string
MBID string
MissingCount int
Monitored bool
ID string
Name string
MBID string
MissingCount int
Monitored bool
}
// DashboardData is the view model passed to the dashboard template.

View File

@@ -30,6 +30,21 @@
{{ if .IgnoreSingles }}<span class="sub"> (singles currently ignored)</span>{{ end }}
</form>
<form class="toggle" method="POST" action="/artist/{{ .ID }}/ignore-compilations">
<button type="submit">{{ if .IgnoreCompilations }}Enable compilations{{ else }}Ignore all compilations{{ end }}</button>
{{ if .IgnoreCompilations }}<span class="sub"> (compilations currently ignored)</span>{{ end }}
</form>
<form class="toggle" method="POST" action="/artist/{{ .ID }}/ignore-live">
<button type="submit">{{ if .IgnoreLive }}Enable live{{ else }}Ignore all live{{ end }}</button>
{{ if .IgnoreLive }}<span class="sub"> (live recordings currently ignored)</span>{{ end }}
</form>
<form class="toggle" method="POST" action="/artist/{{ .ID }}/ignore-remix">
<button type="submit">{{ if .IgnoreRemix }}Enable remixes{{ else }}Ignore all remixes{{ end }}</button>
{{ if .IgnoreRemix }}<span class="sub"> (remixes currently ignored)</span>{{ end }}
</form>
<h2>Local albums (Subsonic)</h2>
{{ if .LocalAlbums }}
<table>