support running nak with multiple lines of stdin sequentially.

This commit is contained in:
fiatjaf 2023-11-07 17:57:43 -03:00
parent 31b42c3499
commit 78932833df
No known key found for this signature in database
GPG Key ID: BAD43C4BE5C1A3A1
4 changed files with 237 additions and 191 deletions

View File

@ -90,15 +90,16 @@ example:
}, },
ArgsUsage: "[relay...]", ArgsUsage: "[relay...]",
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
for stdinEvent := range getStdinLinesOrBlank() {
evt := nostr.Event{ evt := nostr.Event{
Tags: make(nostr.Tags, 0, 3), Tags: make(nostr.Tags, 0, 3),
} }
mustRehashAndResign := false mustRehashAndResign := false
if stdinEvent != "" {
if stdinEvent := getStdin(); stdinEvent != "" {
if err := json.Unmarshal([]byte(stdinEvent), &evt); err != nil { if err := json.Unmarshal([]byte(stdinEvent), &evt); err != nil {
return fmt.Errorf("invalid event received from stdin: %w", err) lineProcessingError(c, "invalid event received from stdin: %s", err)
continue
} }
} }
@ -198,7 +199,9 @@ example:
} }
fmt.Println(result) fmt.Println(result)
} }
}
exitIfLineProcessingError(c)
return nil return nil
}, },
} }

View File

@ -1,7 +1,9 @@
package main package main
import ( import (
"bufio"
"bytes" "bytes"
"context"
"fmt" "fmt"
"io" "io"
"net/url" "net/url"
@ -11,7 +13,36 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
func getStdin() string { const (
LINE_PROCESSING_ERROR = iota
)
func getStdinLinesOrBlank() chan string {
ch := make(chan string)
go func() {
r := bufio.NewReader(os.Stdin)
if _, err := r.Peek(1); err != nil {
ch <- ""
close(ch)
} else {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
ch <- scanner.Text()
}
close(ch)
}
}()
return ch
}
func getStdinOrFirstArgument(c *cli.Context) string {
// try the first argument
target := c.Args().First()
if target != "" {
return target
}
// try the stdin
stat, _ := os.Stdin.Stat() stat, _ := os.Stdin.Stat()
if (stat.Mode() & os.ModeCharDevice) == 0 { if (stat.Mode() & os.ModeCharDevice) == 0 {
read := bytes.NewBuffer(make([]byte, 0, 1000)) read := bytes.NewBuffer(make([]byte, 0, 1000))
@ -23,14 +54,6 @@ func getStdin() string {
return "" return ""
} }
func getStdinOrFirstArgument(c *cli.Context) string {
target := c.Args().First()
if target != "" {
return target
}
return getStdin()
}
func validateRelayURLs(wsurls []string) error { func validateRelayURLs(wsurls []string) error {
for _, wsurl := range wsurls { for _, wsurl := range wsurls {
u, err := url.Parse(wsurl) u, err := url.Parse(wsurl)
@ -49,3 +72,14 @@ func validateRelayURLs(wsurls []string) error {
return nil return nil
} }
func lineProcessingError(c *cli.Context, msg string, args ...any) {
c.Context = context.WithValue(c.Context, LINE_PROCESSING_ERROR, true)
fmt.Fprintf(os.Stderr, msg+"\n", args...)
}
func exitIfLineProcessingError(c *cli.Context) {
if val := c.Context.Value(LINE_PROCESSING_ERROR); val != nil && val.(bool) {
os.Exit(123)
}
}

8
req.go
View File

@ -95,10 +95,12 @@ example:
}, },
ArgsUsage: "[relay...]", ArgsUsage: "[relay...]",
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
for stdinFilter := range getStdinLinesOrBlank() {
filter := nostr.Filter{} filter := nostr.Filter{}
if stdinFilter := getStdin(); stdinFilter != "" { if stdinFilter != "" {
if err := json.Unmarshal([]byte(stdinFilter), &filter); err != nil { if err := json.Unmarshal([]byte(stdinFilter), &filter); err != nil {
return fmt.Errorf("invalid filter received from stdin: %w", err) lineProcessingError(c, "invalid filter received from stdin: %s", err)
continue
} }
} }
@ -175,7 +177,9 @@ example:
fmt.Println(result) fmt.Println(result)
} }
}
exitIfLineProcessingError(c)
return nil return nil
}, },
} }

View File

@ -2,7 +2,6 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt"
"github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
@ -17,21 +16,27 @@ var verify = &cli.Command{
it outputs nothing if the verification is successful. it outputs nothing if the verification is successful.
`, `,
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
for stdinEvent := range getStdinLinesOrBlank() {
evt := nostr.Event{} evt := nostr.Event{}
if stdinEvent := getStdin(); stdinEvent != "" { if stdinEvent != "" {
if err := json.Unmarshal([]byte(stdinEvent), &evt); err != nil { if err := json.Unmarshal([]byte(stdinEvent), &evt); err != nil {
return fmt.Errorf("invalid JSON: %w", err) lineProcessingError(c, "invalid event: %s", err)
continue
} }
} }
if evt.GetID() != evt.ID { if evt.GetID() != evt.ID {
return fmt.Errorf("invalid .id, expected %s, got %s", evt.GetID(), evt.ID) lineProcessingError(c, "invalid .id, expected %s, got %s", evt.GetID(), evt.ID)
continue
} }
if ok, err := evt.CheckSignature(); !ok { if ok, err := evt.CheckSignature(); !ok {
return fmt.Errorf("invalid signature: %w", err) lineProcessingError(c, "invalid signature: %s", err)
continue
}
} }
exitIfLineProcessingError(c)
return nil return nil
}, },
} }