fix fetch with nip05 filter and make req filter options generalize to fetch.

related: https://github.com/fiatjaf/nak/issues/19
This commit is contained in:
fiatjaf 2024-08-20 10:59:28 -03:00
parent 2042b14578
commit ea7b88cfd7
2 changed files with 158 additions and 133 deletions

View File

@ -17,13 +17,13 @@ var fetch = &cli.Command{
nak fetch nevent1qqsxrwm0hd3s3fddh4jc2574z3xzufq6qwuyz2rvv3n087zvym3dpaqprpmhxue69uhhqatzd35kxtnjv4kxz7tfdenju6t0xpnej4 nak fetch nevent1qqsxrwm0hd3s3fddh4jc2574z3xzufq6qwuyz2rvv3n087zvym3dpaqprpmhxue69uhhqatzd35kxtnjv4kxz7tfdenju6t0xpnej4
echo npub1h8spmtw9m2huyv6v2j2qd5zv956z2zdugl6mgx02f2upffwpm3nqv0j4ps | nak fetch --relay wss://relay.nostr.band`, echo npub1h8spmtw9m2huyv6v2j2qd5zv956z2zdugl6mgx02f2upffwpm3nqv0j4ps | nak fetch --relay wss://relay.nostr.band`,
DisableSliceFlagSeparator: true, DisableSliceFlagSeparator: true,
Flags: []cli.Flag{ Flags: append(reqFilterFlags,
&cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "relay", Name: "relay",
Aliases: []string{"r"}, Aliases: []string{"r"},
Usage: "also use these relays to fetch from", Usage: "also use these relays to fetch from",
}, },
}, ),
ArgsUsage: "[nip05_or_nip19_code]", ArgsUsage: "[nip05_or_nip19_code]",
Action: func(ctx context.Context, c *cli.Command) error { Action: func(ctx context.Context, c *cli.Command) error {
sys := sdk.NewSystem() sys := sdk.NewSystem()
@ -48,6 +48,7 @@ var fetch = &cli.Command{
} }
authorHint = pp.PublicKey authorHint = pp.PublicKey
relays = append(relays, pp.Relays...) relays = append(relays, pp.Relays...)
filter.Authors = append(filter.Authors, pp.PublicKey)
} else { } else {
prefix, value, err := nip19.Decode(code) prefix, value, err := nip19.Decode(code)
if err != nil { if err != nil {
@ -70,20 +71,17 @@ var fetch = &cli.Command{
case "naddr": case "naddr":
v := value.(nostr.EntityPointer) v := value.(nostr.EntityPointer)
filter.Tags = nostr.TagMap{"d": []string{v.Identifier}} filter.Tags = nostr.TagMap{"d": []string{v.Identifier}}
filter.Kinds = append(filter.Kinds, v.Kind)
filter.Authors = append(filter.Authors, v.PublicKey) filter.Authors = append(filter.Authors, v.PublicKey)
authorHint = v.PublicKey authorHint = v.PublicKey
relays = append(relays, v.Relays...) relays = append(relays, v.Relays...)
case "nprofile": case "nprofile":
v := value.(nostr.ProfilePointer) v := value.(nostr.ProfilePointer)
filter.Authors = append(filter.Authors, v.PublicKey) filter.Authors = append(filter.Authors, v.PublicKey)
filter.Kinds = append(filter.Kinds, 0)
authorHint = v.PublicKey authorHint = v.PublicKey
relays = append(relays, v.Relays...) relays = append(relays, v.Relays...)
case "npub": case "npub":
v := value.(string) v := value.(string)
filter.Authors = append(filter.Authors, v) filter.Authors = append(filter.Authors, v)
filter.Kinds = append(filter.Kinds, 0)
authorHint = v authorHint = v
} }
} }
@ -93,6 +91,14 @@ var fetch = &cli.Command{
for _, url := range relays { for _, url := range relays {
relays = append(relays, url) relays = append(relays, url)
} }
if len(filter.Kinds) == 0 {
filter.Kinds = append(filter.Kinds, 0)
}
}
if err := applyFlagsToFilter(c, &filter); err != nil {
return err
} }
if len(relays) == 0 { if len(relays) == 0 {

275
req.go
View File

@ -12,7 +12,10 @@ import (
"github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr"
) )
const CATEGORY_FILTER_ATTRIBUTES = "FILTER ATTRIBUTES" const (
CATEGORY_FILTER_ATTRIBUTES = "FILTER ATTRIBUTES"
// CATEGORY_SIGNER = "SIGNER OPTIONS" -- defined at event.go as the same (yes, I know)
)
var req = &cli.Command{ var req = &cli.Command{
Name: "req", Name: "req",
@ -28,69 +31,7 @@ it can also take a filter from stdin, optionally modify it with flags and send i
example: example:
echo '{"kinds": [1], "#t": ["test"]}' | nak req -l 5 -k 4549 --tag t=spam wss://nostr-pub.wellorder.net`, echo '{"kinds": [1], "#t": ["test"]}' | nak req -l 5 -k 4549 --tag t=spam wss://nostr-pub.wellorder.net`,
DisableSliceFlagSeparator: true, DisableSliceFlagSeparator: true,
Flags: []cli.Flag{ Flags: append(reqFilterFlags,
&cli.StringSliceFlag{
Name: "author",
Aliases: []string{"a"},
Usage: "only accept events from these authors (pubkey as hex)",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.StringSliceFlag{
Name: "id",
Aliases: []string{"i"},
Usage: "only accept events with these ids (hex)",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.IntSliceFlag{
Name: "kind",
Aliases: []string{"k"},
Usage: "only accept events with these kind numbers",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.StringSliceFlag{
Name: "tag",
Aliases: []string{"t"},
Usage: "takes a tag like -t e=<id>, only accept events with these tags",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.StringSliceFlag{
Name: "e",
Usage: "shortcut for --tag e=<value>",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.StringSliceFlag{
Name: "p",
Usage: "shortcut for --tag p=<value>",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.StringSliceFlag{
Name: "d",
Usage: "shortcut for --tag d=<value>",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&NaturalTimeFlag{
Name: "since",
Aliases: []string{"s"},
Usage: "only accept events newer than this (unix timestamp)",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&NaturalTimeFlag{
Name: "until",
Aliases: []string{"u"},
Usage: "only accept events older than this (unix timestamp)",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.UintFlag{
Name: "limit",
Aliases: []string{"l"},
Usage: "only accept up to this number of events",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.StringFlag{
Name: "search",
Usage: "a NIP-50 search query, use it only with relays that explicitly support it",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.BoolFlag{ &cli.BoolFlag{
Name: "stream", Name: "stream",
Usage: "keep the subscription open, printing all events as they are returned", Usage: "keep the subscription open, printing all events as they are returned",
@ -119,30 +60,35 @@ example:
Usage: "always perform NIP-42 \"AUTH\" when facing an \"auth-required: \" rejection and try again", Usage: "always perform NIP-42 \"AUTH\" when facing an \"auth-required: \" rejection and try again",
}, },
&cli.BoolFlag{ &cli.BoolFlag{
Name: "force-pre-auth", Name: "force-pre-auth",
Aliases: []string{"fpa"}, Aliases: []string{"fpa"},
Usage: "after connecting, for a NIP-42 \"AUTH\" message to be received, act on it and only then send the \"REQ\"", Usage: "after connecting, for a NIP-42 \"AUTH\" message to be received, act on it and only then send the \"REQ\"",
Category: CATEGORY_SIGNER,
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "sec", Name: "sec",
Usage: "secret key to sign the AUTH challenge, as hex or nsec", Usage: "secret key to sign the AUTH challenge, as hex or nsec",
DefaultText: "the key '1'", DefaultText: "the key '1'",
Value: "0000000000000000000000000000000000000000000000000000000000000001", Value: "0000000000000000000000000000000000000000000000000000000000000001",
Category: CATEGORY_SIGNER,
}, },
&cli.BoolFlag{ &cli.BoolFlag{
Name: "prompt-sec", Name: "prompt-sec",
Usage: "prompt the user to paste a hex or nsec with which to sign the AUTH challenge", Usage: "prompt the user to paste a hex or nsec with which to sign the AUTH challenge",
Category: CATEGORY_SIGNER,
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "connect", Name: "connect",
Usage: "sign AUTH using NIP-46, expects a bunker://... URL", Usage: "sign AUTH using NIP-46, expects a bunker://... URL",
Category: CATEGORY_SIGNER,
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "connect-as", Name: "connect-as",
Usage: "private key to when communicating with the bunker given on --connect", Usage: "private key to when communicating with the bunker given on --connect",
DefaultText: "a random key", DefaultText: "a random key",
Category: CATEGORY_SIGNER,
}, },
}, ),
ArgsUsage: "[relay...]", ArgsUsage: "[relay...]",
Action: func(ctx context.Context, c *cli.Command) error { Action: func(ctx context.Context, c *cli.Command) error {
var pool *nostr.SimplePool var pool *nostr.SimplePool
@ -201,62 +147,8 @@ example:
} }
} }
if authors := c.StringSlice("author"); len(authors) > 0 { if err := applyFlagsToFilter(c, &filter); err != nil {
filter.Authors = append(filter.Authors, authors...) return err
}
if ids := c.StringSlice("id"); len(ids) > 0 {
filter.IDs = append(filter.IDs, ids...)
}
for _, kind64 := range c.IntSlice("kind") {
filter.Kinds = append(filter.Kinds, int(kind64))
}
if search := c.String("search"); search != "" {
filter.Search = search
}
tags := make([][]string, 0, 5)
for _, tagFlag := range c.StringSlice("tag") {
spl := strings.Split(tagFlag, "=")
if len(spl) == 2 && len(spl[0]) == 1 {
tags = append(tags, spl)
} else {
return fmt.Errorf("invalid --tag '%s'", tagFlag)
}
}
for _, etag := range c.StringSlice("e") {
tags = append(tags, []string{"e", etag})
}
for _, ptag := range c.StringSlice("p") {
tags = append(tags, []string{"p", ptag})
}
for _, dtag := range c.StringSlice("d") {
tags = append(tags, []string{"d", dtag})
}
if len(tags) > 0 && filter.Tags == nil {
filter.Tags = make(nostr.TagMap)
}
for _, tag := range tags {
if _, ok := filter.Tags[tag[0]]; !ok {
filter.Tags[tag[0]] = make([]string, 0, 3)
}
filter.Tags[tag[0]] = append(filter.Tags[tag[0]], tag[1])
}
if c.IsSet("since") {
nts := getNaturalDate(c, "since")
filter.Since = &nts
}
if c.IsSet("until") {
nts := getNaturalDate(c, "until")
filter.Until = &nts
}
if limit := c.Uint("limit"); limit != 0 {
filter.Limit = int(limit)
} else if c.IsSet("limit") {
filter.LimitZero = true
} }
if len(relayUrls) > 0 { if len(relayUrls) > 0 {
@ -288,3 +180,130 @@ example:
return nil return nil
}, },
} }
var reqFilterFlags = []cli.Flag{
&cli.StringSliceFlag{
Name: "author",
Aliases: []string{"a"},
Usage: "only accept events from these authors (pubkey as hex)",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.StringSliceFlag{
Name: "id",
Aliases: []string{"i"},
Usage: "only accept events with these ids (hex)",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.IntSliceFlag{
Name: "kind",
Aliases: []string{"k"},
Usage: "only accept events with these kind numbers",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.StringSliceFlag{
Name: "tag",
Aliases: []string{"t"},
Usage: "takes a tag like -t e=<id>, only accept events with these tags",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.StringSliceFlag{
Name: "e",
Usage: "shortcut for --tag e=<value>",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.StringSliceFlag{
Name: "p",
Usage: "shortcut for --tag p=<value>",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.StringSliceFlag{
Name: "d",
Usage: "shortcut for --tag d=<value>",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&NaturalTimeFlag{
Name: "since",
Aliases: []string{"s"},
Usage: "only accept events newer than this (unix timestamp)",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&NaturalTimeFlag{
Name: "until",
Aliases: []string{"u"},
Usage: "only accept events older than this (unix timestamp)",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.UintFlag{
Name: "limit",
Aliases: []string{"l"},
Usage: "only accept up to this number of events",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
&cli.StringFlag{
Name: "search",
Usage: "a NIP-50 search query, use it only with relays that explicitly support it",
Category: CATEGORY_FILTER_ATTRIBUTES,
},
}
func applyFlagsToFilter(c *cli.Command, filter *nostr.Filter) error {
if authors := c.StringSlice("author"); len(authors) > 0 {
filter.Authors = append(filter.Authors, authors...)
}
if ids := c.StringSlice("id"); len(ids) > 0 {
filter.IDs = append(filter.IDs, ids...)
}
for _, kind64 := range c.IntSlice("kind") {
filter.Kinds = append(filter.Kinds, int(kind64))
}
if search := c.String("search"); search != "" {
filter.Search = search
}
tags := make([][]string, 0, 5)
for _, tagFlag := range c.StringSlice("tag") {
spl := strings.Split(tagFlag, "=")
if len(spl) == 2 && len(spl[0]) == 1 {
tags = append(tags, spl)
} else {
return fmt.Errorf("invalid --tag '%s'", tagFlag)
}
}
for _, etag := range c.StringSlice("e") {
tags = append(tags, []string{"e", etag})
}
for _, ptag := range c.StringSlice("p") {
tags = append(tags, []string{"p", ptag})
}
for _, dtag := range c.StringSlice("d") {
tags = append(tags, []string{"d", dtag})
}
if len(tags) > 0 && filter.Tags == nil {
filter.Tags = make(nostr.TagMap)
}
for _, tag := range tags {
if _, ok := filter.Tags[tag[0]]; !ok {
filter.Tags[tag[0]] = make([]string, 0, 3)
}
filter.Tags[tag[0]] = append(filter.Tags[tag[0]], tag[1])
}
if c.IsSet("since") {
nts := getNaturalDate(c, "since")
filter.Since = &nts
}
if c.IsSet("until") {
nts := getNaturalDate(c, "until")
filter.Until = &nts
}
if limit := c.Uint("limit"); limit != 0 {
filter.Limit = int(limit)
} else if c.IsSet("limit") {
filter.LimitZero = true
}
return nil
}