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.
 
 
 
 
 

104 lines
2.6 KiB

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 using SimplePool
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: 50,
}
logFilter(filter, fmt.Sprintf("feed (kind %d)", fs.feedKind))
// Create context with 30-second timeout
queryCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
logger.WithFields(map[string]interface{}{
"relay": feedRelay,
"kind": fs.feedKind,
"limit": 50,
}).Debug("Fetching feed items using SimplePool")
// Use the client's pool to query the feed relay
// SimplePool handles connection pooling and reuse automatically
eventChan := fs.client.GetPool().SubManyEose(queryCtx, []string{feedRelay}, nostr.Filters{filter})
// Collect events and convert to feed items
items := make([]FeedItem, 0, 50)
for incomingEvent := range eventChan {
if incomingEvent.Event != nil {
item := FeedItem{
EventID: incomingEvent.Event.ID,
Author: incomingEvent.Event.PubKey,
Content: incomingEvent.Event.Content,
Time: time.Unix(int64(incomingEvent.Event.CreatedAt), 0),
Link: fmt.Sprintf("https://alexandria.gitcitadel.eu/events?id=nevent1%s", incomingEvent.Event.ID),
}
// Extract title, summary, and image tags
for _, tag := range incomingEvent.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": incomingEvent.Relay.URL,
"event_id": incomingEvent.Event.ID,
}).Debug("Received feed event")
}
}
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
}