2023-08-23 10:33:49 -04:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2024-06-25 21:18:26 -04:00
|
|
|
"context"
|
2023-08-23 10:33:49 -04:00
|
|
|
"encoding/json"
|
2023-10-08 14:31:20 -04:00
|
|
|
"errors"
|
2023-08-23 10:33:49 -04:00
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
|
2024-07-23 14:23:07 -04:00
|
|
|
"github.com/fiatjaf/cli/v3"
|
2024-07-30 10:43:14 -04:00
|
|
|
"github.com/nbd-wtf/go-nostr"
|
2023-08-23 10:33:49 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
var count = &cli.Command{
|
2024-08-07 10:46:07 -04:00
|
|
|
Name: "count",
|
|
|
|
Usage: "generates encoded COUNT messages and optionally use them to talk to relays",
|
|
|
|
Description: `outputs a NIP-45 request (the flags are mostly the same as 'nak req').`,
|
|
|
|
DisableSliceFlagSeparator: true,
|
2023-08-23 10:33:49 -04:00
|
|
|
Flags: []cli.Flag{
|
|
|
|
&cli.StringSliceFlag{
|
|
|
|
Name: "author",
|
|
|
|
Aliases: []string{"a"},
|
|
|
|
Usage: "only accept events from these authors (pubkey as 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.IntFlag{
|
|
|
|
Name: "since",
|
|
|
|
Aliases: []string{"s"},
|
|
|
|
Usage: "only accept events newer than this (unix timestamp)",
|
|
|
|
Category: CATEGORY_FILTER_ATTRIBUTES,
|
|
|
|
},
|
|
|
|
&cli.IntFlag{
|
|
|
|
Name: "until",
|
|
|
|
Aliases: []string{"u"},
|
|
|
|
Usage: "only accept events older than this (unix timestamp)",
|
|
|
|
Category: CATEGORY_FILTER_ATTRIBUTES,
|
|
|
|
},
|
|
|
|
&cli.IntFlag{
|
|
|
|
Name: "limit",
|
|
|
|
Aliases: []string{"l"},
|
|
|
|
Usage: "only accept up to this number of events",
|
|
|
|
Category: CATEGORY_FILTER_ATTRIBUTES,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ArgsUsage: "[relay...]",
|
2024-06-25 21:18:26 -04:00
|
|
|
Action: func(ctx context.Context, c *cli.Command) error {
|
2023-08-23 10:33:49 -04:00
|
|
|
filter := nostr.Filter{}
|
|
|
|
|
|
|
|
if authors := c.StringSlice("author"); len(authors) > 0 {
|
|
|
|
filter.Authors = authors
|
|
|
|
}
|
|
|
|
if ids := c.StringSlice("id"); len(ids) > 0 {
|
|
|
|
filter.IDs = ids
|
|
|
|
}
|
2024-06-25 21:18:26 -04:00
|
|
|
if kinds64 := c.IntSlice("kind"); len(kinds64) > 0 {
|
|
|
|
kinds := make([]int, len(kinds64))
|
|
|
|
for i, v := range kinds64 {
|
|
|
|
kinds[i] = int(v)
|
|
|
|
}
|
2023-08-23 10:33:49 -04:00
|
|
|
filter.Kinds = kinds
|
|
|
|
}
|
|
|
|
|
|
|
|
tags := make([][]string, 0, 5)
|
|
|
|
for _, tagFlag := range c.StringSlice("tag") {
|
2023-12-24 00:46:35 -05:00
|
|
|
spl := strings.SplitN(tagFlag, "=", 2)
|
2023-08-23 10:33:49 -04:00
|
|
|
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})
|
|
|
|
}
|
|
|
|
if len(tags) > 0 {
|
|
|
|
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 since := c.Int("since"); since != 0 {
|
|
|
|
ts := nostr.Timestamp(since)
|
|
|
|
filter.Since = &ts
|
|
|
|
}
|
|
|
|
if until := c.Int("until"); until != 0 {
|
|
|
|
ts := nostr.Timestamp(until)
|
|
|
|
filter.Until = &ts
|
|
|
|
}
|
|
|
|
if limit := c.Int("limit"); limit != 0 {
|
2024-06-25 21:18:26 -04:00
|
|
|
filter.Limit = int(limit)
|
2023-08-23 10:33:49 -04:00
|
|
|
}
|
|
|
|
|
2023-10-08 14:31:20 -04:00
|
|
|
relays := c.Args().Slice()
|
|
|
|
successes := 0
|
|
|
|
failures := make([]error, 0, len(relays))
|
|
|
|
if len(relays) > 0 {
|
|
|
|
for _, relayUrl := range relays {
|
2024-06-25 21:18:26 -04:00
|
|
|
relay, err := nostr.RelayConnect(ctx, relayUrl)
|
2023-10-08 14:31:20 -04:00
|
|
|
if err != nil {
|
|
|
|
failures = append(failures, err)
|
|
|
|
continue
|
|
|
|
}
|
2024-06-25 21:18:26 -04:00
|
|
|
count, err := relay.Count(ctx, nostr.Filters{filter})
|
2023-10-08 14:31:20 -04:00
|
|
|
if err != nil {
|
|
|
|
failures = append(failures, err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
fmt.Printf("%s: %d\n", relay.URL, count)
|
|
|
|
successes++
|
2023-10-08 14:05:51 -04:00
|
|
|
}
|
2023-10-08 14:31:20 -04:00
|
|
|
if successes == 0 {
|
|
|
|
return errors.Join(failures...)
|
2023-08-23 10:33:49 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// no relays given, will just print the filter
|
|
|
|
var result string
|
2023-10-08 14:05:51 -04:00
|
|
|
j, _ := json.Marshal([]any{"COUNT", "nak", filter})
|
|
|
|
result = string(j)
|
2024-01-24 20:38:51 -05:00
|
|
|
stdout(result)
|
2023-08-23 10:33:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|