client.mx raw
1 package main
2
3 import (
4 "smesh.lol/web/common/jsbridge/sw"
5 "smesh.lol/web/common/nostr"
6 "smesh.lol/web/common/relay"
7 )
8
9 // Relay proxy: WebSocket connection management.
10
11 var (
12 rpool *relay.Pool
13 writeRelays []string
14 )
15
16 func initRelayProxy() {
17 rpool = relay.NewPool()
18 }
19
20 func getConn(url string) *relay.Conn {
21 c := rpool.Connect(url)
22 wireConn(c, url)
23 return c
24 }
25
26 func wireConn(c *relay.Conn, url string) {
27 c.SetOnEvent(func(subID string, ev *nostr.Event) {
28 routerOnRelayEvent(url, subID, ev)
29 })
30 c.SetOnEOSE(func(subID string) {
31 routerOnRelayEOSE(subID)
32 })
33 c.SetOnOK(func(eventID string, ok bool, msg string) {
34 okStr := "true"
35 if !ok {
36 okStr = "false"
37 }
38 broadcastToClients("[\"OK\"," + jstr(eventID) + "," + okStr + "," + jstr(msg) + "]")
39 })
40 c.SetOnAuth(func(challenge string) {
41 onRelayAuth(url, challenge)
42 })
43 }
44
45 func onRelayAuth(relayURL, challenge string) {
46 if !hasKey || myPubkey == "" {
47 return
48 }
49 authEv := &nostr.Event{
50 Kind: 22242,
51 Content: "",
52 Tags: nostr.Tags{{"relay", relayURL}, {"challenge", challenge}},
53 CreatedAt: sw.NowSeconds(),
54 }
55 if !identitySignEvent(authEv) {
56 return
57 }
58 c := rpool.Get(relayURL)
59 if c != nil && c.IsOpen() {
60 c.Send("[\"AUTH\"," + authEv.ToJSON() + "]")
61 }
62 }
63
64 func relayPublish(ev *nostr.Event) {
65 for _, url := range writeRelays {
66 getConn(url).Publish(ev)
67 }
68 }
69
70 func urlSuffix(url string) string {
71 n := min(len(url), 8)
72 out := []byte{:0:n}
73 for i := len(url) - n; i < len(url); i++ {
74 c := url[i]
75 if (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') {
76 out = append(out, c)
77 }
78 }
79 return string(out)
80 }
81
82 func handleRelayInfo(clientID, relayURL string) {
83 httpURL := relayURL
84 if len(httpURL) > 6 && httpURL[:6] == "wss://" {
85 httpURL = "https://" + httpURL[6:]
86 } else if len(httpURL) > 5 && httpURL[:5] == "ws://" {
87 httpURL = "http://" + httpURL[5:]
88 }
89 sw.Fetch(httpURL, func(resp sw.Response, ok bool) {
90 sendToClient(clientID, "[\"RELAY_INFO\","+jstr(relayURL)+",null]")
91 })
92 }
93