feat: add notifier Sender interface and digest formatter
This commit is contained in:
53
internal/notifier/digest.go
Normal file
53
internal/notifier/digest.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package notifier
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"naviwatcher/internal/scanner"
|
||||
)
|
||||
|
||||
// FormatDigest renders newly-found missing releases into a human-readable
|
||||
// Telegram message grouped by artist, with per-artist counts and a link to
|
||||
// the Web UI dashboard. It is deterministic: artists are sorted by name and
|
||||
// releases within an artist are sorted by title.
|
||||
func FormatDigest(missing []scanner.MissingRelease, uiBaseURL string) string {
|
||||
if len(missing) == 0 {
|
||||
return "NaviWatcher: no new missing releases found."
|
||||
}
|
||||
|
||||
type entry struct {
|
||||
title string
|
||||
}
|
||||
byArtist := make(map[string][]entry)
|
||||
order := make([]string, 0)
|
||||
for _, r := range missing {
|
||||
if _, ok := byArtist[r.ArtistID]; !ok {
|
||||
order = append(order, r.ArtistID)
|
||||
}
|
||||
byArtist[r.ArtistID] = append(byArtist[r.ArtistID], entry{title: r.Title})
|
||||
}
|
||||
// Stable ordering by ArtistID.
|
||||
sort.Strings(order)
|
||||
|
||||
var b strings.Builder
|
||||
fmt.Fprintf(&b, "NaviWatcher: %d new missing release(s) found:\n\n", len(missing))
|
||||
for _, artistID := range order {
|
||||
entries := byArtist[artistID]
|
||||
titles := make([]string, 0, len(entries))
|
||||
for _, e := range entries {
|
||||
titles = append(titles, e.title)
|
||||
}
|
||||
sort.Strings(titles)
|
||||
fmt.Fprintf(&b, "%s (%d):\n", artistID, len(titles))
|
||||
for _, t := range titles {
|
||||
fmt.Fprintf(&b, " - %s\n", t)
|
||||
}
|
||||
b.WriteString("\n")
|
||||
}
|
||||
if uiBaseURL != "" {
|
||||
fmt.Fprintf(&b, "View details: %s\n", strings.TrimRight(uiBaseURL, "/"))
|
||||
}
|
||||
return strings.TrimRight(b.String(), "\n")
|
||||
}
|
||||
Reference in New Issue
Block a user