helpers.go raw

   1  package directory_client
   2  
   3  import (
   4  	"next.orly.dev/pkg/nostr/encoders/event"
   5  	"next.orly.dev/pkg/protocol/directory"
   6  )
   7  
   8  // EventCollector provides utility methods for collecting specific types of
   9  // directory events from a slice.
  10  type EventCollector struct {
  11  	events []*event.E
  12  }
  13  
  14  // NewEventCollector creates a new event collector for the given events.
  15  func NewEventCollector(events []*event.E) *EventCollector {
  16  	return &EventCollector{events: events}
  17  }
  18  
  19  // RelayIdentities returns all relay identity declarations.
  20  func (ec *EventCollector) RelayIdentities() (identities []*directory.RelayIdentityAnnouncement) {
  21  	identities = make([]*directory.RelayIdentityAnnouncement, 0)
  22  	for _, ev := range ec.events {
  23  		if uint16(ev.Kind) == 39100 {
  24  			if identity, err := directory.ParseRelayIdentityAnnouncement(ev); err == nil {
  25  				identities = append(identities, identity)
  26  			}
  27  		}
  28  	}
  29  	return
  30  }
  31  
  32  // TrustActs returns all trust acts.
  33  func (ec *EventCollector) TrustActs() (acts []*directory.TrustAct) {
  34  	acts = make([]*directory.TrustAct, 0)
  35  	for _, ev := range ec.events {
  36  		if uint16(ev.Kind) == 39101 {
  37  			if act, err := directory.ParseTrustAct(ev); err == nil {
  38  				acts = append(acts, act)
  39  			}
  40  		}
  41  	}
  42  	return
  43  }
  44  
  45  // GroupTagActs returns all group tag acts.
  46  func (ec *EventCollector) GroupTagActs() (acts []*directory.GroupTagAct) {
  47  	acts = make([]*directory.GroupTagAct, 0)
  48  	for _, ev := range ec.events {
  49  		if uint16(ev.Kind) == 39102 {
  50  			if act, err := directory.ParseGroupTagAct(ev); err == nil {
  51  				acts = append(acts, act)
  52  			}
  53  		}
  54  	}
  55  	return
  56  }
  57  
  58  // PublicKeyAdvertisements returns all public key advertisements.
  59  func (ec *EventCollector) PublicKeyAdvertisements() (ads []*directory.PublicKeyAdvertisement) {
  60  	ads = make([]*directory.PublicKeyAdvertisement, 0)
  61  	for _, ev := range ec.events {
  62  		if uint16(ev.Kind) == 39103 {
  63  			if ad, err := directory.ParsePublicKeyAdvertisement(ev); err == nil {
  64  				ads = append(ads, ad)
  65  			}
  66  		}
  67  	}
  68  	return
  69  }
  70  
  71  // ReplicationRequests returns all replication requests.
  72  func (ec *EventCollector) ReplicationRequests() (requests []*directory.DirectoryEventReplicationRequest) {
  73  	requests = make([]*directory.DirectoryEventReplicationRequest, 0)
  74  	for _, ev := range ec.events {
  75  		if uint16(ev.Kind) == 39104 {
  76  			if req, err := directory.ParseDirectoryEventReplicationRequest(ev); err == nil {
  77  				requests = append(requests, req)
  78  			}
  79  		}
  80  	}
  81  	return
  82  }
  83  
  84  // ReplicationResponses returns all replication responses.
  85  func (ec *EventCollector) ReplicationResponses() (responses []*directory.DirectoryEventReplicationResponse) {
  86  	responses = make([]*directory.DirectoryEventReplicationResponse, 0)
  87  	for _, ev := range ec.events {
  88  		if uint16(ev.Kind) == 39105 {
  89  			if resp, err := directory.ParseDirectoryEventReplicationResponse(ev); err == nil {
  90  				responses = append(responses, resp)
  91  			}
  92  		}
  93  	}
  94  	return
  95  }
  96  
  97  // FindRelayIdentity finds a relay identity by relay URL.
  98  func FindRelayIdentity(events []*event.E, relayURL string) (*directory.RelayIdentityAnnouncement, bool) {
  99  	normalizedURL := NormalizeRelayURL(relayURL)
 100  	for _, ev := range events {
 101  		if uint16(ev.Kind) == 39100 {
 102  			if identity, err := directory.ParseRelayIdentityAnnouncement(ev); err == nil {
 103  				if NormalizeRelayURL(identity.RelayURL) == normalizedURL {
 104  					return identity, true
 105  				}
 106  			}
 107  		}
 108  	}
 109  	return nil, false
 110  }
 111  
 112  // FindTrustActsForRelay finds all trust acts targeting a specific relay.
 113  func FindTrustActsForRelay(events []*event.E, targetPubkey string) (acts []*directory.TrustAct) {
 114  	acts = make([]*directory.TrustAct, 0)
 115  	for _, ev := range events {
 116  		if uint16(ev.Kind) == 39101 {
 117  			if act, err := directory.ParseTrustAct(ev); err == nil {
 118  				if act.TargetPubkey == targetPubkey {
 119  					acts = append(acts, act)
 120  				}
 121  			}
 122  		}
 123  	}
 124  	return
 125  }
 126  
 127  // FindGroupTagActsForRelay finds all group tag acts targeting a specific relay.
 128  // Note: This function needs to be updated based on the actual GroupTagAct structure
 129  // which doesn't have a Target field. The filtering logic should be clarified.
 130  func FindGroupTagActsForRelay(events []*event.E, targetPubkey string) (acts []*directory.GroupTagAct) {
 131  	acts = make([]*directory.GroupTagAct, 0)
 132  	for _, ev := range events {
 133  		if uint16(ev.Kind) == 39102 {
 134  			if act, err := directory.ParseGroupTagAct(ev); err == nil {
 135  				// Filter by actor since GroupTagAct doesn't have a Target field
 136  				if act.Actor == targetPubkey {
 137  					acts = append(acts, act)
 138  				}
 139  			}
 140  		}
 141  	}
 142  	return
 143  }
 144  
 145  // FindGroupTagActsByGroup finds all group tag acts for a specific group.
 146  func FindGroupTagActsByGroup(events []*event.E, groupID string) (acts []*directory.GroupTagAct) {
 147  	acts = make([]*directory.GroupTagAct, 0)
 148  	for _, ev := range events {
 149  		if uint16(ev.Kind) == 39102 {
 150  			if act, err := directory.ParseGroupTagAct(ev); err == nil {
 151  				if act.GroupID == groupID {
 152  					acts = append(acts, act)
 153  				}
 154  			}
 155  		}
 156  	}
 157  	return
 158  }
 159  
 160  // TrustGraph represents a directed graph of trust relationships.
 161  type TrustGraph struct {
 162  	// edges maps source pubkey -> list of trust acts
 163  	edges map[string][]*directory.TrustAct
 164  }
 165  
 166  // NewTrustGraph creates a new trust graph instance.
 167  func NewTrustGraph() *TrustGraph {
 168  	return &TrustGraph{
 169  		edges: make(map[string][]*directory.TrustAct),
 170  	}
 171  }
 172  
 173  // AddTrustAct adds a trust act to the graph.
 174  func (tg *TrustGraph) AddTrustAct(act *directory.TrustAct) {
 175  	if act == nil {
 176  		return
 177  	}
 178  	source := string(act.Event.Pubkey)
 179  	tg.edges[source] = append(tg.edges[source], act)
 180  }
 181  
 182  // GetTrustActs returns all trust acts from a source pubkey.
 183  func (tg *TrustGraph) GetTrustActs(source string) []*directory.TrustAct {
 184  	return tg.edges[source]
 185  }
 186  
 187  // GetTrustedBy returns all pubkeys that trust the given target.
 188  func (tg *TrustGraph) GetTrustedBy(target string) []string {
 189  	trustedBy := make([]string, 0)
 190  	for source, acts := range tg.edges {
 191  		for _, act := range acts {
 192  			if act.TargetPubkey == target {
 193  				trustedBy = append(trustedBy, source)
 194  				break
 195  			}
 196  		}
 197  	}
 198  	return trustedBy
 199  }
 200  
 201  // GetTrustTargets returns all pubkeys trusted by the given source.
 202  func (tg *TrustGraph) GetTrustTargets(source string) []string {
 203  	acts := tg.edges[source]
 204  	targets := make(map[string]bool)
 205  	for _, act := range acts {
 206  		targets[act.TargetPubkey] = true
 207  	}
 208  
 209  	result := make([]string, 0, len(targets))
 210  	for target := range targets {
 211  		result = append(result, target)
 212  	}
 213  	return result
 214  }
 215  
 216  // BuildTrustGraph builds a trust graph from a collection of events.
 217  func BuildTrustGraph(events []*event.E) *TrustGraph {
 218  	graph := NewTrustGraph()
 219  	for _, ev := range events {
 220  		if uint16(ev.Kind) == 39101 {
 221  			if act, err := directory.ParseTrustAct(ev); err == nil {
 222  				graph.AddTrustAct(act)
 223  			}
 224  		}
 225  	}
 226  	return graph
 227  }
 228