90 lines
2.0 KiB
Go
90 lines
2.0 KiB
Go
package nostr
|
|
|
|
import (
|
|
"bytes"
|
|
"cmp"
|
|
"net/url"
|
|
"slices"
|
|
"unsafe"
|
|
|
|
"github.com/templexxx/xhex"
|
|
)
|
|
|
|
// IsValidRelayURL checks if a URL is a valid relay URL (ws:// or wss://).
|
|
func IsValidRelayURL(u string) bool {
|
|
parsed, err := url.Parse(u)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
if parsed.Scheme != "wss" && parsed.Scheme != "ws" {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// HexEncodeToString encodes src into a hex string.
|
|
func HexEncodeToString(src []byte) string {
|
|
dst := make([]byte, len(src)*2)
|
|
xhex.Encode(dst, src)
|
|
return unsafe.String(unsafe.SliceData(dst), len(dst))
|
|
}
|
|
|
|
// HexDecodeString decodes a hex string into bytes.
|
|
func HexDecodeString(s string) ([]byte, error) {
|
|
src := unsafe.Slice(unsafe.StringData(s), len(s))
|
|
if len(src)%2 != 0 {
|
|
return nil, xhex.ErrLength
|
|
}
|
|
dst := make([]byte, len(src)/2)
|
|
err := xhex.Decode(dst, src)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return dst, nil
|
|
}
|
|
|
|
// IsValid32ByteHex checks if a string is a valid 32-byte hex string.
|
|
func IsValid32ByteHex(thing string) bool {
|
|
if !isLowerHex(thing) {
|
|
return false
|
|
}
|
|
if len(thing) != 64 {
|
|
return false
|
|
}
|
|
_, err := HexDecodeString(thing)
|
|
return err == nil
|
|
}
|
|
|
|
// CompareEvent is meant to to be used with slices.Sort
|
|
func CompareEvent(a, b Event) int {
|
|
if a.CreatedAt == b.CreatedAt {
|
|
return bytes.Compare(a.ID[:], b.ID[:])
|
|
}
|
|
return cmp.Compare(a.CreatedAt, b.CreatedAt)
|
|
}
|
|
|
|
// CompareEventReverse is meant to to be used with slices.Sort
|
|
func CompareEventReverse(b, a Event) int {
|
|
if a.CreatedAt == b.CreatedAt {
|
|
return bytes.Compare(a.ID[:], b.ID[:])
|
|
}
|
|
return cmp.Compare(a.CreatedAt, b.CreatedAt)
|
|
}
|
|
|
|
// AppendUnique adds items to an array only if they don't already exist in the array.
|
|
// Returns the modified array.
|
|
func AppendUnique[I comparable](arr []I, item ...I) []I {
|
|
for _, item := range item {
|
|
if slices.Contains(arr, item) {
|
|
return arr
|
|
}
|
|
arr = append(arr, item)
|
|
}
|
|
return arr
|
|
}
|
|
|
|
func IsOlder(previous, next Event) bool {
|
|
return previous.CreatedAt < next.CreatedAt ||
|
|
(previous.CreatedAt == next.CreatedAt && bytes.Compare(previous.ID[:], next.ID[:]) == 1)
|
|
}
|