mirror of
https://github.com/nbd-wtf/go-nostr.git
synced 2025-06-24 15:52:25 +02:00
tag helpers in a separate file and nip10 helpers.
This commit is contained in:
parent
69ccfbaa08
commit
381ee2cc01
116
event_aux.go
116
event_aux.go
@ -2,128 +2,12 @@ package nostr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/valyala/fastjson"
|
"github.com/valyala/fastjson"
|
||||||
"golang.org/x/exp/slices"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
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 the prefix, 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 the prefix, 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLast gets all the tags that match the prefix, see [Tag.StartsWith]
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// FilterOut removes all tags that match the prefix, see [Tag.StartsWith]
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// AppendUnique appends a tag if it doesn't exist yet, otherwise does nothing
|
|
||||||
func (tags Tags) AppendUnique(tag Tag) Tags {
|
|
||||||
if tags.GetFirst(tag) == nil {
|
|
||||||
return append(tags, tag)
|
|
||||||
} else {
|
|
||||||
return tags
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Tags) Scan(src interface{}) error {
|
|
||||||
var jtags []byte = make([]byte, 0)
|
|
||||||
|
|
||||||
switch v := src.(type) {
|
|
||||||
case []byte:
|
|
||||||
jtags = v
|
|
||||||
case string:
|
|
||||||
jtags = []byte(v)
|
|
||||||
default:
|
|
||||||
return errors.New("couldn't scan tags, it's not a json string")
|
|
||||||
}
|
|
||||||
|
|
||||||
json.Unmarshal(jtags, &t)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tags Tags) ContainsAny(tagName string, values []string) bool {
|
|
||||||
for _, tag := range tags {
|
|
||||||
if len(tag) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if tag[0] != tagName {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if slices.Contains(values, tag[1]) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (evt *Event) UnmarshalJSON(payload []byte) error {
|
func (evt *Event) UnmarshalJSON(payload []byte) error {
|
||||||
var fastjsonParser fastjson.Parser
|
var fastjsonParser fastjson.Parser
|
||||||
parsed, err := fastjsonParser.ParseBytes(payload)
|
parsed, err := fastjsonParser.ParseBytes(payload)
|
||||||
|
24
nip10/nip10.go
Normal file
24
nip10/nip10.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package nip10
|
||||||
|
|
||||||
|
import "github.com/nbd-wtf/go-nostr"
|
||||||
|
|
||||||
|
func GetThreadRoot(tags nostr.Tags) *nostr.Tag {
|
||||||
|
for _, tag := range tags {
|
||||||
|
if len(tag) >= 4 && tag[0] == "e" && tag[3] == "root" {
|
||||||
|
return &tag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tags.GetFirst([]string{"e", ""})
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetImmediateReply(tags nostr.Tags) *nostr.Tag {
|
||||||
|
for i := len(tags) - 1; i >= 0; i-- {
|
||||||
|
tag := tags[i]
|
||||||
|
if len(tag) >= 4 && tag[0] == "e" && tag[3] == "reply" {
|
||||||
|
return &tag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tags.GetLast([]string{"e", ""})
|
||||||
|
}
|
143
tags.go
Normal file
143
tags.go
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
package nostr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
|
)
|
||||||
|
|
||||||
|
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])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tag Tag) Key() string {
|
||||||
|
if len(tag) > 0 {
|
||||||
|
return tag[0]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tag Tag) Value() string {
|
||||||
|
if len(tag) > 1 {
|
||||||
|
return tag[1]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tag Tag) Relay() string {
|
||||||
|
if tag[0] == "e" || tag[0] == "p" && len(tag) > 2 {
|
||||||
|
return tag[2]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tags []Tag
|
||||||
|
|
||||||
|
// GetFirst gets the first tag in tags that matches the prefix, 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 the prefix, 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLast gets all the tags that match the prefix, see [Tag.StartsWith]
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterOut removes all tags that match the prefix, see [Tag.StartsWith]
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendUnique appends a tag if it doesn't exist yet, otherwise does nothing
|
||||||
|
func (tags Tags) AppendUnique(tag Tag) Tags {
|
||||||
|
if tags.GetFirst(tag) == nil {
|
||||||
|
return append(tags, tag)
|
||||||
|
} else {
|
||||||
|
return tags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tags) Scan(src interface{}) error {
|
||||||
|
var jtags []byte = make([]byte, 0)
|
||||||
|
|
||||||
|
switch v := src.(type) {
|
||||||
|
case []byte:
|
||||||
|
jtags = v
|
||||||
|
case string:
|
||||||
|
jtags = []byte(v)
|
||||||
|
default:
|
||||||
|
return errors.New("couldn't scan tags, it's not a json string")
|
||||||
|
}
|
||||||
|
|
||||||
|
json.Unmarshal(jtags, &t)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tags Tags) ContainsAny(tagName string, values []string) bool {
|
||||||
|
for _, tag := range tags {
|
||||||
|
if len(tag) < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if tag[0] != tagName {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if slices.Contains(values, tag[1]) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user