Files
icecast-ripper/internal/rss/rss.go
2025-04-07 12:47:36 +03:00

93 lines
2.4 KiB
Go

package rss
import (
"fmt"
"log/slog"
"net/url"
"strings"
"time"
"github.com/gorilla/feeds"
"github.com/kemko/icecast-ripper/internal/config"
"github.com/kemko/icecast-ripper/internal/filestore"
)
// Generator creates RSS feeds
type Generator struct {
fileStore *filestore.Store
feedBaseURL string
recordingsPath string
feedTitle string
feedDesc string
}
// New creates a new RSS Generator instance
func New(fileStore *filestore.Store, cfg *config.Config, title, description string) *Generator {
baseURL := cfg.RSSFeedURL
if baseURL == "" {
slog.Warn("RSS_FEED_URL not set, using default")
baseURL = "http://localhost:8080/recordings/"
}
// Ensure base URL ends with a slash
if !strings.HasSuffix(baseURL, "/") {
baseURL += "/"
}
return &Generator{
fileStore: fileStore,
feedBaseURL: baseURL,
recordingsPath: cfg.RecordingsPath,
feedTitle: title,
feedDesc: description,
}
}
// GenerateFeed produces the RSS feed XML as a byte slice
func (g *Generator) GenerateFeed(maxItems int) ([]byte, error) {
recordings, err := g.fileStore.GetRecordedFiles(maxItems)
if err != nil {
return nil, fmt.Errorf("failed to get recorded files: %w", err)
}
feed := &feeds.Feed{
Title: g.feedTitle,
Link: &feeds.Link{Href: g.feedBaseURL},
Description: g.feedDesc,
Created: time.Now(),
}
feed.Items = make([]*feeds.Item, 0, len(recordings))
for _, rec := range recordings {
fileURL, err := url.JoinPath(g.feedBaseURL, rec.Filename)
if err != nil {
slog.Error("Failed to create file URL", "filename", rec.Filename, "error", err)
continue
}
item := &feeds.Item{
Title: fmt.Sprintf("Recording %s", rec.RecordedAt.Format("2006-01-02 15:04")),
Link: &feeds.Link{Href: fileURL},
Description: fmt.Sprintf("Icecast stream recording from %s. Duration: %s",
rec.RecordedAt.Format(time.RFC1123), rec.Duration.String()),
Created: rec.RecordedAt,
Id: rec.Hash,
Enclosure: &feeds.Enclosure{
Url: fileURL,
Length: fmt.Sprintf("%d", rec.FileSize), // Convert int64 to string
Type: "audio/mpeg",
},
}
feed.Items = append(feed.Items, item)
}
rssFeed, err := feed.ToRss()
if err != nil {
return nil, fmt.Errorf("failed to generate RSS feed: %w", err)
}
slog.Debug("RSS feed generated", "itemCount", len(feed.Items))
return []byte(rssFeed), nil
}