a bunch of [32]byte conversions. still more needed.
This commit is contained in:
@@ -5,8 +5,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/dataloader"
|
||||
"fiatjaf.com/nostr"
|
||||
"fiatjaf.com/nostr/sdk/dataloader"
|
||||
)
|
||||
|
||||
// this is similar to replaceable_loader and reuses logic from that.
|
||||
@@ -21,16 +21,16 @@ const (
|
||||
)
|
||||
|
||||
func (sys *System) initializeAddressableDataloaders() {
|
||||
sys.addressableLoaders = make([]*dataloader.Loader[string, []*nostr.Event], 4)
|
||||
sys.addressableLoaders = make([]*dataloader.Loader[nostr.PubKey, []*nostr.Event], 4)
|
||||
sys.addressableLoaders[kind_30000] = sys.createAddressableDataloader(30000)
|
||||
sys.addressableLoaders[kind_30002] = sys.createAddressableDataloader(30002)
|
||||
sys.addressableLoaders[kind_30015] = sys.createAddressableDataloader(30015)
|
||||
sys.addressableLoaders[kind_30030] = sys.createAddressableDataloader(30030)
|
||||
}
|
||||
|
||||
func (sys *System) createAddressableDataloader(kind int) *dataloader.Loader[string, []*nostr.Event] {
|
||||
func (sys *System) createAddressableDataloader(kind uint16) *dataloader.Loader[nostr.PubKey, []*nostr.Event] {
|
||||
return dataloader.NewBatchedLoader(
|
||||
func(ctxs []context.Context, pubkeys []string) map[string]dataloader.Result[[]*nostr.Event] {
|
||||
func(ctxs []context.Context, pubkeys []nostr.PubKey) map[nostr.PubKey]dataloader.Result[[]*nostr.Event] {
|
||||
return sys.batchLoadAddressableEvents(ctxs, kind, pubkeys)
|
||||
},
|
||||
dataloader.Options{
|
||||
@@ -42,11 +42,11 @@ func (sys *System) createAddressableDataloader(kind int) *dataloader.Loader[stri
|
||||
|
||||
func (sys *System) batchLoadAddressableEvents(
|
||||
ctxs []context.Context,
|
||||
kind int,
|
||||
pubkeys []string,
|
||||
) map[string]dataloader.Result[[]*nostr.Event] {
|
||||
kind uint16,
|
||||
pubkeys []nostr.PubKey,
|
||||
) map[nostr.PubKey]dataloader.Result[[]*nostr.Event] {
|
||||
batchSize := len(pubkeys)
|
||||
results := make(map[string]dataloader.Result[[]*nostr.Event], batchSize)
|
||||
results := make(map[nostr.PubKey]dataloader.Result[[]*nostr.Event], batchSize)
|
||||
relayFilter := make([]nostr.DirectedFilter, 0, max(3, batchSize*2))
|
||||
relayFilterIndex := make(map[string]int, max(3, batchSize*2))
|
||||
|
||||
@@ -62,7 +62,7 @@ func (sys *System) batchLoadAddressableEvents(
|
||||
defer cancel()
|
||||
|
||||
// build batched queries for the external relays
|
||||
go func(i int, pubkey string) {
|
||||
go func(i int, pubkey nostr.PubKey) {
|
||||
// gather relays we'll use for this pubkey
|
||||
relays := sys.determineRelaysToQuery(ctx, pubkey, kind)
|
||||
|
||||
@@ -77,8 +77,8 @@ func (sys *System) batchLoadAddressableEvents(
|
||||
dfilter = nostr.DirectedFilter{
|
||||
Relay: relay,
|
||||
Filter: nostr.Filter{
|
||||
Kinds: []int{kind},
|
||||
Authors: make([]string, 0, batchSize-i /* this and all pubkeys after this can be added */),
|
||||
Kinds: []uint16{kind},
|
||||
Authors: make([]nostr.PubKey, 0, batchSize-i /* this and all pubkeys after this can be added */),
|
||||
},
|
||||
}
|
||||
idx = len(relayFilter)
|
||||
|
||||
8
sdk/cache/interface.go
vendored
8
sdk/cache/interface.go
vendored
@@ -3,8 +3,8 @@ package cache
|
||||
import "time"
|
||||
|
||||
type Cache32[V any] interface {
|
||||
Get(k string) (v V, ok bool)
|
||||
Delete(k string)
|
||||
Set(k string, v V) bool
|
||||
SetWithTTL(k string, v V, d time.Duration) bool
|
||||
Get(k [32]byte) (v V, ok bool)
|
||||
Delete(k [32]byte)
|
||||
Set(k [32]byte, v V) bool
|
||||
SetWithTTL(k [32]byte, v V, d time.Duration) bool
|
||||
}
|
||||
|
||||
38
sdk/cache/memory/cache.go
vendored
38
sdk/cache/memory/cache.go
vendored
@@ -2,47 +2,33 @@ package cache_memory
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"time"
|
||||
|
||||
"github.com/dgraph-io/ristretto"
|
||||
)
|
||||
|
||||
type RistrettoCache[V any] struct {
|
||||
Cache *ristretto.Cache[string, V]
|
||||
Cache *ristretto.Cache[uint64, V]
|
||||
}
|
||||
|
||||
func New32[V any](max int64) *RistrettoCache[V] {
|
||||
cache, _ := ristretto.NewCache(&ristretto.Config[string, V]{
|
||||
func New[V any](max int64) *RistrettoCache[V] {
|
||||
cache, _ := ristretto.NewCache(&ristretto.Config[uint64, V]{
|
||||
NumCounters: max * 10,
|
||||
MaxCost: max,
|
||||
BufferItems: 64,
|
||||
KeyToHash: func(key string) (uint64, uint64) { return h32(key), 0 },
|
||||
KeyToHash: func(key uint64) (uint64, uint64) { return key, 0 },
|
||||
})
|
||||
return &RistrettoCache[V]{Cache: cache}
|
||||
}
|
||||
|
||||
func (s RistrettoCache[V]) Get(k string) (v V, ok bool) { return s.Cache.Get(k) }
|
||||
func (s RistrettoCache[V]) Delete(k string) { s.Cache.Del(k) }
|
||||
func (s RistrettoCache[V]) Set(k string, v V) bool { return s.Cache.Set(k, v, 1) }
|
||||
func (s RistrettoCache[V]) SetWithTTL(k string, v V, d time.Duration) bool {
|
||||
return s.Cache.SetWithTTL(k, v, 1, d)
|
||||
func (s RistrettoCache[V]) Get(k [32]byte) (v V, ok bool) {
|
||||
return s.Cache.Get(binary.BigEndian.Uint64(k[32-8:]))
|
||||
}
|
||||
func (s RistrettoCache[V]) Delete(k [32]byte) { s.Cache.Del(binary.BigEndian.Uint64(k[32-8:])) }
|
||||
func (s RistrettoCache[V]) Set(k [32]byte, v V) bool {
|
||||
return s.Cache.Set(binary.BigEndian.Uint64(k[32-8:]), v, 1)
|
||||
}
|
||||
|
||||
func h32(key string) uint64 {
|
||||
// we get an event id or pubkey as hex,
|
||||
// so just extract the last 8 bytes from it and turn them into a uint64
|
||||
return shortUint64(key)
|
||||
}
|
||||
|
||||
func shortUint64(idOrPubkey string) uint64 {
|
||||
length := len(idOrPubkey)
|
||||
if length < 8 {
|
||||
return 0
|
||||
}
|
||||
b, err := hex.DecodeString(idOrPubkey[length-8:])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return uint64(binary.BigEndian.Uint32(b))
|
||||
func (s RistrettoCache[V]) SetWithTTL(k [32]byte, v V, d time.Duration) bool {
|
||||
return s.Cache.SetWithTTL(binary.BigEndian.Uint64(k[32-8:]), v, 1, d)
|
||||
}
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
package sdk
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr/sdk/kvstore"
|
||||
"fiatjaf.com/nostr"
|
||||
"fiatjaf.com/nostr/sdk/kvstore"
|
||||
)
|
||||
|
||||
const eventRelayPrefix = byte('r')
|
||||
|
||||
// makeEventRelayKey creates a key for storing event relay information.
|
||||
// It uses the first 8 bytes of the event ID to create a compact key.
|
||||
func makeEventRelayKey(eventID []byte) []byte {
|
||||
func makeEventRelayKey(id nostr.ID) []byte {
|
||||
// format: 'r' + first 8 bytes of event ID
|
||||
key := make([]byte, 9)
|
||||
key[0] = eventRelayPrefix
|
||||
copy(key[1:], eventID[:8])
|
||||
copy(key[1:], id[:8])
|
||||
return key
|
||||
}
|
||||
|
||||
@@ -75,15 +74,9 @@ func decodeRelayList(data []byte) []string {
|
||||
|
||||
// trackEventRelay records that an event was seen on a particular relay.
|
||||
// If onlyIfItExists is true, it will only update existing records and not create new ones.
|
||||
func (sys *System) trackEventRelay(eventID string, relay string, onlyIfItExists bool) {
|
||||
// decode the event ID hex into bytes
|
||||
idBytes, err := hex.DecodeString(eventID)
|
||||
if err != nil || len(idBytes) < 8 {
|
||||
return
|
||||
}
|
||||
|
||||
func (sys *System) trackEventRelay(id nostr.ID, relay string, onlyIfItExists bool) {
|
||||
// get the key for this event
|
||||
key := makeEventRelayKey(idBytes)
|
||||
key := makeEventRelayKey(id)
|
||||
|
||||
// update the relay list atomically
|
||||
sys.KVStore.Update(key, func(data []byte) ([]byte, error) {
|
||||
@@ -111,15 +104,9 @@ func (sys *System) trackEventRelay(eventID string, relay string, onlyIfItExists
|
||||
|
||||
// GetEventRelays returns all known relay URLs an event is known to be available on.
|
||||
// It is based on information kept on KVStore.
|
||||
func (sys *System) GetEventRelays(eventID string) ([]string, error) {
|
||||
// decode the event ID hex into bytes
|
||||
idBytes, err := hex.DecodeString(eventID)
|
||||
if err != nil || len(idBytes) < 8 {
|
||||
return nil, fmt.Errorf("invalid event id")
|
||||
}
|
||||
|
||||
func (sys *System) GetEventRelays(id nostr.ID) ([]string, error) {
|
||||
// get the key for this event
|
||||
key := makeEventRelayKey(idBytes)
|
||||
key := makeEventRelayKey(id)
|
||||
|
||||
// get stored relay list
|
||||
data, err := sys.KVStore.Get(key)
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"fiatjaf.com/nostr"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -29,7 +29,7 @@ func makePubkeyStreamKey(prefix byte, pubkey string) []byte {
|
||||
// each pubkey (stored in KVStore) onwards.
|
||||
func (sys *System) StreamLiveFeed(
|
||||
ctx context.Context,
|
||||
pubkeys []string,
|
||||
pubkeys []nostr.PubKey,
|
||||
kinds []int,
|
||||
) (<-chan *nostr.Event, error) {
|
||||
events := make(chan *nostr.Event)
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"fiatjaf.com/nostr"
|
||||
"github.com/fiatjaf/eventstore/slicestore"
|
||||
"github.com/fiatjaf/khatru"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -56,9 +56,9 @@ func TestStreamLiveFeed(t *testing.T) {
|
||||
|
||||
// generate two random keypairs for testing
|
||||
sk1 := nostr.GeneratePrivateKey()
|
||||
pk1, _ := nostr.GetPublicKey(sk1)
|
||||
pk1 := nostr.GetPublicKey(sk1)
|
||||
sk2 := nostr.GeneratePrivateKey()
|
||||
pk2, _ := nostr.GetPublicKey(sk2)
|
||||
pk2 := nostr.GetPublicKey(sk2)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
@@ -131,7 +131,7 @@ func TestStreamLiveFeed(t *testing.T) {
|
||||
go sys.Pool.PublishMany(ctx, []string{"ws://localhost:48482", "ws://localhost:48483"}, evt2)
|
||||
|
||||
// start streaming events for both pubkeys
|
||||
events, err := sys.StreamLiveFeed(ctx, []string{pk1, pk2}, []int{1})
|
||||
events, err := sys.StreamLiveFeed(ctx, []nostr.PubKey{pk1, pk2}, []int{1})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to start streaming: %v", err)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package badgerh
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math"
|
||||
"slices"
|
||||
|
||||
"fiatjaf.com/nostr"
|
||||
"fiatjaf.com/nostr/sdk/hints"
|
||||
"github.com/dgraph-io/badger/v4"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/hints"
|
||||
)
|
||||
|
||||
var _ hints.HintsDB = (*BadgerHints)(nil)
|
||||
@@ -30,7 +29,7 @@ func (bh *BadgerHints) Close() {
|
||||
bh.db.Close()
|
||||
}
|
||||
|
||||
func (bh *BadgerHints) Save(pubkey string, relay string, hintkey hints.HintKey, ts nostr.Timestamp) {
|
||||
func (bh *BadgerHints) Save(pubkey nostr.PubKey, relay string, hintkey hints.HintKey, ts nostr.Timestamp) {
|
||||
if now := nostr.Now(); ts > now {
|
||||
ts = now
|
||||
}
|
||||
@@ -64,7 +63,7 @@ func (bh *BadgerHints) Save(pubkey string, relay string, hintkey hints.HintKey,
|
||||
}
|
||||
}
|
||||
|
||||
func (bh *BadgerHints) TopN(pubkey string, n int) []string {
|
||||
func (bh *BadgerHints) TopN(pubkey nostr.PubKey, n int) []string {
|
||||
type relayScore struct {
|
||||
relay string
|
||||
score int64
|
||||
@@ -73,7 +72,7 @@ func (bh *BadgerHints) TopN(pubkey string, n int) []string {
|
||||
scores := make([]relayScore, 0, n)
|
||||
err := bh.db.View(func(txn *badger.Txn) error {
|
||||
opts := badger.DefaultIteratorOptions
|
||||
opts.Prefix, _ = hex.DecodeString(pubkey)
|
||||
opts.Prefix = pubkey[:]
|
||||
it := txn.NewIterator(opts)
|
||||
defer it.Close()
|
||||
|
||||
@@ -112,7 +111,7 @@ func (bh *BadgerHints) TopN(pubkey string, n int) []string {
|
||||
return result
|
||||
}
|
||||
|
||||
func (bh *BadgerHints) GetDetailedScores(pubkey string, n int) []hints.RelayScores {
|
||||
func (bh *BadgerHints) GetDetailedScores(pubkey nostr.PubKey, n int) []hints.RelayScores {
|
||||
type relayScore struct {
|
||||
relay string
|
||||
tss timestamps
|
||||
@@ -121,11 +120,10 @@ func (bh *BadgerHints) GetDetailedScores(pubkey string, n int) []hints.RelayScor
|
||||
|
||||
scores := make([]relayScore, 0, n)
|
||||
err := bh.db.View(func(txn *badger.Txn) error {
|
||||
prefix, _ := hex.DecodeString(pubkey)
|
||||
it := txn.NewIterator(badger.DefaultIteratorOptions)
|
||||
defer it.Close()
|
||||
|
||||
for it.Seek(prefix); it.ValidForPrefix(prefix); it.Next() {
|
||||
for it.Seek(pubkey[:]); it.ValidForPrefix(pubkey[:]); it.Next() {
|
||||
item := it.Item()
|
||||
k := item.Key()
|
||||
relay := string(k[32:])
|
||||
@@ -172,7 +170,7 @@ func (bh *BadgerHints) PrintScores() {
|
||||
it := txn.NewIterator(badger.DefaultIteratorOptions)
|
||||
defer it.Close()
|
||||
|
||||
var lastPubkey string
|
||||
var lastPubkey nostr.PubKey
|
||||
i := 0
|
||||
|
||||
for it.Seek(nil); it.Valid(); it.Next() {
|
||||
|
||||
@@ -2,20 +2,19 @@ package badgerh
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"fiatjaf.com/nostr"
|
||||
)
|
||||
|
||||
func encodeKey(pubhintkey, relay string) []byte {
|
||||
func encodeKey(pubhintkey nostr.PubKey, relay string) []byte {
|
||||
k := make([]byte, 32+len(relay))
|
||||
hex.Decode(k[0:32], []byte(pubhintkey))
|
||||
copy(k[0:32], pubhintkey[:])
|
||||
copy(k[32:], relay)
|
||||
return k
|
||||
}
|
||||
|
||||
func parseKey(k []byte) (pubkey string, relay string) {
|
||||
pubkey = hex.EncodeToString(k[0:32])
|
||||
func parseKey(k []byte) (pubkey nostr.PubKey, relay string) {
|
||||
pubkey = [32]byte(k[0:32])
|
||||
relay = string(k[32:])
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package hints
|
||||
|
||||
import "github.com/nbd-wtf/go-nostr"
|
||||
import (
|
||||
"fiatjaf.com/nostr"
|
||||
)
|
||||
|
||||
type RelayScores struct {
|
||||
Relay string
|
||||
@@ -9,8 +11,8 @@ type RelayScores struct {
|
||||
}
|
||||
|
||||
type HintsDB interface {
|
||||
TopN(pubkey string, n int) []string
|
||||
Save(pubkey string, relay string, key HintKey, score nostr.Timestamp)
|
||||
TopN(pubkey nostr.PubKey, n int) []string
|
||||
Save(pubkey nostr.PubKey, relay string, key HintKey, score nostr.Timestamp)
|
||||
PrintScores()
|
||||
GetDetailedScores(pubkey string, n int) []RelayScores
|
||||
GetDetailedScores(pubkey nostr.PubKey, n int) []RelayScores
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package hints
|
||||
|
||||
import "github.com/nbd-wtf/go-nostr"
|
||||
import "fiatjaf.com/nostrlib"
|
||||
|
||||
const END_OF_WORLD nostr.Timestamp = 2208999600 // 2040-01-01
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"slices"
|
||||
"sync"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/hints"
|
||||
"fiatjaf.com/nostrlib"
|
||||
"fiatjaf.com/nostrlib/sdk/hints"
|
||||
)
|
||||
|
||||
var _ hints.HintsDB = (*HintDB)(nil)
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/hints"
|
||||
"fiatjaf.com/nostrlib"
|
||||
"fiatjaf.com/nostrlib/sdk/hints"
|
||||
)
|
||||
|
||||
type SQLHints struct {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr/sdk/hints/sqlh"
|
||||
"fiatjaf.com/nostrlib/sdk/hints/sqlh"
|
||||
"github.com/stretchr/testify/require"
|
||||
_ "github.com/tursodatabase/go-libsql"
|
||||
)
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/hints/sqlh"
|
||||
"fiatjaf.com/nostrlib/sdk/hints/sqlh"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr/sdk/hints/memoryh"
|
||||
"fiatjaf.com/nostrlib/sdk/hints/memoryh"
|
||||
)
|
||||
|
||||
func TestMemoryHints(t *testing.T) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr/sdk/hints/sqlh"
|
||||
"fiatjaf.com/nostrlib/sdk/hints/sqlh"
|
||||
"github.com/stretchr/testify/require"
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/hints"
|
||||
"fiatjaf.com/nostrlib"
|
||||
"fiatjaf.com/nostrlib/sdk/hints"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr/sdk/hints/sqlh"
|
||||
"fiatjaf.com/nostrlib/sdk/hints/sqlh"
|
||||
_ "github.com/ncruces/go-sqlite3/driver"
|
||||
_ "github.com/ncruces/go-sqlite3/embed"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip05"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
"fiatjaf.com/nostrlib"
|
||||
"fiatjaf.com/nostrlib/nip05"
|
||||
"fiatjaf.com/nostrlib/nip19"
|
||||
)
|
||||
|
||||
// InputToProfile turns any npub/nprofile/hex/nip05 input into a ProfilePointer (or nil).
|
||||
|
||||
@@ -2,7 +2,7 @@ package badger
|
||||
|
||||
import (
|
||||
"github.com/dgraph-io/badger/v4"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/kvstore"
|
||||
"fiatjaf.com/nostrlib/sdk/kvstore"
|
||||
)
|
||||
|
||||
var _ kvstore.KVStore = (*Store)(nil)
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/PowerDNS/lmdb-go/lmdb"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/kvstore"
|
||||
"fiatjaf.com/nostrlib/sdk/kvstore"
|
||||
)
|
||||
|
||||
var _ kvstore.KVStore = (*Store)(nil)
|
||||
|
||||
@@ -3,7 +3,7 @@ package memory
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr/sdk/kvstore"
|
||||
"fiatjaf.com/nostrlib/sdk/kvstore"
|
||||
)
|
||||
|
||||
var _ kvstore.KVStore = (*Store)(nil)
|
||||
|
||||
23
sdk/list.go
23
sdk/list.go
@@ -3,23 +3,22 @@ package sdk
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/cache"
|
||||
"fiatjaf.com/nostr"
|
||||
"fiatjaf.com/nostr/sdk/cache"
|
||||
)
|
||||
|
||||
type GenericList[I TagItemWithValue] struct {
|
||||
PubKey string `json:"-"` // must always be set otherwise things will break
|
||||
PubKey nostr.PubKey `json:"-"` // must always be set otherwise things will break
|
||||
Event *nostr.Event `json:"-"` // may be empty if a contact list event wasn't found
|
||||
|
||||
Items []I
|
||||
}
|
||||
|
||||
type TagItemWithValue interface {
|
||||
Value() string
|
||||
Value() any
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -30,8 +29,8 @@ var (
|
||||
func fetchGenericList[I TagItemWithValue](
|
||||
sys *System,
|
||||
ctx context.Context,
|
||||
pubkey string,
|
||||
actualKind int,
|
||||
pubkey nostr.PubKey,
|
||||
actualKind uint16,
|
||||
replaceableIndex replaceableIndex,
|
||||
parseTag func(nostr.Tag) (I, bool),
|
||||
cache cache.Cache32[GenericList[I]],
|
||||
@@ -39,8 +38,8 @@ func fetchGenericList[I TagItemWithValue](
|
||||
// we have 60 mutexes, so we can load up to 60 lists at the same time, but if we do the same exact
|
||||
// call that will do it only once, the subsequent ones will wait for a result to be cached
|
||||
// and then return it from cache -- 13 is an arbitrary index for the pubkey
|
||||
n, _ := strconv.ParseUint(pubkey[14:16], 16, 8)
|
||||
lockIdx := (n + uint64(actualKind)) % 60
|
||||
n := pubkey[7]
|
||||
lockIdx := (uint16(n) + actualKind) % 60
|
||||
genericListMutexes[lockIdx].Lock()
|
||||
|
||||
if valueWasJustCached[lockIdx] {
|
||||
@@ -58,7 +57,7 @@ func fetchGenericList[I TagItemWithValue](
|
||||
|
||||
v := GenericList[I]{PubKey: pubkey}
|
||||
|
||||
events, _ := sys.StoreRelay.QuerySync(ctx, nostr.Filter{Kinds: []int{actualKind}, Authors: []string{pubkey}})
|
||||
events, _ := sys.StoreRelay.QuerySync(ctx, nostr.Filter{Kinds: []uint16{actualKind}, Authors: []nostr.PubKey{pubkey}})
|
||||
if len(events) != 0 {
|
||||
// ok, we found something locally
|
||||
items := parseItemsFromEventTags(events[0], parseTag)
|
||||
@@ -104,7 +103,7 @@ func fetchGenericList[I TagItemWithValue](
|
||||
func tryFetchListFromNetwork[I TagItemWithValue](
|
||||
ctx context.Context,
|
||||
sys *System,
|
||||
pubkey string,
|
||||
pubkey nostr.PubKey,
|
||||
replaceableIndex replaceableIndex,
|
||||
parseTag func(nostr.Tag) (I, bool),
|
||||
) *GenericList[I] {
|
||||
@@ -140,7 +139,7 @@ func parseItemsFromEventTags[I TagItemWithValue](
|
||||
return result
|
||||
}
|
||||
|
||||
func getLocalStoreRefreshDaysForKind(kind int) nostr.Timestamp {
|
||||
func getLocalStoreRefreshDaysForKind(kind uint16) nostr.Timestamp {
|
||||
switch kind {
|
||||
case 0:
|
||||
return 7
|
||||
|
||||
@@ -2,11 +2,9 @@ package sdk
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
cache_memory "github.com/nbd-wtf/go-nostr/sdk/cache/memory"
|
||||
"fiatjaf.com/nostr"
|
||||
cache_memory "fiatjaf.com/nostr/sdk/cache/memory"
|
||||
)
|
||||
|
||||
type EventRef struct{ nostr.Pointer }
|
||||
@@ -15,7 +13,7 @@ func (e EventRef) Value() string { return e.Pointer.AsTagReference() }
|
||||
|
||||
func (sys *System) FetchBookmarkList(ctx context.Context, pubkey string) GenericList[EventRef] {
|
||||
if sys.BookmarkListCache == nil {
|
||||
sys.BookmarkListCache = cache_memory.New32[GenericList[EventRef]](1000)
|
||||
sys.BookmarkListCache = cache_memory.New[GenericList[EventRef]](1000)
|
||||
}
|
||||
|
||||
ml, _ := fetchGenericList(sys, ctx, pubkey, 10003, kind_10003, parseEventRef, sys.BookmarkListCache)
|
||||
@@ -24,7 +22,7 @@ func (sys *System) FetchBookmarkList(ctx context.Context, pubkey string) Generic
|
||||
|
||||
func (sys *System) FetchPinList(ctx context.Context, pubkey string) GenericList[EventRef] {
|
||||
if sys.PinListCache == nil {
|
||||
sys.PinListCache = cache_memory.New32[GenericList[EventRef]](1000)
|
||||
sys.PinListCache = cache_memory.New[GenericList[EventRef]](1000)
|
||||
}
|
||||
|
||||
ml, _ := fetchGenericList(sys, ctx, pubkey, 10001, kind_10001, parseEventRef, sys.PinListCache)
|
||||
@@ -37,36 +35,16 @@ func parseEventRef(tag nostr.Tag) (evr EventRef, ok bool) {
|
||||
}
|
||||
switch tag[0] {
|
||||
case "e":
|
||||
if !nostr.IsValid32ByteHex(tag[1]) {
|
||||
pointer, err := nostr.EventPointerFromTag(tag)
|
||||
if err != nil {
|
||||
return evr, false
|
||||
}
|
||||
pointer := nostr.EventPointer{
|
||||
ID: tag[1],
|
||||
}
|
||||
if len(tag) >= 3 {
|
||||
pointer.Relays = []string{nostr.NormalizeURL(tag[2])}
|
||||
if len(tag) >= 4 {
|
||||
pointer.Author = tag[3]
|
||||
}
|
||||
}
|
||||
evr.Pointer = pointer
|
||||
case "a":
|
||||
spl := strings.SplitN(tag[1], ":", 3)
|
||||
if len(spl) != 3 || !nostr.IsValidPublicKey(spl[1]) {
|
||||
pointer, err := nostr.EntityPointerFromTag(tag)
|
||||
if err != nil {
|
||||
return evr, false
|
||||
}
|
||||
pointer := nostr.EntityPointer{
|
||||
PublicKey: spl[1],
|
||||
Identifier: spl[2],
|
||||
}
|
||||
if kind, err := strconv.Atoi(spl[0]); err != nil {
|
||||
return evr, false
|
||||
} else {
|
||||
pointer.Kind = kind
|
||||
}
|
||||
if len(tag) >= 3 {
|
||||
pointer.Relays = []string{nostr.NormalizeURL(tag[2])}
|
||||
}
|
||||
evr.Pointer = pointer
|
||||
default:
|
||||
return evr, false
|
||||
|
||||
@@ -5,39 +5,39 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
cache_memory "github.com/nbd-wtf/go-nostr/sdk/cache/memory"
|
||||
"fiatjaf.com/nostr"
|
||||
cache_memory "fiatjaf.com/nostr/sdk/cache/memory"
|
||||
)
|
||||
|
||||
type ProfileRef struct {
|
||||
Pubkey string
|
||||
Pubkey nostr.PubKey
|
||||
Relay string
|
||||
Petname string
|
||||
}
|
||||
|
||||
func (f ProfileRef) Value() string { return f.Pubkey }
|
||||
func (f ProfileRef) Value() nostr.PubKey { return f.Pubkey }
|
||||
|
||||
func (sys *System) FetchFollowList(ctx context.Context, pubkey string) GenericList[ProfileRef] {
|
||||
func (sys *System) FetchFollowList(ctx context.Context, pubkey nostr.PubKey) GenericList[ProfileRef] {
|
||||
if sys.FollowListCache == nil {
|
||||
sys.FollowListCache = cache_memory.New32[GenericList[ProfileRef]](1000)
|
||||
sys.FollowListCache = cache_memory.New[GenericList[ProfileRef]](1000)
|
||||
}
|
||||
|
||||
fl, _ := fetchGenericList(sys, ctx, pubkey, 3, kind_3, parseProfileRef, sys.FollowListCache)
|
||||
return fl
|
||||
}
|
||||
|
||||
func (sys *System) FetchMuteList(ctx context.Context, pubkey string) GenericList[ProfileRef] {
|
||||
func (sys *System) FetchMuteList(ctx context.Context, pubkey nostr.PubKey) GenericList[ProfileRef] {
|
||||
if sys.MuteListCache == nil {
|
||||
sys.MuteListCache = cache_memory.New32[GenericList[ProfileRef]](1000)
|
||||
sys.MuteListCache = cache_memory.New[GenericList[ProfileRef]](1000)
|
||||
}
|
||||
|
||||
ml, _ := fetchGenericList(sys, ctx, pubkey, 10000, kind_10000, parseProfileRef, sys.MuteListCache)
|
||||
return ml
|
||||
}
|
||||
|
||||
func (sys *System) FetchFollowSets(ctx context.Context, pubkey string) GenericSets[ProfileRef] {
|
||||
func (sys *System) FetchFollowSets(ctx context.Context, pubkey nostr.PubKey) GenericSets[ProfileRef] {
|
||||
if sys.FollowSetsCache == nil {
|
||||
sys.FollowSetsCache = cache_memory.New32[GenericSets[ProfileRef]](1000)
|
||||
sys.FollowSetsCache = cache_memory.New[GenericSets[ProfileRef]](1000)
|
||||
}
|
||||
|
||||
ml, _ := fetchGenericSets(sys, ctx, pubkey, 30000, kind_30000, parseProfileRef, sys.FollowSetsCache)
|
||||
@@ -52,11 +52,13 @@ func parseProfileRef(tag nostr.Tag) (fw ProfileRef, ok bool) {
|
||||
return fw, false
|
||||
}
|
||||
|
||||
fw.Pubkey = tag[1]
|
||||
if !nostr.IsValidPublicKey(fw.Pubkey) {
|
||||
pubkey, err := nostr.PubKeyFromHex(fw.Pubkey)
|
||||
if err != nil {
|
||||
return fw, false
|
||||
}
|
||||
|
||||
fw.Pubkey = pubkey
|
||||
|
||||
if len(tag) > 2 {
|
||||
if _, err := url.Parse(tag[2]); err == nil {
|
||||
fw.Relay = nostr.NormalizeURL(tag[2])
|
||||
|
||||
@@ -3,8 +3,8 @@ package sdk
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
cache_memory "github.com/nbd-wtf/go-nostr/sdk/cache/memory"
|
||||
"fiatjaf.com/nostr"
|
||||
cache_memory "fiatjaf.com/nostr/sdk/cache/memory"
|
||||
)
|
||||
|
||||
type Relay struct {
|
||||
@@ -19,32 +19,32 @@ type RelayURL string
|
||||
|
||||
func (r RelayURL) Value() string { return string(r) }
|
||||
|
||||
func (sys *System) FetchRelayList(ctx context.Context, pubkey string) GenericList[Relay] {
|
||||
func (sys *System) FetchRelayList(ctx context.Context, pubkey nostr.PubKey) GenericList[Relay] {
|
||||
ml, _ := fetchGenericList(sys, ctx, pubkey, 10002, kind_10002, parseRelayFromKind10002, sys.RelayListCache)
|
||||
return ml
|
||||
}
|
||||
|
||||
func (sys *System) FetchBlockedRelayList(ctx context.Context, pubkey string) GenericList[RelayURL] {
|
||||
func (sys *System) FetchBlockedRelayList(ctx context.Context, pubkey nostr.PubKey) GenericList[RelayURL] {
|
||||
if sys.BlockedRelayListCache == nil {
|
||||
sys.BlockedRelayListCache = cache_memory.New32[GenericList[RelayURL]](1000)
|
||||
sys.BlockedRelayListCache = cache_memory.New[GenericList[RelayURL]](1000)
|
||||
}
|
||||
|
||||
ml, _ := fetchGenericList(sys, ctx, pubkey, 10006, kind_10006, parseRelayURL, sys.BlockedRelayListCache)
|
||||
return ml
|
||||
}
|
||||
|
||||
func (sys *System) FetchSearchRelayList(ctx context.Context, pubkey string) GenericList[RelayURL] {
|
||||
func (sys *System) FetchSearchRelayList(ctx context.Context, pubkey nostr.PubKey) GenericList[RelayURL] {
|
||||
if sys.SearchRelayListCache == nil {
|
||||
sys.SearchRelayListCache = cache_memory.New32[GenericList[RelayURL]](1000)
|
||||
sys.SearchRelayListCache = cache_memory.New[GenericList[RelayURL]](1000)
|
||||
}
|
||||
|
||||
ml, _ := fetchGenericList(sys, ctx, pubkey, 10007, kind_10007, parseRelayURL, sys.SearchRelayListCache)
|
||||
return ml
|
||||
}
|
||||
|
||||
func (sys *System) FetchRelaySets(ctx context.Context, pubkey string) GenericSets[RelayURL] {
|
||||
func (sys *System) FetchRelaySets(ctx context.Context, pubkey nostr.PubKey) GenericSets[RelayURL] {
|
||||
if sys.RelaySetsCache == nil {
|
||||
sys.RelaySetsCache = cache_memory.New32[GenericSets[RelayURL]](1000)
|
||||
sys.RelaySetsCache = cache_memory.New[GenericSets[RelayURL]](1000)
|
||||
}
|
||||
|
||||
ml, _ := fetchGenericSets(sys, ctx, pubkey, 30002, kind_30002, parseRelayURL, sys.RelaySetsCache)
|
||||
@@ -52,7 +52,11 @@ func (sys *System) FetchRelaySets(ctx context.Context, pubkey string) GenericSet
|
||||
}
|
||||
|
||||
func parseRelayFromKind10002(tag nostr.Tag) (rl Relay, ok bool) {
|
||||
if u := tag.Value(); u != "" && tag[0] == "r" {
|
||||
if len(tag) < 2 {
|
||||
return rl, false
|
||||
}
|
||||
|
||||
if u := tag[1]; u != "" && tag[0] == "r" {
|
||||
if !nostr.IsValidRelayURL(u) {
|
||||
return rl, false
|
||||
}
|
||||
@@ -78,7 +82,11 @@ func parseRelayFromKind10002(tag nostr.Tag) (rl Relay, ok bool) {
|
||||
}
|
||||
|
||||
func parseRelayURL(tag nostr.Tag) (rl RelayURL, ok bool) {
|
||||
if u := tag.Value(); u != "" && tag[0] == "relay" {
|
||||
if len(tag) < 2 {
|
||||
return rl, false
|
||||
}
|
||||
|
||||
if u := tag[1]; u != "" && tag[0] == "relay" {
|
||||
if !nostr.IsValidRelayURL(u) {
|
||||
return rl, false
|
||||
}
|
||||
|
||||
@@ -3,26 +3,26 @@ package sdk
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
cache_memory "github.com/nbd-wtf/go-nostr/sdk/cache/memory"
|
||||
"fiatjaf.com/nostr"
|
||||
cache_memory "fiatjaf.com/nostr/sdk/cache/memory"
|
||||
)
|
||||
|
||||
type Topic string
|
||||
|
||||
func (r Topic) Value() string { return string(r) }
|
||||
|
||||
func (sys *System) FetchTopicList(ctx context.Context, pubkey string) GenericList[Topic] {
|
||||
func (sys *System) FetchTopicList(ctx context.Context, pubkey nostr.PubKey) GenericList[Topic] {
|
||||
if sys.TopicListCache == nil {
|
||||
sys.TopicListCache = cache_memory.New32[GenericList[Topic]](1000)
|
||||
sys.TopicListCache = cache_memory.New[GenericList[Topic]](1000)
|
||||
}
|
||||
|
||||
ml, _ := fetchGenericList(sys, ctx, pubkey, 10015, kind_10015, parseTopicString, sys.TopicListCache)
|
||||
return ml
|
||||
}
|
||||
|
||||
func (sys *System) FetchTopicSets(ctx context.Context, pubkey string) GenericSets[Topic] {
|
||||
func (sys *System) FetchTopicSets(ctx context.Context, pubkey nostr.PubKey) GenericSets[Topic] {
|
||||
if sys.TopicSetsCache == nil {
|
||||
sys.TopicSetsCache = cache_memory.New32[GenericSets[Topic]](1000)
|
||||
sys.TopicSetsCache = cache_memory.New[GenericSets[Topic]](1000)
|
||||
}
|
||||
|
||||
ml, _ := fetchGenericSets(sys, ctx, pubkey, 30015, kind_30015, parseTopicString, sys.TopicSetsCache)
|
||||
@@ -30,8 +30,12 @@ func (sys *System) FetchTopicSets(ctx context.Context, pubkey string) GenericSet
|
||||
}
|
||||
|
||||
func parseTopicString(tag nostr.Tag) (t Topic, ok bool) {
|
||||
if t := tag.Value(); t != "" && tag[0] == "t" {
|
||||
if len(tag) < 2 {
|
||||
return t, false
|
||||
}
|
||||
if t := tag[1]; t != "" && tag[0] == "t" {
|
||||
return Topic(t), true
|
||||
}
|
||||
|
||||
return t, false
|
||||
}
|
||||
|
||||
@@ -2,18 +2,17 @@ package sdk
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"fiatjaf.com/nostr"
|
||||
)
|
||||
|
||||
var kvStoreLastFetchPrefix = byte('f')
|
||||
|
||||
func makeLastFetchKey(kind int, pubkey string) []byte {
|
||||
func makeLastFetchKey(kind uint16, pubkey nostr.PubKey) []byte {
|
||||
buf := make([]byte, 1+5+32)
|
||||
buf[0] = kvStoreLastFetchPrefix
|
||||
binary.LittleEndian.PutUint32(buf[1:], uint32(kind))
|
||||
hex.Decode(buf[5:], []byte(pubkey))
|
||||
copy(buf[5:], pubkey[:])
|
||||
return buf
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip05"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/hints"
|
||||
"fiatjaf.com/nostrlib"
|
||||
"fiatjaf.com/nostrlib/nip05"
|
||||
"fiatjaf.com/nostrlib/nip19"
|
||||
"fiatjaf.com/nostrlib/sdk/hints"
|
||||
)
|
||||
|
||||
// ProfileMetadata represents user profile information from kind 0 events.
|
||||
|
||||
@@ -2,14 +2,15 @@ package sdk
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"fiatjaf.com/nostr"
|
||||
)
|
||||
|
||||
var outboxShortTermCache = [256]ostcEntry{}
|
||||
|
||||
type ostcEntry struct {
|
||||
pubkey string
|
||||
pubkey nostr.PubKey
|
||||
relays []string
|
||||
when time.Time
|
||||
}
|
||||
@@ -18,8 +19,8 @@ type ostcEntry struct {
|
||||
// NIP-05, past attempts at fetching data from a user from a given relay, including successes and failures, and
|
||||
// the "write" relays of kind:10002, in order to determine the best possible list of relays where a user might be
|
||||
// currently publishing their events to.
|
||||
func (sys *System) FetchOutboxRelays(ctx context.Context, pubkey string, n int) []string {
|
||||
ostcIndex, _ := strconv.ParseUint(pubkey[12:14], 16, 8)
|
||||
func (sys *System) FetchOutboxRelays(ctx context.Context, pubkey nostr.PubKey, n int) []string {
|
||||
ostcIndex := pubkey[7]
|
||||
now := time.Now()
|
||||
if entry := outboxShortTermCache[ostcIndex]; entry.pubkey == pubkey && entry.when.Add(time.Minute*2).After(now) {
|
||||
return entry.relays
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/dataloader"
|
||||
"fiatjaf.com/nostr"
|
||||
"fiatjaf.com/nostr/sdk/dataloader"
|
||||
)
|
||||
|
||||
type replaceableIndex int
|
||||
@@ -33,7 +33,7 @@ const (
|
||||
type EventResult dataloader.Result[*nostr.Event]
|
||||
|
||||
func (sys *System) initializeReplaceableDataloaders() {
|
||||
sys.replaceableLoaders = make([]*dataloader.Loader[string, *nostr.Event], 12)
|
||||
sys.replaceableLoaders = make([]*dataloader.Loader[nostr.PubKey, *nostr.Event], 12)
|
||||
sys.replaceableLoaders[kind_0] = sys.createReplaceableDataloader(0)
|
||||
sys.replaceableLoaders[kind_3] = sys.createReplaceableDataloader(3)
|
||||
sys.replaceableLoaders[kind_10000] = sys.createReplaceableDataloader(10000)
|
||||
@@ -48,9 +48,9 @@ func (sys *System) initializeReplaceableDataloaders() {
|
||||
sys.replaceableLoaders[kind_10030] = sys.createReplaceableDataloader(10030)
|
||||
}
|
||||
|
||||
func (sys *System) createReplaceableDataloader(kind int) *dataloader.Loader[string, *nostr.Event] {
|
||||
func (sys *System) createReplaceableDataloader(kind uint16) *dataloader.Loader[nostr.PubKey, *nostr.Event] {
|
||||
return dataloader.NewBatchedLoader(
|
||||
func(ctxs []context.Context, pubkeys []string) map[string]dataloader.Result[*nostr.Event] {
|
||||
func(ctxs []context.Context, pubkeys []nostr.PubKey) map[nostr.PubKey]dataloader.Result[*nostr.Event] {
|
||||
return sys.batchLoadReplaceableEvents(ctxs, kind, pubkeys)
|
||||
},
|
||||
dataloader.Options{
|
||||
@@ -62,11 +62,11 @@ func (sys *System) createReplaceableDataloader(kind int) *dataloader.Loader[stri
|
||||
|
||||
func (sys *System) batchLoadReplaceableEvents(
|
||||
ctxs []context.Context,
|
||||
kind int,
|
||||
pubkeys []string,
|
||||
) map[string]dataloader.Result[*nostr.Event] {
|
||||
kind uint16,
|
||||
pubkeys []nostr.PubKey,
|
||||
) map[nostr.PubKey]dataloader.Result[*nostr.Event] {
|
||||
batchSize := len(pubkeys)
|
||||
results := make(map[string]dataloader.Result[*nostr.Event], batchSize)
|
||||
results := make(map[nostr.PubKey]dataloader.Result[*nostr.Event], batchSize)
|
||||
relayFilter := make([]nostr.DirectedFilter, 0, max(3, batchSize*2))
|
||||
relayFilterIndex := make(map[string]int, max(3, batchSize*2))
|
||||
|
||||
@@ -83,7 +83,7 @@ func (sys *System) batchLoadReplaceableEvents(
|
||||
defer cancel()
|
||||
|
||||
// build batched queries for the external relays
|
||||
go func(i int, pubkey string) {
|
||||
go func(i int, pubkey nostr.PubKey) {
|
||||
// gather relays we'll use for this pubkey
|
||||
relays := sys.determineRelaysToQuery(ctx, pubkey, kind)
|
||||
|
||||
@@ -98,8 +98,8 @@ func (sys *System) batchLoadReplaceableEvents(
|
||||
dfilter = nostr.DirectedFilter{
|
||||
Relay: relay,
|
||||
Filter: nostr.Filter{
|
||||
Kinds: []int{kind},
|
||||
Authors: make([]string, 0, batchSize-i /* this and all pubkeys after this can be added */),
|
||||
Kinds: []uint16{kind},
|
||||
Authors: make([]nostr.PubKey, 0, batchSize-i /* this and all pubkeys after this can be added */),
|
||||
},
|
||||
}
|
||||
idx = len(relayFilter)
|
||||
@@ -122,7 +122,7 @@ func (sys *System) batchLoadReplaceableEvents(
|
||||
// query all relays with the prepared filters
|
||||
wg.Wait()
|
||||
multiSubs := sys.Pool.BatchedSubManyEose(aggregatedContext, relayFilter,
|
||||
nostr.WithLabel("repl~"+strconv.Itoa(kind)),
|
||||
nostr.WithLabel("repl~"+strconv.Itoa(int(kind))),
|
||||
)
|
||||
for {
|
||||
select {
|
||||
@@ -141,7 +141,7 @@ func (sys *System) batchLoadReplaceableEvents(
|
||||
}
|
||||
}
|
||||
|
||||
func (sys *System) determineRelaysToQuery(ctx context.Context, pubkey string, kind int) []string {
|
||||
func (sys *System) determineRelaysToQuery(ctx context.Context, pubkey nostr.PubKey, kind uint16) []string {
|
||||
var relays []string
|
||||
|
||||
// search in specific relays for user
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"fiatjaf.com/nostrlib"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package sdk
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"fiatjaf.com/nostrlib"
|
||||
)
|
||||
|
||||
func (sys *System) SearchUsers(ctx context.Context, query string) []ProfileMetadata {
|
||||
|
||||
19
sdk/set.go
19
sdk/set.go
@@ -3,17 +3,16 @@ package sdk
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/cache"
|
||||
"fiatjaf.com/nostr"
|
||||
"fiatjaf.com/nostr/sdk/cache"
|
||||
)
|
||||
|
||||
// this is similar to list.go and inherits code from that.
|
||||
|
||||
type GenericSets[I TagItemWithValue] struct {
|
||||
PubKey string `json:"-"`
|
||||
PubKey nostr.PubKey `json:"-"`
|
||||
Events []*nostr.Event `json:"-"`
|
||||
|
||||
Sets map[string][]I
|
||||
@@ -22,14 +21,14 @@ type GenericSets[I TagItemWithValue] struct {
|
||||
func fetchGenericSets[I TagItemWithValue](
|
||||
sys *System,
|
||||
ctx context.Context,
|
||||
pubkey string,
|
||||
actualKind int,
|
||||
pubkey nostr.PubKey,
|
||||
actualKind uint16,
|
||||
addressableIndex addressableIndex,
|
||||
parseTag func(nostr.Tag) (I, bool),
|
||||
cache cache.Cache32[GenericSets[I]],
|
||||
) (fl GenericSets[I], fromInternal bool) {
|
||||
n, _ := strconv.ParseUint(pubkey[14:16], 16, 8)
|
||||
lockIdx := (n + uint64(actualKind)) % 60
|
||||
n := pubkey[7]
|
||||
lockIdx := (uint16(n) + actualKind) % 60
|
||||
genericListMutexes[lockIdx].Lock()
|
||||
|
||||
if valueWasJustCached[lockIdx] {
|
||||
@@ -47,7 +46,7 @@ func fetchGenericSets[I TagItemWithValue](
|
||||
|
||||
v := GenericSets[I]{PubKey: pubkey}
|
||||
|
||||
events, _ := sys.StoreRelay.QuerySync(ctx, nostr.Filter{Kinds: []int{actualKind}, Authors: []string{pubkey}})
|
||||
events, _ := sys.StoreRelay.QuerySync(ctx, nostr.Filter{Kinds: []uint16{actualKind}, Authors: []nostr.PubKey{pubkey}})
|
||||
if len(events) != 0 {
|
||||
// ok, we found something locally
|
||||
sets := parseSetsFromEvents(events, parseTag)
|
||||
@@ -93,7 +92,7 @@ func fetchGenericSets[I TagItemWithValue](
|
||||
func tryFetchSetsFromNetwork[I TagItemWithValue](
|
||||
ctx context.Context,
|
||||
sys *System,
|
||||
pubkey string,
|
||||
pubkey nostr.PubKey,
|
||||
addressableIndex addressableIndex,
|
||||
parseTag func(nostr.Tag) (I, bool),
|
||||
) *GenericSets[I] {
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"slices"
|
||||
"sync"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/hints"
|
||||
"fiatjaf.com/nostrlib"
|
||||
"fiatjaf.com/nostrlib/nip19"
|
||||
"fiatjaf.com/nostrlib/sdk/hints"
|
||||
)
|
||||
|
||||
// FetchSpecificEventParameters contains options for fetching specific events.
|
||||
|
||||
@@ -4,16 +4,16 @@ import (
|
||||
"context"
|
||||
"math/rand/v2"
|
||||
|
||||
"fiatjaf.com/nostr"
|
||||
"fiatjaf.com/nostr/sdk/cache"
|
||||
cache_memory "fiatjaf.com/nostr/sdk/cache/memory"
|
||||
"fiatjaf.com/nostr/sdk/dataloader"
|
||||
"fiatjaf.com/nostr/sdk/hints"
|
||||
"fiatjaf.com/nostr/sdk/hints/memoryh"
|
||||
"fiatjaf.com/nostr/sdk/kvstore"
|
||||
kvstore_memory "fiatjaf.com/nostr/sdk/kvstore/memory"
|
||||
"github.com/fiatjaf/eventstore"
|
||||
"github.com/fiatjaf/eventstore/nullstore"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/cache"
|
||||
cache_memory "github.com/nbd-wtf/go-nostr/sdk/cache/memory"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/dataloader"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/hints"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/hints/memoryh"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/kvstore"
|
||||
kvstore_memory "github.com/nbd-wtf/go-nostr/sdk/kvstore/memory"
|
||||
)
|
||||
|
||||
// System represents the core functionality of the SDK, providing access to
|
||||
@@ -53,8 +53,8 @@ type System struct {
|
||||
|
||||
StoreRelay nostr.RelayStore
|
||||
|
||||
replaceableLoaders []*dataloader.Loader[string, *nostr.Event]
|
||||
addressableLoaders []*dataloader.Loader[string, []*nostr.Event]
|
||||
replaceableLoaders []*dataloader.Loader[nostr.PubKey, *nostr.Event]
|
||||
addressableLoaders []*dataloader.Loader[nostr.PubKey, []*nostr.Event]
|
||||
}
|
||||
|
||||
// SystemModifier is a function that modifies a System instance.
|
||||
@@ -130,10 +130,10 @@ func NewSystem(mods ...SystemModifier) *System {
|
||||
}
|
||||
|
||||
if sys.MetadataCache == nil {
|
||||
sys.MetadataCache = cache_memory.New32[ProfileMetadata](8000)
|
||||
sys.MetadataCache = cache_memory.New[ProfileMetadata](8000)
|
||||
}
|
||||
if sys.RelayListCache == nil {
|
||||
sys.RelayListCache = cache_memory.New32[GenericList[Relay]](8000)
|
||||
sys.RelayListCache = cache_memory.New[GenericList[Relay]](8000)
|
||||
}
|
||||
|
||||
if sys.Store == nil {
|
||||
|
||||
@@ -3,12 +3,12 @@ package sdk
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"fiatjaf.com/nostr"
|
||||
"fiatjaf.com/nostrlib/sdk/hints"
|
||||
"github.com/nbd-wtf/go-nostr/nip27"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/hints"
|
||||
)
|
||||
|
||||
func (sys *System) TrackQueryAttempts(relay string, author string, kind int) {
|
||||
func (sys *System) TrackQueryAttempts(relay string, author nostr.PubKey, kind uint16) {
|
||||
if IsVirtualRelay(relay) {
|
||||
return
|
||||
}
|
||||
@@ -83,8 +83,10 @@ func (sys *System) trackEventHints(ie nostr.RelayEvent) {
|
||||
if p, err := url.Parse(tag[2]); err != nil || (p.Scheme != "wss" && p.Scheme != "ws") {
|
||||
continue
|
||||
}
|
||||
if tag[0] == "p" && nostr.IsValidPublicKey(tag[1]) {
|
||||
sys.Hints.Save(tag[1], nostr.NormalizeURL(tag[2]), hints.LastInHint, ie.CreatedAt)
|
||||
if tag[0] == "p" {
|
||||
if pk, err := nostr.PubKeyFromHex(tag[1]); err == nil {
|
||||
sys.Hints.Save(pk, nostr.NormalizeURL(tag[2]), hints.LastInHint, ie.CreatedAt)
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
@@ -101,8 +103,10 @@ func (sys *System) trackEventHints(ie nostr.RelayEvent) {
|
||||
if p, err := url.Parse(tag[2]); err != nil || (p.Scheme != "wss" && p.Scheme != "ws") {
|
||||
continue
|
||||
}
|
||||
if tag[0] == "p" && nostr.IsValidPublicKey(tag[1]) {
|
||||
sys.Hints.Save(tag[1], nostr.NormalizeURL(tag[2]), hints.LastInHint, ie.CreatedAt)
|
||||
if tag[0] == "p" {
|
||||
if pk, err := nostr.PubKeyFromHex(tag[1]); err == nil {
|
||||
sys.Hints.Save(pk, nostr.NormalizeURL(tag[2]), hints.LastInHint, ie.CreatedAt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +148,7 @@ func (sys *System) trackEventHints(ie nostr.RelayEvent) {
|
||||
}
|
||||
|
||||
// TrackEventRelaysD is a companion to TrackEventRelays meant to be used with WithDuplicateMiddleware()
|
||||
func (sys *System) TrackEventRelaysD(relay, id string) {
|
||||
func (sys *System) TrackEventRelaysD(relay string, id nostr.ID) {
|
||||
if IsVirtualRelay(relay) {
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user