You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

99 lines
2.7 KiB

package nostr
import (
"context"
"fmt"
"log"
"time"
"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 only, with retries
func (fs *FeedService) FetchFeedItems(ctx context.Context, feedRelay string, maxEvents int) ([]FeedItem, error) {
if feedRelay == "" {
return nil, fmt.Errorf("feed relay not configured")
}
filter := nostr.Filter{
Kinds: []int{fs.feedKind},
Limit: maxEvents,
}
logFilter(filter, fmt.Sprintf("feed (kind %d)", fs.feedKind))
const maxRetries = 3
var lastErr error
// Retry up to 3 times for the configured feed relay only
for attempt := 1; attempt <= maxRetries; attempt++ {
if attempt > 1 {
log.Printf("Retrying feed relay %s (attempt %d/%d)", feedRelay, attempt, maxRetries)
// Wait a bit before retrying (exponential backoff: 1s, 2s)
waitTime := time.Duration(attempt-1) * time.Second
time.Sleep(waitTime)
}
// Create a context with timeout for this attempt
attemptCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
// Connect to the relay
relayConn, err := fs.client.ConnectToRelay(attemptCtx, feedRelay)
if err != nil {
log.Printf("Failed to connect to feed relay %s (attempt %d/%d): %v", feedRelay, attempt, maxRetries, err)
lastErr = err
cancel()
continue // Try next attempt
}
// Try to fetch events
events, err := relayConn.QuerySync(attemptCtx, filter)
relayConn.Close()
cancel()
if err != nil {
log.Printf("Failed to fetch feed events from %s (attempt %d/%d): %v", feedRelay, attempt, maxRetries, err)
lastErr = err
continue // Try next attempt
}
// Success! Convert events to feed items
items := make([]FeedItem, 0, len(events))
for _, event := range events {
item := FeedItem{
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),
}
items = append(items, item)
}
log.Printf("Successfully fetched %d feed items from %s (attempt %d/%d)", len(items), feedRelay, attempt, maxRetries)
return items, nil
}
// All retries failed
return nil, fmt.Errorf("failed to fetch feed from %s after %d retries (last error: %w)", feedRelay, maxRetries, lastErr)
}
// FeedItem represents a feed item
type FeedItem struct {
Author string
Content string
Time time.Time
Link string
}