package nostr import ( "context" "fmt" "time" "gitcitadel-online/internal/logger" "github.com/nbd-wtf/go-nostr" ) // FeedService handles feed operations type FeedService struct { client *Client feedKind int // Feed event kind (from config) } // NewFeedService creates a new feed service func NewFeedService(client *Client, feedKind int) *FeedService { return &FeedService{ client: client, feedKind: feedKind, } } // FetchFeedItems fetches recent feed events from the configured feed relay // Uses the standard ProcessEventsWithCache process func (fs *FeedService) FetchFeedItems(ctx context.Context, feedRelay string, maxEvents int) ([]FeedItem, error) { if feedRelay == "" { return nil, fmt.Errorf("feed relay not configured") } // Use standard process: fetch 2x limit, merge cache, deduplicate, filter deletions, sort, limit, fetch profiles result, err := fs.client.ProcessEventsWithCache(ctx, fs.feedKind, maxEvents, make(map[string]*nostr.Event), feedRelay, "", 0) if err != nil { return nil, fmt.Errorf("failed to process feed events: %w", err) } // Convert events to feed items items := make([]FeedItem, 0, len(result.Events)) for _, event := range result.Events { item := FeedItem{ EventID: event.ID, Author: event.PubKey, Content: event.Content, Time: time.Unix(int64(event.CreatedAt), 0), Link: fmt.Sprintf("https://alexandria.gitcitadel.eu/events?id=nevent1%s", event.ID), } // Extract title, summary, and image tags for _, tag := range event.Tags { if len(tag) > 0 && len(tag) > 1 { switch tag[0] { case "title": item.Title = tag[1] case "summary": item.Summary = tag[1] case "image": item.Image = tag[1] } } } items = append(items, item) } logger.WithFields(map[string]interface{}{ "relay": feedRelay, "items": len(items), }).Info("Successfully fetched feed items") return items, nil } // FeedItem represents a feed item type FeedItem struct { EventID string Author string Content string Time time.Time Link string Title string Summary string Image string }