// Package sync is the standalone relay-to-relay sync client. // Subscribes to a remote relay and forwards all events to a local relay. package main import ( "fmt" "os" "time" "smesh.lol/pkg/nostr/envelope" "smesh.lol/pkg/nostr/filter" "smesh.lol/pkg/nostr/ws" ) func main() { args := os.Args[1:] if len(args) < 1 { fmt.Fprintln(os.Stderr, "usage: smesh-sync [local-relay-url]") os.Exit(1) } remoteURL := args[0] localURL := "ws://127.0.0.1:3334" if len(args) >= 2 { localURL = args[1] } for { syncOnce(remoteURL, localURL) fmt.Fprintln(os.Stderr, "sync: disconnected, reconnecting in 30s...") time.Sleep(30 * time.Second) } } func syncOnce(remoteURL, localURL string) { fmt.Fprintf(os.Stderr, "sync: connecting to remote %s\n", remoteURL) remote, err := ws.Dial(remoteURL) if err != nil { fmt.Fprintf(os.Stderr, "sync: remote connect error: %v\n", err) return } defer remote.Close() fmt.Fprintf(os.Stderr, "sync: connecting to local %s\n", localURL) local, err := ws.Dial(localURL) if err != nil { fmt.Fprintf(os.Stderr, "sync: local connect error: %v\n", err) return } defer local.Close() f := &filter.F{} req := &envelope.Req{ Subscription: []byte("sync"), Filters: &filter.S{f}, } if err := remote.WriteText(req.Marshal(nil)); err != nil { fmt.Fprintf(os.Stderr, "sync: subscribe error: %v\n", err) return } var forwarded int64 eosed := false for { op, payload, err := remote.ReadMessage() if err != nil { fmt.Fprintf(os.Stderr, "sync: read error (%d forwarded): %v\n", forwarded, err) return } if op == ws.OpClose { fmt.Fprintf(os.Stderr, "sync: remote closed (%d forwarded)\n", forwarded) return } if op != ws.OpText { continue } label, rem, _ := envelope.Identify(payload) switch label { case envelope.EventLabel: var es envelope.EventSubmission if _, err := es.Unmarshal(rem); err != nil { continue } fwd := &envelope.EventSubmission{E: es.E} if err := local.WriteText(fwd.Marshal(nil)); err != nil { fmt.Fprintf(os.Stderr, "sync: local publish error: %v\n", err) return } if _, _, err := local.ReadMessage(); err != nil { fmt.Fprintf(os.Stderr, "sync: local read error: %v\n", err) return } forwarded++ if forwarded%1000 == 0 { fmt.Fprintf(os.Stderr, "sync: %d events forwarded\n", forwarded) } case envelope.EOSELabel: if !eosed { eosed = true fmt.Fprintf(os.Stderr, "sync: EOSE — historical sync complete (%d forwarded). streaming live...\n", forwarded) } } } }