mirror of https://github.com/fiatjaf/nak.git
Compare commits
5 Commits
9292fd7482
...
4cc27596d2
Author | SHA1 | Date |
---|---|---|
|
4cc27596d2 | |
|
b316646821 | |
|
d3975679e4 | |
|
23e27da077 | |
|
1a221a133c |
31
README.md
31
README.md
|
@ -3,6 +3,8 @@
|
|||
install with `go install github.com/fiatjaf/nak@latest` or
|
||||
[download a binary](https://github.com/fiatjaf/nak/releases).
|
||||
|
||||
or get the source with `git clone https://github.com/fiatjaf/nak` then install with `go install` or run with docker using `docker build -t nak . && docker run nak event`.
|
||||
|
||||
## what can you do with it?
|
||||
|
||||
take a look at the help text that comes in it to learn all possibilities, but here are some:
|
||||
|
@ -128,17 +130,13 @@ type the password to decrypt your secret key: **********
|
|||
985d66d2644dfa7676e26046914470d66ebc7fa783a3f57f139fde32d0d631d7
|
||||
```
|
||||
|
||||
### sign an event using [Amber](https://github.com/greenart7c3/Amber) (or other bunker provider)
|
||||
### sign an event using a bunker provider (amber, promenade etc)
|
||||
```shell
|
||||
~> export NOSTR_CLIENT_KEY="$(nak key generate)"
|
||||
~> nak event --sec 'bunker://a9e0f110f636f3191644110c19a33448daf09d7cda9708a769e91b7e91340208?relay=wss%3A%2F%2Frelay.damus.io&relay=wss%3A%2F%2Frelay.nsecbunker.com&relay=wss%3A%2F%2Fnos.lol&secret=TWfGbjQCLxUf' -c 'hello from bunker'
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Remember to set a `NOSTR_CLIENT_KEY` permanently on your shell, otherwise you'll only be able to use the bunker once. For `bash`:
|
||||
> ```shell
|
||||
> echo 'export NOSTR_CLIENT_KEY="$(nak key generate)"' >> ~/.bashrc
|
||||
> ```
|
||||
(in most cases it's better to set `NOSTR_CLIENT_KEY` permanently on your shell, as that identity will be recorded by the bunker provider.)
|
||||
|
||||
### sign an event using a NIP-49 encrypted key
|
||||
```shell
|
||||
|
@ -180,16 +178,11 @@ you can also display a QR code for the bunker URI by adding the `--qrcode` flag:
|
|||
~> nak bunker --qrcode --sec ncryptsec1... relay.damus.io
|
||||
```
|
||||
|
||||
### start a bunker that persists its metadata to disc
|
||||
### start a bunker that persists its metadata (secret key, relays, authorized client pubkeys) to disc
|
||||
```shell
|
||||
~> nak bunker --persist --sec ncryptsec1... relay.nsec.app nos.lol
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> when you start a bunker with `--persist` or `--profile`, it will store `--sec` credentials and authorized keys in
|
||||
> `~/.config/nak/bunker`. if you don't want your private key to be stored in plain text, you can
|
||||
> [encrypt it with NIP-49](#encrypt-key-with-nip-49) it beforehand.
|
||||
|
||||
```shell
|
||||
then later just
|
||||
|
||||
|
@ -250,7 +243,7 @@ type the password to decrypt your secret key: ********
|
|||
~> nak req -i 412f2d3e73acc312942c055ac2a695dc60bf58ff97e06689a8a79e97796c4cdb relay.westernbtc.com | jq -r .content > ~/.jq
|
||||
```
|
||||
|
||||
### watch a NIP-53 livestream (zap.stream etc)
|
||||
### watch a NIP-53 livestream (zap.stream, amethyst, shosho etc)
|
||||
```shell
|
||||
~> # this requires the jq utils from the step above
|
||||
~> mpv $(nak fetch naddr1qqjxvvm9xscnsdtx95cxvcfk956rsvtx943rje3k95mx2dp389jnwwrp8ymxgqg4waehxw309aex2mrp0yhxgctdw4eju6t09upzpn6956apxcad0mfp8grcuugdysg44eepex68h50t73zcathmfs49qvzqqqrkvu7ed38k | jq -r 'tag_value("streaming")')
|
||||
|
@ -307,20 +300,12 @@ echo "#surely you're joking, mr npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn6
|
|||
# and there is a --confirm flag that gives you a chance to confirm before actually publishing the result to relays.
|
||||
```
|
||||
|
||||
### record and publish an audio note of 10s (yakbak etc) signed from a bunker
|
||||
### record and publish an audio note (yakbak, nostur etc) signed from a bunker
|
||||
```shell
|
||||
ffmpeg -f alsa -i default -f webm -t 00:00:03 pipe:1 | nak blossom --server blossom.primal.net upload | jq -rc '{content: .url}' | nak event -k 1222 --sec 'bunker://urlgoeshere' pyramid.fiatjaf.com nostr.wine
|
||||
```
|
||||
|
||||
### from a file with events get only those that have kind 1111 and were created by a given pubkey
|
||||
```shell
|
||||
~> cat all.jsonl | nak filter -k 1111 > filtered.jsonl
|
||||
```
|
||||
### run nak in Docker
|
||||
|
||||
If you want to run nak inside a container (i.e. to run nak as a server, or to avoid installing the Go toolchain) you can run it with Docker:
|
||||
|
||||
```shell
|
||||
docker build -t nak .
|
||||
docker run nak event
|
||||
~> cat all.jsonl | nak filter -k 1111 -a 117673e191b10fe1aedf1736ee74de4cffd4c132ca701960b70a5abad5870faa > filtered.jsonl
|
||||
```
|
||||
|
|
4
count.go
4
count.go
|
@ -141,7 +141,9 @@ var count = &cli.Command{
|
|||
}
|
||||
for _, relayUrl := range relayUrls {
|
||||
relay, _ := sys.Pool.EnsureRelay(relayUrl)
|
||||
count, hllRegisters, err := relay.Count(ctx, filter, nostr.SubscriptionOptions{})
|
||||
count, hllRegisters, err := relay.Count(ctx, filter, nostr.SubscriptionOptions{
|
||||
Label: "nak-count",
|
||||
})
|
||||
fmt.Fprintf(os.Stderr, "%s%s: ", strings.Repeat(" ", biggerUrlSize-len(relayUrl)), relayUrl)
|
||||
|
||||
if err != nil {
|
||||
|
|
4
fetch.go
4
fetch.go
|
@ -106,7 +106,9 @@ var fetch = &cli.Command{
|
|||
continue
|
||||
}
|
||||
|
||||
for ie := range sys.Pool.FetchMany(ctx, relays, filter, nostr.SubscriptionOptions{}) {
|
||||
for ie := range sys.Pool.FetchMany(ctx, relays, filter, nostr.SubscriptionOptions{
|
||||
Label: "nak-fetch",
|
||||
}) {
|
||||
stdout(ie.Event)
|
||||
}
|
||||
}
|
||||
|
|
10
go.mod
10
go.mod
|
@ -4,7 +4,7 @@ go 1.24.1
|
|||
|
||||
require (
|
||||
fiatjaf.com/lib v0.3.1
|
||||
fiatjaf.com/nostr v0.0.0-20250715161459-840e2846ed15
|
||||
fiatjaf.com/nostr v0.0.0-20250818235102-c8d5aa703fab
|
||||
github.com/bep/debounce v1.2.1
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.5
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
||||
|
@ -16,11 +16,12 @@ require (
|
|||
github.com/mailru/easyjson v0.9.0
|
||||
github.com/mark3labs/mcp-go v0.8.3
|
||||
github.com/markusmobius/go-dateparser v1.2.3
|
||||
github.com/mattn/go-isatty v0.0.20
|
||||
github.com/mattn/go-tty v0.0.7
|
||||
github.com/mdp/qrterminal/v3 v3.2.1
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/urfave/cli/v3 v3.0.0-beta1
|
||||
golang.org/x/exp v0.0.0-20250717185816-542afb5b7346
|
||||
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6
|
||||
golang.org/x/term v0.32.0
|
||||
)
|
||||
|
||||
|
@ -42,7 +43,7 @@ require (
|
|||
github.com/dgraph-io/ristretto/v2 v2.1.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/elliotchance/pie/v2 v2.7.0 // indirect
|
||||
github.com/elnosh/gonuts v0.3.1-0.20250123162555-7c0381a585e3 // indirect
|
||||
github.com/elnosh/gonuts v0.4.2 // indirect
|
||||
github.com/fasthttp/websocket v1.5.12 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
|
@ -56,7 +57,6 @@ require (
|
|||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/magefile/mage v1.14.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
|
@ -76,7 +76,7 @@ require (
|
|||
golang.org/x/crypto v0.36.0 // indirect
|
||||
golang.org/x/net v0.37.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
google.golang.org/protobuf v1.36.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
|
16
go.sum
16
go.sum
|
@ -1,8 +1,8 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
fiatjaf.com/lib v0.3.1 h1:/oFQwNtFRfV+ukmOCxfBEAuayoLwXp4wu2/fz5iHpwA=
|
||||
fiatjaf.com/lib v0.3.1/go.mod h1:Ycqq3+mJ9jAWu7XjbQI1cVr+OFgnHn79dQR5oTII47g=
|
||||
fiatjaf.com/nostr v0.0.0-20250715161459-840e2846ed15 h1:XQq9DyW9j14wRKCU0cNyBUDCjJO6HAm+rK9abLLJKes=
|
||||
fiatjaf.com/nostr v0.0.0-20250715161459-840e2846ed15/go.mod h1:lJ9x/Ehcq/7x2mf6iMlC4AOjPUh3WbfLMY+3PyaPRNs=
|
||||
fiatjaf.com/nostr v0.0.0-20250818235102-c8d5aa703fab h1:zMp+G9Et5Z7ku/WUflZpmQzDIAB/Ah00Ms3cMtX9Pw4=
|
||||
fiatjaf.com/nostr v0.0.0-20250818235102-c8d5aa703fab/go.mod h1:j7AfnEAevFuLcpH4Y1RYM27sYJfshL3An6ZSAQNlUlY=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/FastFilter/xorfilter v0.2.1 h1:lbdeLG9BdpquK64ZsleBS8B4xO/QW1IM0gMzF7KaBKc=
|
||||
github.com/FastFilter/xorfilter v0.2.1/go.mod h1:aumvdkhscz6YBZF9ZA/6O4fIoNod4YR50kIVGGZ7l9I=
|
||||
|
@ -80,8 +80,8 @@ github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+m
|
|||
github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
|
||||
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/elnosh/gonuts v0.3.1-0.20250123162555-7c0381a585e3 h1:k7evIqJ2BtFn191DgY/b03N2bMYA/iQwzr4f/uHYn20=
|
||||
github.com/elnosh/gonuts v0.3.1-0.20250123162555-7c0381a585e3/go.mod h1:vgZomh4YQk7R3w4ltZc0sHwCmndfHkuX6V4sga/8oNs=
|
||||
github.com/elnosh/gonuts v0.4.2 h1:/WubPAWGxTE+okJ0WPvmtEzTzpi04RGxiTHAF1FYU+M=
|
||||
github.com/elnosh/gonuts v0.4.2/go.mod h1:vgZomh4YQk7R3w4ltZc0sHwCmndfHkuX6V4sga/8oNs=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
|
@ -212,6 +212,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.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
|
||||
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
|
||||
github.com/urfave/cli/v3 v3.0.0-beta1 h1:6DTaaUarcM0wX7qj5Hcvs+5Dm3dyUTBbEwIWAjcw9Zg=
|
||||
github.com/urfave/cli/v3 v3.0.0-beta1/go.mod h1:FnIeEMYu+ko8zP1F9Ypr3xkZMIDqW3DR92yUtY39q1Y=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
|
@ -236,6 +238,8 @@ golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZv
|
|||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20250717185816-542afb5b7346 h1:vuCObX8mQzik1tfEcYxWZBuVsmQtD1IjxCyPKM18Bh4=
|
||||
golang.org/x/exp v0.0.0-20250717185816-542afb5b7346/go.mod h1:A+z0yzpGtvnG90cToK5n2tu8UJVP2XUATh+r+sfOOOc=
|
||||
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 h1:SbTAbRFnd5kjQXbczszQ0hdk3ctwYf3qBNH9jIsGclE=
|
||||
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
|
@ -269,8 +273,8 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/chzyer/readline"
|
||||
"github.com/fatih/color"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/mattn/go-isatty"
|
||||
"github.com/mattn/go-tty"
|
||||
"github.com/urfave/cli/v3"
|
||||
"golang.org/x/term"
|
||||
|
@ -315,6 +316,10 @@ func supportsDynamicMultilineMagic() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
if !isatty.IsTerminal(os.Stdout.Fd()) {
|
||||
return false
|
||||
}
|
||||
|
||||
width, _, err := term.GetSize(int(os.Stderr.Fd()))
|
||||
if err != nil {
|
||||
return false
|
||||
|
|
8
mcp.go
8
mcp.go
|
@ -165,7 +165,9 @@ var mcpServer = &cli.Command{
|
|||
res := strings.Builder{}
|
||||
res.WriteString("Search results: ")
|
||||
l := 0
|
||||
for result := range sys.Pool.FetchMany(ctx, []string{"relay.nostr.band", "nostr.wine"}, filter, nostr.SubscriptionOptions{}) {
|
||||
for result := range sys.Pool.FetchMany(ctx, []string{"relay.nostr.band", "nostr.wine"}, filter, nostr.SubscriptionOptions{
|
||||
Label: "nak-mcp-search",
|
||||
}) {
|
||||
l++
|
||||
pm, _ := sdk.ParseMetadata(result.Event)
|
||||
res.WriteString(fmt.Sprintf("\n\nResult %d\nUser name: \"%s\"\nPublic key: \"%s\"\nDescription: \"%s\"\n",
|
||||
|
@ -219,7 +221,9 @@ var mcpServer = &cli.Command{
|
|||
}
|
||||
}
|
||||
|
||||
events := sys.Pool.FetchMany(ctx, []string{relay}, filter, nostr.SubscriptionOptions{})
|
||||
events := sys.Pool.FetchMany(ctx, []string{relay}, filter, nostr.SubscriptionOptions{
|
||||
Label: "nak-mcp-profile-events",
|
||||
})
|
||||
|
||||
result := strings.Builder{}
|
||||
for ie := range events {
|
||||
|
|
Loading…
Reference in New Issue