mirror of
https://github.com/fiatjaf/nak.git
synced 2025-12-08 16:48:51 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3dfcec69b7 | ||
|
|
14b69f36cf | ||
|
|
3f7089e27e | ||
|
|
6a75c8aec3 | ||
|
|
b17887fe21 | ||
|
|
77103cae0c | ||
|
|
59a2c16b42 |
@@ -81,3 +81,8 @@ invalid .id, expected 05bd99d54cb835f427e0092c4275ee44c7ff51219eff417c19f70c9e2c
|
||||
```shell
|
||||
nak req -l 100 -k 1 -a 2edbcea694d164629854a52583458fd6d965b161e3c48b57d3aff01940558884 wss://relay.damus.io | jq -r '.content | match("nostr:((note1|nevent1)[a-z0-9]+)";"g") | .captures[0].string' | nak decode | jq -cr '{ids: [.id]}' | nak req wss://relay.damus.io
|
||||
```
|
||||
|
||||
## Contributing to this repository
|
||||
|
||||
Use NIP-34 to send your patches to `naddr1qqpkucttqy28wumn8ghj7un9d3shjtnyv9kh2uewd9hsz9nhwden5te0wfjkccte9ehx7um5wghxyctwvsq3vamnwvaz7tmjv4kxz7fwwpexjmtpdshxuet5qgsg04q5ypr6f4n65mv7e5hs05z50hy7vvgua8uc8szwtp262cfwn6srqsqqqauedy5x7y`.
|
||||
|
||||
|
||||
2
count.go
2
count.go
@@ -139,7 +139,7 @@ var count = &cli.Command{
|
||||
var result string
|
||||
j, _ := json.Marshal([]any{"COUNT", "nak", filter})
|
||||
result = string(j)
|
||||
fmt.Println(result)
|
||||
stdout(result)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
@@ -68,7 +67,7 @@ var decode = &cli.Command{
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Println(decodeResult.JSON())
|
||||
stdout(decodeResult.JSON())
|
||||
|
||||
}
|
||||
|
||||
|
||||
41
encode.go
41
encode.go
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@@ -29,13 +30,13 @@ var encode = &cli.Command{
|
||||
Usage: "encode a hex public key into bech32 'npub' format",
|
||||
Action: func(c *cli.Context) error {
|
||||
for target := range getStdinLinesOrFirstArgument(c) {
|
||||
if err := validate32BytesHex(target); err != nil {
|
||||
lineProcessingError(c, "invalid public key: %s", target, err)
|
||||
if ok := nostr.IsValidPublicKey(target); !ok {
|
||||
lineProcessingError(c, "invalid public key: %s", target)
|
||||
continue
|
||||
}
|
||||
|
||||
if npub, err := nip19.EncodePublicKey(target); err == nil {
|
||||
fmt.Println(npub)
|
||||
stdout(npub)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
@@ -50,13 +51,13 @@ var encode = &cli.Command{
|
||||
Usage: "encode a hex private key into bech32 'nsec' format",
|
||||
Action: func(c *cli.Context) error {
|
||||
for target := range getStdinLinesOrFirstArgument(c) {
|
||||
if err := validate32BytesHex(target); err != nil {
|
||||
lineProcessingError(c, "invalid private key: %s", target, err)
|
||||
if ok := nostr.IsValid32ByteHex(target); !ok {
|
||||
lineProcessingError(c, "invalid private key: %s", target)
|
||||
continue
|
||||
}
|
||||
|
||||
if npub, err := nip19.EncodePrivateKey(target); err == nil {
|
||||
fmt.Println(npub)
|
||||
stdout(npub)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
@@ -78,8 +79,8 @@ var encode = &cli.Command{
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
for target := range getStdinLinesOrFirstArgument(c) {
|
||||
if err := validate32BytesHex(target); err != nil {
|
||||
lineProcessingError(c, "invalid public key: %s", target, err)
|
||||
if ok := nostr.IsValid32ByteHex(target); !ok {
|
||||
lineProcessingError(c, "invalid public key: %s", target)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -89,7 +90,7 @@ var encode = &cli.Command{
|
||||
}
|
||||
|
||||
if npub, err := nip19.EncodeProfile(target, relays); err == nil {
|
||||
fmt.Println(npub)
|
||||
stdout(npub)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
@@ -115,15 +116,15 @@ var encode = &cli.Command{
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
for target := range getStdinLinesOrFirstArgument(c) {
|
||||
if err := validate32BytesHex(target); err != nil {
|
||||
lineProcessingError(c, "invalid event id: %s", target, err)
|
||||
if ok := nostr.IsValid32ByteHex(target); !ok {
|
||||
lineProcessingError(c, "invalid event id: %s", target)
|
||||
continue
|
||||
}
|
||||
|
||||
author := c.String("author")
|
||||
if author != "" {
|
||||
if err := validate32BytesHex(author); err != nil {
|
||||
return err
|
||||
if ok := nostr.IsValidPublicKey(author); !ok {
|
||||
return fmt.Errorf("invalid 'author' public key")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +134,7 @@ var encode = &cli.Command{
|
||||
}
|
||||
|
||||
if npub, err := nip19.EncodeEvent(target, relays, author); err == nil {
|
||||
fmt.Println(npub)
|
||||
stdout(npub)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
@@ -174,8 +175,8 @@ var encode = &cli.Command{
|
||||
Action: func(c *cli.Context) error {
|
||||
for d := range getStdinLinesOrBlank() {
|
||||
pubkey := c.String("pubkey")
|
||||
if err := validate32BytesHex(pubkey); err != nil {
|
||||
return err
|
||||
if ok := nostr.IsValidPublicKey(pubkey); !ok {
|
||||
return fmt.Errorf("invalid 'pubkey'")
|
||||
}
|
||||
|
||||
kind := c.Int("kind")
|
||||
@@ -197,7 +198,7 @@ var encode = &cli.Command{
|
||||
}
|
||||
|
||||
if npub, err := nip19.EncodeEntity(pubkey, kind, d, relays); err == nil {
|
||||
fmt.Println(npub)
|
||||
stdout(npub)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
@@ -212,13 +213,13 @@ var encode = &cli.Command{
|
||||
Usage: "generate note1 event codes (not recommended)",
|
||||
Action: func(c *cli.Context) error {
|
||||
for target := range getStdinLinesOrFirstArgument(c) {
|
||||
if err := validate32BytesHex(target); err != nil {
|
||||
lineProcessingError(c, "invalid event id: %s", target, err)
|
||||
if ok := nostr.IsValid32ByteHex(target); !ok {
|
||||
lineProcessingError(c, "invalid event id: %s", target)
|
||||
continue
|
||||
}
|
||||
|
||||
if note, err := nip19.EncodeNote(target); err == nil {
|
||||
fmt.Println(note)
|
||||
stdout(note)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
|
||||
28
event.go
28
event.go
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/mailru/easyjson"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
"github.com/nbd-wtf/go-nostr/nson"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/exp/slices"
|
||||
@@ -51,6 +52,10 @@ example:
|
||||
Name: "auth",
|
||||
Usage: "always perform NIP-42 \"AUTH\" when facing an \"auth-required: \" rejection and try again",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "nevent",
|
||||
Usage: "print the nevent code (to stderr) after the event is published",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "nson",
|
||||
Usage: "encode the event using NSON",
|
||||
@@ -87,6 +92,11 @@ example:
|
||||
Usage: "shortcut for --tag p=<value>",
|
||||
Category: CATEGORY_EVENT_FIELDS,
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "d",
|
||||
Usage: "shortcut for --tag d=<value>",
|
||||
Category: CATEGORY_EVENT_FIELDS,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "created-at",
|
||||
Aliases: []string{"time", "ts"},
|
||||
@@ -165,16 +175,20 @@ example:
|
||||
tagValues := strings.Split(tagValue, ";")
|
||||
tag = append(tag, tagValues...)
|
||||
// ~
|
||||
tags = append(tags, tag)
|
||||
tags = tags.AppendUnique(tag)
|
||||
}
|
||||
}
|
||||
|
||||
for _, etag := range c.StringSlice("e") {
|
||||
tags = append(tags, []string{"e", etag})
|
||||
tags = tags.AppendUnique([]string{"e", etag})
|
||||
mustRehashAndResign = true
|
||||
}
|
||||
for _, ptag := range c.StringSlice("p") {
|
||||
tags = append(tags, []string{"p", ptag})
|
||||
tags = tags.AppendUnique([]string{"p", ptag})
|
||||
mustRehashAndResign = true
|
||||
}
|
||||
for _, dtag := range c.StringSlice("d") {
|
||||
tags = tags.AppendUnique([]string{"d", dtag})
|
||||
mustRehashAndResign = true
|
||||
}
|
||||
if len(tags) > 0 {
|
||||
@@ -217,9 +231,10 @@ example:
|
||||
j, _ := easyjson.Marshal(&evt)
|
||||
result = string(j)
|
||||
}
|
||||
fmt.Println(result)
|
||||
stdout(result)
|
||||
|
||||
// publish to relays
|
||||
successRelays := make([]string, 0, len(relays))
|
||||
if len(relays) > 0 {
|
||||
os.Stdout.Sync()
|
||||
for _, relay := range relays {
|
||||
@@ -232,6 +247,7 @@ example:
|
||||
if err == nil {
|
||||
// published fine
|
||||
log("success.\n")
|
||||
successRelays = append(successRelays, relay.URL)
|
||||
continue // continue to next relay
|
||||
}
|
||||
|
||||
@@ -250,6 +266,10 @@ example:
|
||||
}
|
||||
log("failed: %s\n", err)
|
||||
}
|
||||
if len(successRelays) > 0 && c.Bool("nevent") {
|
||||
nevent, _ := nip19.EncodeEvent(evt.ID, successRelays, evt.PubKey)
|
||||
log(nevent + "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
4
fetch.go
4
fetch.go
@@ -1,8 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
sdk "github.com/nbd-wtf/nostr-sdk"
|
||||
@@ -93,7 +91,7 @@ var fetch = &cli.Command{
|
||||
}
|
||||
|
||||
for ie := range pool.SubManyEose(c.Context, relays, nostr.Filters{filter}) {
|
||||
fmt.Println(ie.Event)
|
||||
stdout(ie.Event)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
go.mod
2
go.mod
@@ -8,7 +8,7 @@ require (
|
||||
github.com/bgentry/speakeasy v0.1.0
|
||||
github.com/mailru/easyjson v0.7.7
|
||||
github.com/manifoldco/promptui v0.9.0
|
||||
github.com/nbd-wtf/go-nostr v0.28.0
|
||||
github.com/nbd-wtf/go-nostr v0.28.1
|
||||
github.com/nbd-wtf/nostr-sdk v0.0.5
|
||||
github.com/urfave/cli/v2 v2.25.7
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
|
||||
|
||||
4
go.sum
4
go.sum
@@ -76,8 +76,8 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
|
||||
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
|
||||
github.com/nbd-wtf/go-nostr v0.28.0 h1:SLYyoFeCNYb7HyWtmPUzD6rifBOMR66Spj5fzCk+5GE=
|
||||
github.com/nbd-wtf/go-nostr v0.28.0/go.mod h1:OQ8sNLFJnsj17BdqZiLSmjJBIFTfDqckEYC3utS4qoY=
|
||||
github.com/nbd-wtf/go-nostr v0.28.1 h1:XQi/lBsigBXHRm7IDBJE7SR9citCh9srgf8sA5iVW3A=
|
||||
github.com/nbd-wtf/go-nostr v0.28.1/go.mod h1:OQ8sNLFJnsj17BdqZiLSmjJBIFTfDqckEYC3utS4qoY=
|
||||
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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
|
||||
19
helpers.go
19
helpers.go
@@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -26,6 +25,8 @@ var log = func(msg string, args ...any) {
|
||||
fmt.Fprintf(os.Stderr, msg, args...)
|
||||
}
|
||||
|
||||
var stdout = fmt.Println
|
||||
|
||||
func isPiped() bool {
|
||||
stat, _ := os.Stdin.Stat()
|
||||
return stat.Mode()&os.ModeCharDevice == 0
|
||||
@@ -96,20 +97,6 @@ func validateRelayURLs(wsurls []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func validate32BytesHex(target string) error {
|
||||
if _, err := hex.DecodeString(target); err != nil {
|
||||
return fmt.Errorf("target '%s' is not valid hex: %s", target, err)
|
||||
}
|
||||
if len(target) != 64 {
|
||||
return fmt.Errorf("expected '%s' to be 64 characters (32 bytes), got %d", target, len(target))
|
||||
}
|
||||
if strings.ToLower(target) != target {
|
||||
return fmt.Errorf("expected target to be all lowercase hex. try again with '%s'", strings.ToLower(target))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func connectToAllRelays(
|
||||
ctx context.Context,
|
||||
relayUrls []string,
|
||||
@@ -163,7 +150,7 @@ func gatherSecretKeyFromArguments(c *cli.Context) (string, error) {
|
||||
return "", fmt.Errorf("invalid secret key: too large")
|
||||
}
|
||||
sec = strings.Repeat("0", 64-len(sec)) + sec // left-pad
|
||||
if err := validate32BytesHex(sec); err != nil {
|
||||
if ok := nostr.IsValid32ByteHex(sec); !ok {
|
||||
return "", fmt.Errorf("invalid secret key")
|
||||
}
|
||||
|
||||
|
||||
23
main.go
23
main.go
@@ -1,15 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var q int
|
||||
|
||||
var app = &cli.App{
|
||||
Name: "nak",
|
||||
Usage: "the nostr army knife command-line tool",
|
||||
Name: "nak",
|
||||
Suggest: true,
|
||||
UseShortOptionHandling: true,
|
||||
Usage: "the nostr army knife command-line tool",
|
||||
Commands: []*cli.Command{
|
||||
req,
|
||||
count,
|
||||
@@ -23,12 +26,16 @@ var app = &cli.App{
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "silent",
|
||||
Usage: "do not print logs and info messages to stderr",
|
||||
Aliases: []string{"s"},
|
||||
Name: "quiet",
|
||||
Usage: "do not print logs and info messages to stderr, use -qq to also not print anything to stdout",
|
||||
Count: &q,
|
||||
Aliases: []string{"q"},
|
||||
Action: func(ctx *cli.Context, b bool) error {
|
||||
if b {
|
||||
if q >= 1 {
|
||||
log = func(msg string, args ...any) {}
|
||||
if q >= 2 {
|
||||
stdout = func(a ...any) (int, error) { return 0, nil }
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
@@ -38,7 +45,7 @@ var app = &cli.App{
|
||||
|
||||
func main() {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
fmt.Println(err)
|
||||
stdout(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
2
relay.go
2
relay.go
@@ -31,7 +31,7 @@ var relay = &cli.Command{
|
||||
}
|
||||
|
||||
pretty, _ := json.MarshalIndent(info, "", " ")
|
||||
fmt.Println(string(pretty))
|
||||
stdout(string(pretty))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
12
req.go
12
req.go
@@ -62,6 +62,11 @@ example:
|
||||
Usage: "shortcut for --tag p=<value>",
|
||||
Category: CATEGORY_FILTER_ATTRIBUTES,
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "d",
|
||||
Usage: "shortcut for --tag d=<value>",
|
||||
Category: CATEGORY_FILTER_ATTRIBUTES,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "since",
|
||||
Aliases: []string{"s"},
|
||||
@@ -179,6 +184,9 @@ example:
|
||||
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)
|
||||
@@ -223,7 +231,7 @@ example:
|
||||
fn = pool.SubMany
|
||||
}
|
||||
for ie := range fn(c.Context, relayUrls, nostr.Filters{filter}) {
|
||||
fmt.Println(ie.Event)
|
||||
stdout(ie.Event)
|
||||
}
|
||||
} else {
|
||||
// no relays given, will just print the filter
|
||||
@@ -235,7 +243,7 @@ example:
|
||||
result = string(j)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
stdout(result)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user