nostr-poster/internal/api/global_relay_service.go

139 lines
3.4 KiB
Go

// internal/api/global_relay_service.go
package api
import (
"fmt"
"git.sovbit.dev/Enki/nostr-poster/internal/db"
"git.sovbit.dev/Enki/nostr-poster/internal/models"
"go.uber.org/zap"
)
// GlobalRelayService provides functionality for managing global relays
type GlobalRelayService struct {
db *db.DB
logger *zap.Logger
}
// NewGlobalRelayService creates a new GlobalRelayService
func NewGlobalRelayService(db *db.DB, logger *zap.Logger) *GlobalRelayService {
return &GlobalRelayService{
db: db,
logger: logger,
}
}
// GetUserGlobalRelays gets all global relays for a user
func (s *GlobalRelayService) GetUserGlobalRelays(ownerPubkey string) ([]*models.Relay, error) {
query := `
SELECT id, url, read, write, owner_pubkey
FROM global_relays
WHERE owner_pubkey = ?
ORDER BY id
`
var relays []*models.Relay
err := s.db.Select(&relays, query, ownerPubkey)
if err != nil {
return nil, fmt.Errorf("failed to get global relays: %w", err)
}
return relays, nil
}
// AddGlobalRelay adds a global relay for a user
func (s *GlobalRelayService) AddGlobalRelay(relay *models.Relay) error {
query := `
INSERT INTO global_relays (url, read, write, owner_pubkey)
VALUES (?, ?, ?, ?)
`
_, err := s.db.Exec(query, relay.URL, relay.Read, relay.Write, relay.OwnerPubkey)
if err != nil {
return fmt.Errorf("failed to add global relay: %w", err)
}
return nil
}
// UpdateGlobalRelay updates a global relay
func (s *GlobalRelayService) UpdateGlobalRelay(relay *models.Relay) error {
query := `
UPDATE global_relays
SET url = ?, read = ?, write = ?
WHERE id = ? AND owner_pubkey = ?
`
_, err := s.db.Exec(query, relay.URL, relay.Read, relay.Write, relay.ID, relay.OwnerPubkey)
if err != nil {
return fmt.Errorf("failed to update global relay: %w", err)
}
return nil
}
// DeleteGlobalRelay deletes a global relay
func (s *GlobalRelayService) DeleteGlobalRelay(relayID int64, ownerPubkey string) error {
query := `
DELETE FROM global_relays
WHERE id = ? AND owner_pubkey = ?
`
_, err := s.db.Exec(query, relayID, ownerPubkey)
if err != nil {
return fmt.Errorf("failed to delete global relay: %w", err)
}
return nil
}
// GetAllRelaysForPosting gets a combined list of bot-specific and global relays for posting
func (s *GlobalRelayService) GetAllRelaysForPosting(botID int64, ownerPubkey string) ([]*models.Relay, error) {
// First, get bot-specific relays
query1 := `
SELECT id, bot_id, url, read, write
FROM relays
WHERE bot_id = ?
`
var botRelays []*models.Relay
err := s.db.Select(&botRelays, query1, botID)
if err != nil {
return nil, fmt.Errorf("failed to get bot relays: %w", err)
}
// Then, get global relays
query2 := `
SELECT id, url, read, write, owner_pubkey
FROM global_relays
WHERE owner_pubkey = ?
`
var globalRelays []*models.Relay
err = s.db.Select(&globalRelays, query2, ownerPubkey)
if err != nil {
return nil, fmt.Errorf("failed to get global relays: %w", err)
}
// Combine both sets, avoiding duplicates
// We'll consider a relay a duplicate if it has the same URL
urlMap := make(map[string]bool)
var combined []*models.Relay
// Add bot relays first (they take precedence)
for _, relay := range botRelays {
urlMap[relay.URL] = true
combined = append(combined, relay)
}
// Add global relays if they don't conflict
for _, relay := range globalRelays {
if !urlMap[relay.URL] {
// Set the bot ID for consistency
relay.BotID = botID
combined = append(combined, relay)
}
}
return combined, nil
}