Compare commits

..

8 Commits

Author SHA1 Message Date
fiatjaf
c2045e9299 wip 2024-08-19 10:51:16 -03:00
fiatjaf
9690dc70cb nak req --paginate 2024-08-18 23:38:03 -03:00
fiatjaf
c90e61dbec set .DisableSliceFlagSeparator to true.
fixes nostr:nevent1qqs9qwgwnr2rzguzrgt99hhhyv8e84mcdr4mnk86uvm6ndjvzl4rjxqpzpmhxue69uhkztnwdaejumr0dshsz9mhwden5te0vf5hgcm0d9hx2u3wwdhkx6tpdshszxnhwden5te0vfhhxarj9ekx2cm5w4exjene9ehx2ap0j8u0fj
2024-08-07 11:46:08 -03:00
fiatjaf
d226cd6ce4 fix password input lowercasing characters.
fixes https://github.com/fiatjaf/nak/issues/28
2024-08-06 11:05:08 -03:00
fiatjaf
3d78e91f62 bunker: deny getPublicKey() even though it's harmless.
fixes https://github.com/fiatjaf/nak/issues/27
2024-08-06 10:56:08 -03:00
fiatjaf
84965f2253 don't set limit to zero on --stream 2024-08-03 10:52:46 -03:00
fiatjaf
928c73513c just move imports around. 2024-07-30 11:43:14 -03:00
fiatjaf
a36142604d compile to riscv64. 2024-07-27 10:32:32 -03:00
20 changed files with 274 additions and 69 deletions

View File

@@ -25,10 +25,14 @@ jobs:
strategy: strategy:
matrix: matrix:
goos: [linux, freebsd, darwin, windows] goos: [linux, freebsd, darwin, windows]
goarch: [amd64, arm64] goarch: [amd64, arm64, riscv64]
exclude: exclude:
- goarch: arm64 - goarch: arm64
goos: windows goos: windows
- goarch: riscv64
goos: windows
- goarch: riscv64
goos: darwin
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: wangyoucao577/go-release-action@v1.40 - uses: wangyoucao577/go-release-action@v1.40

View File

@@ -173,6 +173,13 @@ listening at [wss://relay.damus.io wss://nos.lol wss://relay.nsecbunker.com]:
{"kind":1,"id":"f030fccd90c783858dfcee204af94826cf0f1c85d6fc85a0087e9e5172419393","pubkey":"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","created_at":1719677535,"tags":[["-"],["e","f59911b561c37c90b01e9e5c2557307380835c83399756f4d62d8167227e420a","wss://relay.whatever.com","root","a9e0f110f636f3191644110c19a33448daf09d7cda9708a769e91b7e91340208"],["p","a9e0f110f636f3191644110c19a33448daf09d7cda9708a769e91b7e91340208","wss://p-relay.com"]],"content":"I know the future","sig":"8b36a74e29df8bc12bed66896820da6940d4d9409721b3ed2e910c838833a178cb45fd5bb1c6eb6adc66ab2808bfac9f6644a2c55a6570bb2ad90f221c9c7551"} {"kind":1,"id":"f030fccd90c783858dfcee204af94826cf0f1c85d6fc85a0087e9e5172419393","pubkey":"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","created_at":1719677535,"tags":[["-"],["e","f59911b561c37c90b01e9e5c2557307380835c83399756f4d62d8167227e420a","wss://relay.whatever.com","root","a9e0f110f636f3191644110c19a33448daf09d7cda9708a769e91b7e91340208"],["p","a9e0f110f636f3191644110c19a33448daf09d7cda9708a769e91b7e91340208","wss://p-relay.com"]],"content":"I know the future","sig":"8b36a74e29df8bc12bed66896820da6940d4d9409721b3ed2e910c838833a178cb45fd5bb1c6eb6adc66ab2808bfac9f6644a2c55a6570bb2ad90f221c9c7551"}
``` ```
### download the latest 50000 notes from a relay, regardless of their natural query limits, by paginating requests
```shell
~> nak req -k 1 --limit 50000 --paginate --paginate-interval 2s nos.lol > events.jsonl
~> wc -l events.jsonl
50000 events.jsonl
```
## contributing to this repository ## contributing to this repository
Use NIP-34 to send your patches to `naddr1qqpkucttqy28wumn8ghj7un9d3shjtnwdaehgu3wvfnsz9nhwden5te0wfjkccte9ehx7um5wghxyctwvsq3gamnwvaz7tmjv4kxz7fwv3sk6atn9e5k7q3q80cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsxpqqqpmej2wctpn`. Use NIP-34 to send your patches to `naddr1qqpkucttqy28wumn8ghj7un9d3shjtnwdaehgu3wvfnsz9nhwden5te0wfjkccte9ehx7um5wghxyctwvsq3gamnwvaz7tmjv4kxz7fwv3sk6atn9e5k7q3q80cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsxpqqqpmej2wctpn`.

View File

@@ -11,10 +11,10 @@ import (
"time" "time"
"github.com/fatih/color" "github.com/fatih/color"
"github.com/fiatjaf/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/fiatjaf/cli/v3"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
) )
@@ -23,6 +23,7 @@ var bunker = &cli.Command{
Usage: "starts a NIP-46 signer daemon with the given --sec key", Usage: "starts a NIP-46 signer daemon with the given --sec key",
ArgsUsage: "[relay...]", ArgsUsage: "[relay...]",
Description: ``, Description: ``,
DisableSliceFlagSeparator: true,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
Name: "sec", Name: "sec",
@@ -177,7 +178,7 @@ var bunker = &cli.Command{
}() }()
} }
return harmless || slices.Contains(authorizedKeys, from) || slices.Contains(authorizedSecrets, secret) return slices.Contains(authorizedKeys, from) || slices.Contains(authorizedSecrets, secret)
} }
for ie := range events { for ie := range events {

View File

@@ -7,14 +7,15 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/nbd-wtf/go-nostr"
"github.com/fiatjaf/cli/v3" "github.com/fiatjaf/cli/v3"
"github.com/nbd-wtf/go-nostr"
) )
var count = &cli.Command{ var count = &cli.Command{
Name: "count", Name: "count",
Usage: "generates encoded COUNT messages and optionally use them to talk to relays", 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').`, Description: `outputs a NIP-45 request (the flags are mostly the same as 'nak req').`,
DisableSliceFlagSeparator: true,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "author", Name: "author",

View File

@@ -6,10 +6,10 @@ import (
"encoding/json" "encoding/json"
"strings" "strings"
"github.com/fiatjaf/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"
sdk "github.com/nbd-wtf/nostr-sdk" sdk "github.com/nbd-wtf/nostr-sdk"
"github.com/fiatjaf/cli/v3"
) )
var decode = &cli.Command{ var decode = &cli.Command{
@@ -20,6 +20,7 @@ var decode = &cli.Command{
nak decode nevent1qqs29yet5tp0qq5xu5qgkeehkzqh5qu46739axzezcxpj4tjlkx9j7gpr4mhxue69uhkummnw3ez6ur4vgh8wetvd3hhyer9wghxuet5sh59ud nak decode nevent1qqs29yet5tp0qq5xu5qgkeehkzqh5qu46739axzezcxpj4tjlkx9j7gpr4mhxue69uhkummnw3ez6ur4vgh8wetvd3hhyer9wghxuet5sh59ud
nak decode nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpz4mhxue69uhk2er9dchxummnw3ezumrpdejqz8thwden5te0dehhxarj94c82c3wwajkcmr0wfjx2u3wdejhgqgcwaehxw309aex2mrp0yhxummnw3exzarf9e3k7mgnp0sh5 nak decode nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpz4mhxue69uhk2er9dchxummnw3ezumrpdejqz8thwden5te0dehhxarj94c82c3wwajkcmr0wfjx2u3wdejhgqgcwaehxw309aex2mrp0yhxummnw3exzarf9e3k7mgnp0sh5
nak decode nsec1jrmyhtjhgd9yqalps8hf9mayvd58852gtz66m7tqpacjedkp6kxq4dyxsr`, nak decode nsec1jrmyhtjhgd9yqalps8hf9mayvd58852gtz66m7tqpacjedkp6kxq4dyxsr`,
DisableSliceFlagSeparator: true,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.BoolFlag{ &cli.BoolFlag{
Name: "id", Name: "id",

View File

@@ -4,9 +4,9 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/fiatjaf/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/fiatjaf/cli/v3"
) )
var encode = &cli.Command{ var encode = &cli.Command{
@@ -25,10 +25,12 @@ var encode = &cli.Command{
} }
return nil return nil
}, },
DisableSliceFlagSeparator: true,
Commands: []*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",
DisableSliceFlagSeparator: true,
Action: func(ctx context.Context, c *cli.Command) 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 {
@@ -50,6 +52,7 @@ var encode = &cli.Command{
{ {
Name: "nsec", Name: "nsec",
Usage: "encode a hex private key into bech32 'nsec' format", Usage: "encode a hex private key into bech32 'nsec' format",
DisableSliceFlagSeparator: true,
Action: func(ctx context.Context, c *cli.Command) 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 {
@@ -78,6 +81,7 @@ var encode = &cli.Command{
Usage: "attach relay hints to nprofile code", Usage: "attach relay hints to nprofile code",
}, },
}, },
DisableSliceFlagSeparator: true,
Action: func(ctx context.Context, c *cli.Command) 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 {
@@ -116,6 +120,7 @@ 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",
}, },
}, },
DisableSliceFlagSeparator: true,
Action: func(ctx context.Context, c *cli.Command) 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 {
@@ -174,6 +179,7 @@ var encode = &cli.Command{
Usage: "attach relay hints to naddr code", Usage: "attach relay hints to naddr code",
}, },
}, },
DisableSliceFlagSeparator: true,
Action: func(ctx context.Context, c *cli.Command) 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")
@@ -213,6 +219,7 @@ var encode = &cli.Command{
{ {
Name: "note", Name: "note",
Usage: "generate note1 event codes (not recommended)", Usage: "generate note1 event codes (not recommended)",
DisableSliceFlagSeparator: true,
Action: func(ctx context.Context, c *cli.Command) 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 {

View File

@@ -8,10 +8,10 @@ import (
"strings" "strings"
"time" "time"
"github.com/fiatjaf/cli/v3"
"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/nip19"
"github.com/fiatjaf/cli/v3"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
) )
@@ -31,6 +31,7 @@ if an event -- or a partial event -- is given on stdin, the flags can be used to
example: example:
echo '{"id":"a889df6a387419ff204305f4c2d296ee328c3cd4f8b62f205648a541b4554dfb","pubkey":"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5","created_at":1698623783,"kind":1,"tags":[],"content":"hello from the nostr army knife","sig":"84876e1ee3e726da84e5d195eb79358b2b3eaa4d9bd38456fde3e8a2af3f1cd4cda23f23fda454869975b3688797d4c66e12f4c51c1b43c6d2997c5e61865661"}' | nak event wss://offchain.pub echo '{"id":"a889df6a387419ff204305f4c2d296ee328c3cd4f8b62f205648a541b4554dfb","pubkey":"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5","created_at":1698623783,"kind":1,"tags":[],"content":"hello from the nostr army knife","sig":"84876e1ee3e726da84e5d195eb79358b2b3eaa4d9bd38456fde3e8a2af3f1cd4cda23f23fda454869975b3688797d4c66e12f4c51c1b43c6d2997c5e61865661"}' | nak event wss://offchain.pub
echo '{"tags": [["t", "spam"]]}' | nak event -c 'this is spam'`, echo '{"tags": [["t", "spam"]]}' | nak event -c 'this is spam'`,
DisableSliceFlagSeparator: true,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
Name: "sec", Name: "sec",

View File

@@ -3,10 +3,10 @@ package main
import ( import (
"context" "context"
"github.com/fiatjaf/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"
sdk "github.com/nbd-wtf/nostr-sdk" sdk "github.com/nbd-wtf/nostr-sdk"
"github.com/fiatjaf/cli/v3"
) )
var fetch = &cli.Command{ var fetch = &cli.Command{
@@ -15,6 +15,7 @@ var fetch = &cli.Command{
Description: `example usage: Description: `example usage:
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,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "relay", Name: "relay",

View File

@@ -6,9 +6,9 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/fiatjaf/cli/v3"
"github.com/markusmobius/go-dateparser" "github.com/markusmobius/go-dateparser"
"github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr"
"github.com/fiatjaf/cli/v3"
) )
type NaturalTimeFlag = cli.FlagBase[nostr.Timestamp, struct{}, naturalTimeValue] type NaturalTimeFlag = cli.FlagBase[nostr.Timestamp, struct{}, naturalTimeValue]

15
go.mod
View File

@@ -9,22 +9,25 @@ require (
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/decred/dcrd/dcrec/secp256k1/v4 v4.3.0
github.com/fatih/color v1.16.0 github.com/fatih/color v1.16.0
github.com/fiatjaf/cli/v3 v3.0.0-20240723181502-e7dd498b16ae
github.com/fiatjaf/eventstore v0.7.1
github.com/fiatjaf/khatru v0.7.5
github.com/mailru/easyjson v0.7.7 github.com/mailru/easyjson v0.7.7
github.com/markusmobius/go-dateparser v1.2.3 github.com/markusmobius/go-dateparser v1.2.3
github.com/nbd-wtf/go-nostr v0.34.2 github.com/nbd-wtf/go-nostr v0.34.5
github.com/nbd-wtf/nostr-sdk v0.0.5 github.com/nbd-wtf/nostr-sdk v0.0.5
golang.org/x/exp v0.0.0-20240707233637-46b078467d37 golang.org/x/exp v0.0.0-20240707233637-46b078467d37
) )
require ( require (
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/btcsuite/btcd/btcutil v1.1.3 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect
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/decred/dcrd/crypto/blake256 v1.0.1 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect
github.com/elliotchance/pie/v2 v2.7.0 // indirect github.com/elliotchance/pie/v2 v2.7.0 // indirect
github.com/fiatjaf/cli/v3 v3.0.0-20240723181502-e7dd498b16ae // indirect github.com/fasthttp/websocket v1.5.7 // 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
github.com/gobwas/ws v1.4.0 // indirect github.com/gobwas/ws v1.4.0 // indirect
@@ -32,16 +35,22 @@ require (
github.com/hablullah/go-juliandays v1.0.0 // indirect github.com/hablullah/go-juliandays v1.0.0 // indirect
github.com/jalaali/go-jalaali v0.0.0-20210801064154-80525e88d958 // indirect github.com/jalaali/go-jalaali v0.0.0-20210801064154-80525e88d958 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/compress v1.17.8 // indirect
github.com/magefile/mage v1.14.0 // indirect github.com/magefile/mage v1.14.0 // indirect
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/rs/cors v1.7.0 // indirect
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
github.com/tetratelabs/wazero v1.2.1 // indirect github.com/tetratelabs/wazero v1.2.1 // 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
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.51.0 // indirect
github.com/wasilibs/go-re2 v1.3.0 // indirect github.com/wasilibs/go-re2 v1.3.0 // indirect
golang.org/x/crypto v0.21.0 // indirect golang.org/x/crypto v0.21.0 // indirect
golang.org/x/net v0.22.0 // indirect
golang.org/x/sys v0.22.0 // indirect golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect golang.org/x/text v0.16.0 // indirect
) )

26
go.sum
View File

@@ -1,4 +1,6 @@
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M=
github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
@@ -42,14 +44,16 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
github.com/elliotchance/pie/v2 v2.7.0 h1:FqoIKg4uj0G/CrLGuMS9ejnFKa92lxE1dEgBD3pShXg= github.com/elliotchance/pie/v2 v2.7.0 h1:FqoIKg4uj0G/CrLGuMS9ejnFKa92lxE1dEgBD3pShXg=
github.com/elliotchance/pie/v2 v2.7.0/go.mod h1:18t0dgGFH006g4eVdDtWfgFZPQEgl10IoEO8YWEq3Og= github.com/elliotchance/pie/v2 v2.7.0/go.mod h1:18t0dgGFH006g4eVdDtWfgFZPQEgl10IoEO8YWEq3Og=
github.com/fasthttp/websocket v1.5.7 h1:0a6o2OfeATvtGgoMKleURhLT6JqWPg7fYfWnH4KHau4=
github.com/fasthttp/websocket v1.5.7/go.mod h1:bC4fxSono9czeXHQUVKxsC0sNjbm7lPJR04GDFqClfU=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/fiatjaf/cli/v3 v3.0.0-20240714232133-bb036558919f h1:SQ5W4q4HfpAPA8e8uPADqs4dhI6VvVwUq00DtlpHIt0=
github.com/fiatjaf/cli/v3 v3.0.0-20240714232133-bb036558919f/go.mod h1:Z1ItyMma7t6I7zHG9OpbExhHQOSkFf/96n+mAZ9MtVI=
github.com/fiatjaf/cli/v3 v3.0.0-20240723181502-e7dd498b16ae h1:0B/1dU3YECIbPoBIRTQ4c0scZCNz9TVHtQpiODGrTTo= github.com/fiatjaf/cli/v3 v3.0.0-20240723181502-e7dd498b16ae h1:0B/1dU3YECIbPoBIRTQ4c0scZCNz9TVHtQpiODGrTTo=
github.com/fiatjaf/cli/v3 v3.0.0-20240723181502-e7dd498b16ae/go.mod h1:aAWPO4bixZZxPtOnH6K3q4GbQ0jftUNDW9Oa861IRew= github.com/fiatjaf/cli/v3 v3.0.0-20240723181502-e7dd498b16ae/go.mod h1:aAWPO4bixZZxPtOnH6K3q4GbQ0jftUNDW9Oa861IRew=
github.com/fiatjaf/eventstore v0.2.16 h1:NR64mnyUT5nJR8Sj2AwJTd1Hqs5kKJcCFO21ggUkvWg= github.com/fiatjaf/eventstore v0.7.1 h1:5f2yvEtYvsvMBNttysmXhSSum5M1qwvPzjEQ/BFue7Q=
github.com/fiatjaf/eventstore v0.2.16/go.mod h1:rUc1KhVufVmC+HUOiuPweGAcvG6lEOQCkRCn2Xn5VRA= github.com/fiatjaf/eventstore v0.7.1/go.mod h1:ek/yWbanKVG767fK51Q3+6Mvi5oEHYSsdPym40nZexw=
github.com/fiatjaf/khatru v0.7.5 h1:UFo+cdbqHDn1W4Q4h03y3vzh1BiU+6fLYK48oWU2K34=
github.com/fiatjaf/khatru v0.7.5/go.mod h1:WVqij7X9Vr9UAMIwafQbKVFKxc42Np37vyficwUr/nQ=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
@@ -82,6 +86,8 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo= github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo=
github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
@@ -93,8 +99,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/nbd-wtf/go-nostr v0.34.2 h1:9b4qZ29DhQf9xEWN8/7zfDD868r1jFbpjrR3c+BHc+E= github.com/nbd-wtf/go-nostr v0.34.5 h1:vti8WqvGWbVoWAPniaz7li2TpCyC+7ZS62Gmy7ib/z0=
github.com/nbd-wtf/go-nostr v0.34.2/go.mod h1:NZQkxl96ggbO8rvDpVjcsojJqKTPwqhP4i82O7K5DJs= github.com/nbd-wtf/go-nostr v0.34.5/go.mod h1:NZQkxl96ggbO8rvDpVjcsojJqKTPwqhP4i82O7K5DJs=
github.com/nbd-wtf/nostr-sdk v0.0.5 h1:rec+FcDizDVO0W25PX0lgYMXvP7zNNOgI3Fu9UCm4BY= github.com/nbd-wtf/nostr-sdk v0.0.5 h1:rec+FcDizDVO0W25PX0lgYMXvP7zNNOgI3Fu9UCm4BY=
github.com/nbd-wtf/nostr-sdk v0.0.5/go.mod h1:iJJsikesCGLNFZ9dLqhLPDzdt924EagUmdQxT3w2Lmk= github.com/nbd-wtf/nostr-sdk v0.0.5/go.mod h1:iJJsikesCGLNFZ9dLqhLPDzdt924EagUmdQxT3w2Lmk=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
@@ -110,6 +116,10 @@ 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/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk=
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
@@ -124,6 +134,10 @@ 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/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
github.com/wasilibs/go-re2 v1.3.0 h1:LFhBNzoStM3wMie6rN2slD1cuYH2CGiHpvNL3UtcsMw= github.com/wasilibs/go-re2 v1.3.0 h1:LFhBNzoStM3wMie6rN2slD1cuYH2CGiHpvNL3UtcsMw=
github.com/wasilibs/go-re2 v1.3.0/go.mod h1:AafrCXVvGRJJOImMajgJ2M7rVmWyisVK7sFshbxnVrg= github.com/wasilibs/go-re2 v1.3.0/go.mod h1:AafrCXVvGRJJOImMajgJ2M7rVmWyisVK7sFshbxnVrg=
github.com/wasilibs/nottinygc v0.4.0 h1:h1TJMihMC4neN6Zq+WKpLxgd9xCFMw7O9ETLwY2exJQ= github.com/wasilibs/nottinygc v0.4.0 h1:h1TJMihMC4neN6Zq+WKpLxgd9xCFMw7O9ETLwY2exJQ=

View File

@@ -13,11 +13,11 @@ import (
"github.com/chzyer/readline" "github.com/chzyer/readline"
"github.com/fatih/color" "github.com/fatih/color"
"github.com/fiatjaf/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/nbd-wtf/go-nostr/nip49" "github.com/nbd-wtf/go-nostr/nip49"
"github.com/fiatjaf/cli/v3"
) )
const ( const (
@@ -261,22 +261,18 @@ func askPassword(msg string, shouldAskAgain func(answer string) bool) (string, e
EnableMask: true, EnableMask: true,
MaskRune: '*', MaskRune: '*',
} }
return _ask(config, msg, "", shouldAskAgain)
}
func _ask(config *readline.Config, msg string, defaultValue string, shouldAskAgain func(answer string) bool) (string, error) {
rl, err := readline.NewEx(config) rl, err := readline.NewEx(config)
if err != nil { if err != nil {
return "", err return "", err
} }
rl.WriteStdin([]byte(defaultValue))
for { for {
answer, err := rl.Readline() answer, err := rl.Readline()
if err != nil { if err != nil {
return "", err return "", err
} }
answer = strings.TrimSpace(strings.ToLower(answer)) answer = strings.TrimSpace(answer)
if shouldAskAgain != nil && shouldAskAgain(answer) { if shouldAskAgain != nil && shouldAskAgain(answer) {
continue continue
} }

8
key.go
View File

@@ -11,16 +11,17 @@ import (
"github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/schnorr/musig2" "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
"github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/fiatjaf/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/nip49" "github.com/nbd-wtf/go-nostr/nip49"
"github.com/fiatjaf/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: ``,
DisableSliceFlagSeparator: true,
Commands: []*cli.Command{ Commands: []*cli.Command{
generate, generate,
public, public,
@@ -34,6 +35,7 @@ var generate = &cli.Command{
Name: "generate", Name: "generate",
Usage: "generates a secret key", Usage: "generates a secret key",
Description: ``, Description: ``,
DisableSliceFlagSeparator: true,
Action: func(ctx context.Context, c *cli.Command) error { Action: func(ctx context.Context, c *cli.Command) error {
sec := nostr.GeneratePrivateKey() sec := nostr.GeneratePrivateKey()
stdout(sec) stdout(sec)
@@ -46,6 +48,7 @@ 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]",
DisableSliceFlagSeparator: true,
Action: func(ctx context.Context, c *cli.Command) error { Action: func(ctx context.Context, c *cli.Command) error {
for sec := range getSecretKeysFromStdinLinesOrSlice(ctx, c, c.Args().Slice()) { for sec := range getSecretKeysFromStdinLinesOrSlice(ctx, c, c.Args().Slice()) {
pubkey, err := nostr.GetPublicKey(sec) pubkey, err := nostr.GetPublicKey(sec)
@@ -64,6 +67,7 @@ var encrypt = &cli.Command{
Usage: "encrypts a secret key and prints an ncryptsec code", Usage: "encrypts a secret key and prints an ncryptsec code",
Description: `uses the NIP-49 standard.`, Description: `uses the NIP-49 standard.`,
ArgsUsage: "<secret> <password>", ArgsUsage: "<secret> <password>",
DisableSliceFlagSeparator: true,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.IntFlag{ &cli.IntFlag{
Name: "logn", Name: "logn",
@@ -102,6 +106,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>",
DisableSliceFlagSeparator: true,
Action: func(ctx context.Context, c *cli.Command) error { Action: func(ctx context.Context, c *cli.Command) error {
var ncryptsec string var ncryptsec string
var password string var password string
@@ -152,6 +157,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...]",
DisableSliceFlagSeparator: true,
Action: func(ctx context.Context, c *cli.Command) 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"`

View File

@@ -13,6 +13,7 @@ var app = &cli.Command{
UseShortOptionHandling: true, UseShortOptionHandling: true,
AllowFlagsAfterArguments: true, AllowFlagsAfterArguments: true,
Usage: "the nostr army knife command-line tool", Usage: "the nostr army knife command-line tool",
DisableSliceFlagSeparator: true,
Commands: []*cli.Command{ Commands: []*cli.Command{
req, req,
count, count,

View File

@@ -16,7 +16,7 @@ import (
) )
func performMusig( func performMusig(
ctx context.Context, _ context.Context,
sec string, sec string,
evt *nostr.Event, evt *nostr.Event,
numSigners int, numSigners int,

73
paginate.go Normal file
View File

@@ -0,0 +1,73 @@
package main
import (
"context"
"math"
"slices"
"time"
"github.com/nbd-wtf/go-nostr"
)
func paginateWithPoolAndParams(pool *nostr.SimplePool, interval time.Duration, globalLimit uint64) func(ctx context.Context, urls []string, filters nostr.Filters) chan nostr.IncomingEvent {
return func(ctx context.Context, urls []string, filters nostr.Filters) chan nostr.IncomingEvent {
// filters will always be just one
filter := filters[0]
nextUntil := nostr.Now()
if filter.Until != nil {
nextUntil = *filter.Until
}
if globalLimit == 0 {
globalLimit = uint64(filter.Limit)
if globalLimit == 0 && !filter.LimitZero {
globalLimit = math.MaxUint64
}
}
var globalCount uint64 = 0
globalCh := make(chan nostr.IncomingEvent)
repeatedCache := make([]string, 0, 300)
nextRepeatedCache := make([]string, 0, 300)
go func() {
defer close(globalCh)
for {
filter.Until = &nextUntil
time.Sleep(interval)
keepGoing := false
for evt := range pool.SubManyEose(ctx, urls, nostr.Filters{filter}) {
if slices.Contains(repeatedCache, evt.ID) {
continue
}
keepGoing = true // if we get one that isn't repeated, then keep trying to get more
nextRepeatedCache = append(nextRepeatedCache, evt.ID)
globalCh <- evt
globalCount++
if globalCount >= globalLimit {
return
}
if evt.CreatedAt < *filter.Until {
nextUntil = evt.CreatedAt
}
}
if !keepGoing {
return
}
repeatedCache = nextRepeatedCache
nextRepeatedCache = nextRepeatedCache[:0]
}
}()
return globalCh
}
}

View File

@@ -11,10 +11,10 @@ import (
"io" "io"
"net/http" "net/http"
"github.com/fiatjaf/cli/v3"
"github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip11" "github.com/nbd-wtf/go-nostr/nip11"
"github.com/nbd-wtf/go-nostr/nip86" "github.com/nbd-wtf/go-nostr/nip86"
"github.com/fiatjaf/cli/v3"
) )
var relay = &cli.Command{ var relay = &cli.Command{
@@ -23,6 +23,7 @@ var relay = &cli.Command{
Description: `example: Description: `example:
nak relay nostr.wine`, nak relay nostr.wine`,
ArgsUsage: "<relay-url>", ArgsUsage: "<relay-url>",
DisableSliceFlagSeparator: true,
Action: func(ctx context.Context, c *cli.Command) 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 == "" {

23
req.go
View File

@@ -7,9 +7,9 @@ import (
"os" "os"
"strings" "strings"
"github.com/fiatjaf/cli/v3"
"github.com/mailru/easyjson" "github.com/mailru/easyjson"
"github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr"
"github.com/fiatjaf/cli/v3"
) )
const CATEGORY_FILTER_ATTRIBUTES = "FILTER ATTRIBUTES" const CATEGORY_FILTER_ATTRIBUTES = "FILTER ATTRIBUTES"
@@ -27,6 +27,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,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "author", Name: "author",
@@ -95,6 +96,20 @@ example:
Usage: "keep the subscription open, printing all events as they are returned", Usage: "keep the subscription open, printing all events as they are returned",
DefaultText: "false, will close on EOSE", DefaultText: "false, will close on EOSE",
}, },
&cli.BoolFlag{
Name: "paginate",
Usage: "make multiple REQs to the relay decreasing the value of 'until' until 'limit' or 'since' conditions are met",
DefaultText: "false",
},
&cli.DurationFlag{
Name: "paginate-interval",
Usage: "time between queries when using --paginate",
},
&cli.UintFlag{
Name: "paginate-global-limit",
Usage: "global limit at which --paginate should stop",
DefaultText: "uses the value given by --limit/-l or infinite",
},
&cli.BoolFlag{ &cli.BoolFlag{
Name: "bare", Name: "bare",
Usage: "when printing the filter, print just the filter, not enveloped in a [\"REQ\", ...] array", Usage: "when printing the filter, print just the filter, not enveloped in a [\"REQ\", ...] array",
@@ -240,13 +255,15 @@ example:
if limit := c.Uint("limit"); limit != 0 { if limit := c.Uint("limit"); limit != 0 {
filter.Limit = int(limit) filter.Limit = int(limit)
} else if c.IsSet("limit") || c.Bool("stream") { } else if c.IsSet("limit") {
filter.LimitZero = true filter.LimitZero = true
} }
if len(relayUrls) > 0 { if len(relayUrls) > 0 {
fn := pool.SubManyEose fn := pool.SubManyEose
if c.Bool("stream") { if c.Bool("paginate") {
fn = paginateWithPoolAndParams(pool, c.Duration("paginate-interval"), c.Uint("paginate-global-limit"))
} else if c.Bool("stream") {
fn = pool.SubMany fn = pool.SubMany
} }

64
serve.go Normal file
View File

@@ -0,0 +1,64 @@
package main
import (
"context"
"fmt"
"os"
"github.com/fatih/color"
"github.com/fiatjaf/cli/v3"
"github.com/fiatjaf/eventstore/slicestore"
"github.com/fiatjaf/khatru"
)
var serve = &cli.Command{
Name: "serve",
Usage: "starts an in-memory relay for testing purposes",
DisableSliceFlagSeparator: true,
Flags: []cli.Flag{
&cli.UintFlag{
Name: "port",
Usage: "port where to listen for connections",
},
&cli.StringFlag{
Name: "events",
Usage: "file containing the initial batch of events that will be served by the relay as newline-separated JSON (jsonl)",
DefaultText: "the relay will start empty",
},
},
Action: func(ctx context.Context, c *cli.Command) error {
db := slicestore.SliceStore{}
reader :=
if path := c.String("events"); path != "" {
f, err := os.Open(path)
if err != nil {
return fmt.Errorf("failed to file at '%s': %w", path, err)
}
} else if isPiped() {
}
rl := khatru.NewRelay()
rl.QueryEvents = append(rl.QueryEvents, db.QueryEvents)
rl.CountEvents = append(rl.CountEvents, db.CountEvents)
rl.DeleteEvent = append(rl.DeleteEvent, db.DeleteEvent)
rl.StoreEvent = append(rl.StoreEvent, db.SaveEvent)
started := make(chan bool)
exited := make(chan bool)
go func() {
err := rl.Start("127.0.0.1", int(c.Uint("port")), started)
if err != nil {
log("error: %s", err)
}
exited <- true
}()
bold := color.New(color.Bold).Sprint
italic := color.New(color.Italic).Sprint
<-started
log()
},
}

View File

@@ -4,8 +4,8 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"github.com/nbd-wtf/go-nostr"
"github.com/fiatjaf/cli/v3" "github.com/fiatjaf/cli/v3"
"github.com/nbd-wtf/go-nostr"
) )
var verify = &cli.Command{ var verify = &cli.Command{
@@ -15,6 +15,7 @@ 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.`,
DisableSliceFlagSeparator: true,
Action: func(ctx context.Context, c *cli.Command) 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{}