mirror of
https://github.com/fiatjaf/nak.git
synced 2025-05-04 21:39:56 -04:00
nice dynamic UI when connecting to relays, and go much faster concurrently.
This commit is contained in:
parent
50119e21e6
commit
9547711e8d
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
nak
|
nak
|
||||||
mnt
|
mnt
|
||||||
|
nak.exe
|
||||||
|
@ -11,10 +11,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/urfave/cli/v3"
|
|
||||||
"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/nip19"
|
||||||
"github.com/nbd-wtf/go-nostr/nip46"
|
"github.com/nbd-wtf/go-nostr/nip46"
|
||||||
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var bunker = &cli.Command{
|
var bunker = &cli.Command{
|
||||||
@ -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, false)
|
relays := connectToAllRelays(ctx, 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)
|
||||||
|
7
count.go
7
count.go
@ -6,10 +6,10 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/urfave/cli/v3"
|
|
||||||
"github.com/nbd-wtf/go-nostr"
|
"github.com/nbd-wtf/go-nostr"
|
||||||
"github.com/nbd-wtf/go-nostr/nip45"
|
"github.com/nbd-wtf/go-nostr/nip45"
|
||||||
"github.com/nbd-wtf/go-nostr/nip45/hyperloglog"
|
"github.com/nbd-wtf/go-nostr/nip45/hyperloglog"
|
||||||
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var count = &cli.Command{
|
var count = &cli.Command{
|
||||||
@ -70,10 +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,
|
relays := connectToAllRelays(ctx, relayUrls, nil)
|
||||||
relayUrls,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
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)
|
||||||
|
2
dvm.go
2
dvm.go
@ -60,7 +60,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, false)
|
relays := connectToAllRelays(ctx, 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)
|
||||||
|
14
event.go
14
event.go
@ -134,7 +134,7 @@ example:
|
|||||||
// try to connect to the relays here
|
// try to connect to the relays here
|
||||||
var relays []*nostr.Relay
|
var relays []*nostr.Relay
|
||||||
if relayUrls := c.Args().Slice(); len(relayUrls) > 0 {
|
if relayUrls := c.Args().Slice(); len(relayUrls) > 0 {
|
||||||
relays = connectToAllRelays(ctx, relayUrls, false)
|
relays = connectToAllRelays(ctx, 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)
|
||||||
@ -209,13 +209,19 @@ example:
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, etag := range c.StringSlice("e") {
|
for _, etag := range c.StringSlice("e") {
|
||||||
tags = tags.AppendUnique([]string{"e", etag})
|
if tags.FindWithValue("e", etag) == nil {
|
||||||
|
tags = append(tags, nostr.Tag{"e", etag})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for _, ptag := range c.StringSlice("p") {
|
for _, ptag := range c.StringSlice("p") {
|
||||||
tags = tags.AppendUnique([]string{"p", ptag})
|
if tags.FindWithValue("p", ptag) == nil {
|
||||||
|
tags = append(tags, nostr.Tag{"p", ptag})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for _, dtag := range c.StringSlice("d") {
|
for _, dtag := range c.StringSlice("d") {
|
||||||
tags = tags.AppendUnique([]string{"d", dtag})
|
if tags.FindWithValue("d", dtag) == nil {
|
||||||
|
tags = append(tags, nostr.Tag{"d", dtag})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if len(tags) > 0 {
|
if len(tags) > 0 {
|
||||||
for _, tag := range tags {
|
for _, tag := range tags {
|
||||||
|
1
go.mod
1
go.mod
@ -20,6 +20,7 @@ require (
|
|||||||
github.com/nbd-wtf/go-nostr v0.51.8
|
github.com/nbd-wtf/go-nostr v0.51.8
|
||||||
github.com/urfave/cli/v3 v3.0.0-beta1
|
github.com/urfave/cli/v3 v3.0.0-beta1
|
||||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394
|
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394
|
||||||
|
golang.org/x/term v0.30.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
2
go.sum
2
go.sum
@ -247,6 +247,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
|
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
||||||
|
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
182
helpers.go
182
helpers.go
@ -10,8 +10,10 @@ import (
|
|||||||
"net/textproto"
|
"net/textproto"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
@ -19,6 +21,7 @@ import (
|
|||||||
"github.com/nbd-wtf/go-nostr"
|
"github.com/nbd-wtf/go-nostr"
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
var sys *sdk.System
|
var sys *sdk.System
|
||||||
@ -149,7 +152,7 @@ func normalizeAndValidateRelayURLs(wsurls []string) error {
|
|||||||
func connectToAllRelays(
|
func connectToAllRelays(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
relayUrls []string,
|
relayUrls []string,
|
||||||
forcePreAuth bool,
|
preAuthSigner func(ctx context.Context, 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(),
|
||||||
@ -163,52 +166,149 @@ func connectToAllRelays(
|
|||||||
)
|
)
|
||||||
|
|
||||||
relays := make([]*nostr.Relay, 0, len(relayUrls))
|
relays := make([]*nostr.Relay, 0, len(relayUrls))
|
||||||
relayLoop:
|
|
||||||
for _, url := range relayUrls {
|
|
||||||
log("connecting to %s... ", url)
|
|
||||||
if relay, err := sys.Pool.EnsureRelay(url); err == nil {
|
|
||||||
if forcePreAuth {
|
|
||||||
log("waiting for auth challenge... ")
|
|
||||||
signer := opts[0].(nostr.WithAuthHandler)
|
|
||||||
time.Sleep(time.Millisecond * 200)
|
|
||||||
challengeWaitLoop:
|
|
||||||
for {
|
|
||||||
// beginhack
|
|
||||||
// here starts the biggest and ugliest hack of this codebase
|
|
||||||
if err := relay.Auth(ctx, func(authEvent *nostr.Event) error {
|
|
||||||
challengeTag := authEvent.Tags.Find("challenge")
|
|
||||||
if challengeTag[1] == "" {
|
|
||||||
return fmt.Errorf("auth not received yet *****")
|
|
||||||
}
|
|
||||||
return signer(ctx, nostr.RelayEvent{Event: authEvent, Relay: relay})
|
|
||||||
}); err == nil {
|
|
||||||
// auth succeeded
|
|
||||||
break challengeWaitLoop
|
|
||||||
} else {
|
|
||||||
// auth failed
|
|
||||||
if strings.HasSuffix(err.Error(), "auth not received yet *****") {
|
|
||||||
// it failed because we didn't receive the challenge yet, so keep waiting
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
continue challengeWaitLoop
|
|
||||||
} else {
|
|
||||||
// it failed for some other reason, so skip this relay
|
|
||||||
log(err.Error() + "\n")
|
|
||||||
continue relayLoop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// endhack
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
relays = append(relays, relay)
|
if supportsDynamicMultilineMagic() {
|
||||||
log("ok.\n")
|
// overcomplicated multiline rendering magic
|
||||||
} else {
|
lines := make([][][]byte, len(relayUrls))
|
||||||
log(err.Error() + "\n")
|
flush := func() {
|
||||||
|
for _, line := range lines {
|
||||||
|
for _, part := range line {
|
||||||
|
os.Stderr.Write(part)
|
||||||
|
}
|
||||||
|
os.Stderr.Write([]byte{'\n'})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render := func() {
|
||||||
|
clearLines(len(lines))
|
||||||
|
flush()
|
||||||
|
}
|
||||||
|
flush()
|
||||||
|
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
wg.Add(len(relayUrls))
|
||||||
|
for i, url := range relayUrls {
|
||||||
|
lines[i] = make([][]byte, 1, 2)
|
||||||
|
logthis := func(s string, args ...any) {
|
||||||
|
lines[i] = append(lines[i], []byte(fmt.Sprintf(s, args...)))
|
||||||
|
render()
|
||||||
|
}
|
||||||
|
colorizepreamble := func(c func(string, ...any) string) {
|
||||||
|
lines[i][0] = []byte(fmt.Sprintf("%s... ", c(url)))
|
||||||
|
}
|
||||||
|
colorizepreamble(color.CyanString)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
relay := connectToSingleRelay(ctx, url, preAuthSigner, colorizepreamble, logthis)
|
||||||
|
if relay != nil {
|
||||||
|
relays = append(relays, relay)
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
} else {
|
||||||
|
// simple flow
|
||||||
|
for _, url := range relayUrls {
|
||||||
|
log("connecting to %s... ", url)
|
||||||
|
relay := connectToSingleRelay(ctx, url, preAuthSigner, nil, log)
|
||||||
|
if relay != nil {
|
||||||
|
relays = append(relays, relay)
|
||||||
|
}
|
||||||
|
log("\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return relays
|
return relays
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func connectToSingleRelay(
|
||||||
|
ctx context.Context,
|
||||||
|
url string,
|
||||||
|
preAuthSigner func(ctx context.Context, 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 {
|
||||||
|
if relay, err := sys.Pool.EnsureRelay(url); err == nil {
|
||||||
|
if preAuthSigner != nil {
|
||||||
|
if colorizepreamble != nil {
|
||||||
|
colorizepreamble(color.YellowString)
|
||||||
|
}
|
||||||
|
logthis("waiting for auth challenge... ")
|
||||||
|
time.Sleep(time.Millisecond * 200)
|
||||||
|
|
||||||
|
for range 5 {
|
||||||
|
if err := relay.Auth(ctx, func(authEvent *nostr.Event) error {
|
||||||
|
challengeTag := authEvent.Tags.Find("challenge")
|
||||||
|
if challengeTag[1] == "" {
|
||||||
|
return fmt.Errorf("auth not received yet *****") // what a giant hack
|
||||||
|
}
|
||||||
|
return preAuthSigner(ctx, logthis, nostr.RelayEvent{Event: authEvent, Relay: relay})
|
||||||
|
}); err == nil {
|
||||||
|
// auth succeeded
|
||||||
|
goto preauthSuccess
|
||||||
|
} else {
|
||||||
|
// auth failed
|
||||||
|
if strings.HasSuffix(err.Error(), "auth not received yet *****") {
|
||||||
|
// it failed because we didn't receive the challenge yet, so keep waiting
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
// it failed for some other reason, so skip this relay
|
||||||
|
if colorizepreamble != nil {
|
||||||
|
colorizepreamble(color.RedString)
|
||||||
|
}
|
||||||
|
logthis(err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if colorizepreamble != nil {
|
||||||
|
colorizepreamble(color.RedString)
|
||||||
|
}
|
||||||
|
logthis("failed to get an AUTH challenge in enough time.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
preauthSuccess:
|
||||||
|
if colorizepreamble != nil {
|
||||||
|
colorizepreamble(color.GreenString)
|
||||||
|
}
|
||||||
|
logthis("ok.")
|
||||||
|
return relay
|
||||||
|
} else {
|
||||||
|
if colorizepreamble != nil {
|
||||||
|
colorizepreamble(color.RedString)
|
||||||
|
}
|
||||||
|
logthis(err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func clearLines(lineCount int) {
|
||||||
|
for i := 0; i < lineCount; i++ {
|
||||||
|
os.Stderr.Write([]byte("\033[0A\033[2K\r"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func supportsDynamicMultilineMagic() bool {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !term.IsTerminal(0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
width, _, err := term.GetSize(0)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if width < 110 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
65
req.go
65
req.go
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"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"
|
||||||
)
|
)
|
||||||
@ -76,35 +77,46 @@ example:
|
|||||||
Action: func(ctx context.Context, c *cli.Command) error {
|
Action: func(ctx context.Context, c *cli.Command) error {
|
||||||
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
|
||||||
|
authSigner := func(ctx context.Context, log func(s string, args ...any), authEvent nostr.RelayEvent) (err error) {
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
log("auth to %s failed: %s",
|
||||||
|
authEvent.Tags.Find("relay")[1],
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if !c.Bool("auth") && !c.Bool("force-pre-auth") {
|
||||||
|
return fmt.Errorf("auth not authorized")
|
||||||
|
}
|
||||||
|
kr, _, err := gatherKeyerFromArguments(ctx, c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pk, _ := kr.GetPublicKey(ctx)
|
||||||
|
npub, _ := nip19.EncodePublicKey(pk)
|
||||||
|
log("performing auth as %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,
|
||||||
relayUrls,
|
relayUrls,
|
||||||
c.Bool("force-pre-auth"),
|
forcePreAuthSigner,
|
||||||
nostr.WithAuthHandler(
|
nostr.WithAuthHandler(func(ctx context.Context, authEvent nostr.RelayEvent) error {
|
||||||
func(ctx context.Context, authEvent nostr.RelayEvent) (err error) {
|
return authSigner(ctx, func(s string, args ...any) { log(s+"\n", args...) }, authEvent)
|
||||||
defer func() {
|
}),
|
||||||
if err != nil {
|
|
||||||
log("auth to %s failed: %s\n",
|
|
||||||
authEvent.Tags.Find("relay")[1],
|
|
||||||
err,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if !c.Bool("auth") && !c.Bool("force-pre-auth") {
|
|
||||||
return fmt.Errorf("auth not authorized")
|
|
||||||
}
|
|
||||||
kr, _, err := gatherKeyerFromArguments(ctx, c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
pk, _ := kr.GetPublicKey(ctx)
|
|
||||||
log("performing auth as %s... ", pk)
|
|
||||||
|
|
||||||
return kr.SignEvent(ctx, authEvent.Event)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// stop here already if all connections failed
|
||||||
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)
|
||||||
@ -121,6 +133,7 @@ example:
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// go line by line from stdin or run once with input from flags
|
||||||
for stdinFilter := range getJsonsOrBlank() {
|
for stdinFilter := range getJsonsOrBlank() {
|
||||||
filter := nostr.Filter{}
|
filter := nostr.Filter{}
|
||||||
if stdinFilter != "" {
|
if stdinFilter != "" {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user