mirror of
https://github.com/fiatjaf/nak.git
synced 2026-07-22 07:48:27 +00:00
add --jq-raw flag to print jq string results unquoted, like jq -r
This commit is contained in:
committed by
fiatjaf
parent
62fa610a06
commit
cbfc16f354
14
cli_test.go
14
cli_test.go
@@ -229,3 +229,17 @@ func TestNaturalTimestamps(t *testing.T) {
|
||||
require.Equal(t, nostr.Timestamp(1526711839), evt.CreatedAt)
|
||||
require.Equal(t, "nn", evt.Content)
|
||||
}
|
||||
|
||||
func TestEventJQ(t *testing.T) {
|
||||
// default: string results come out JSON-quoted, like plain jq
|
||||
quoted := call(t, "nak event --ts 1699485669 -c hello --jq .content")
|
||||
require.Equal(t, `"hello"`, quoted)
|
||||
|
||||
// --jq-raw: string results come out unquoted, like `jq -r`
|
||||
raw := call(t, "nak event --ts 1699485669 -c hello --jq .content --jq-raw")
|
||||
require.Equal(t, "hello", raw)
|
||||
|
||||
// --jq-raw on a non-string result is still JSON-encoded, like `jq -r`
|
||||
num := call(t, "nak event --ts 1699485669 -k 7 --jq .kind --jq-raw")
|
||||
require.Equal(t, "7", num)
|
||||
}
|
||||
|
||||
10
event.go
10
event.go
@@ -95,6 +95,11 @@ example:
|
||||
Usage: "filter returned events with jq expression",
|
||||
Category: CATEGORY_EXTRAS,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "jq-raw",
|
||||
Usage: "print --jq string results without JSON quoting, like `jq -r`",
|
||||
Category: CATEGORY_EXTRAS,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "nevent",
|
||||
Usage: "print the nevent code (to stderr) after the event is published",
|
||||
@@ -187,7 +192,7 @@ example:
|
||||
return err
|
||||
}
|
||||
|
||||
jq, err := jqPrepare(c.String("jq"))
|
||||
jq, err := jqPrepare(c.String("jq"), c.Bool("jq-raw"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -422,12 +427,11 @@ example:
|
||||
}
|
||||
stdout(result)
|
||||
} else {
|
||||
v, matches, err := jq(evt)
|
||||
out, matches, err := jq(evt)
|
||||
if err != nil {
|
||||
return fmt.Errorf("jq filter failed: %w", err)
|
||||
}
|
||||
if matches {
|
||||
out, _ := json.MarshalToString(v)
|
||||
stdout(out)
|
||||
}
|
||||
}
|
||||
|
||||
8
fetch.go
8
fetch.go
@@ -28,10 +28,14 @@ var fetch = &cli.Command{
|
||||
Name: "jq",
|
||||
Usage: "filter returned events with jq expression",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "jq-raw",
|
||||
Usage: "print --jq string results without JSON quoting, like `jq -r`",
|
||||
},
|
||||
),
|
||||
ArgsUsage: "[nip05_or_nip19_code]",
|
||||
Action: func(ctx context.Context, c *cli.Command) error {
|
||||
jq, err := jqPrepare(c.String("jq"))
|
||||
jq, err := jqPrepare(c.String("jq"), c.Bool("jq-raw"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -131,7 +135,7 @@ var fetch = &cli.Command{
|
||||
if !matches {
|
||||
continue
|
||||
}
|
||||
out, _ = json.MarshalToString(v)
|
||||
out = v
|
||||
}
|
||||
stdout(out)
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@ example:
|
||||
Name: "jq",
|
||||
Usage: "filter matching events with jq expression",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "jq-raw",
|
||||
Usage: "print --jq string results without JSON quoting, like `jq -r`",
|
||||
},
|
||||
),
|
||||
ArgsUsage: "[event_json] [base_filter_json]",
|
||||
Action: func(ctx context.Context, c *cli.Command) error {
|
||||
@@ -59,7 +63,7 @@ example:
|
||||
return err
|
||||
}
|
||||
|
||||
jq, err := jqPrepare(c.String("jq"))
|
||||
jq, err := jqPrepare(c.String("jq"), c.Bool("jq-raw"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -104,7 +108,7 @@ example:
|
||||
if !matches {
|
||||
continue
|
||||
}
|
||||
out, _ = json.MarshalToString(v)
|
||||
out = v
|
||||
}
|
||||
stdout(out)
|
||||
} else {
|
||||
|
||||
29
jq.go
29
jq.go
@@ -19,9 +19,11 @@ def time: .created_at | gmtime | strftime("%H:%M:%S");
|
||||
def datetime: .created_at | gmtime | strftime("%Y-%m-%dT%H:%M:%SZ");
|
||||
`
|
||||
|
||||
type jqProcessor func(nostr.Event) (any, bool, error)
|
||||
// jqProcessor runs the compiled jq expression against an event and returns the
|
||||
// rendered output string. When matches is false the event should be skipped.
|
||||
type jqProcessor func(nostr.Event) (out string, matches bool, err error)
|
||||
|
||||
func jqPrepare(expr string) (jqProcessor, error) {
|
||||
func jqPrepare(expr string, raw bool) (jqProcessor, error) {
|
||||
if expr == "" {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -36,30 +38,43 @@ func jqPrepare(expr string) (jqProcessor, error) {
|
||||
return nil, fmt.Errorf("failed to compile jq expression: %w", err)
|
||||
}
|
||||
|
||||
return func(evt nostr.Event) (any, bool, error) {
|
||||
return func(evt nostr.Event) (string, bool, error) {
|
||||
input, err := toJQInput(evt)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
return "", false, err
|
||||
}
|
||||
|
||||
iter := code.Run(input)
|
||||
for {
|
||||
v, ok := iter.Next()
|
||||
if !ok {
|
||||
return v, false, nil
|
||||
return "", false, nil
|
||||
}
|
||||
|
||||
if err, ok := v.(error); ok {
|
||||
return v, false, err
|
||||
return "", false, err
|
||||
}
|
||||
|
||||
if jqTruthy(v) {
|
||||
return v, true, nil
|
||||
return jqStringify(v, raw), true, nil
|
||||
}
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// jqStringify renders a jq result value. In raw mode string results are printed
|
||||
// without JSON quoting (like `jq -r`); non-string results are always
|
||||
// JSON-encoded.
|
||||
func jqStringify(v any, raw bool) string {
|
||||
if raw {
|
||||
if s, ok := v.(string); ok {
|
||||
return s
|
||||
}
|
||||
}
|
||||
out, _ := json.MarshalToString(v)
|
||||
return out
|
||||
}
|
||||
|
||||
func toJQInput(v any) (any, error) {
|
||||
data, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
|
||||
10
req.go
10
req.go
@@ -46,6 +46,10 @@ example:
|
||||
Name: "jq",
|
||||
Usage: "filter returned events with jq expression",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "jq-raw",
|
||||
Usage: "print --jq string results without JSON quoting, like `jq -r`",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "no-verify",
|
||||
Usage: "skip event signature verification from relays",
|
||||
@@ -124,7 +128,7 @@ example:
|
||||
return fmt.Errorf("relay URLs are incompatible with --bare or --spell")
|
||||
}
|
||||
|
||||
jq, err := jqPrepare(c.String("jq"))
|
||||
jq, err := jqPrepare(c.String("jq"), c.Bool("jq-raw"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -437,7 +441,7 @@ readevents:
|
||||
if !matches {
|
||||
continue
|
||||
}
|
||||
out, _ = json.MarshalToString(v)
|
||||
out = v
|
||||
}
|
||||
stdout(out)
|
||||
|
||||
@@ -641,7 +645,7 @@ func (p PrintingQuerierPublisher) Publish(ctx context.Context, evt nostr.Event)
|
||||
if !matches {
|
||||
return nil
|
||||
}
|
||||
out, _ = json.MarshalToString(v)
|
||||
out = v
|
||||
}
|
||||
stdout(out)
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user