1
0
mirror of https://github.com/fiatjaf/nak.git synced 2025-05-03 13:19:55 -04:00

much more colors everywhere and everything is prettier.

This commit is contained in:
fiatjaf 2025-04-03 14:50:25 -03:00
parent 7ae2e686cb
commit 703c186958
11 changed files with 207 additions and 118 deletions

@ -49,7 +49,7 @@ var bunker = &cli.Command{
qs := url.Values{} qs := url.Values{}
relayURLs := make([]string, 0, c.Args().Len()) relayURLs := make([]string, 0, c.Args().Len())
if relayUrls := c.Args().Slice(); len(relayUrls) > 0 { if relayUrls := c.Args().Slice(); len(relayUrls) > 0 {
relays := connectToAllRelays(ctx, relayUrls, nil) relays := connectToAllRelays(ctx, c, relayUrls, nil)
if len(relays) == 0 { if len(relays) == 0 {
log("failed to connect to any of the given relays.\n") log("failed to connect to any of the given relays.\n")
os.Exit(3) os.Exit(3)

@ -70,7 +70,7 @@ var count = &cli.Command{
biggerUrlSize := 0 biggerUrlSize := 0
relayUrls := c.Args().Slice() relayUrls := c.Args().Slice()
if len(relayUrls) > 0 { if len(relayUrls) > 0 {
relays := connectToAllRelays(ctx, relayUrls, nil) relays := connectToAllRelays(ctx, c, relayUrls, nil)
if len(relays) == 0 { if len(relays) == 0 {
log("failed to connect to any of the given relays.\n") log("failed to connect to any of the given relays.\n")
os.Exit(3) os.Exit(3)

12
dvm.go

@ -7,7 +7,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/fatih/color"
"github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip90" "github.com/nbd-wtf/go-nostr/nip90"
"github.com/urfave/cli/v3" "github.com/urfave/cli/v3"
@ -60,7 +59,7 @@ var dvm = &cli.Command{
Flags: flags, Flags: flags,
Action: func(ctx context.Context, c *cli.Command) error { Action: func(ctx context.Context, c *cli.Command) error {
relayUrls := c.StringSlice("relay") relayUrls := c.StringSlice("relay")
relays := connectToAllRelays(ctx, relayUrls, nil) relays := connectToAllRelays(ctx, c, relayUrls, nil)
if len(relays) == 0 { if len(relays) == 0 {
log("failed to connect to any of the given relays.\n") log("failed to connect to any of the given relays.\n")
os.Exit(3) os.Exit(3)
@ -103,10 +102,7 @@ var dvm = &cli.Command{
log("- publishing job request... ") log("- publishing job request... ")
first := true first := true
for res := range sys.Pool.PublishMany(ctx, relayUrls, evt) { for res := range sys.Pool.PublishMany(ctx, relayUrls, evt) {
cleanUrl, ok := strings.CutPrefix(res.RelayURL, "wss://") cleanUrl, _ := strings.CutPrefix(res.RelayURL, "wss://")
if !ok {
cleanUrl = res.RelayURL
}
if !first { if !first {
log(", ") log(", ")
@ -114,9 +110,9 @@ var dvm = &cli.Command{
first = false first = false
if res.Error != nil { if res.Error != nil {
log("%s: %s", color.RedString(cleanUrl), res.Error) log("%s: %s", colors.errorf(cleanUrl), res.Error)
} else { } else {
log("%s: ok", color.GreenString(cleanUrl)) log("%s: ok", colors.successf(cleanUrl))
} }
} }

129
event.go

@ -8,6 +8,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/fatih/color"
"github.com/mailru/easyjson" "github.com/mailru/easyjson"
"github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip13" "github.com/nbd-wtf/go-nostr/nip13"
@ -133,8 +134,17 @@ example:
Action: func(ctx context.Context, c *cli.Command) error { Action: func(ctx context.Context, c *cli.Command) error {
// try to connect to the relays here // try to connect to the relays here
var relays []*nostr.Relay 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 { 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 { if len(relays) == 0 {
log("failed to connect to any of the given relays.\n") log("failed to connect to any of the given relays.\n")
os.Exit(3) os.Exit(3)
@ -301,37 +311,104 @@ example:
successRelays := make([]string, 0, len(relays)) successRelays := make([]string, 0, len(relays))
if len(relays) > 0 { if len(relays) > 0 {
os.Stdout.Sync() os.Stdout.Sync()
for _, relay := range relays {
publish: if supportsDynamicMultilineMagic() {
log("publishing to %s... ", relay.URL) // overcomplicated multiline rendering magic
ctx, cancel := context.WithTimeout(ctx, 10*time.Second) ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel() defer cancel()
err := relay.Publish(ctx, evt) urls := make([]string, len(relays))
if err == nil { lines := make([][][]byte, len(urls))
// published fine flush := func() {
log("success.\n") for _, line := range lines {
successRelays = append(successRelays, relay.URL) for _, part := range line {
continue // continue to next relay os.Stderr.Write(part)
} }
os.Stderr.Write([]byte{'\n'})
// 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)
} }
} }
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") { if len(successRelays) > 0 && c.Bool("nevent") {
nevent, _ := nip19.EncodeEvent(evt.ID, successRelays, evt.PubKey) nevent, _ := nip19.EncodeEvent(evt.ID, successRelays, evt.PubKey)
log(nevent + "\n") log(nevent + "\n")

2
go.mod

@ -77,3 +77,5 @@ require (
golang.org/x/sys v0.31.0 // indirect golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.23.0 // indirect golang.org/x/text v0.23.0 // indirect
) )
replace github.com/nbd-wtf/go-nostr => ../go-nostr

6
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/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/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/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 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= 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= 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 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= 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/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 h1:f3QZdXy7uGVz+4uCJy2nTZyM0yTBj8yANEHhqlXZ9FE=
github.com/coder/websocket v1.8.13/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= 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= 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/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 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 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/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.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=

@ -3,6 +3,7 @@ package main
import ( import (
"bufio" "bufio"
"context" "context"
"errors"
"fmt" "fmt"
"iter" "iter"
"math/rand" "math/rand"
@ -19,6 +20,7 @@ import (
"github.com/fatih/color" "github.com/fatih/color"
jsoniter "github.com/json-iterator/go" jsoniter "github.com/json-iterator/go"
"github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip19"
"github.com/nbd-wtf/go-nostr/sdk" "github.com/nbd-wtf/go-nostr/sdk"
"github.com/urfave/cli/v3" "github.com/urfave/cli/v3"
"golang.org/x/term" "golang.org/x/term"
@ -151,8 +153,9 @@ func normalizeAndValidateRelayURLs(wsurls []string) error {
func connectToAllRelays( func connectToAllRelays(
ctx context.Context, ctx context.Context,
c *cli.Command,
relayUrls []string, 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, opts ...nostr.PoolOption,
) []*nostr.Relay { ) []*nostr.Relay {
sys.Pool = nostr.NewSimplePool(context.Background(), sys.Pool = nostr.NewSimplePool(context.Background(),
@ -198,7 +201,7 @@ func connectToAllRelays(
colorizepreamble(color.CyanString) colorizepreamble(color.CyanString)
go func() { go func() {
relay := connectToSingleRelay(ctx, url, preAuthSigner, colorizepreamble, logthis) relay := connectToSingleRelay(ctx, c, url, preAuthSigner, colorizepreamble, logthis)
if relay != nil { if relay != nil {
relays = append(relays, relay) relays = append(relays, relay)
} }
@ -210,7 +213,7 @@ func connectToAllRelays(
// simple flow // simple flow
for _, url := range relayUrls { for _, url := range relayUrls {
log("connecting to %s... ", color.CyanString(url)) 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 { if relay != nil {
relays = append(relays, relay) relays = append(relays, relay)
} }
@ -223,8 +226,9 @@ func connectToAllRelays(
func connectToSingleRelay( func connectToSingleRelay(
ctx context.Context, ctx context.Context,
c *cli.Command,
url string, 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), colorizepreamble func(c func(string, ...any) string),
logthis func(s string, args ...any), logthis func(s string, args ...any),
) *nostr.Relay { ) *nostr.Relay {
@ -242,7 +246,7 @@ func connectToSingleRelay(
if challengeTag[1] == "" { if challengeTag[1] == "" {
return fmt.Errorf("auth not received yet *****") // what a giant hack 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 { }); err == nil {
// auth succeeded // auth succeeded
goto preauthSuccess goto preauthSuccess
@ -255,7 +259,7 @@ func connectToSingleRelay(
} else { } else {
// it failed for some other reason, so skip this relay // it failed for some other reason, so skip this relay
if colorizepreamble != nil { if colorizepreamble != nil {
colorizepreamble(color.RedString) colorizepreamble(colors.errorf)
} }
logthis(err.Error()) logthis(err.Error())
return nil return nil
@ -263,7 +267,7 @@ func connectToSingleRelay(
} }
} }
if colorizepreamble != nil { if colorizepreamble != nil {
colorizepreamble(color.RedString) colorizepreamble(colors.errorf)
} }
logthis("failed to get an AUTH challenge in enough time.") logthis("failed to get an AUTH challenge in enough time.")
return nil return nil
@ -271,15 +275,18 @@ func connectToSingleRelay(
preauthSuccess: preauthSuccess:
if colorizepreamble != nil { if colorizepreamble != nil {
colorizepreamble(color.GreenString) colorizepreamble(colors.successf)
} }
logthis("ok.") logthis("ok.")
return relay return relay
} else { } else {
if colorizepreamble != nil { 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 return nil
} }
} }
@ -309,6 +316,29 @@ func supportsDynamicMultilineMagic() bool {
return true 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 { func lineProcessingError(ctx context.Context, msg string, args ...any) context.Context {
log(msg+"\n", args...) log(msg+"\n", args...)
return context.WithValue(ctx, LINE_PROCESSING_ERROR, true) 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 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 { var colors = struct {
reset func(...any) (int, error) reset func(...any) (int, error)
italic func(...any) string italic func(...any) string
italicf func(string, ...any) string italicf func(string, ...any) string
bold func(...any) string bold func(...any) string
boldf func(string, ...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.Reset).Print,
color.New(color.Italic).Sprint, color.New(color.Italic).Sprint,
color.New(color.Italic).Sprintf, color.New(color.Italic).Sprintf,
color.New(color.Bold).Sprint, color.New(color.Bold).Sprint,
color.New(color.Bold).Sprintf, 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,
} }

@ -348,11 +348,7 @@ func (e *EntityDir) handleWrite() {
success := false success := false
first := true first := true
for res := range e.root.sys.Pool.PublishMany(e.root.ctx, relays, evt) { for res := range e.root.sys.Pool.PublishMany(e.root.ctx, relays, evt) {
cleanUrl, ok := strings.CutPrefix(res.RelayURL, "wss://") cleanUrl, _ := strings.CutPrefix(res.RelayURL, "wss://")
if !ok {
cleanUrl = res.RelayURL
}
if !first { if !first {
log(", ") log(", ")
} }

@ -179,11 +179,7 @@ func (n *ViewDir) publishNote() {
success := false success := false
first := true first := true
for res := range n.root.sys.Pool.PublishMany(n.root.ctx, relays, evt) { for res := range n.root.sys.Pool.PublishMany(n.root.ctx, relays, evt) {
cleanUrl, ok := strings.CutPrefix(res.RelayURL, "wss://") cleanUrl, _ := strings.CutPrefix(res.RelayURL, "wss://")
if !ok {
cleanUrl = res.RelayURL
}
if !first { if !first {
log(", ") log(", ")
} }

36
req.go

@ -9,7 +9,6 @@ import (
"github.com/fatih/color" "github.com/fatih/color"
"github.com/mailru/easyjson" "github.com/mailru/easyjson"
"github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip19"
"github.com/nbd-wtf/go-nostr/nip77" "github.com/nbd-wtf/go-nostr/nip77"
"github.com/urfave/cli/v3" "github.com/urfave/cli/v3"
) )
@ -79,44 +78,21 @@ example:
relayUrls := c.Args().Slice() relayUrls := c.Args().Slice()
if len(relayUrls) > 0 { if len(relayUrls) > 0 {
// this is used both for the normal AUTH (after "auth-required:" is received) or forced pre-auth // 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 // connect to all relays we expect to use in this call in parallel
forcePreAuthSigner := authSigner forcePreAuthSigner := authSigner
if !c.Bool("force-pre-auth") { if !c.Bool("force-pre-auth") {
forcePreAuthSigner = nil forcePreAuthSigner = nil
} }
relays := connectToAllRelays(ctx, relays := connectToAllRelays(
ctx,
c,
relayUrls, relayUrls,
forcePreAuthSigner, forcePreAuthSigner,
nostr.WithAuthHandler(func(ctx context.Context, authEvent nostr.RelayEvent) error { 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") { if strings.HasPrefix(s, "authenticating as") {
url := authEvent.Tags.Find("relay")[1] cleanUrl, _ := strings.CutPrefix(authEvent.Relay.URL, "wss://")
s = "authenticating to " + color.CyanString(url) + " as" + s[len("authenticating as"):] s = "authenticating to " + color.CyanString(cleanUrl) + " as" + s[len("authenticating as"):]
} }
log(s+"\n", args...) log(s+"\n", args...)
}, authEvent) }, authEvent)

@ -6,7 +6,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/fatih/color"
"github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip60" "github.com/nbd-wtf/go-nostr/nip60"
"github.com/nbd-wtf/go-nostr/nip61" "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) log("- saving kind:%d event (%s)... ", event.Kind, desc)
first := true first := true
for res := range sys.Pool.PublishMany(ctx, relays, event) { for res := range sys.Pool.PublishMany(ctx, relays, event) {
cleanUrl, ok := strings.CutPrefix(res.RelayURL, "wss://") cleanUrl, _ := strings.CutPrefix(res.RelayURL, "wss://")
if !ok {
cleanUrl = res.RelayURL
}
if !first { if !first {
log(", ") log(", ")
} }
first = false first = false
if res.Error != nil { if res.Error != nil {
log("%s: %s", color.RedString(cleanUrl), res.Error) log("%s: %s", colors.errorf(cleanUrl), res.Error)
} else { } else {
log("%s: ok", color.GreenString(cleanUrl)) log("%s: ok", colors.successf(cleanUrl))
} }
} }
log("\n") log("\n")
@ -376,19 +371,15 @@ var wallet = &cli.Command{
log("- publishing nutzap... ") log("- publishing nutzap... ")
first := true first := true
for res := range results { for res := range results {
cleanUrl, ok := strings.CutPrefix(res.RelayURL, "wss://") cleanUrl, _ := strings.CutPrefix(res.RelayURL, "wss://")
if !ok {
cleanUrl = res.RelayURL
}
if !first { if !first {
log(", ") log(", ")
} }
first = false first = false
if res.Error != nil { if res.Error != nil {
log("%s: %s", color.RedString(cleanUrl), res.Error) log("%s: %s", colors.errorf(cleanUrl), res.Error)
} else { } 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... ") log("- saving kind:10019 event... ")
first := true first := true
for res := range sys.Pool.PublishMany(ctx, relays, evt) { for res := range sys.Pool.PublishMany(ctx, relays, evt) {
cleanUrl, ok := strings.CutPrefix(res.RelayURL, "wss://") cleanUrl, _ := strings.CutPrefix(res.RelayURL, "wss://")
if !ok {
cleanUrl = res.RelayURL
}
if !first { if !first {
log(", ") log(", ")
@ -474,9 +462,9 @@ var wallet = &cli.Command{
first = false first = false
if res.Error != nil { if res.Error != nil {
log("%s: %s", color.RedString(cleanUrl), res.Error) log("%s: %s", colors.errorf(cleanUrl), res.Error)
} else { } else {
log("%s: ok", color.GreenString(cleanUrl)) log("%s: ok", colors.successf(cleanUrl))
} }
} }