fix: address code review findings

- notifier: show artist display names (not internal IDs) in digest; resolve
  names from artist_settings and fall back to ID when unavailable
- notifier: skip sending an empty digest to avoid daily spam
- config: require telegram token/chat_id when enabled
- web: warn loudly when auth is disabled on a non-loopback bind; add HTTP
  server timeouts
- web: treat SetReleaseIgnored "release not found" as benign redirect (0 rows)
- musicbrainz: reject low-score/name-mismatched MBID resolutions instead of
  silently caching the wrong artist
- database: remove dead duplicate err check; harden DSN param appending
- musicbrainz: check rows.Err() after iterating existing releases
This commit is contained in:
2026-07-19 23:46:05 +03:00
parent 389d177d85
commit 7cdb473d9c
12 changed files with 189 additions and 22 deletions

View File

@@ -16,8 +16,10 @@ import (
// Releases already present in notifications_sent are excluded upstream by
// GetUnnotifiedReleases, so this is idempotent across runs.
//
// If there are no unnotified releases the digest reports "no new missing
// releases" and nothing is marked sent (there is nothing to mark).
// If there are no unnotified releases nothing is sent (the caller's scheduler
// is responsible for not spamming the operator with an empty digest). When
// releases are present, each is marked sent so a subsequent run will not
// re-notify it.
//
// uiBaseURL is the externally-reachable base URL of the Web UI, appended to the
// digest so operators can jump to the dashboard.
@@ -42,7 +44,28 @@ func NotifyOnce(ctx context.Context, db *database.DB, sender Sender, cfg config.
})
}
message := FormatDigest(missing, uiBaseURL)
// Resolve human-readable artist names so the digest shows recognizable
// labels instead of opaque internal artist IDs. A lookup failure for a
// single artist must not abort the whole digest, so errors are ignored and
// that artist falls back to its ID via artistLabel.
names := make(map[string]string, len(missing))
for _, r := range unnotified {
if _, ok := names[r.ArtistID]; ok {
continue
}
settings, err := database.GetArtistSettings(db, r.ArtistID)
if err == nil && settings.Name != "" {
names[r.ArtistID] = settings.Name
}
}
message := FormatDigest(missing, uiBaseURL, names)
// Nothing to report: skip sending so the operator is not spammed with an
// empty digest on every cron fire. The startup fire likewise stays quiet
// until the first genuinely missing release appears.
if len(unnotified) == 0 {
return 0, nil
}
if err := sender.Send(ctx, message); err != nil {
return 0, fmt.Errorf("notifier: send digest: %w", err)
}