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