client.go raw
1 package main
2
3 import (
4 "common/jsbridge/sw"
5 "common/nostr"
6 "common/relay"
7 )
8
9 // Relay Proxy — WebSocket connection management.
10 // Receives events from relays, routes them to the Subscription Router.
11
12 var (
13 rpool *relay.Pool
14 writeRelays []string
15 )
16
17 func initRelayProxy() {
18 rpool = relay.NewPool()
19 }
20
21 func getConn(url string) *relay.Conn {
22 c := rpool.Connect(url)
23 wireConn(c, url)
24 return c
25 }
26
27 func wireConn(c *relay.Conn, url string) {
28 c.SetOnEvent(func(_ string, ev *nostr.Event) {
29 routerOnRelayEvent(url, ev)
30 })
31 c.SetOnEOSE(func(subID string) {
32 routerOnRelayEOSE(subID)
33 })
34 c.SetOnOK(func(eventID string, ok bool, msg string) {
35 okStr := "true"
36 if !ok {
37 okStr = "false"
38 }
39 fwdAll("[\"OK\"," + jstr(eventID) + "," + okStr + "," + jstr(msg) + "]")
40 })
41 c.SetOnAuth(func(challenge string) {
42 onRelayAuth(url, challenge)
43 })
44 c.ScheduleReconnect = func(fn func()) {
45 sw.SetTimeout(5000, fn)
46 }
47 }
48
49 func onRelayAuth(relayURL, challenge string) {
50 if myPubkey == "" {
51 return
52 }
53 authEv := &nostr.Event{
54 Kind: 22242,
55 PubKey: myPubkey,
56 Content: "",
57 Tags: nostr.Tags{{"relay", relayURL}, {"challenge", challenge}},
58 CreatedAt: sw.NowSeconds(),
59 }
60 // Proxy signing through shell SW -> signer extension.
61 cryptoProxy("signEvent", "", authEv.ToJSON(), func(signedJSON, errMsg string) {
62 if errMsg != "" || signedJSON == "" {
63 return
64 }
65 c := rpool.Get(relayURL)
66 if c != nil && c.IsOpen() {
67 c.Send("[\"AUTH\"," + signedJSON + "]")
68 }
69 })
70 }
71
72 func relayPublish(ev *nostr.Event) {
73 for _, url := range writeRelays {
74 getConn(url).Publish(ev)
75 }
76 }
77
78 func relayPublishExcept(ev *nostr.Event, exceptURL string) {
79 for _, wr := range writeRelays {
80 if wr != exceptURL {
81 getConn(wr).Publish(ev)
82 }
83 }
84 }
85
86 func urlSuffix(url string) string {
87 n := min(len(url), 8)
88 out := make([]byte, 0, n)
89 for i := len(url) - n; i < len(url); i++ {
90 c := url[i]
91 if (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') {
92 out = append(out, c)
93 }
94 }
95 return string(out)
96 }
97
98 func handleRelayInfo(clientID, relayURL string) {
99 fwd(clientID, "[\"RELAY_INFO\","+jstr(relayURL)+",null]")
100 }
101