package api import ( "errors" "net/http" "time" "github.com/jackc/pgx/v5" "git.fabledsword.com/bvandeusen/minstrel/internal/apierror" "git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq" "git.fabledsword.com/bvandeusen/minstrel/internal/playlists" ) // discoverRefreshResp is the wire shape for POST // /api/playlists/system/discover/refresh. playlist_id is null when // the build succeeded but the user's library yielded no eligible // tracks (degenerate empty-library); track_count is 0 in that case. type discoverRefreshResp struct { PlaylistID *string `json:"playlist_id"` TrackCount int32 `json:"track_count"` } // handleDiscoverRefresh re-runs BuildSystemPlaylists synchronously // for the calling user, then returns the resulting Discover row's // id + track_count. Used by the frontend's refresh affordances on // the detail page header and the home tile kebab. // // Authenticated user only (gated by the authed sub-router's // RequireUser middleware). Each user only ever refreshes their own // Discover — no admin route, no cross-user impersonation. func (h *handlers) handleDiscoverRefresh(w http.ResponseWriter, r *http.Request) { user, ok := requireUser(w, r) if !ok { return } if err := playlists.BuildSystemPlaylists(r.Context(), h.pool, h.logger, user.ID, time.Now(), h.dataDir); err != nil { h.logger.Error("discover refresh: build failed", "user_id", uuidToString(user.ID), "err", err) writeErr(w, apierror.InternalMsg("build failed", err)) return } sysVariant := "discover" pl, err := dbq.New(h.pool).GetSystemPlaylistByVariantForUser(r.Context(), dbq.GetSystemPlaylistByVariantForUserParams{ UserID: user.ID, SystemVariant: &sysVariant, }) if err != nil { if errors.Is(err, pgx.ErrNoRows) { // Build succeeded but no Discover row produced — empty library. writeJSON(w, http.StatusOK, discoverRefreshResp{ PlaylistID: nil, TrackCount: 0, }) return } h.logger.Error("discover refresh: lookup failed", "user_id", uuidToString(user.ID), "err", err) writeErr(w, apierror.InternalMsg("lookup failed", err)) return } idStr := uuidToString(pl.ID) writeJSON(w, http.StatusOK, discoverRefreshResp{ PlaylistID: &idStr, TrackCount: pl.TrackCount, }) }