diff --git a/bunker.go b/bunker.go index 64d2d4e..4732af5 100644 --- a/bunker.go +++ b/bunker.go @@ -50,7 +50,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) + _, relays := connectToAllRelays(ctx, relayUrls, false) if len(relays) == 0 { log("failed to connect to any of the given relays.\n") os.Exit(3) diff --git a/event.go b/event.go index 6e6b225..9fc3f4d 100644 --- a/event.go +++ b/event.go @@ -145,7 +145,7 @@ example: // try to connect to the relays here var relays []*nostr.Relay if relayUrls := c.Args().Slice(); len(relayUrls) > 0 { - _, relays = connectToAllRelays(ctx, relayUrls) + _, relays = connectToAllRelays(ctx, relayUrls, false) if len(relays) == 0 { log("failed to connect to any of the given relays.\n") os.Exit(3) diff --git a/helpers.go b/helpers.go index d6778db..673165a 100644 --- a/helpers.go +++ b/helpers.go @@ -9,6 +9,7 @@ import ( "net/url" "os" "strings" + "time" "github.com/chzyer/readline" "github.com/fatih/color" @@ -117,13 +118,48 @@ func normalizeAndValidateRelayURLs(wsurls []string) error { func connectToAllRelays( ctx context.Context, relayUrls []string, + forcePreAuth bool, opts ...nostr.PoolOption, ) (*nostr.SimplePool, []*nostr.Relay) { relays := make([]*nostr.Relay, 0, len(relayUrls)) pool := nostr.NewSimplePool(ctx, opts...) +relayLoop: for _, url := range relayUrls { log("connecting to %s... ", url) if relay, err := 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.GetFirst([]string{"challenge", ""}) + if (*challengeTag)[1] == "" { + return fmt.Errorf("auth not received yet *****") + } + return signer(authEvent) + }); 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) log("ok.\n") } else { diff --git a/req.go b/req.go index 3ab5295..b987866 100644 --- a/req.go +++ b/req.go @@ -104,6 +104,11 @@ example: Name: "auth", Usage: "always perform NIP-42 \"AUTH\" when facing an \"auth-required: \" rejection and try again", }, + &cli.BoolFlag{ + Name: "force-pre-auth", + Aliases: []string{"fpa"}, + Usage: "after connecting, for a NIP-42 \"AUTH\" message to be received, act on it and only then send the \"REQ\"", + }, &cli.StringFlag{ Name: "sec", Usage: "secret key to sign the AUTH challenge, as hex or nsec", @@ -127,11 +132,12 @@ example: ArgsUsage: "[relay...]", Action: func(ctx context.Context, c *cli.Command) error { var pool *nostr.SimplePool + relayUrls := c.Args().Slice() if len(relayUrls) > 0 { var relays []*nostr.Relay - pool, relays = connectToAllRelays(ctx, relayUrls, nostr.WithAuthHandler(func(evt *nostr.Event) error { - if !c.Bool("auth") { + pool, relays = connectToAllRelays(ctx, relayUrls, c.Bool("force-pre-auth"), nostr.WithAuthHandler(func(evt *nostr.Event) error { + if !c.Bool("auth") && !c.Bool("force-pre-auth") { return fmt.Errorf("auth not authorized") } sec, bunker, err := gatherSecretKeyOrBunkerFromArguments(ctx, c) @@ -148,7 +154,7 @@ example: } else { pk, _ = nostr.GetPublicKey(sec) } - log("performing auth as %s...\n", pk) + log("performing auth as %s... ", pk) if bunker != nil { return bunker.SignEvent(ctx, evt)