diff --git a/README.md b/README.md index 4b86db8..d467414 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,13 @@ # nostr army knife -A toolkit for debugging all things Nostr as a webpage. +this repository contains two things: + +1. a command-line tool for decoding and encoding nostr entities + +written in go using [go-nostr](https://github.com/nbd-wtf/go-nostr) and distributed as a single binary. + +2. a toolkit for debugging all things nostr as a webpage: ![](https://user-images.githubusercontent.com/1653275/227681805-0cd20b39-de0d-4fcb-abb4-de3283404e8f.png) -Made with [Scala](https://scala-lang.org/) and [Calico](https://www.armanbilge.com/calico/). Icon by [Smashicons](https://www.flaticon.com/free-icons/switzerland). +written in [scala](https://scala-lang.org/) with [calico](https://www.armanbilge.com/calico/) and [snow](https://github.com/fiatjaf/snow) diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..cf7ee94 --- /dev/null +++ b/go.mod @@ -0,0 +1,23 @@ +module git.fiatjaf.com/nak + +go 1.20 + +require ( + github.com/nbd-wtf/go-nostr v0.17.1 + github.com/urfave/cli/v2 v2.25.3 +) + +require ( + github.com/SaveTheRbtz/generic-sync-map-go v0.0.0-20220414055132-a37292614db8 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + golang.org/x/exp v0.0.0-20221106115401-f9659909a136 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..f05d95d --- /dev/null +++ b/go.sum @@ -0,0 +1,30 @@ +github.com/SaveTheRbtz/generic-sync-map-go v0.0.0-20220414055132-a37292614db8 h1:Xa6tp8DPDhdV+k23uiTC/GrAYOe4IdyJVKtob4KW3GA= +github.com/SaveTheRbtz/generic-sync-map-go v0.0.0-20220414055132-a37292614db8/go.mod h1:ihkm1viTbO/LOsgdGoFPBSvzqvx7ibvkMzYp3CgtHik= +github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= +github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/nbd-wtf/go-nostr v0.17.1 h1:dRyNNf1rx5vGYi9AH1A/mcKKQg8ZSiY8uRUJGObXPPI= +github.com/nbd-wtf/go-nostr v0.17.1/go.mod h1:YCDHJtaFQE76d1ZkcUsTkz3dYNP+bldo5CIQwXPPcbk= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/urfave/cli/v2 v2.25.3 h1:VJkt6wvEBOoSjPFQvOkv6iWIrsJyCrKGtCtxXWwmGeY= +github.com/urfave/cli/v2 v2.25.3/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +golang.org/x/exp v0.0.0-20221106115401-f9659909a136 h1:Fq7F/w7MAa1KJ5bt2aJ62ihqp9HDcRuyILskkpIAurw= +golang.org/x/exp v0.0.0-20221106115401-f9659909a136/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc h1:zK/HqS5bZxDptfPJNq8v7vJfXtkU7r9TLIoSr1bXaP4= diff --git a/main.go b/main.go new file mode 100644 index 0000000..3f512b1 --- /dev/null +++ b/main.go @@ -0,0 +1,129 @@ +package main + +import ( + "fmt" + "log" + "os" + "strings" + + "github.com/nbd-wtf/go-nostr" + "github.com/urfave/cli/v2" +) + +func main() { + app := &cli.App{ + Name: "nak", + Usage: "the nostr army knife command-line tool", + Commands: []*cli.Command{ + { + Name: "req", + Usage: "generates an encoded REQ message to be sent to a relay", + Description: `example usage (with 'nostcat'): + nak req -k 1 -a 3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d | nostcat wss://nostr-pub.wellorder.net + `, + Flags: []cli.Flag{ + &cli.StringSliceFlag{ + Name: "author", + Aliases: []string{"a"}, + Usage: "only accept events from these authors (pubkey as hex)", + }, + &cli.StringSliceFlag{ + Name: "id", + Aliases: []string{"i"}, + Usage: "only accept events with these ids (hex)", + }, + &cli.IntSliceFlag{ + Name: "kind", + Aliases: []string{"k"}, + Usage: "only accept events with these kind numbers", + }, + &cli.StringSliceFlag{ + Name: "tag", + Aliases: []string{"t"}, + Usage: "takes a tag like -t e=, only accept events with these tags", + }, + &cli.StringSliceFlag{ + Name: "event-tag", + Aliases: []string{"e"}, + Usage: "shortcut for --tag e=", + }, + &cli.StringSliceFlag{ + Name: "pubkey-tag", + Aliases: []string{"p"}, + Usage: "shortcut for --tag p=", + }, + &cli.IntFlag{ + Name: "since", + Aliases: []string{"s"}, + Usage: "only accept events newer than this (unix timestamp)", + }, + &cli.IntFlag{ + Name: "until", + Aliases: []string{"u"}, + Usage: "only accept events older than this (unix timestamp)", + }, + &cli.IntFlag{ + Name: "limit", + Aliases: []string{"l"}, + Usage: "only accept up to this number of events", + }, + }, + Action: func(c *cli.Context) error { + 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 + } + if kinds := c.IntSlice("kind"); len(kinds) > 0 { + filter.Kinds = kinds + } + + tags := make([][]string, 0, 5) + for _, tagFlag := range c.StringSlice("tag") { + spl := strings.Split(tagFlag, "=") + if len(spl) == 2 && len(spl[0]) == 1 { + tags = append(tags, spl) + } + } + for _, etag := range c.StringSlice("event-tag") { + tags = append(tags, []string{"e", etag}) + } + for _, ptag := range c.StringSlice("pubkey-tag") { + 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 { + filter.Limit = limit + } + + fmt.Println(filter.String()) + return nil + }, + }, + }, + } + + if err := app.Run(os.Args); err != nil { + log.Fatalf("failed to run cli: %s", err) + } +}