Files
NaviWatcher/internal/database/notifications.go
Vladimir Zagainov ce1c39e14b fix: address code review findings
- Preserve MBID and last_synced across periodic artist syncs (INSERT OR
  REPLACE was wiping them, forcing MusicBrainz re-resolution every cycle)
- Exclude unmonitored artists from unnotified-release digest query
- Require telegram.cron_schedule when telegram.enabled is true
- Add same-origin CSRF defense to state-changing web POST routes
- Skip WAL/busy_timeout pragmas for :memory: databases (no-op there)
- Scan mbid as sql.NullString in GetAllArtistSettings to tolerate NULLs
2026-07-19 23:51:15 +03:00

73 lines
2.2 KiB
Go

package database
import (
"fmt"
)
// MarkNotificationSent records that a notification has been sent for the given RGID.
func MarkNotificationSent(db *DB, rgid string) error {
_, err := db.Conn().Exec(
"INSERT INTO notifications_sent (rgid) VALUES (?)",
rgid,
)
if err != nil {
return fmt.Errorf("mark notification sent: %w", err)
}
return nil
}
// IsNotificationSent checks whether a notification has already been sent for the given RGID.
func IsNotificationSent(db *DB, rgid string) (bool, error) {
var count int
err := db.Conn().QueryRow(
"SELECT COUNT(*) FROM notifications_sent WHERE rgid = ?", rgid,
).Scan(&count)
if err != nil {
return false, fmt.Errorf("check notification sent: %w", err)
}
return count > 0, nil
}
// GetUnnotifiedReleases returns all external_release rows for monitored artists
// that have no entry in notifications_sent. Releases belonging to unmonitored
// artists are excluded so the digest honors the monitoring contract.
func GetUnnotifiedReleases(db *DB) ([]ExternalRelease, error) {
rows, err := db.Conn().Query(`
SELECT e.rgid, e.artist_id, e.title, e.type, e.release_date, e.is_ignored
FROM external_releases e
JOIN artist_settings s ON e.artist_id = s.id
LEFT JOIN notifications_sent n ON e.rgid = n.rgid
WHERE s.monitored = 1 AND n.rgid IS NULL AND e.is_ignored = 0
`)
if err != nil {
return nil, fmt.Errorf("query unnotified releases: %w", err)
}
defer rows.Close()
var results []ExternalRelease
for rows.Next() {
var r ExternalRelease
if err := rows.Scan(&r.RGID, &r.ArtistID, &r.Title, &r.Type, &r.ReleaseDate, &r.IsIgnored); err != nil {
return nil, fmt.Errorf("scan unnotified release: %w", err)
}
results = append(results, r)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate unnotified releases: %w", err)
}
return results, nil
}
// GetNotificationSentAt returns the sent_at time for a given RGID.
// Returns sql.ErrNoRows if no notification has been sent.
func GetNotificationSentAt(db *DB, rgid string) (string, error) {
var sentAt string
err := db.Conn().QueryRow(
"SELECT sent_at FROM notifications_sent WHERE rgid = ? ORDER BY sent_at DESC LIMIT 1", rgid,
).Scan(&sentAt)
if err != nil {
return "", err
}
return sentAt, nil
}