mirror of
https://github.com/nbd-wtf/go-nostr.git
synced 2025-07-04 12:33:04 +02:00
deprecate all useless tag methods, implement Find() and friends.
This commit is contained in:
18
event.go
18
event.go
@ -69,8 +69,22 @@ func (evt *Event) Serialize() []byte {
|
|||||||
dst = append(dst, ',')
|
dst = append(dst, ',')
|
||||||
|
|
||||||
// tags
|
// tags
|
||||||
dst = evt.Tags.marshalTo(dst)
|
dst = append(dst, '[')
|
||||||
dst = append(dst, ',')
|
for i, tag := range evt.Tags {
|
||||||
|
if i > 0 {
|
||||||
|
dst = append(dst, ',')
|
||||||
|
}
|
||||||
|
// tag item
|
||||||
|
dst = append(dst, '[')
|
||||||
|
for i, s := range tag {
|
||||||
|
if i > 0 {
|
||||||
|
dst = append(dst, ',')
|
||||||
|
}
|
||||||
|
dst = escapeString(dst, s)
|
||||||
|
}
|
||||||
|
dst = append(dst, ']')
|
||||||
|
}
|
||||||
|
dst = append(dst, "],"...)
|
||||||
|
|
||||||
// content needs to be escaped in general as it is user generated.
|
// content needs to be escaped in general as it is user generated.
|
||||||
dst = escapeString(dst, evt.Content)
|
dst = escapeString(dst, evt.Content)
|
||||||
|
@ -2,24 +2,27 @@ package nip10
|
|||||||
|
|
||||||
import "github.com/nbd-wtf/go-nostr"
|
import "github.com/nbd-wtf/go-nostr"
|
||||||
|
|
||||||
func GetThreadRoot(tags nostr.Tags) *nostr.Tag {
|
func GetThreadRoot(tags nostr.Tags) *nostr.EventPointer {
|
||||||
for _, tag := range tags {
|
for _, tag := range tags {
|
||||||
if len(tag) >= 4 && tag[0] == "e" && tag[3] == "root" {
|
if len(tag) >= 4 && tag[0] == "e" && tag[3] == "root" {
|
||||||
return &tag
|
p, _ := nostr.EventPointerFromTag(tag)
|
||||||
|
return &p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tags.GetFirst([]string{"e", ""})
|
firstE := tags.Find("e")
|
||||||
|
if firstE != nil {
|
||||||
|
return &nostr.EventPointer{
|
||||||
|
ID: firstE[1],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: this was misnamed, use GetImmediateParent instead.
|
func GetImmediateParent(tags nostr.Tags) *nostr.EventPointer {
|
||||||
func GetImmediateReply(tags nostr.Tags) *nostr.Tag {
|
var parent nostr.Tag
|
||||||
return GetImmediateParent(tags)
|
var lastE nostr.Tag
|
||||||
}
|
|
||||||
|
|
||||||
func GetImmediateParent(tags nostr.Tags) *nostr.Tag {
|
|
||||||
var root *nostr.Tag
|
|
||||||
var lastE *nostr.Tag
|
|
||||||
|
|
||||||
for i := 0; i <= len(tags)-1; i++ {
|
for i := 0; i <= len(tags)-1; i++ {
|
||||||
tag := tags[i]
|
tag := tags[i]
|
||||||
|
@ -24,9 +24,9 @@ var (
|
|||||||
// if the target is bigger than the actual difficulty then it returns 0.
|
// if the target is bigger than the actual difficulty then it returns 0.
|
||||||
func CommittedDifficulty(event *nostr.Event) int {
|
func CommittedDifficulty(event *nostr.Event) int {
|
||||||
work := 0
|
work := 0
|
||||||
if nonceTag := event.Tags.GetFirst([]string{"nonce", ""}); nonceTag != nil && len(*nonceTag) >= 3 {
|
if nonceTag := event.Tags.Find("nonce"); nonceTag != nil && len(nonceTag) >= 3 {
|
||||||
work = Difficulty(event.ID)
|
work = Difficulty(event.ID)
|
||||||
target, _ := strconv.Atoi((*nonceTag)[2])
|
target, _ := strconv.Atoi(nonceTag[2])
|
||||||
if target <= work {
|
if target <= work {
|
||||||
work = target
|
work = target
|
||||||
} else {
|
} else {
|
||||||
|
@ -26,9 +26,9 @@ func HyperLogLogEventPubkeyOffsetsAndReferencesForEvent(evt *nostr.Event) iter.S
|
|||||||
//
|
//
|
||||||
// reaction counts:
|
// reaction counts:
|
||||||
// (only the last "e" tag counts)
|
// (only the last "e" tag counts)
|
||||||
lastE := evt.Tags.GetLast([]string{"e", ""})
|
lastE := evt.Tags.FindLast("e")
|
||||||
if lastE != nil {
|
if lastE != nil {
|
||||||
v := (*lastE)[1]
|
v := lastE[1]
|
||||||
if nostr.IsValid32ByteHex(v) {
|
if nostr.IsValid32ByteHex(v) {
|
||||||
// 32th nibble of "e" tag
|
// 32th nibble of "e" tag
|
||||||
p, _ := strconv.ParseInt(v[32:33], 16, 64)
|
p, _ := strconv.ParseInt(v[32:33], 16, 64)
|
||||||
|
12
tag_test.go
12
tag_test.go
@ -19,20 +19,10 @@ func TestTagHelpers(t *testing.T) {
|
|||||||
assert.Nil(t, tags.GetFirst([]string{"x", ""}), "got with wrong prefix")
|
assert.Nil(t, tags.GetFirst([]string{"x", ""}), "got with wrong prefix")
|
||||||
assert.NotNil(t, tags.GetFirst([]string{"p", "abcdef", "wss://"}), "failed to get with existing prefix")
|
assert.NotNil(t, tags.GetFirst([]string{"p", "abcdef", "wss://"}), "failed to get with existing prefix")
|
||||||
assert.NotNil(t, tags.GetFirst([]string{"p", "abcdef", ""}), "failed to get with existing prefix (blank last string)")
|
assert.NotNil(t, tags.GetFirst([]string{"p", "abcdef", ""}), "failed to get with existing prefix (blank last string)")
|
||||||
assert.Equal(t, "ffffff", (*(tags.GetLast([]string{"e"})))[1], "failed to get last")
|
assert.Equal(t, "ffffff", tags.FindLast("e")[1], "failed to get last")
|
||||||
assert.Equal(t, 2, len(tags.GetAll([]string{"e", ""})), "failed to get all")
|
assert.Equal(t, 2, len(tags.GetAll([]string{"e", ""})), "failed to get all")
|
||||||
c := make(Tags, 0, 2)
|
c := make(Tags, 0, 2)
|
||||||
for _, tag := range tags.All([]string{"e", ""}) {
|
for _, tag := range tags.All([]string{"e", ""}) {
|
||||||
c = append(c, tag)
|
c = append(c, tag)
|
||||||
}
|
}
|
||||||
assert.Equal(t, tags.GetAll([]string{"e", ""}), c)
|
|
||||||
assert.Equal(t, 5, len(tags.AppendUnique(Tag{"e", "ffffff"})), "append unique changed the array size when existed")
|
|
||||||
assert.Equal(t, 6, len(tags.AppendUnique(Tag{"e", "bbbbbb"})), "append unique failed to append when didn't exist")
|
|
||||||
assert.Equal(t, "ffffff", tags.AppendUnique(Tag{"e", "eeeeee"})[4][1], "append unique changed the order")
|
|
||||||
assert.Equal(t, "eeeeee", tags.AppendUnique(Tag{"e", "eeeeee"})[3][1], "append unique changed the order")
|
|
||||||
|
|
||||||
filtered := tags.FilterOut([]string{"e"})
|
|
||||||
tags.FilterOutInPlace([]string{"e"})
|
|
||||||
assert.ElementsMatch(t, filtered, tags)
|
|
||||||
assert.Len(t, filtered, 3)
|
|
||||||
}
|
}
|
||||||
|
102
tags.go
102
tags.go
@ -9,18 +9,8 @@ import (
|
|||||||
|
|
||||||
type Tag []string
|
type Tag []string
|
||||||
|
|
||||||
// StartsWith checks if a tag contains a prefix.
|
// Deprecated: this is too cumbersome for no reason when what we actually want is
|
||||||
// for example,
|
// the simpler logic present in Find and FindWithValue.
|
||||||
//
|
|
||||||
// ["p", "abcdef...", "wss://relay.com"]
|
|
||||||
//
|
|
||||||
// would match against
|
|
||||||
//
|
|
||||||
// ["p", "abcdef..."]
|
|
||||||
//
|
|
||||||
// or even
|
|
||||||
//
|
|
||||||
// ["p", "abcdef...", "wss://"]
|
|
||||||
func (tag Tag) StartsWith(prefix []string) bool {
|
func (tag Tag) StartsWith(prefix []string) bool {
|
||||||
prefixLen := len(prefix)
|
prefixLen := len(prefix)
|
||||||
|
|
||||||
@ -37,6 +27,7 @@ func (tag Tag) StartsWith(prefix []string) bool {
|
|||||||
return strings.HasPrefix(tag[prefixLen-1], prefix[prefixLen-1])
|
return strings.HasPrefix(tag[prefixLen-1], prefix[prefixLen-1])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: write these inline instead
|
||||||
func (tag Tag) Key() string {
|
func (tag Tag) Key() string {
|
||||||
if len(tag) > 0 {
|
if len(tag) > 0 {
|
||||||
return tag[0]
|
return tag[0]
|
||||||
@ -44,6 +35,7 @@ func (tag Tag) Key() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: write these inline instead
|
||||||
func (tag Tag) Value() string {
|
func (tag Tag) Value() string {
|
||||||
if len(tag) > 1 {
|
if len(tag) > 1 {
|
||||||
return tag[1]
|
return tag[1]
|
||||||
@ -51,6 +43,7 @@ func (tag Tag) Value() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: write these inline instead
|
||||||
func (tag Tag) Relay() string {
|
func (tag Tag) Relay() string {
|
||||||
if len(tag) > 2 && (tag[0] == "e" || tag[0] == "p") {
|
if len(tag) > 2 && (tag[0] == "e" || tag[0] == "p") {
|
||||||
return NormalizeURL(tag[2])
|
return NormalizeURL(tag[2])
|
||||||
@ -70,7 +63,7 @@ func (tags Tags) GetD() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFirst gets the first tag in tags that matches the prefix, see [Tag.StartsWith]
|
// Deprecated: use Find or FindWithValue instead
|
||||||
func (tags Tags) GetFirst(tagPrefix []string) *Tag {
|
func (tags Tags) GetFirst(tagPrefix []string) *Tag {
|
||||||
for _, v := range tags {
|
for _, v := range tags {
|
||||||
if v.StartsWith(tagPrefix) {
|
if v.StartsWith(tagPrefix) {
|
||||||
@ -80,7 +73,7 @@ func (tags Tags) GetFirst(tagPrefix []string) *Tag {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLast gets the last tag in tags that matches the prefix, see [Tag.StartsWith]
|
// Deprecated: use FindLast or FindLastWithValue instead
|
||||||
func (tags Tags) GetLast(tagPrefix []string) *Tag {
|
func (tags Tags) GetLast(tagPrefix []string) *Tag {
|
||||||
for i := len(tags) - 1; i >= 0; i-- {
|
for i := len(tags) - 1; i >= 0; i-- {
|
||||||
v := tags[i]
|
v := tags[i]
|
||||||
@ -91,7 +84,7 @@ func (tags Tags) GetLast(tagPrefix []string) *Tag {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAll gets all the tags that match the prefix, see [Tag.StartsWith]
|
// Deprecated: use FindAll instead
|
||||||
func (tags Tags) GetAll(tagPrefix []string) Tags {
|
func (tags Tags) GetAll(tagPrefix []string) Tags {
|
||||||
result := make(Tags, 0, len(tags))
|
result := make(Tags, 0, len(tags))
|
||||||
for _, v := range tags {
|
for _, v := range tags {
|
||||||
@ -102,7 +95,7 @@ func (tags Tags) GetAll(tagPrefix []string) Tags {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// All returns an iterator for all the tags that match the prefix, see [Tag.StartsWith]
|
// Deprecated: use FindAll instead
|
||||||
func (tags Tags) All(tagPrefix []string) iter.Seq2[int, Tag] {
|
func (tags Tags) All(tagPrefix []string) iter.Seq2[int, Tag] {
|
||||||
return func(yield func(int, Tag) bool) {
|
return func(yield func(int, Tag) bool) {
|
||||||
for i, v := range tags {
|
for i, v := range tags {
|
||||||
@ -115,7 +108,7 @@ func (tags Tags) All(tagPrefix []string) iter.Seq2[int, Tag] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterOut returns a new slice with only the elements that match the prefix, see [Tag.StartsWith]
|
// Deprecated: this is useless, write your own
|
||||||
func (tags Tags) FilterOut(tagPrefix []string) Tags {
|
func (tags Tags) FilterOut(tagPrefix []string) Tags {
|
||||||
filtered := make(Tags, 0, len(tags))
|
filtered := make(Tags, 0, len(tags))
|
||||||
for _, v := range tags {
|
for _, v := range tags {
|
||||||
@ -126,7 +119,7 @@ func (tags Tags) FilterOut(tagPrefix []string) Tags {
|
|||||||
return filtered
|
return filtered
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterOutInPlace removes all tags that match the prefix, but potentially reorders the tags in unpredictable ways, see [Tag.StartsWith]
|
// Deprecated: this is useless, write your own
|
||||||
func (tags *Tags) FilterOutInPlace(tagPrefix []string) {
|
func (tags *Tags) FilterOutInPlace(tagPrefix []string) {
|
||||||
for i := 0; i < len(*tags); i++ {
|
for i := 0; i < len(*tags); i++ {
|
||||||
tag := (*tags)[i]
|
tag := (*tags)[i]
|
||||||
@ -140,8 +133,7 @@ func (tags *Tags) FilterOutInPlace(tagPrefix []string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendUnique appends a tag if it doesn't exist yet, otherwise does nothing.
|
// Deprecated: write your own instead with Find() and append()
|
||||||
// the uniqueness comparison is done based only on the first 2 elements of the tag.
|
|
||||||
func (tags Tags) AppendUnique(tag Tag) Tags {
|
func (tags Tags) AppendUnique(tag Tag) Tags {
|
||||||
n := len(tag)
|
n := len(tag)
|
||||||
if n > 2 {
|
if n > 2 {
|
||||||
@ -154,6 +146,49 @@ func (tags Tags) AppendUnique(tag Tag) Tags {
|
|||||||
return tags
|
return tags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find returns the first tag with the given key/tagName that also has one value (i.e. at least 2 items)
|
||||||
|
func (tags Tags) Find(key string) Tag {
|
||||||
|
for _, v := range tags {
|
||||||
|
if len(v) >= 2 && v[0] == key {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindWithValue is like Find, but also checks if the value (the second item) matches
|
||||||
|
func (tags Tags) FindWithValue(key, value string) Tag {
|
||||||
|
for _, v := range tags {
|
||||||
|
if len(v) >= 2 && v[1] == value && v[0] == key {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindLast is like Find, but starts at the end
|
||||||
|
func (tags Tags) FindLast(key string) Tag {
|
||||||
|
for i := len(tags) - 1; i >= 0; i-- {
|
||||||
|
v := tags[i]
|
||||||
|
if len(v) >= 2 && v[0] == key {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindLastWithValue is like FindLast, but starts at the end
|
||||||
|
func (tags Tags) FindLastWithValue(key, value string) Tag {
|
||||||
|
for i := len(tags) - 1; i >= 0; i-- {
|
||||||
|
v := tags[i]
|
||||||
|
if len(v) >= 2 && v[1] == value && v[0] == key {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// this exists to satisfy Postgres and stuff and should probably be removed in the future since it's too specific
|
||||||
func (t *Tags) Scan(src any) error {
|
func (t *Tags) Scan(src any) error {
|
||||||
var jtags []byte
|
var jtags []byte
|
||||||
|
|
||||||
@ -187,30 +222,3 @@ func (tags Tags) ContainsAny(tagName string, values []string) bool {
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marshal Tag. Used for Serialization so string escaping should be as in RFC8259.
|
|
||||||
func (tag Tag) marshalTo(dst []byte) []byte {
|
|
||||||
dst = append(dst, '[')
|
|
||||||
for i, s := range tag {
|
|
||||||
if i > 0 {
|
|
||||||
dst = append(dst, ',')
|
|
||||||
}
|
|
||||||
dst = escapeString(dst, s)
|
|
||||||
}
|
|
||||||
dst = append(dst, ']')
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalTo appends the JSON encoded byte of Tags as [][]string to dst.
|
|
||||||
// String escaping is as described in RFC8259.
|
|
||||||
func (tags Tags) marshalTo(dst []byte) []byte {
|
|
||||||
dst = append(dst, '[')
|
|
||||||
for i, tag := range tags {
|
|
||||||
if i > 0 {
|
|
||||||
dst = append(dst, ',')
|
|
||||||
}
|
|
||||||
dst = tag.marshalTo(dst)
|
|
||||||
}
|
|
||||||
dst = append(dst, ']')
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user