mirror of
https://github.com/nbd-wtf/go-nostr.git
synced 2025-06-01 18:49:33 +02:00
some helper functions for tags.
This commit is contained in:
parent
cdc9b61db1
commit
8a12bb2c18
83
event_aux.go
83
event_aux.go
@ -4,13 +4,88 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/valyala/fastjson"
|
"github.com/valyala/fastjson"
|
||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Tags [][]string
|
type Tag []string
|
||||||
|
|
||||||
|
// StartsWith checks if a tag contains a prefix.
|
||||||
|
// for example,
|
||||||
|
// ["p", "abcdef...", "wss://relay.com"]
|
||||||
|
// would match against
|
||||||
|
// ["p", "abcdef..."]
|
||||||
|
// or even
|
||||||
|
// ["p", "abcdef...", "wss://"]
|
||||||
|
func (tag Tag) StartsWith(prefix []string) bool {
|
||||||
|
prefixLen := len(prefix)
|
||||||
|
|
||||||
|
if prefixLen > len(tag) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// check initial elements for equality
|
||||||
|
for i := 0; i < prefixLen-1; i++ {
|
||||||
|
if prefix[i] != tag[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check last element just for a prefix
|
||||||
|
return strings.HasPrefix(tag[prefixLen-1], prefix[prefixLen-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tags []Tag
|
||||||
|
|
||||||
|
// GetFirst gets the first tag in tags that matches tagPrefix, see [Tag.StartsWith]
|
||||||
|
func (tags Tags) GetFirst(tagPrefix []string) *Tag {
|
||||||
|
for _, v := range tags {
|
||||||
|
if v.StartsWith(tagPrefix) {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLast gets the last tag in tags that matches tagPrefix, see [Tag.StartsWith]
|
||||||
|
func (tags Tags) GetLast(tagPrefix []string) *Tag {
|
||||||
|
for i := len(tags) - 1; i >= 0; i-- {
|
||||||
|
v := tags[i]
|
||||||
|
if v.StartsWith(tagPrefix) {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tags Tags) GetAll(tagPrefix []string) Tags {
|
||||||
|
result := make(Tags, 0, len(tags))
|
||||||
|
for _, v := range tags {
|
||||||
|
if v.StartsWith(tagPrefix) {
|
||||||
|
result = append(result, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tags Tags) FilterOut(tagPrefix []string) Tags {
|
||||||
|
filtered := make(Tags, 0, len(tags))
|
||||||
|
for _, v := range tags {
|
||||||
|
if !v.StartsWith(tagPrefix) {
|
||||||
|
filtered = append(filtered, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filtered
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tags Tags) AppendUnique(tag Tag) Tags {
|
||||||
|
if tags.GetFirst(tag) == nil {
|
||||||
|
return append(tags.FilterOut(tag), tag)
|
||||||
|
} else {
|
||||||
|
return tags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Tags) Scan(src interface{}) error {
|
func (t *Tags) Scan(src interface{}) error {
|
||||||
var jtags []byte = make([]byte, 0)
|
var jtags []byte = make([]byte, 0)
|
||||||
@ -147,14 +222,14 @@ func fastjsonArrayToTags(v *fastjson.Value) (Tags, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sll := make([][]string, len(arr))
|
sll := make(Tags, len(arr))
|
||||||
for i, v := range arr {
|
for i, v := range arr {
|
||||||
subarr, err := v.Array()
|
subarr, err := v.Array()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sl := make([]string, len(subarr))
|
sl := make(Tag, len(subarr))
|
||||||
for j, subv := range subarr {
|
for j, subv := range subarr {
|
||||||
sb, err := subv.StringBytes()
|
sb, err := subv.StringBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -165,7 +240,7 @@ func fastjsonArrayToTags(v *fastjson.Value) (Tags, error) {
|
|||||||
sll[i] = sl
|
sll[i] = sl
|
||||||
}
|
}
|
||||||
|
|
||||||
return Tags(sll), nil
|
return sll, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagsToFastjsonArray(arena *fastjson.Arena, tags Tags) *fastjson.Value {
|
func tagsToFastjsonArray(arena *fastjson.Arena, tags Tags) *fastjson.Value {
|
||||||
|
48
tag_test.go
Normal file
48
tag_test.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package nostr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTagHelpers(t *testing.T) {
|
||||||
|
tags := Tags{
|
||||||
|
Tag{"x"},
|
||||||
|
Tag{"p", "abcdef", "wss://x.com"},
|
||||||
|
Tag{"p", "123456", "wss://y.com"},
|
||||||
|
Tag{"e", "eeeeee"},
|
||||||
|
Tag{"e", "ffffff"},
|
||||||
|
}
|
||||||
|
|
||||||
|
if tags.GetFirst([]string{"x"}) == nil {
|
||||||
|
t.Error("failed to get existing prefix")
|
||||||
|
}
|
||||||
|
if tags.GetFirst([]string{"x", ""}) != nil {
|
||||||
|
t.Error("got with wrong prefix")
|
||||||
|
}
|
||||||
|
if tags.GetFirst([]string{"p", "abcdef", "wss://"}) == nil {
|
||||||
|
t.Error("failed to get with existing prefix")
|
||||||
|
}
|
||||||
|
if tags.GetFirst([]string{"p", "abcdef", ""}) == nil {
|
||||||
|
t.Error("failed to get with existing prefix (blank last string)")
|
||||||
|
}
|
||||||
|
if (*(tags.GetLast([]string{"e"})))[1] != "ffffff" {
|
||||||
|
t.Error("failed to get last")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(tags.GetAll([]string{"e", ""})) != 2 {
|
||||||
|
t.Error("failed to get all")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(tags.AppendUnique(Tag{"e", "ffffff"})) != 5 {
|
||||||
|
t.Error("append unique changed the array size when existed")
|
||||||
|
}
|
||||||
|
if len(tags.AppendUnique(Tag{"e", "bbbbbb"})) != 6 {
|
||||||
|
t.Error("append unique failed to append when didn't exist")
|
||||||
|
}
|
||||||
|
if tags.AppendUnique(Tag{"e", "eeeeee"})[4][1] != "ffffff" {
|
||||||
|
t.Error("append unique changed the order")
|
||||||
|
}
|
||||||
|
if tags.AppendUnique(Tag{"e", "eeeeee"})[3][1] != "eeeeee" {
|
||||||
|
t.Error("append unique changed the order")
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user