package scrobble import ( "context" "errors" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" "git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq" ) // MaybeEnqueue inserts a scrobble_queue row for the given play_event if: // 1. The user has listenbrainz_enabled = true with a non-empty token. // 2. The play_event passes Qualifies(). // // Idempotent via UNIQUE(play_event_id) — re-runs are no-ops. // // Best-effort: callers (the playevents.Writer hooks) should log returned // errors but not propagate them, since scrobble delivery is enrichment // and must not block the canonical play history. func MaybeEnqueue(ctx context.Context, q *dbq.Queries, playEventID pgtype.UUID) error { pe, err := q.GetPlayEventByID(ctx, playEventID) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return nil } return err } // Only closed events qualify (DurationPlayedMs/CompletionRatio populated). if pe.DurationPlayedMs == nil || pe.CompletionRatio == nil { return nil } if !Qualifies(int(*pe.DurationPlayedMs), *pe.CompletionRatio) { return nil } cfg, err := q.GetListenBrainzConfig(ctx, pe.UserID) if err != nil { return err } if !cfg.ListenbrainzEnabled || cfg.ListenbrainzToken == nil || *cfg.ListenbrainzToken == "" { return nil } _, err = q.EnqueueScrobble(ctx, dbq.EnqueueScrobbleParams{ UserID: pe.UserID, PlayEventID: pe.ID, }) return err }