diff --git a/bunker.go b/bunker.go index 0787e18..12e8e32 100644 --- a/bunker.go +++ b/bunker.go @@ -49,7 +49,7 @@ var bunker = &cli.Command{ qs := url.Values{} relayURLs := make([]string, 0, c.Args().Len()) if relayUrls := c.Args().Slice(); len(relayUrls) > 0 { - relays := connectToAllRelays(ctx, relayUrls, nil) + relays := connectToAllRelays(ctx, c, relayUrls, nil) if len(relays) == 0 { log("failed to connect to any of the given relays.\n") os.Exit(3) diff --git a/count.go b/count.go index 26157b0..c01b65e 100644 --- a/count.go +++ b/count.go @@ -70,7 +70,7 @@ var count = &cli.Command{ biggerUrlSize := 0 relayUrls := c.Args().Slice() if len(relayUrls) > 0 { - relays := connectToAllRelays(ctx, relayUrls, nil) + relays := connectToAllRelays(ctx, c, relayUrls, nil) if len(relays) == 0 { log("failed to connect to any of the given relays.\n") os.Exit(3) diff --git a/dvm.go b/dvm.go index 88ed9cc..5e05e39 100644 --- a/dvm.go +++ b/dvm.go @@ -7,7 +7,6 @@ import ( "strconv" "strings" - "github.com/fatih/color" "github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr/nip90" "github.com/urfave/cli/v3" @@ -60,7 +59,7 @@ var dvm = &cli.Command{ Flags: flags, Action: func(ctx context.Context, c *cli.Command) error { relayUrls := c.StringSlice("relay") - relays := connectToAllRelays(ctx, relayUrls, nil) + relays := connectToAllRelays(ctx, c, relayUrls, nil) if len(relays) == 0 { log("failed to connect to any of the given relays.\n") os.Exit(3) @@ -103,10 +102,7 @@ var dvm = &cli.Command{ log("- publishing job request... ") first := true for res := range sys.Pool.PublishMany(ctx, relayUrls, evt) { - cleanUrl, ok := strings.CutPrefix(res.RelayURL, "wss://") - if !ok { - cleanUrl = res.RelayURL - } + cleanUrl, _ := strings.CutPrefix(res.RelayURL, "wss://") if !first { log(", ") @@ -114,9 +110,9 @@ var dvm = &cli.Command{ first = false if res.Error != nil { - log("%s: %s", color.RedString(cleanUrl), res.Error) + log("%s: %s", colors.errorf(cleanUrl), res.Error) } else { - log("%s: ok", color.GreenString(cleanUrl)) + log("%s: ok", colors.successf(cleanUrl)) } } diff --git a/event.go b/event.go index 5bae947..f4b86bb 100644 --- a/event.go +++ b/event.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "github.com/fatih/color" "github.com/mailru/easyjson" "github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr/nip13" @@ -133,8 +134,17 @@ example: Action: func(ctx context.Context, c *cli.Command) error { // try to connect to the relays here var relays []*nostr.Relay + + // these are defaults, they will be replaced if we use the magic dynamic thing + logthis := func(relayUrl string, s string, args ...any) { log(s, args...) } + colorizethis := func(relayUrl string, colorize func(string, ...any) string) {} + if relayUrls := c.Args().Slice(); len(relayUrls) > 0 { - relays = connectToAllRelays(ctx, relayUrls, nil) + relays = connectToAllRelays(ctx, c, relayUrls, nil, + nostr.WithAuthHandler(func(ctx context.Context, authEvent nostr.RelayEvent) error { + return authSigner(ctx, c, func(s string, args ...any) {}, authEvent) + }), + ) if len(relays) == 0 { log("failed to connect to any of the given relays.\n") os.Exit(3) @@ -301,37 +311,104 @@ example: successRelays := make([]string, 0, len(relays)) if len(relays) > 0 { os.Stdout.Sync() - for _, relay := range relays { - publish: - log("publishing to %s... ", relay.URL) + + if supportsDynamicMultilineMagic() { + // overcomplicated multiline rendering magic ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() - err := relay.Publish(ctx, evt) - if err == nil { - // published fine - log("success.\n") - successRelays = append(successRelays, relay.URL) - continue // continue to next relay - } - - // error publishing - if strings.HasPrefix(err.Error(), "msg: auth-required:") && kr != nil && doAuth { - // if the relay is requesting auth and we can auth, let's do it - pk, _ := kr.GetPublicKey(ctx) - log("performing auth as %s... ", pk) - if err := relay.Auth(ctx, func(authEvent *nostr.Event) error { - return kr.SignEvent(ctx, authEvent) - }); err == nil { - // try to publish again, but this time don't try to auth again - doAuth = false - goto publish - } else { - log("auth error: %s. ", err) + urls := make([]string, len(relays)) + lines := make([][][]byte, len(urls)) + flush := func() { + for _, line := range lines { + for _, part := range line { + os.Stderr.Write(part) + } + os.Stderr.Write([]byte{'\n'}) } } - log("failed: %s\n", err) + render := func() { + clearLines(len(lines)) + flush() + } + flush() + + logthis = func(relayUrl, s string, args ...any) { + idx := slices.Index(urls, relayUrl) + lines[idx] = append(lines[idx], []byte(fmt.Sprintf(s, args...))) + render() + } + colorizethis = func(relayUrl string, colorize func(string, ...any) string) { + cleanUrl, _ := strings.CutPrefix(relayUrl, "wss://") + idx := slices.Index(urls, relayUrl) + lines[idx][0] = []byte(fmt.Sprintf("publishing to %s... ", colorize(cleanUrl))) + render() + } + + for i, relay := range relays { + urls[i] = relay.URL + lines[i] = make([][]byte, 1, 3) + colorizethis(relay.URL, color.CyanString) + } + render() + + for res := range sys.Pool.PublishMany(ctx, urls, evt) { + if res.Error == nil { + colorizethis(res.RelayURL, colors.successf) + logthis(res.RelayURL, "success.") + successRelays = append(successRelays, res.RelayURL) + } else { + colorizethis(res.RelayURL, colors.errorf) + + // in this case it's likely that the lowest-level error is the one that will be more helpful + low := unwrapAll(res.Error) + + // hack for some messages such as from relay.westernbtc.com + msg := strings.ReplaceAll(low.Error(), evt.PubKey, "author") + + // do not allow the message to overflow the term window + msg = clampMessage(msg, 20+len(res.RelayURL)) + + logthis(res.RelayURL, msg) + } + } + } else { + // normal dumb flow + for _, relay := range relays { + publish: + cleanUrl, _ := strings.CutPrefix(relay.URL, "wss://") + log("publishing to %s... ", color.CyanString(cleanUrl)) + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + defer cancel() + + err := relay.Publish(ctx, evt) + if err == nil { + // published fine + log("success.\n") + successRelays = append(successRelays, relay.URL) + continue // continue to next relay + } + + // error publishing + if strings.HasPrefix(err.Error(), "msg: auth-required:") && kr != nil && doAuth { + // if the relay is requesting auth and we can auth, let's do it + pk, _ := kr.GetPublicKey(ctx) + npub, _ := nip19.EncodePublicKey(pk) + log("authenticating as %s... ", color.YellowString("%s…%s", npub[0:7], npub[58:])) + if err := relay.Auth(ctx, func(authEvent *nostr.Event) error { + return kr.SignEvent(ctx, authEvent) + }); err == nil { + // try to publish again, but this time don't try to auth again + doAuth = false + goto publish + } else { + log("auth error: %s. ", err) + } + } + log("failed: %s\n", err) + } } + if len(successRelays) > 0 && c.Bool("nevent") { nevent, _ := nip19.EncodeEvent(evt.ID, successRelays, evt.PubKey) log(nevent + "\n") diff --git a/go.mod b/go.mod index 4b7b3a6..add0a56 100644 --- a/go.mod +++ b/go.mod @@ -77,3 +77,5 @@ require ( golang.org/x/sys v0.31.0 // indirect golang.org/x/text v0.23.0 // indirect ) + +replace github.com/nbd-wtf/go-nostr => ../go-nostr diff --git a/go.sum b/go.sum index 9a3a22d..af918e9 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,6 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/bytedance/sonic v1.13.1 h1:Jyd5CIvdFnkOWuKXr+wm4Nyk2h0yAFsr8ucJgEasO3g= -github.com/bytedance/sonic v1.13.1/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= @@ -55,8 +53,6 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= -github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo= -github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= github.com/coder/websocket v1.8.13 h1:f3QZdXy7uGVz+4uCJy2nTZyM0yTBj8yANEHhqlXZ9FE= github.com/coder/websocket v1.8.13/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -157,8 +153,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/nbd-wtf/go-nostr v0.51.8 h1:CIoS+YqChcm4e1L1rfMZ3/mIwTz4CwApM2qx7MHNzmE= -github.com/nbd-wtf/go-nostr v0.51.8/go.mod h1:d6+DfvMWYG5pA3dmNMBJd6WCHVDDhkXbHqvfljf0Gzg= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= diff --git a/helpers.go b/helpers.go index 184136b..247dd83 100644 --- a/helpers.go +++ b/helpers.go @@ -3,6 +3,7 @@ package main import ( "bufio" "context" + "errors" "fmt" "iter" "math/rand" @@ -19,6 +20,7 @@ import ( "github.com/fatih/color" jsoniter "github.com/json-iterator/go" "github.com/nbd-wtf/go-nostr" + "github.com/nbd-wtf/go-nostr/nip19" "github.com/nbd-wtf/go-nostr/sdk" "github.com/urfave/cli/v3" "golang.org/x/term" @@ -151,8 +153,9 @@ func normalizeAndValidateRelayURLs(wsurls []string) error { func connectToAllRelays( ctx context.Context, + c *cli.Command, relayUrls []string, - preAuthSigner func(ctx context.Context, log func(s string, args ...any), authEvent nostr.RelayEvent) (err error), // if this exists we will force preauth + preAuthSigner func(ctx context.Context, c *cli.Command, log func(s string, args ...any), authEvent nostr.RelayEvent) (err error), // if this exists we will force preauth opts ...nostr.PoolOption, ) []*nostr.Relay { sys.Pool = nostr.NewSimplePool(context.Background(), @@ -198,7 +201,7 @@ func connectToAllRelays( colorizepreamble(color.CyanString) go func() { - relay := connectToSingleRelay(ctx, url, preAuthSigner, colorizepreamble, logthis) + relay := connectToSingleRelay(ctx, c, url, preAuthSigner, colorizepreamble, logthis) if relay != nil { relays = append(relays, relay) } @@ -210,7 +213,7 @@ func connectToAllRelays( // simple flow for _, url := range relayUrls { log("connecting to %s... ", color.CyanString(url)) - relay := connectToSingleRelay(ctx, url, preAuthSigner, nil, log) + relay := connectToSingleRelay(ctx, c, url, preAuthSigner, nil, log) if relay != nil { relays = append(relays, relay) } @@ -223,8 +226,9 @@ func connectToAllRelays( func connectToSingleRelay( ctx context.Context, + c *cli.Command, url string, - preAuthSigner func(ctx context.Context, log func(s string, args ...any), authEvent nostr.RelayEvent) (err error), + preAuthSigner func(ctx context.Context, c *cli.Command, log func(s string, args ...any), authEvent nostr.RelayEvent) (err error), colorizepreamble func(c func(string, ...any) string), logthis func(s string, args ...any), ) *nostr.Relay { @@ -242,7 +246,7 @@ func connectToSingleRelay( if challengeTag[1] == "" { return fmt.Errorf("auth not received yet *****") // what a giant hack } - return preAuthSigner(ctx, logthis, nostr.RelayEvent{Event: authEvent, Relay: relay}) + return preAuthSigner(ctx, c, logthis, nostr.RelayEvent{Event: authEvent, Relay: relay}) }); err == nil { // auth succeeded goto preauthSuccess @@ -255,7 +259,7 @@ func connectToSingleRelay( } else { // it failed for some other reason, so skip this relay if colorizepreamble != nil { - colorizepreamble(color.RedString) + colorizepreamble(colors.errorf) } logthis(err.Error()) return nil @@ -263,7 +267,7 @@ func connectToSingleRelay( } } if colorizepreamble != nil { - colorizepreamble(color.RedString) + colorizepreamble(colors.errorf) } logthis("failed to get an AUTH challenge in enough time.") return nil @@ -271,15 +275,18 @@ func connectToSingleRelay( preauthSuccess: if colorizepreamble != nil { - colorizepreamble(color.GreenString) + colorizepreamble(colors.successf) } logthis("ok.") return relay } else { if colorizepreamble != nil { - colorizepreamble(color.RedString) + colorizepreamble(colors.errorf) } - logthis(err.Error()) + + // if we're here that means we've failed to connect, this may be a huge message + // but we're likely to only be interested in the lowest level error (although we can leave space) + logthis(clampError(err, len(url)+12)) return nil } } @@ -309,6 +316,29 @@ func supportsDynamicMultilineMagic() bool { return true } +func authSigner(ctx context.Context, c *cli.Command, log func(s string, args ...any), authEvent nostr.RelayEvent) (err error) { + defer func() { + if err != nil { + cleanUrl, _ := strings.CutPrefix(authEvent.Relay.URL, "wss://") + log("%s auth failed: %s", colors.errorf(cleanUrl), err) + } + }() + + if !c.Bool("auth") && !c.Bool("force-pre-auth") { + return fmt.Errorf("auth required, but --auth flag not given") + } + kr, _, err := gatherKeyerFromArguments(ctx, c) + if err != nil { + return err + } + + pk, _ := kr.GetPublicKey(ctx) + npub, _ := nip19.EncodePublicKey(pk) + log("authenticating as %s... ", color.YellowString("%s…%s", npub[0:7], npub[58:])) + + return kr.SignEvent(ctx, authEvent.Event) +} + func lineProcessingError(ctx context.Context, msg string, args ...any) context.Context { log(msg+"\n", args...) return context.WithValue(ctx, LINE_PROCESSING_ERROR, true) @@ -334,16 +364,50 @@ func leftPadKey(k string) string { return strings.Repeat("0", 64-len(k)) + k } +func unwrapAll(err error) error { + low := err + for n := low; n != nil; n = errors.Unwrap(low) { + low = n + } + return low +} + +func clampMessage(msg string, prefixAlreadyPrinted int) string { + termSize, _, _ := term.GetSize(0) + if len(msg) > termSize-prefixAlreadyPrinted { + msg = msg[0:termSize-prefixAlreadyPrinted-1] + "…" + } + return msg +} + +func clampError(err error, prefixAlreadyPrinted int) string { + termSize, _, _ := term.GetSize(0) + msg := err.Error() + if len(msg) > termSize-prefixAlreadyPrinted { + err = unwrapAll(err) + msg = clampMessage(err.Error(), prefixAlreadyPrinted) + } + return msg +} + var colors = struct { - reset func(...any) (int, error) - italic func(...any) string - italicf func(string, ...any) string - bold func(...any) string - boldf func(string, ...any) string + reset func(...any) (int, error) + italic func(...any) string + italicf func(string, ...any) string + bold func(...any) string + boldf func(string, ...any) string + error func(...any) string + errorf func(string, ...any) string + success func(...any) string + successf func(string, ...any) string }{ color.New(color.Reset).Print, color.New(color.Italic).Sprint, color.New(color.Italic).Sprintf, color.New(color.Bold).Sprint, color.New(color.Bold).Sprintf, + color.New(color.Bold, color.FgHiRed).Sprint, + color.New(color.Bold, color.FgHiRed).Sprintf, + color.New(color.Bold, color.FgHiGreen).Sprint, + color.New(color.Bold, color.FgHiGreen).Sprintf, } diff --git a/nostrfs/entitydir.go b/nostrfs/entitydir.go index 852a53f..ed8bd76 100644 --- a/nostrfs/entitydir.go +++ b/nostrfs/entitydir.go @@ -348,11 +348,7 @@ func (e *EntityDir) handleWrite() { success := false first := true for res := range e.root.sys.Pool.PublishMany(e.root.ctx, relays, evt) { - cleanUrl, ok := strings.CutPrefix(res.RelayURL, "wss://") - if !ok { - cleanUrl = res.RelayURL - } - + cleanUrl, _ := strings.CutPrefix(res.RelayURL, "wss://") if !first { log(", ") } diff --git a/nostrfs/viewdir.go b/nostrfs/viewdir.go index b861290..1dbbd90 100644 --- a/nostrfs/viewdir.go +++ b/nostrfs/viewdir.go @@ -179,11 +179,7 @@ func (n *ViewDir) publishNote() { success := false first := true for res := range n.root.sys.Pool.PublishMany(n.root.ctx, relays, evt) { - cleanUrl, ok := strings.CutPrefix(res.RelayURL, "wss://") - if !ok { - cleanUrl = res.RelayURL - } - + cleanUrl, _ := strings.CutPrefix(res.RelayURL, "wss://") if !first { log(", ") } diff --git a/req.go b/req.go index a2b8d92..3221fdd 100644 --- a/req.go +++ b/req.go @@ -9,7 +9,6 @@ import ( "github.com/fatih/color" "github.com/mailru/easyjson" "github.com/nbd-wtf/go-nostr" - "github.com/nbd-wtf/go-nostr/nip19" "github.com/nbd-wtf/go-nostr/nip77" "github.com/urfave/cli/v3" ) @@ -79,44 +78,21 @@ example: relayUrls := c.Args().Slice() if len(relayUrls) > 0 { // this is used both for the normal AUTH (after "auth-required:" is received) or forced pre-auth - authSigner := func(ctx context.Context, log func(s string, args ...any), authEvent nostr.RelayEvent) (err error) { - defer func() { - if err != nil { - log("%s failed: %s", - authEvent.Tags.Find("relay")[1], - err, - ) - } - }() - - if !c.Bool("auth") && !c.Bool("force-pre-auth") { - return fmt.Errorf("auth required, but --auth flag not given") - } - kr, _, err := gatherKeyerFromArguments(ctx, c) - if err != nil { - return err - } - - pk, _ := kr.GetPublicKey(ctx) - npub, _ := nip19.EncodePublicKey(pk) - log("authenticating as %s... ", color.YellowString("%s…%s", npub[0:7], npub[58:])) - - return kr.SignEvent(ctx, authEvent.Event) - } - // connect to all relays we expect to use in this call in parallel forcePreAuthSigner := authSigner if !c.Bool("force-pre-auth") { forcePreAuthSigner = nil } - relays := connectToAllRelays(ctx, + relays := connectToAllRelays( + ctx, + c, relayUrls, forcePreAuthSigner, nostr.WithAuthHandler(func(ctx context.Context, authEvent nostr.RelayEvent) error { - return authSigner(ctx, func(s string, args ...any) { + return authSigner(ctx, c, func(s string, args ...any) { if strings.HasPrefix(s, "authenticating as") { - url := authEvent.Tags.Find("relay")[1] - s = "authenticating to " + color.CyanString(url) + " as" + s[len("authenticating as"):] + cleanUrl, _ := strings.CutPrefix(authEvent.Relay.URL, "wss://") + s = "authenticating to " + color.CyanString(cleanUrl) + " as" + s[len("authenticating as"):] } log(s+"\n", args...) }, authEvent) diff --git a/wallet.go b/wallet.go index aebde63..088aaa5 100644 --- a/wallet.go +++ b/wallet.go @@ -6,7 +6,6 @@ import ( "strconv" "strings" - "github.com/fatih/color" "github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr/nip60" "github.com/nbd-wtf/go-nostr/nip61" @@ -60,20 +59,16 @@ func prepareWallet(ctx context.Context, c *cli.Command) (*nip60.Wallet, func(), log("- saving kind:%d event (%s)... ", event.Kind, desc) first := true for res := range sys.Pool.PublishMany(ctx, relays, event) { - cleanUrl, ok := strings.CutPrefix(res.RelayURL, "wss://") - if !ok { - cleanUrl = res.RelayURL - } - + cleanUrl, _ := strings.CutPrefix(res.RelayURL, "wss://") if !first { log(", ") } first = false if res.Error != nil { - log("%s: %s", color.RedString(cleanUrl), res.Error) + log("%s: %s", colors.errorf(cleanUrl), res.Error) } else { - log("%s: ok", color.GreenString(cleanUrl)) + log("%s: ok", colors.successf(cleanUrl)) } } log("\n") @@ -376,19 +371,15 @@ var wallet = &cli.Command{ log("- publishing nutzap... ") first := true for res := range results { - cleanUrl, ok := strings.CutPrefix(res.RelayURL, "wss://") - if !ok { - cleanUrl = res.RelayURL - } - + cleanUrl, _ := strings.CutPrefix(res.RelayURL, "wss://") if !first { log(", ") } first = false if res.Error != nil { - log("%s: %s", color.RedString(cleanUrl), res.Error) + log("%s: %s", colors.errorf(cleanUrl), res.Error) } else { - log("%s: ok", color.GreenString(cleanUrl)) + log("%s: ok", colors.successf(cleanUrl)) } } @@ -463,10 +454,7 @@ var wallet = &cli.Command{ log("- saving kind:10019 event... ") first := true for res := range sys.Pool.PublishMany(ctx, relays, evt) { - cleanUrl, ok := strings.CutPrefix(res.RelayURL, "wss://") - if !ok { - cleanUrl = res.RelayURL - } + cleanUrl, _ := strings.CutPrefix(res.RelayURL, "wss://") if !first { log(", ") @@ -474,9 +462,9 @@ var wallet = &cli.Command{ first = false if res.Error != nil { - log("%s: %s", color.RedString(cleanUrl), res.Error) + log("%s: %s", colors.errorf(cleanUrl), res.Error) } else { - log("%s: ok", color.GreenString(cleanUrl)) + log("%s: ok", colors.successf(cleanUrl)) } }