sdk taking shape.
This commit is contained in:
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
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
|
||||
}
|
||||
Vendored
+48
@@ -0,0 +1,48 @@
|
||||
package cache_memory
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"time"
|
||||
|
||||
"github.com/dgraph-io/ristretto"
|
||||
)
|
||||
|
||||
type RistrettoCache[V any] struct {
|
||||
Cache *ristretto.Cache[string, V]
|
||||
}
|
||||
|
||||
func New32[V any](max int64) *RistrettoCache[V] {
|
||||
cache, _ := ristretto.NewCache(&ristretto.Config[string, V]{
|
||||
NumCounters: max * 10,
|
||||
MaxCost: max,
|
||||
BufferItems: 64,
|
||||
KeyToHash: func(key string) (uint64, uint64) { return h32(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 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))
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package sdk
|
||||
|
||||
type Follow struct {
|
||||
Pubkey string
|
||||
Relay string
|
||||
Petname string
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package sdk
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/sdk/cache"
|
||||
)
|
||||
|
||||
type System struct {
|
||||
relaysCache cache.Cache32[[]Relay]
|
||||
followsCache cache.Cache32[[]Follow]
|
||||
metadataCache cache.Cache32[*ProfileMetadata]
|
||||
pool *nostr.SimplePool
|
||||
metadataRelays []string
|
||||
relayListRelays []string
|
||||
}
|
||||
|
||||
func (sys System) FetchRelaysForPubkey(ctx context.Context, pubkey string) []Relay {
|
||||
if v, ok := sys.relaysCache.Get(pubkey); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Second*5)
|
||||
defer cancel()
|
||||
res := FetchRelaysForPubkey(ctx, sys.pool, pubkey, sys.relayListRelays...)
|
||||
sys.relaysCache.SetWithTTL(pubkey, res, time.Hour*6)
|
||||
return res
|
||||
}
|
||||
|
||||
func (sys System) FetchOutboxRelaysForPubkey(ctx context.Context, pubkey string) []string {
|
||||
relays := sys.FetchRelaysForPubkey(ctx, pubkey)
|
||||
result := make([]string, 0, len(relays))
|
||||
for _, relay := range relays {
|
||||
if relay.Outbox {
|
||||
result = append(result, relay.URL)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package sdk
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
)
|
||||
|
||||
type ProfileMetadata struct {
|
||||
pubkey string
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
DisplayName string `json:"display_name,omitempty"`
|
||||
About string `json:"about,omitempty"`
|
||||
Website string `json:"website,omitempty"`
|
||||
Picture string `json:"picture,omitempty"`
|
||||
Banner string `json:"banner,omitempty"`
|
||||
NIP05 string `json:"nip05,omitempty"`
|
||||
LUD16 string `json:"lud16,omitempty"`
|
||||
}
|
||||
|
||||
func (p ProfileMetadata) Npub() string {
|
||||
v, _ := nip19.EncodePublicKey(p.pubkey)
|
||||
return v
|
||||
}
|
||||
|
||||
func (p ProfileMetadata) Nprofile(ctx context.Context, sys *System, nrelays int) string {
|
||||
v, _ := nip19.EncodeProfile(p.pubkey, sys.FetchOutboxRelaysForPubkey(ctx, p.pubkey))
|
||||
return v
|
||||
}
|
||||
|
||||
func ParseMetadata(event *nostr.Event) (*ProfileMetadata, error) {
|
||||
if event.Kind != 0 {
|
||||
return nil, fmt.Errorf("event %s is kind %d, not 0", event.ID, event.Kind)
|
||||
}
|
||||
|
||||
var meta ProfileMetadata
|
||||
if err := json.Unmarshal([]byte(event.Content), &meta); err != nil {
|
||||
cont := event.Content
|
||||
if len(cont) > 100 {
|
||||
cont = cont[0:99]
|
||||
}
|
||||
return nil, fmt.Errorf("failed to parse metadata (%s) from event %s: %w", cont, event.ID, err)
|
||||
}
|
||||
|
||||
return &meta, nil
|
||||
}
|
||||
+4
-9
@@ -13,18 +13,13 @@ type Relay struct {
|
||||
Outbox bool
|
||||
}
|
||||
|
||||
func FetchRelaysForPubkey(ctx context.Context, pool *nostr.SimplePool, pubkey string, extraRelays ...string) []Relay {
|
||||
func FetchOutboxRelaysForPubkey(ctx context.Context, pool *nostr.SimplePool, pubkey string, n int) {
|
||||
}
|
||||
|
||||
func FetchRelaysForPubkey(ctx context.Context, pool *nostr.SimplePool, pubkey string, relays ...string) []Relay {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
relays := append(extraRelays,
|
||||
"wss://nostr-pub.wellorder.net",
|
||||
"wss://relay.damus.io",
|
||||
"wss://nos.lol",
|
||||
"wss://nostr.mom",
|
||||
"wss://relay.nostr.bg",
|
||||
)
|
||||
|
||||
ch := pool.SubManyEose(ctx, relays, nostr.Filters{
|
||||
{
|
||||
Kinds: []int{
|
||||
|
||||
Reference in New Issue
Block a user