This commit is contained in:
2026-08-23 14:13:18 -05:00
parent 789bf91eed
commit 866f243f1b
37 changed files with 1761 additions and 58 deletions
+50 -4
View File
@@ -2,6 +2,7 @@ package web
import (
"context"
"fmt"
"net/http"
"net/url"
"time"
@@ -283,10 +284,10 @@ func (h *Web) handleAdminScanner(w http.ResponseWriter, r *http.Request) {
// --- System settings ---
func (h *Web) handleAdminSettings(w http.ResponseWriter, r *http.Request) {
h.renderAdminSettings(w, r, "", "")
h.renderAdminSettings(w, r, "", "", nil)
}
func (h *Web) renderAdminSettings(w http.ResponseWriter, r *http.Request, flash, kind string) {
func (h *Web) renderAdminSettings(w http.ResponseWriter, r *http.Request, flash, kind string, photoResults []ArtistPhotoOutcome) {
trusted := ""
for i, p := range h.Config.ExtAuth.TrustedSources {
if i > 0 {
@@ -301,6 +302,8 @@ func (h *Web) renderAdminSettings(w http.ResponseWriter, r *http.Request, flash,
ExtAuthEnabled bool
ExtAuthTrustedSources string
ExtAuthHeader string
ArtistPhotosEnabled bool
ArtistPhotoResults []ArtistPhotoOutcome
}{
ScanInterval: database.GetSetting(h.DB, "scan_interval", h.Config.ScanInterval.String()),
FFmpegPath: database.GetSetting(h.DB, "ffmpeg_path", h.Config.FFmpegPath),
@@ -308,6 +311,8 @@ func (h *Web) renderAdminSettings(w http.ResponseWriter, r *http.Request, flash,
ExtAuthEnabled: h.Config.ExtAuth.Enabled,
ExtAuthTrustedSources: trusted,
ExtAuthHeader: h.Config.ExtAuth.UserHeader,
ArtistPhotosEnabled: h.Config.EnableArtistPhotos,
ArtistPhotoResults: photoResults,
})
}
@@ -318,11 +323,52 @@ func (h *Web) handleAdminSettingsUpdate(w http.ResponseWriter, r *http.Request)
}
interval := r.FormValue("scan_interval")
if _, err := time.ParseDuration(interval); err != nil {
h.renderAdminSettings(w, r, "Invalid scan interval: "+err.Error(), "danger")
h.renderAdminSettings(w, r, "Invalid scan interval: "+err.Error(), "danger", nil)
return
}
_ = database.SetSetting(h.DB, "scan_interval", interval)
_ = database.SetSetting(h.DB, "ffmpeg_path", r.FormValue("ffmpeg_path"))
_ = database.SetSetting(h.DB, "ffprobe_path", r.FormValue("ffprobe_path"))
h.renderAdminSettings(w, r, "Settings saved. Some changes take effect after a restart.", "success")
h.renderAdminSettings(w, r, "Settings saved. Some changes take effect after a restart.", "success", nil)
}
// handleAdminArtistPhotosRefresh runs a synchronous, admin-triggered
// fetch of every eligible artist's photo and reports the outcome for
// each one — including failures — rather than the silent best-effort
// background fetch normally used when an artist's page is viewed.
func (h *Web) handleAdminArtistPhotosRefresh(w http.ResponseWriter, r *http.Request) {
// Unlike the best-effort background fetch on an artist's page (gated
// by EnableArtistPhotos, since that one runs unattended on every
// visit), this is an explicit, one-off admin action — it runs
// regardless of the config toggle so it doubles as a way to check
// what's actually happening (bad network, no confident name match,
// an API error) without editing the environment first.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()
results, err := h.RefreshAllArtistPhotos(ctx)
if err != nil {
h.renderAdminSettings(w, r, "Artist photo refresh failed: "+err.Error(), "danger", nil)
return
}
var fetched, notFound, skipped, failed int
for _, res := range results {
switch {
case res.Error != "":
failed++
case res.Status == "fetched":
fetched++
case res.Status == "no photo found":
notFound++
default:
skipped++
}
}
kind := "success"
if failed > 0 {
kind = "warning"
}
flash := fmt.Sprintf("Artist photo refresh complete: %d fetched, %d no photo found, %d skipped, %d failed (see below).",
fetched, notFound, skipped, failed)
h.renderAdminSettings(w, r, flash, kind, results)
}