mirror of
https://github.com/fiatjaf/nak.git
synced 2026-06-04 17:51:15 +02:00
84 lines
1.6 KiB
Go
84 lines
1.6 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"fiatjaf.com/nostr"
|
|
"github.com/itchyny/gojq"
|
|
)
|
|
|
|
const eventJQPrelude = `
|
|
def tags(tagName): .tags | map(select(.[0] == tagName));
|
|
def tag(tagName): tags(tagName) | .[0];
|
|
def value(tagName): tag(tagName)[1];
|
|
def has(tagName): (tags(tagName) | length) > 0;
|
|
def hasnt(tagName): (tags(tagName) | length) == 0;
|
|
def has_value(tagName; tagValue): tags(tagName) | map(select(.[1] == tagValue)) | length > 0;
|
|
`
|
|
|
|
type jqProcessor func(nostr.Event) (any, bool, error)
|
|
|
|
func jqPrepare(expr string) (jqProcessor, error) {
|
|
if expr == "" {
|
|
return nil, nil
|
|
}
|
|
|
|
query, err := gojq.Parse(eventJQPrelude + expr)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid jq expression: %w", err)
|
|
}
|
|
|
|
code, err := gojq.Compile(query)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to compile jq expression: %w", err)
|
|
}
|
|
|
|
return func(evt nostr.Event) (any, bool, error) {
|
|
input, err := toJQInput(evt)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
|
|
iter := code.Run(input)
|
|
for {
|
|
v, ok := iter.Next()
|
|
if !ok {
|
|
return v, false, nil
|
|
}
|
|
|
|
if err, ok := v.(error); ok {
|
|
return v, false, err
|
|
}
|
|
|
|
if jqTruthy(v) {
|
|
return v, true, nil
|
|
}
|
|
}
|
|
}, nil
|
|
}
|
|
|
|
func toJQInput(v any) (any, error) {
|
|
data, err := json.Marshal(v)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to marshal jq input: %w", err)
|
|
}
|
|
|
|
var input any
|
|
if err := json.Unmarshal(data, &input); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal jq input: %w", err)
|
|
}
|
|
|
|
return input, nil
|
|
}
|
|
|
|
func jqTruthy(v any) bool {
|
|
switch v := v.(type) {
|
|
case nil:
|
|
return false
|
|
case bool:
|
|
return v
|
|
default:
|
|
return true
|
|
}
|
|
}
|