update to cli v3.

This commit is contained in:
fiatjaf 2024-06-25 22:18:26 -03:00
parent 2079ddf818
commit dba2ed0b5f
14 changed files with 133 additions and 127 deletions

View File

@ -14,7 +14,7 @@ import (
"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/v2" "github.com/urfave/cli/v3"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
) )
@ -45,12 +45,12 @@ var bunker = &cli.Command{
Usage: "pubkeys for which we will always respond", Usage: "pubkeys for which we will always respond",
}, },
}, },
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
// try to connect to the relays here // try to connect to the relays here
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(c.Context, relayUrls) _, relays := connectToAllRelays(ctx, relayUrls)
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)
@ -65,7 +65,7 @@ var bunker = &cli.Command{
} }
// gather the secret key // gather the secret key
sec, _, err := gatherSecretKeyOrBunkerFromArguments(c) sec, _, err := gatherSecretKeyOrBunkerFromArguments(ctx, c)
if err != nil { if err != nil {
return err return err
} }
@ -143,9 +143,9 @@ var bunker = &cli.Command{
printBunkerInfo() printBunkerInfo()
// subscribe to relays // subscribe to relays
pool := nostr.NewSimplePool(c.Context) pool := nostr.NewSimplePool(ctx)
now := nostr.Now() now := nostr.Now()
events := pool.SubMany(c.Context, relayURLs, nostr.Filters{ events := pool.SubMany(ctx, relayURLs, nostr.Filters{
{ {
Kinds: []int{nostr.KindNostrConnect}, Kinds: []int{nostr.KindNostrConnect},
Tags: nostr.TagMap{"p": []string{pubkey}}, Tags: nostr.TagMap{"p": []string{pubkey}},
@ -160,7 +160,7 @@ var bunker = &cli.Command{
// just a gimmick // just a gimmick
var cancelPreviousBunkerInfoPrint context.CancelFunc var cancelPreviousBunkerInfoPrint context.CancelFunc
_, cancel := context.WithCancel(c.Context) _, cancel := context.WithCancel(ctx)
cancelPreviousBunkerInfoPrint = cancel cancelPreviousBunkerInfoPrint = cancel
// asking user for authorization // asking user for authorization
@ -199,7 +199,7 @@ var bunker = &cli.Command{
for _, relayURL := range relayURLs { for _, relayURL := range relayURLs {
go func(relayURL string) { go func(relayURL string) {
if relay, _ := pool.EnsureRelay(relayURL); relay != nil { if relay, _ := pool.EnsureRelay(relayURL); relay != nil {
err := relay.Publish(c.Context, eventResponse) err := relay.Publish(ctx, eventResponse)
printLock.Lock() printLock.Lock()
if err == nil { if err == nil {
log("* sent response through %s\n", relay.URL) log("* sent response through %s\n", relay.URL)
@ -215,7 +215,7 @@ var bunker = &cli.Command{
// just after handling one request we trigger this // just after handling one request we trigger this
go func() { go func() {
ctx, cancel := context.WithCancel(c.Context) ctx, cancel := context.WithCancel(ctx)
defer cancel() defer cancel()
cancelPreviousBunkerInfoPrint = cancel cancelPreviousBunkerInfoPrint = cancel
// the idea is that we will print the bunker URL again so it is easier to copy-paste by users // the idea is that we will print the bunker URL again so it is easier to copy-paste by users

View File

@ -1,13 +1,14 @@
package main package main
import ( import (
"context"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"strings" "strings"
"github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v3"
) )
var count = &cli.Command{ var count = &cli.Command{
@ -63,7 +64,7 @@ var count = &cli.Command{
}, },
}, },
ArgsUsage: "[relay...]", ArgsUsage: "[relay...]",
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
filter := nostr.Filter{} filter := nostr.Filter{}
if authors := c.StringSlice("author"); len(authors) > 0 { if authors := c.StringSlice("author"); len(authors) > 0 {
@ -72,7 +73,11 @@ var count = &cli.Command{
if ids := c.StringSlice("id"); len(ids) > 0 { if ids := c.StringSlice("id"); len(ids) > 0 {
filter.IDs = ids filter.IDs = ids
} }
if kinds := c.IntSlice("kind"); len(kinds) > 0 { if kinds64 := c.IntSlice("kind"); len(kinds64) > 0 {
kinds := make([]int, len(kinds64))
for i, v := range kinds64 {
kinds[i] = int(v)
}
filter.Kinds = kinds filter.Kinds = kinds
} }
@ -110,7 +115,7 @@ var count = &cli.Command{
filter.Until = &ts filter.Until = &ts
} }
if limit := c.Int("limit"); limit != 0 { if limit := c.Int("limit"); limit != 0 {
filter.Limit = limit filter.Limit = int(limit)
} }
relays := c.Args().Slice() relays := c.Args().Slice()
@ -118,12 +123,12 @@ var count = &cli.Command{
failures := make([]error, 0, len(relays)) failures := make([]error, 0, len(relays))
if len(relays) > 0 { if len(relays) > 0 {
for _, relayUrl := range relays { for _, relayUrl := range relays {
relay, err := nostr.RelayConnect(c.Context, relayUrl) relay, err := nostr.RelayConnect(ctx, relayUrl)
if err != nil { if err != nil {
failures = append(failures, err) failures = append(failures, err)
continue continue
} }
count, err := relay.Count(c.Context, nostr.Filters{filter}) count, err := relay.Count(ctx, nostr.Filters{filter})
if err != nil { if err != nil {
failures = append(failures, err) failures = append(failures, err)
continue continue

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"strings" "strings"
@ -8,7 +9,7 @@ import (
"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"
sdk "github.com/nbd-wtf/nostr-sdk" sdk "github.com/nbd-wtf/nostr-sdk"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v3"
) )
var decode = &cli.Command{ var decode = &cli.Command{
@ -32,7 +33,7 @@ var decode = &cli.Command{
}, },
}, },
ArgsUsage: "<npub | nprofile | nip05 | nevent | naddr | nsec>", ArgsUsage: "<npub | nprofile | nip05 | nevent | naddr | nsec>",
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
for input := range getStdinLinesOrArguments(c.Args()) { for input := range getStdinLinesOrArguments(c.Args()) {
if strings.HasPrefix(input, "nostr:") { if strings.HasPrefix(input, "nostr:") {
input = input[6:] input = input[6:]
@ -49,12 +50,12 @@ var decode = &cli.Command{
decodeResult.HexResult.PrivateKey = hex.EncodeToString(b) decodeResult.HexResult.PrivateKey = hex.EncodeToString(b)
decodeResult.HexResult.PublicKey = hex.EncodeToString(b) decodeResult.HexResult.PublicKey = hex.EncodeToString(b)
} else { } else {
lineProcessingError(c, "hex string with invalid number of bytes: %d", len(b)) lineProcessingError(ctx, "hex string with invalid number of bytes: %d", len(b))
continue continue
} }
} else if evp := sdk.InputToEventPointer(input); evp != nil { } else if evp := sdk.InputToEventPointer(input); evp != nil {
decodeResult = DecodeResult{EventPointer: evp} decodeResult = DecodeResult{EventPointer: evp}
} else if pp := sdk.InputToProfile(c.Context, input); pp != nil { } else if pp := sdk.InputToProfile(ctx, input); pp != nil {
decodeResult = DecodeResult{ProfilePointer: pp} decodeResult = DecodeResult{ProfilePointer: pp}
} else if prefix, value, err := nip19.Decode(input); err == nil && prefix == "naddr" { } else if prefix, value, err := nip19.Decode(input); err == nil && prefix == "naddr" {
ep := value.(nostr.EntityPointer) ep := value.(nostr.EntityPointer)
@ -63,7 +64,7 @@ var decode = &cli.Command{
decodeResult.PrivateKey.PrivateKey = value.(string) decodeResult.PrivateKey.PrivateKey = value.(string)
decodeResult.PrivateKey.PublicKey, _ = nostr.GetPublicKey(value.(string)) decodeResult.PrivateKey.PublicKey, _ = nostr.GetPublicKey(value.(string))
} else { } else {
lineProcessingError(c, "couldn't decode input '%s': %s", input, err) lineProcessingError(ctx, "couldn't decode input '%s': %s", input, err)
continue continue
} }
@ -71,7 +72,7 @@ var decode = &cli.Command{
} }
exitIfLineProcessingError(c) exitIfLineProcessingError(ctx)
return nil return nil
}, },
} }

View File

@ -1,11 +1,12 @@
package main package main
import ( import (
"context"
"fmt" "fmt"
"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/urfave/cli/v2" "github.com/urfave/cli/v3"
) )
var encode = &cli.Command{ var encode = &cli.Command{
@ -18,20 +19,20 @@ var encode = &cli.Command{
nak encode nevent <event-id> nak encode nevent <event-id>
nak encode nevent --author <pubkey-hex> --relay <relay-url> --relay <other-relay> <event-id> nak encode nevent --author <pubkey-hex> --relay <relay-url> --relay <other-relay> <event-id>
nak encode nsec <privkey-hex>`, nak encode nsec <privkey-hex>`,
Before: func(c *cli.Context) error { Before: func(ctx context.Context, c *cli.Command) error {
if c.Args().Len() < 1 { if c.Args().Len() < 1 {
return fmt.Errorf("expected more than 1 argument.") return fmt.Errorf("expected more than 1 argument.")
} }
return nil return nil
}, },
Subcommands: []*cli.Command{ Commands: []*cli.Command{
{ {
Name: "npub", Name: "npub",
Usage: "encode a hex public key into bech32 'npub' format", Usage: "encode a hex public key into bech32 'npub' format",
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
for target := range getStdinLinesOrArguments(c.Args()) { for target := range getStdinLinesOrArguments(c.Args()) {
if ok := nostr.IsValidPublicKey(target); !ok { if ok := nostr.IsValidPublicKey(target); !ok {
lineProcessingError(c, "invalid public key: %s", target) lineProcessingError(ctx, "invalid public key: %s", target)
continue continue
} }
@ -42,17 +43,17 @@ var encode = &cli.Command{
} }
} }
exitIfLineProcessingError(c) exitIfLineProcessingError(ctx)
return nil return nil
}, },
}, },
{ {
Name: "nsec", Name: "nsec",
Usage: "encode a hex private key into bech32 'nsec' format", Usage: "encode a hex private key into bech32 'nsec' format",
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
for target := range getStdinLinesOrArguments(c.Args()) { for target := range getStdinLinesOrArguments(c.Args()) {
if ok := nostr.IsValid32ByteHex(target); !ok { if ok := nostr.IsValid32ByteHex(target); !ok {
lineProcessingError(c, "invalid private key: %s", target) lineProcessingError(ctx, "invalid private key: %s", target)
continue continue
} }
@ -63,7 +64,7 @@ var encode = &cli.Command{
} }
} }
exitIfLineProcessingError(c) exitIfLineProcessingError(ctx)
return nil return nil
}, },
}, },
@ -77,10 +78,10 @@ var encode = &cli.Command{
Usage: "attach relay hints to nprofile code", Usage: "attach relay hints to nprofile code",
}, },
}, },
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
for target := range getStdinLinesOrArguments(c.Args()) { for target := range getStdinLinesOrArguments(c.Args()) {
if ok := nostr.IsValid32ByteHex(target); !ok { if ok := nostr.IsValid32ByteHex(target); !ok {
lineProcessingError(c, "invalid public key: %s", target) lineProcessingError(ctx, "invalid public key: %s", target)
continue continue
} }
@ -96,7 +97,7 @@ var encode = &cli.Command{
} }
} }
exitIfLineProcessingError(c) exitIfLineProcessingError(ctx)
return nil return nil
}, },
}, },
@ -115,10 +116,10 @@ var encode = &cli.Command{
Usage: "attach an author pubkey as a hint to the nevent code", Usage: "attach an author pubkey as a hint to the nevent code",
}, },
}, },
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
for target := range getStdinLinesOrArguments(c.Args()) { for target := range getStdinLinesOrArguments(c.Args()) {
if ok := nostr.IsValid32ByteHex(target); !ok { if ok := nostr.IsValid32ByteHex(target); !ok {
lineProcessingError(c, "invalid event id: %s", target) lineProcessingError(ctx, "invalid event id: %s", target)
continue continue
} }
@ -141,7 +142,7 @@ var encode = &cli.Command{
} }
} }
exitIfLineProcessingError(c) exitIfLineProcessingError(ctx)
return nil return nil
}, },
}, },
@ -161,7 +162,7 @@ var encode = &cli.Command{
Aliases: []string{"author", "a", "p"}, Aliases: []string{"author", "a", "p"},
Required: true, Required: true,
}, },
&cli.Int64Flag{ &cli.IntFlag{
Name: "kind", Name: "kind",
Aliases: []string{"k"}, Aliases: []string{"k"},
Usage: "kind of referred replaceable event", Usage: "kind of referred replaceable event",
@ -173,7 +174,7 @@ var encode = &cli.Command{
Usage: "attach relay hints to naddr code", Usage: "attach relay hints to naddr code",
}, },
}, },
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
for d := range getStdinLinesOrBlank() { for d := range getStdinLinesOrBlank() {
pubkey := c.String("pubkey") pubkey := c.String("pubkey")
if ok := nostr.IsValidPublicKey(pubkey); !ok { if ok := nostr.IsValidPublicKey(pubkey); !ok {
@ -188,7 +189,7 @@ var encode = &cli.Command{
if d == "" { if d == "" {
d = c.String("identifier") d = c.String("identifier")
if d == "" { if d == "" {
lineProcessingError(c, "\"d\" tag identifier can't be empty") lineProcessingError(ctx, "\"d\" tag identifier can't be empty")
continue continue
} }
} }
@ -198,24 +199,24 @@ var encode = &cli.Command{
return err return err
} }
if npub, err := nip19.EncodeEntity(pubkey, kind, d, relays); err == nil { if npub, err := nip19.EncodeEntity(pubkey, int(kind), d, relays); err == nil {
stdout(npub) stdout(npub)
} else { } else {
return err return err
} }
} }
exitIfLineProcessingError(c) exitIfLineProcessingError(ctx)
return nil return nil
}, },
}, },
{ {
Name: "note", Name: "note",
Usage: "generate note1 event codes (not recommended)", Usage: "generate note1 event codes (not recommended)",
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
for target := range getStdinLinesOrArguments(c.Args()) { for target := range getStdinLinesOrArguments(c.Args()) {
if ok := nostr.IsValid32ByteHex(target); !ok { if ok := nostr.IsValid32ByteHex(target); !ok {
lineProcessingError(c, "invalid event id: %s", target) lineProcessingError(ctx, "invalid event id: %s", target)
continue continue
} }
@ -226,7 +227,7 @@ var encode = &cli.Command{
} }
} }
exitIfLineProcessingError(c) exitIfLineProcessingError(ctx)
return nil return nil
}, },
}, },

View File

@ -13,7 +13,7 @@ import (
"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/nson" "github.com/nbd-wtf/go-nostr/nson"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v3"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
) )
@ -36,7 +36,7 @@ example:
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
Name: "sec", Name: "sec",
Usage: "secret key to sign the event, as hex or nsec", Usage: "secret key to sign the event, as nsec, ncryptsec or hex",
DefaultText: "the key '1'", DefaultText: "the key '1'",
Value: "0000000000000000000000000000000000000000000000000000000000000001", Value: "0000000000000000000000000000000000000000000000000000000000000001",
}, },
@ -141,11 +141,11 @@ example:
}, },
}, },
ArgsUsage: "[relay...]", ArgsUsage: "[relay...]",
Action: func(c *cli.Context) 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
if relayUrls := c.Args().Slice(); len(relayUrls) > 0 { if relayUrls := c.Args().Slice(); len(relayUrls) > 0 {
_, relays = connectToAllRelays(c.Context, relayUrls) _, relays = connectToAllRelays(ctx, relayUrls)
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)
@ -158,7 +158,7 @@ example:
} }
}() }()
sec, bunker, err := gatherSecretKeyOrBunkerFromArguments(c) sec, bunker, err := gatherSecretKeyOrBunkerFromArguments(ctx, c)
if err != nil { if err != nil {
return err return err
} }
@ -176,14 +176,14 @@ example:
if stdinEvent != "" { if stdinEvent != "" {
if err := easyjson.Unmarshal([]byte(stdinEvent), &evt); err != nil { if err := easyjson.Unmarshal([]byte(stdinEvent), &evt); err != nil {
lineProcessingError(c, "invalid event received from stdin: %s", err) lineProcessingError(ctx, "invalid event received from stdin: %s", err)
continue continue
} }
kindWasSupplied = strings.Contains(stdinEvent, `"kind"`) kindWasSupplied = strings.Contains(stdinEvent, `"kind"`)
} }
if kind := c.Int("kind"); slices.Contains(c.FlagNames(), "kind") { if kind := c.Int("kind"); slices.Contains(c.FlagNames(), "kind") {
evt.Kind = kind evt.Kind = int(kind)
mustRehashAndResign = true mustRehashAndResign = true
} else if !kindWasSupplied { } else if !kindWasSupplied {
evt.Kind = 1 evt.Kind = 1
@ -248,7 +248,7 @@ example:
if evt.Sig == "" || mustRehashAndResign { if evt.Sig == "" || mustRehashAndResign {
if bunker != nil { if bunker != nil {
if err := bunker.SignEvent(c.Context, &evt); err != nil { if err := bunker.SignEvent(ctx, &evt); err != nil {
return fmt.Errorf("failed to sign with bunker: %w", err) return fmt.Errorf("failed to sign with bunker: %w", err)
} }
} else if numSigners := c.Uint("musig"); numSigners > 1 && sec != "" { } else if numSigners := c.Uint("musig"); numSigners > 1 && sec != "" {
@ -256,7 +256,7 @@ example:
secNonce := c.String("musig-nonce-secret") secNonce := c.String("musig-nonce-secret")
pubNonces := c.StringSlice("musig-nonce") pubNonces := c.StringSlice("musig-nonce")
partialSigs := c.StringSlice("musig-partial") partialSigs := c.StringSlice("musig-partial")
signed, err := performMusig(c.Context, signed, err := performMusig(ctx,
sec, &evt, int(numSigners), pubkeys, pubNonces, secNonce, partialSigs) sec, &evt, int(numSigners), pubkeys, pubNonces, secNonce, partialSigs)
if err != nil { if err != nil {
return fmt.Errorf("musig error: %w", err) return fmt.Errorf("musig error: %w", err)
@ -291,7 +291,7 @@ example:
for _, relay := range relays { for _, relay := range relays {
publish: publish:
log("publishing to %s... ", relay.URL) log("publishing to %s... ", relay.URL)
ctx, cancel := context.WithTimeout(c.Context, 10*time.Second) ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel() defer cancel()
err := relay.Publish(ctx, evt) err := relay.Publish(ctx, evt)
@ -307,7 +307,7 @@ example:
// if the relay is requesting auth and we can auth, let's do it // if the relay is requesting auth and we can auth, let's do it
var pk string var pk string
if bunker != nil { if bunker != nil {
pk, err = bunker.GetPublicKey(c.Context) pk, err = bunker.GetPublicKey(ctx)
if err != nil { if err != nil {
return fmt.Errorf("failed to get public key from bunker: %w", err) return fmt.Errorf("failed to get public key from bunker: %w", err)
} }
@ -315,9 +315,9 @@ example:
pk, _ = nostr.GetPublicKey(sec) pk, _ = nostr.GetPublicKey(sec)
} }
log("performing auth as %s... ", pk) log("performing auth as %s... ", pk)
if err := relay.Auth(c.Context, func(evt *nostr.Event) error { if err := relay.Auth(ctx, func(evt *nostr.Event) error {
if bunker != nil { if bunker != nil {
return bunker.SignEvent(c.Context, evt) return bunker.SignEvent(ctx, evt)
} }
return evt.Sign(sec) return evt.Sign(sec)
}); err == nil { }); err == nil {
@ -337,7 +337,7 @@ example:
} }
} }
exitIfLineProcessingError(c) exitIfLineProcessingError(ctx)
return nil return nil
}, },
} }

View File

@ -1,10 +1,12 @@
package main package main
import ( import (
"context"
"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"
sdk "github.com/nbd-wtf/nostr-sdk" sdk "github.com/nbd-wtf/nostr-sdk"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v3"
) )
var fetch = &cli.Command{ var fetch = &cli.Command{
@ -21,8 +23,8 @@ var fetch = &cli.Command{
}, },
}, },
ArgsUsage: "[nip19code]", ArgsUsage: "[nip19code]",
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
pool := nostr.NewSimplePool(c.Context) pool := nostr.NewSimplePool(ctx)
defer func() { defer func() {
pool.Relays.Range(func(_ string, relay *nostr.Relay) bool { pool.Relays.Range(func(_ string, relay *nostr.Relay) bool {
@ -36,7 +38,7 @@ var fetch = &cli.Command{
prefix, value, err := nip19.Decode(code) prefix, value, err := nip19.Decode(code)
if err != nil { if err != nil {
lineProcessingError(c, "failed to decode: %s", err) lineProcessingError(ctx, "failed to decode: %s", err)
continue continue
} }
@ -75,7 +77,7 @@ var fetch = &cli.Command{
} }
if authorHint != "" { if authorHint != "" {
relayList := sdk.FetchRelaysForPubkey(c.Context, pool, authorHint, relayList := sdk.FetchRelaysForPubkey(ctx, pool, authorHint,
"wss://purplepag.es", "wss://relay.damus.io", "wss://relay.noswhere.com", "wss://purplepag.es", "wss://relay.damus.io", "wss://relay.noswhere.com",
"wss://nos.lol", "wss://public.relaying.io", "wss://relay.nostr.band") "wss://nos.lol", "wss://public.relaying.io", "wss://relay.nostr.band")
for _, relayListItem := range relayList { for _, relayListItem := range relayList {
@ -86,16 +88,16 @@ var fetch = &cli.Command{
} }
if len(relays) == 0 { if len(relays) == 0 {
lineProcessingError(c, "no relay hints found") lineProcessingError(ctx, "no relay hints found")
continue continue
} }
for ie := range pool.SubManyEose(c.Context, relays, nostr.Filters{filter}) { for ie := range pool.SubManyEose(ctx, relays, nostr.Filters{filter}) {
stdout(ie.Event) stdout(ie.Event)
} }
} }
exitIfLineProcessingError(c) exitIfLineProcessingError(ctx)
return nil return nil
}, },
} }

6
go.mod
View File

@ -7,11 +7,12 @@ toolchain go1.21.0
require ( require (
github.com/btcsuite/btcd/btcec/v2 v2.3.3 github.com/btcsuite/btcd/btcec/v2 v2.3.3
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0
github.com/fatih/color v1.16.0 github.com/fatih/color v1.16.0
github.com/mailru/easyjson v0.7.7 github.com/mailru/easyjson v0.7.7
github.com/nbd-wtf/go-nostr v0.31.2 github.com/nbd-wtf/go-nostr v0.31.2
github.com/nbd-wtf/nostr-sdk v0.0.5 github.com/nbd-wtf/nostr-sdk v0.0.5
github.com/urfave/cli/v2 v2.25.7 github.com/urfave/cli/v3 v3.0.0-alpha9
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
) )
@ -20,9 +21,7 @@ require (
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
github.com/chzyer/logex v1.1.10 // indirect github.com/chzyer/logex v1.1.10 // indirect
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/fiatjaf/eventstore v0.2.16 // indirect github.com/fiatjaf/eventstore v0.2.16 // indirect
github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect github.com/gobwas/pool v0.2.1 // indirect
@ -31,7 +30,6 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/puzpuzpuz/xsync/v3 v3.1.0 // indirect github.com/puzpuzpuz/xsync/v3 v3.1.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/tidwall/gjson v1.17.1 // indirect github.com/tidwall/gjson v1.17.1 // indirect
github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect

8
go.sum
View File

@ -29,8 +29,6 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5O
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
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=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@ -96,8 +94,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/puzpuzpuz/xsync/v3 v3.1.0 h1:EewKT7/LNac5SLiEblJeUu8z5eERHrmRLnMQL2d7qX4= github.com/puzpuzpuz/xsync/v3 v3.1.0 h1:EewKT7/LNac5SLiEblJeUu8z5eERHrmRLnMQL2d7qX4=
github.com/puzpuzpuz/xsync/v3 v3.1.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/puzpuzpuz/xsync/v3 v3.1.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
@ -110,8 +106,8 @@ github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JT
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v3 v3.0.0-alpha9 h1:P0RMy5fQm1AslQS+XCmy9UknDXctOmG/q/FZkUFnJSo=
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/cli/v3 v3.0.0-alpha9/go.mod h1:0kK/RUFHyh+yIKSfWxwheGndfnrvYSmYFVeKCh03ZUc=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=

View File

@ -16,7 +16,7 @@ import (
"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/nbd-wtf/go-nostr/nip49" "github.com/nbd-wtf/go-nostr/nip49"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v3"
) )
const ( const (
@ -133,18 +133,18 @@ func connectToAllRelays(
return pool, relays return pool, relays
} }
func lineProcessingError(c *cli.Context, msg string, args ...any) { func lineProcessingError(ctx context.Context, msg string, args ...any) {
c.Context = context.WithValue(c.Context, LINE_PROCESSING_ERROR, true) ctx = context.WithValue(ctx, LINE_PROCESSING_ERROR, true)
log(msg+"\n", args...) log(msg+"\n", args...)
} }
func exitIfLineProcessingError(c *cli.Context) { func exitIfLineProcessingError(ctx context.Context) {
if val := c.Context.Value(LINE_PROCESSING_ERROR); val != nil && val.(bool) { if val := ctx.Value(LINE_PROCESSING_ERROR); val != nil && val.(bool) {
os.Exit(123) os.Exit(123)
} }
} }
func gatherSecretKeyOrBunkerFromArguments(c *cli.Context) (string, *nip46.BunkerClient, error) { func gatherSecretKeyOrBunkerFromArguments(ctx context.Context, c *cli.Command) (string, *nip46.BunkerClient, error) {
var err error var err error
if bunkerURL := c.String("connect"); bunkerURL != "" { if bunkerURL := c.String("connect"); bunkerURL != "" {
@ -154,7 +154,7 @@ func gatherSecretKeyOrBunkerFromArguments(c *cli.Context) (string, *nip46.Bunker
} else { } else {
clientKey = nostr.GeneratePrivateKey() clientKey = nostr.GeneratePrivateKey()
} }
bunker, err := nip46.ConnectBunker(c.Context, clientKey, bunkerURL, nil, func(s string) { bunker, err := nip46.ConnectBunker(ctx, clientKey, bunkerURL, nil, func(s string) {
fmt.Fprintf(color.Error, color.CyanString("[nip46]: open the following URL: %s"), s) fmt.Fprintf(color.Error, color.CyanString("[nip46]: open the following URL: %s"), s)
}) })
return "", bunker, err return "", bunker, err

31
key.go
View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -13,14 +14,14 @@ import (
"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/nip49" "github.com/nbd-wtf/go-nostr/nip49"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v3"
) )
var key = &cli.Command{ var key = &cli.Command{
Name: "key", Name: "key",
Usage: "operations on secret keys: generate, derive, encrypt, decrypt.", Usage: "operations on secret keys: generate, derive, encrypt, decrypt.",
Description: ``, Description: ``,
Subcommands: []*cli.Command{ Commands: []*cli.Command{
generate, generate,
public, public,
encrypt, encrypt,
@ -33,7 +34,7 @@ var generate = &cli.Command{
Name: "generate", Name: "generate",
Usage: "generates a secret key", Usage: "generates a secret key",
Description: ``, Description: ``,
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
sec := nostr.GeneratePrivateKey() sec := nostr.GeneratePrivateKey()
stdout(sec) stdout(sec)
return nil return nil
@ -45,11 +46,11 @@ var public = &cli.Command{
Usage: "computes a public key from a secret key", Usage: "computes a public key from a secret key",
Description: ``, Description: ``,
ArgsUsage: "[secret]", ArgsUsage: "[secret]",
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
for sec := range getSecretKeysFromStdinLinesOrSlice(c, c.Args().Slice()) { for sec := range getSecretKeysFromStdinLinesOrSlice(ctx, c, c.Args().Slice()) {
pubkey, err := nostr.GetPublicKey(sec) pubkey, err := nostr.GetPublicKey(sec)
if err != nil { if err != nil {
lineProcessingError(c, "failed to derive public key: %s", err) lineProcessingError(ctx, "failed to derive public key: %s", err)
continue continue
} }
stdout(pubkey) stdout(pubkey)
@ -71,7 +72,7 @@ var encrypt = &cli.Command{
DefaultText: "16", DefaultText: "16",
}, },
}, },
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
keys := make([]string, 0, 1) keys := make([]string, 0, 1)
var password string var password string
switch c.Args().Len() { switch c.Args().Len() {
@ -84,10 +85,10 @@ var encrypt = &cli.Command{
if password == "" { if password == "" {
return fmt.Errorf("no password given") return fmt.Errorf("no password given")
} }
for sec := range getSecretKeysFromStdinLinesOrSlice(c, keys) { for sec := range getSecretKeysFromStdinLinesOrSlice(ctx, c, keys) {
ncryptsec, err := nip49.Encrypt(sec, password, uint8(c.Int("logn")), 0x02) ncryptsec, err := nip49.Encrypt(sec, password, uint8(c.Int("logn")), 0x02)
if err != nil { if err != nil {
lineProcessingError(c, "failed to encrypt: %s", err) lineProcessingError(ctx, "failed to encrypt: %s", err)
continue continue
} }
stdout(ncryptsec) stdout(ncryptsec)
@ -101,7 +102,7 @@ var decrypt = &cli.Command{
Usage: "takes an ncrypsec and a password and decrypts it into an nsec", Usage: "takes an ncrypsec and a password and decrypts it into an nsec",
Description: `uses the NIP-49 standard.`, Description: `uses the NIP-49 standard.`,
ArgsUsage: "<ncryptsec-code> <password>", ArgsUsage: "<ncryptsec-code> <password>",
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
var ncryptsec string var ncryptsec string
var password string var password string
switch c.Args().Len() { switch c.Args().Len() {
@ -132,7 +133,7 @@ var decrypt = &cli.Command{
for ncryptsec := range getStdinLinesOrArgumentsFromSlice([]string{ncryptsec}) { for ncryptsec := range getStdinLinesOrArgumentsFromSlice([]string{ncryptsec}) {
sec, err := nip49.Decrypt(ncryptsec, password) sec, err := nip49.Decrypt(ncryptsec, password)
if err != nil { if err != nil {
lineProcessingError(c, "failed to decrypt: %s", err) lineProcessingError(ctx, "failed to decrypt: %s", err)
continue continue
} }
nsec, _ := nip19.EncodePrivateKey(sec) nsec, _ := nip19.EncodePrivateKey(sec)
@ -153,7 +154,7 @@ var combine = &cli.Command{
However, if the intent is to check if two existing Nostr pubkeys match a given combined pubkey, then it might be sufficient to calculate the combined key for all the possible combinations of pubkeys in the input.`, However, if the intent is to check if two existing Nostr pubkeys match a given combined pubkey, then it might be sufficient to calculate the combined key for all the possible combinations of pubkeys in the input.`,
ArgsUsage: "[pubkey...]", ArgsUsage: "[pubkey...]",
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
type Combination struct { type Combination struct {
Variants []string `json:"input_variants"` Variants []string `json:"input_variants"`
Output struct { Output struct {
@ -253,7 +254,7 @@ However, if the intent is to check if two existing Nostr pubkeys match a given c
}, },
} }
func getSecretKeysFromStdinLinesOrSlice(c *cli.Context, keys []string) chan string { func getSecretKeysFromStdinLinesOrSlice(ctx context.Context, c *cli.Command, keys []string) chan string {
ch := make(chan string) ch := make(chan string)
go func() { go func() {
for sec := range getStdinLinesOrArgumentsFromSlice(keys) { for sec := range getStdinLinesOrArgumentsFromSlice(keys) {
@ -263,13 +264,13 @@ func getSecretKeysFromStdinLinesOrSlice(c *cli.Context, keys []string) chan stri
if strings.HasPrefix(sec, "nsec1") { if strings.HasPrefix(sec, "nsec1") {
_, data, err := nip19.Decode(sec) _, data, err := nip19.Decode(sec)
if err != nil { if err != nil {
lineProcessingError(c, "invalid nsec code: %s", err) lineProcessingError(ctx, "invalid nsec code: %s", err)
continue continue
} }
sec = data.(string) sec = data.(string)
} }
if !nostr.IsValid32ByteHex(sec) { if !nostr.IsValid32ByteHex(sec) {
lineProcessingError(c, "invalid hex key") lineProcessingError(ctx, "invalid hex key")
continue continue
} }
ch <- sec ch <- sec

13
main.go
View File

@ -1,14 +1,13 @@
package main package main
import ( import (
"context"
"os" "os"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v3"
) )
var q int var app = &cli.Command{
var app = &cli.App{
Name: "nak", Name: "nak",
Suggest: true, Suggest: true,
UseShortOptionHandling: true, UseShortOptionHandling: true,
@ -29,9 +28,9 @@ var app = &cli.App{
&cli.BoolFlag{ &cli.BoolFlag{
Name: "quiet", Name: "quiet",
Usage: "do not print logs and info messages to stderr, use -qq to also not print anything to stdout", Usage: "do not print logs and info messages to stderr, use -qq to also not print anything to stdout",
Count: &q,
Aliases: []string{"q"}, Aliases: []string{"q"},
Action: func(ctx *cli.Context, b bool) error { Action: func(ctx context.Context, c *cli.Command, b bool) error {
q := c.Count("quiet")
if q >= 1 { if q >= 1 {
log = func(msg string, args ...any) {} log = func(msg string, args ...any) {}
if q >= 2 { if q >= 2 {
@ -45,7 +44,7 @@ var app = &cli.App{
} }
func main() { func main() {
if err := app.Run(os.Args); err != nil { if err := app.Run(context.Background(), os.Args); err != nil {
stdout(err) stdout(err)
os.Exit(1) os.Exit(1)
} }

View File

@ -1,12 +1,13 @@
package main package main
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings" "strings"
"github.com/nbd-wtf/go-nostr/nip11" "github.com/nbd-wtf/go-nostr/nip11"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v3"
) )
var relay = &cli.Command{ var relay = &cli.Command{
@ -15,7 +16,7 @@ var relay = &cli.Command{
Description: `example: Description: `example:
nak relay nostr.wine`, nak relay nostr.wine`,
ArgsUsage: "<relay-url>", ArgsUsage: "<relay-url>",
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
for url := range getStdinLinesOrArguments(c.Args()) { for url := range getStdinLinesOrArguments(c.Args()) {
if url == "" { if url == "" {
return fmt.Errorf("specify the <relay-url>") return fmt.Errorf("specify the <relay-url>")
@ -25,9 +26,9 @@ var relay = &cli.Command{
url = "wss://" + url url = "wss://" + url
} }
info, err := nip11.Fetch(c.Context, url) info, err := nip11.Fetch(ctx, url)
if err != nil { if err != nil {
lineProcessingError(c, "failed to fetch '%s' information document: %w", url, err) lineProcessingError(ctx, "failed to fetch '%s' information document: %w", url, err)
continue continue
} }

25
req.go
View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"os" "os"
@ -9,7 +10,7 @@ import (
"github.com/mailru/easyjson" "github.com/mailru/easyjson"
"github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v3"
) )
const CATEGORY_FILTER_ATTRIBUTES = "FILTER ATTRIBUTES" const CATEGORY_FILTER_ATTRIBUTES = "FILTER ATTRIBUTES"
@ -124,23 +125,23 @@ example:
}, },
}, },
ArgsUsage: "[relay...]", ArgsUsage: "[relay...]",
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
var pool *nostr.SimplePool var pool *nostr.SimplePool
relayUrls := c.Args().Slice() relayUrls := c.Args().Slice()
if len(relayUrls) > 0 { if len(relayUrls) > 0 {
var relays []*nostr.Relay var relays []*nostr.Relay
pool, relays = connectToAllRelays(c.Context, relayUrls, nostr.WithAuthHandler(func(evt *nostr.Event) error { pool, relays = connectToAllRelays(ctx, relayUrls, nostr.WithAuthHandler(func(evt *nostr.Event) error {
if !c.Bool("auth") { if !c.Bool("auth") {
return fmt.Errorf("auth not authorized") return fmt.Errorf("auth not authorized")
} }
sec, bunker, err := gatherSecretKeyOrBunkerFromArguments(c) sec, bunker, err := gatherSecretKeyOrBunkerFromArguments(ctx, c)
if err != nil { if err != nil {
return err return err
} }
var pk string var pk string
if bunker != nil { if bunker != nil {
pk, err = bunker.GetPublicKey(c.Context) pk, err = bunker.GetPublicKey(ctx)
if err != nil { if err != nil {
return fmt.Errorf("failed to get public key from bunker: %w", err) return fmt.Errorf("failed to get public key from bunker: %w", err)
} }
@ -150,7 +151,7 @@ example:
log("performing auth as %s...\n", pk) log("performing auth as %s...\n", pk)
if bunker != nil { if bunker != nil {
return bunker.SignEvent(c.Context, evt) return bunker.SignEvent(ctx, evt)
} else { } else {
return evt.Sign(sec) return evt.Sign(sec)
} }
@ -175,7 +176,7 @@ example:
filter := nostr.Filter{} filter := nostr.Filter{}
if stdinFilter != "" { if stdinFilter != "" {
if err := easyjson.Unmarshal([]byte(stdinFilter), &filter); err != nil { if err := easyjson.Unmarshal([]byte(stdinFilter), &filter); err != nil {
lineProcessingError(c, "invalid filter '%s' received from stdin: %s", stdinFilter, err) lineProcessingError(ctx, "invalid filter '%s' received from stdin: %s", stdinFilter, err)
continue continue
} }
} }
@ -186,8 +187,8 @@ example:
if ids := c.StringSlice("id"); len(ids) > 0 { if ids := c.StringSlice("id"); len(ids) > 0 {
filter.IDs = append(filter.IDs, ids...) filter.IDs = append(filter.IDs, ids...)
} }
if kinds := c.IntSlice("kind"); len(kinds) > 0 { for _, kind64 := range c.IntSlice("kind") {
filter.Kinds = append(filter.Kinds, kinds...) filter.Kinds = append(filter.Kinds, int(kind64))
} }
if search := c.String("search"); search != "" { if search := c.String("search"); search != "" {
filter.Search = search filter.Search = search
@ -245,7 +246,7 @@ example:
} }
} }
if limit := c.Int("limit"); limit != 0 { if limit := c.Int("limit"); limit != 0 {
filter.Limit = limit filter.Limit = int(limit)
} else if c.IsSet("limit") || c.Bool("stream") { } else if c.IsSet("limit") || c.Bool("stream") {
filter.LimitZero = true filter.LimitZero = true
} }
@ -255,7 +256,7 @@ example:
if c.Bool("stream") { if c.Bool("stream") {
fn = pool.SubMany fn = pool.SubMany
} }
for ie := range fn(c.Context, relayUrls, nostr.Filters{filter}) { for ie := range fn(ctx, relayUrls, nostr.Filters{filter}) {
stdout(ie.Event) stdout(ie.Event)
} }
} else { } else {
@ -272,7 +273,7 @@ example:
} }
} }
exitIfLineProcessingError(c) exitIfLineProcessingError(ctx)
return nil return nil
}, },
} }

View File

@ -1,10 +1,11 @@
package main package main
import ( import (
"context"
"encoding/json" "encoding/json"
"github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v3"
) )
var verify = &cli.Command{ var verify = &cli.Command{
@ -14,28 +15,28 @@ var verify = &cli.Command{
echo '{"id":"a889df6a387419ff204305f4c2d296ee328c3cd4f8b62f205648a541b4554dfb","pubkey":"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5","created_at":1698623783,"kind":1,"tags":[],"content":"hello from the nostr army knife","sig":"84876e1ee3e726da84e5d195eb79358b2b3eaa4d9bd38456fde3e8a2af3f1cd4cda23f23fda454869975b3688797d4c66e12f4c51c1b43c6d2997c5e61865661"}' | nak verify echo '{"id":"a889df6a387419ff204305f4c2d296ee328c3cd4f8b62f205648a541b4554dfb","pubkey":"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5","created_at":1698623783,"kind":1,"tags":[],"content":"hello from the nostr army knife","sig":"84876e1ee3e726da84e5d195eb79358b2b3eaa4d9bd38456fde3e8a2af3f1cd4cda23f23fda454869975b3688797d4c66e12f4c51c1b43c6d2997c5e61865661"}' | nak verify
it outputs nothing if the verification is successful.`, it outputs nothing if the verification is successful.`,
Action: func(c *cli.Context) error { Action: func(ctx context.Context, c *cli.Command) error {
for stdinEvent := range getStdinLinesOrArguments(c.Args()) { for stdinEvent := range getStdinLinesOrArguments(c.Args()) {
evt := nostr.Event{} evt := nostr.Event{}
if stdinEvent != "" { if stdinEvent != "" {
if err := json.Unmarshal([]byte(stdinEvent), &evt); err != nil { if err := json.Unmarshal([]byte(stdinEvent), &evt); err != nil {
lineProcessingError(c, "invalid event: %s", err) lineProcessingError(ctx, "invalid event: %s", err)
continue continue
} }
} }
if evt.GetID() != evt.ID { if evt.GetID() != evt.ID {
lineProcessingError(c, "invalid .id, expected %s, got %s", evt.GetID(), evt.ID) lineProcessingError(ctx, "invalid .id, expected %s, got %s", evt.GetID(), evt.ID)
continue continue
} }
if ok, err := evt.CheckSignature(); !ok { if ok, err := evt.CheckSignature(); !ok {
lineProcessingError(c, "invalid signature: %s", err) lineProcessingError(ctx, "invalid signature: %s", err)
continue continue
} }
} }
exitIfLineProcessingError(c) exitIfLineProcessingError(ctx)
return nil return nil
}, },
} }