mirror of
https://github.com/fiatjaf/nak.git
synced 2025-12-08 16:48:51 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d02301b2d | ||
|
|
9bbc87b27a | ||
|
|
88a07a3504 | ||
|
|
8a934cc76b | ||
|
|
e0c967efa9 | ||
|
|
36c32ae308 | ||
|
|
6d23509d8c | ||
|
|
29b6ecbafe | ||
|
|
11f37afa5b | ||
|
|
cf1694704e | ||
|
|
b3ef2c1289 | ||
|
|
cfdea699bc | ||
|
|
014c6bc11d | ||
|
|
0240866fa1 | ||
|
|
a4d9ceecfa |
1
.github/workflows/release-cli.yml
vendored
1
.github/workflows/release-cli.yml
vendored
@@ -40,6 +40,7 @@ jobs:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
goos: ${{ matrix.goos }}
|
||||
goarch: ${{ matrix.goarch }}
|
||||
ldflags: -X main.version=${{ github.ref }}
|
||||
overwrite: true
|
||||
md5sum: false
|
||||
sha256sum: false
|
||||
|
||||
29
README.md
29
README.md
@@ -200,6 +200,35 @@ listening at [wss://relay.damus.io wss://nos.lol wss://relay.nsecbunker.com]:
|
||||
{"kind":1,"id":"0000009dcc7c62056eafdb41fac817379ec2becf0ce27c5fbe98d0735d968147","pubkey":"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","created_at":1724160828,"tags":[["nonce","515504","24"]],"content":"hello getwired.app and labour.fiatjaf.com","sig":"7edb988065ccc12779fe99270945b212f3723838f315d76d5e90e9ffa27198f13fa556614295f518d968d55bab81878167d4162b3a7cf81a6b423c6761bd504c"}
|
||||
```
|
||||
|
||||
### make a nostr event signed with a key given as an environment variable
|
||||
|
||||
```shell
|
||||
~> export NOSTR_SECRET_KEY=ncryptsec1qggyy9vw0nclmw8ly9caz6aa7f85a4ufhsct64uva337pulsdw00n6twa2lzhzk2znzsyu60urx9s08lx00ke6ual3lszyn5an9zarm6s70lw5lj6dv3mj3f9p4tvp0we6qyz4gp420mapfmvqheuttv
|
||||
~> nak event -c 'it supports keys as hex, nsec or ncryptsec'
|
||||
type the password to decrypt your secret key: ********
|
||||
{"kind":1,"id":"5cbf3feb9a7d99c3ee2a88693a591caca1a8348fea427b3652c27f7a8a76af48","pubkey":"b00bcab55375d8c7b731dd9841f6d805ff1cf6fdc945e7326786deb5ddac6ce4","created_at":1724247924,"tags":[],"content":"it supports keys as hex, nsec or ncryptsec","sig":"fb3fd170bc10e5042322c7a05dd4bbd8ac9947b39026b8a7afd1ee02524e8e3aa1d9554e9c7b6181ca1b45cab01cd06643bdffa5ce678b475e6b185e1c14b085"}
|
||||
```
|
||||
|
||||
### download some helpful `jq` functions for dealing with nostr events
|
||||
```shell
|
||||
~> nak req -i 412f2d3e73acc312942c055ac2a695dc60bf58ff97e06689a8a79e97796c4cdb relay.westernbtc.com | jq -r .content > ~/.jq
|
||||
```
|
||||
|
||||
### watch a NIP-53 livestream (zap.stream etc)
|
||||
```shell
|
||||
~> # this requires the jq utils from the step above
|
||||
~> mpv $(nak fetch naddr1qqjxvvm9xscnsdtx95cxvcfk956rsvtx943rje3k95mx2dp389jnwwrp8ymxgqg4waehxw309aex2mrp0yhxgctdw4eju6t09upzpn6956apxcad0mfp8grcuugdysg44eepex68h50t73zcathmfs49qvzqqqrkvu7ed38k | jq -r 'tag_value("streaming")')
|
||||
~>
|
||||
~> # or without the utils
|
||||
~> mpv $(nak fetch naddr1qqjxvvm9xscnsdtx95cxvcfk956rsvtx943rje3k95mx2dp389jnwwrp8ymxgqg4waehxw309aex2mrp0yhxgctdw4eju6t09upzpn6956apxcad0mfp8grcuugdysg44eepex68h50t73zcathmfs49qvzqqqrkvu7ed38k | jq -r '.tags | map(select(.[0] == "streaming") | .[1])[0]')
|
||||
```
|
||||
|
||||
### download a NIP-35 torrent from an `nevent`
|
||||
```shell
|
||||
~> # this requires the jq utils from two steps above
|
||||
~> aria2c $(nak fetch nevent1qqsdsg6x7uujekac4ga7k7qa9q9sx8gqj7xzjf5w9us0dm0ghvf4ugspp4mhxue69uhkummn9ekx7mq6dw9y4 | jq -r '"magnet:?xt=urn:btih:\(tag_value("x"))&dn=\(tag_value("title"))&tr=http%3A%2F%2Ftracker.loadpeers.org%3A8080%2FxvRKfvAlnfuf5EfxTT5T0KIVPtbqAHnX%2Fannounce&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A6969%2Fannounce&tr=udp%3A%2F%2Fopen.stealth.si%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.torrent.eu.org%3A451%2Fannounce&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=\(tags("tracker") | map(.[1] | @uri) | join("&tr="))"')
|
||||
```
|
||||
|
||||
## contributing to this repository
|
||||
|
||||
Use NIP-34 to send your patches to `naddr1qqpkucttqy28wumn8ghj7un9d3shjtnwdaehgu3wvfnsz9nhwden5te0wfjkccte9ehx7um5wghxyctwvsq3gamnwvaz7tmjv4kxz7fwv3sk6atn9e5k7q3q80cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsxpqqqpmej2wctpn`.
|
||||
|
||||
@@ -29,7 +29,6 @@ var bunker = &cli.Command{
|
||||
Name: "sec",
|
||||
Usage: "secret key to sign the event, as hex or nsec",
|
||||
DefaultText: "the key '1'",
|
||||
Value: "0000000000000000000000000000000000000000000000000000000000000001",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "prompt-sec",
|
||||
@@ -85,8 +84,8 @@ var bunker = &cli.Command{
|
||||
return err
|
||||
}
|
||||
npub, _ := nip19.EncodePublicKey(pubkey)
|
||||
bold := color.New(color.Bold).Sprintf
|
||||
italic := color.New(color.Italic).Sprintf
|
||||
bold := color.New(color.Bold).Sprint
|
||||
italic := color.New(color.Italic).Sprint
|
||||
|
||||
// this function will be called every now and then
|
||||
printBunkerInfo := func() {
|
||||
@@ -132,7 +131,7 @@ var bunker = &cli.Command{
|
||||
)
|
||||
|
||||
log("listening at %v:\n pubkey: %s \n npub: %s%s%s\n to restart: %s\n bunker: %s\n\n",
|
||||
bold("%v", relayURLs),
|
||||
bold(relayURLs),
|
||||
bold(pubkey),
|
||||
bold(npub),
|
||||
authorizedKeysStr,
|
||||
|
||||
@@ -59,8 +59,11 @@ var decode = &cli.Command{
|
||||
} else if pp := sdk.InputToProfile(ctx, input); pp != nil {
|
||||
decodeResult = DecodeResult{ProfilePointer: pp}
|
||||
} else if prefix, value, err := nip19.Decode(input); err == nil && prefix == "naddr" {
|
||||
ep := value.(nostr.EntityPointer)
|
||||
decodeResult = DecodeResult{EntityPointer: &ep}
|
||||
if ep, ok := value.(nostr.EntityPointer); ok {
|
||||
decodeResult = DecodeResult{EntityPointer: &ep}
|
||||
} else {
|
||||
ctx = lineProcessingError(ctx, "couldn't decode naddr: %s", err)
|
||||
}
|
||||
} else if prefix, value, err := nip19.Decode(input); err == nil && prefix == "nsec" {
|
||||
decodeResult.PrivateKey.PrivateKey = value.(string)
|
||||
decodeResult.PrivateKey.PublicKey, _ = nostr.GetPublicKey(value.(string))
|
||||
|
||||
13
event.go
13
event.go
@@ -42,7 +42,6 @@ example:
|
||||
Name: "sec",
|
||||
Usage: "secret key to sign the event, as nsec, ncryptsec or hex",
|
||||
DefaultText: "the key '1'",
|
||||
Value: "0000000000000000000000000000000000000000000000000000000000000001",
|
||||
Category: CATEGORY_SIGNER,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
@@ -126,7 +125,7 @@ example:
|
||||
&cli.StringSliceFlag{
|
||||
Name: "tag",
|
||||
Aliases: []string{"t"},
|
||||
Usage: "sets a tag field on the event, takes a value like -t e=<id>",
|
||||
Usage: "sets a tag field on the event, takes a value like -t e=<id> or -t sometag=\"value one;value two;value three\"",
|
||||
Category: CATEGORY_EVENT_FIELDS,
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
@@ -203,8 +202,8 @@ example:
|
||||
mustRehashAndResign = true
|
||||
}
|
||||
|
||||
if content := c.String("content"); content != "" {
|
||||
evt.Content = content
|
||||
if c.IsSet("content") {
|
||||
evt.Content = c.String("content")
|
||||
mustRehashAndResign = true
|
||||
} else if evt.Content == "" && evt.Kind == 1 {
|
||||
evt.Content = "hello from the nostr army knife"
|
||||
@@ -269,8 +268,10 @@ example:
|
||||
evt.PubKey, _ = nostr.GetPublicKey(sec)
|
||||
}
|
||||
|
||||
// try to generate work with this difficulty -- essentially forever
|
||||
nip13.Generate(&evt, int(difficulty), time.Hour*24*365)
|
||||
// try to generate work with this difficulty -- runs forever
|
||||
nonceTag, _ := nip13.DoWork(ctx, evt, int(difficulty))
|
||||
evt.Tags = append(evt.Tags, nonceTag)
|
||||
|
||||
mustRehashAndResign = true
|
||||
}
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ func ExampleReqWithFlagsAfter3() {
|
||||
}
|
||||
|
||||
func ExampleNaturalTimestamps() {
|
||||
app.Run(ctx, []string{"nak", "event", "-t", "plu=pla", "-e", "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24", "--ts", "2018-05-19 03:37:19", "-c", "nn"})
|
||||
app.Run(ctx, []string{"nak", "event", "-t", "plu=pla", "-e", "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24", "--ts", "May 19 2018 03:37:19", "-c", "nn"})
|
||||
// Output:
|
||||
// {"kind":1,"id":"0000d199127d5e15046b0a3f2885d464ee18f70968303665ef76326a7d828312","pubkey":"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","created_at":1724160467,"tags":[["plu","pla"],["e","3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24"],["nonce","24783","16"]],"content":"nn","sig":"99471b43ce82ca01fb9b61f36b45ca542870854b2466a9d3884891598f7d7baef36d07f4b02bb194f2f6f781973f24c3d946f702c82321c6cb0c564e76cf43db"}
|
||||
// {"kind":0,"id":"b10da0095f96aa2accd99fa3d93bf29a76f51d2594cf5a0a52f8e961aecd0b67","pubkey":"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","created_at":1526711839,"tags":[["plu","pla"],["e","3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24"]],"content":"nn","sig":"988442c97064a041ba5e2bfbd64e84d3f819b2169e865511d9d53e74667949ff165325942acaa2ca233c8b529adedf12cf44088cf04081b56d098c5f4d52dd8f"}
|
||||
}
|
||||
|
||||
12
fetch.go
12
fetch.go
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/fiatjaf/cli/v3"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
@@ -68,8 +69,11 @@ var fetch = &cli.Command{
|
||||
authorHint = v.Author
|
||||
}
|
||||
relays = append(relays, v.Relays...)
|
||||
case "note":
|
||||
filter.IDs = append(filter.IDs, value.(string))
|
||||
case "naddr":
|
||||
v := value.(nostr.EntityPointer)
|
||||
filter.Kinds = []int{v.Kind}
|
||||
filter.Tags = nostr.TagMap{"d": []string{v.Identifier}}
|
||||
filter.Authors = append(filter.Authors, v.PublicKey)
|
||||
authorHint = v.PublicKey
|
||||
@@ -83,6 +87,8 @@ var fetch = &cli.Command{
|
||||
v := value.(string)
|
||||
filter.Authors = append(filter.Authors, v)
|
||||
authorHint = v
|
||||
default:
|
||||
return fmt.Errorf("unexpected prefix %s", prefix)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,10 +97,10 @@ var fetch = &cli.Command{
|
||||
for _, url := range relays {
|
||||
relays = append(relays, url)
|
||||
}
|
||||
}
|
||||
|
||||
if len(filter.Kinds) == 0 {
|
||||
filter.Kinds = append(filter.Kinds, 0)
|
||||
}
|
||||
if len(filter.Authors) > 0 && len(filter.Kinds) == 0 {
|
||||
filter.Kinds = append(filter.Kinds, 0)
|
||||
}
|
||||
|
||||
if err := applyFlagsToFilter(c, &filter); err != nil {
|
||||
|
||||
8
go.mod
8
go.mod
@@ -1,8 +1,8 @@
|
||||
module github.com/fiatjaf/nak
|
||||
|
||||
go 1.22
|
||||
go 1.23
|
||||
|
||||
toolchain go1.22.4
|
||||
toolchain go1.23.0
|
||||
|
||||
require (
|
||||
github.com/bep/debounce v1.2.1
|
||||
@@ -15,8 +15,8 @@ require (
|
||||
github.com/fiatjaf/khatru v0.7.5
|
||||
github.com/mailru/easyjson v0.7.7
|
||||
github.com/markusmobius/go-dateparser v1.2.3
|
||||
github.com/nbd-wtf/go-nostr v0.34.7
|
||||
github.com/nbd-wtf/nostr-sdk v0.5.0
|
||||
github.com/nbd-wtf/go-nostr v0.34.14
|
||||
github.com/nbd-wtf/nostr-sdk v0.5.3
|
||||
golang.org/x/exp v0.0.0-20240707233637-46b078467d37
|
||||
)
|
||||
|
||||
|
||||
8
go.sum
8
go.sum
@@ -113,10 +113,10 @@ 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.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/nbd-wtf/go-nostr v0.34.7 h1:gQP3rHC+aBw3dsu9ubZn8tV0eDBmLrMpmNCjj5nFUTE=
|
||||
github.com/nbd-wtf/go-nostr v0.34.7/go.mod h1:NZQkxl96ggbO8rvDpVjcsojJqKTPwqhP4i82O7K5DJs=
|
||||
github.com/nbd-wtf/nostr-sdk v0.5.0 h1:zrMxcvMSxkw29RyfXEdF3XW5rUWLuT5Q9oBAhd5dyew=
|
||||
github.com/nbd-wtf/nostr-sdk v0.5.0/go.mod h1:MJ7gYv3XiZKU6MHSM0N7oHqQAQhbvpgGQk4Q+XUdIUs=
|
||||
github.com/nbd-wtf/go-nostr v0.34.14 h1:o4n2LkuAtdIjNYJ23sFbcx68UXLnji4j8hYR1Sd2wgI=
|
||||
github.com/nbd-wtf/go-nostr v0.34.14/go.mod h1:NZQkxl96ggbO8rvDpVjcsojJqKTPwqhP4i82O7K5DJs=
|
||||
github.com/nbd-wtf/nostr-sdk v0.5.3 h1:jaiT7xm2h3iksM96PQKlbl5zDpMuZFF3fVj8TknWoJU=
|
||||
github.com/nbd-wtf/nostr-sdk v0.5.3/go.mod h1:9zlqzVbIczMHeN3fy3Ib2/fStRupTPVLvy54Htd9FCE=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
|
||||
@@ -196,12 +196,13 @@ func gatherSecretKeyOrBunkerFromArguments(ctx context.Context, c *cli.Command) (
|
||||
return "", bunker, err
|
||||
}
|
||||
|
||||
// take private from flags, environment variable or default to 1
|
||||
sec := c.String("sec")
|
||||
|
||||
// check in the environment for the secret key
|
||||
if sec == "" {
|
||||
if key, ok := os.LookupEnv("NOSTR_PRIVATE_KEY"); ok {
|
||||
if key, ok := os.LookupEnv("NOSTR_SECRET_KEY"); ok {
|
||||
sec = key
|
||||
} else {
|
||||
sec = "0000000000000000000000000000000000000000000000000000000000000001"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,6 +215,7 @@ func gatherSecretKeyOrBunkerFromArguments(ctx context.Context, c *cli.Command) (
|
||||
return "", nil, fmt.Errorf("failed to get secret key: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(sec, "ncryptsec1") {
|
||||
sec, err = promptDecrypt(sec)
|
||||
if err != nil {
|
||||
@@ -230,6 +232,7 @@ func gatherSecretKeyOrBunkerFromArguments(ctx context.Context, c *cli.Command) (
|
||||
if ok := nostr.IsValid32ByteHex(sec); !ok {
|
||||
return "", nil, fmt.Errorf("invalid secret key")
|
||||
}
|
||||
|
||||
return sec, nil, nil
|
||||
}
|
||||
|
||||
|
||||
3
main.go
3
main.go
@@ -7,6 +7,8 @@ import (
|
||||
"github.com/fiatjaf/cli/v3"
|
||||
)
|
||||
|
||||
var version string = "debug"
|
||||
|
||||
var app = &cli.Command{
|
||||
Name: "nak",
|
||||
Suggest: true,
|
||||
@@ -27,6 +29,7 @@ var app = &cli.Command{
|
||||
bunker,
|
||||
serve,
|
||||
},
|
||||
Version: version,
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "quiet",
|
||||
|
||||
1
relay.go
1
relay.go
@@ -79,7 +79,6 @@ var relay = &cli.Command{
|
||||
Name: "sec",
|
||||
Usage: "secret key to sign the event, as nsec, ncryptsec or hex",
|
||||
DefaultText: "the key '1'",
|
||||
Value: "0000000000000000000000000000000000000000000000000000000000000001",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "prompt-sec",
|
||||
|
||||
Reference in New Issue
Block a user