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