diff --git a/data.go b/data.go index a8ba3fa..e8d96ce 100644 --- a/data.go +++ b/data.go @@ -40,7 +40,7 @@ type Data struct { func grabData(ctx context.Context, code string) (Data, error) { // code can be a nevent or naddr, in which case we try to fetch the associated event - event, relays, err := getEvent(ctx, code) + event, relays, err := getEvent(ctx, code, true) if err != nil { return Data{}, fmt.Errorf("error fetching event: %w", err) } diff --git a/go.mod b/go.mod index 18f23bb..f45d7b7 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/kelseyhightower/envconfig v1.4.0 github.com/microcosm-cc/bluemonday v1.0.24 github.com/nbd-wtf/emoji v0.0.3 - github.com/nbd-wtf/go-nostr v0.38.1 + github.com/nbd-wtf/go-nostr v0.38.2 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/pelletier/go-toml v1.9.5 github.com/puzpuzpuz/xsync/v3 v3.4.0 diff --git a/go.sum b/go.sum index 5b555d3..670b82f 100644 --- a/go.sum +++ b/go.sum @@ -156,8 +156,8 @@ github.com/mna/pigeon v1.1.0 h1:EjlvVbkGnNGemf8OrjeJX0nH8orujY/HkJgzJtd7kxc= github.com/mna/pigeon v1.1.0/go.mod h1:rkFeDZ0gc+YbnrXPw0q2RlI0QRuKBBPu67fgYIyGRNg= github.com/nbd-wtf/emoji v0.0.3 h1:YtkT7MVPXvqU1SQjvC/CShlWexnREzqNCxmhUnL00CA= github.com/nbd-wtf/emoji v0.0.3/go.mod h1:tS6D9iI34qwBmWc5g8X7tVDkWXulqbTJRsvsM6QsS88= -github.com/nbd-wtf/go-nostr v0.38.1 h1:D0moEtIpjhWs2zbgeRyokA4TOLzBdumtpL1/O7/frww= -github.com/nbd-wtf/go-nostr v0.38.1/go.mod h1:TGKGj00BmJRXvRe0LlpDN3KKbELhhPXgBwUEhzu3Oq0= +github.com/nbd-wtf/go-nostr v0.38.2 h1:8PP+U8dx81jVEL89k/xMAejAlDeSDJ9ywNiyOj82so8= +github.com/nbd-wtf/go-nostr v0.38.2/go.mod h1:TGKGj00BmJRXvRe0LlpDN3KKbELhhPXgBwUEhzu3Oq0= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= diff --git a/image_utils.go b/image_utils.go index 9fe232d..516cf8c 100644 --- a/image_utils.go +++ b/image_utils.go @@ -213,7 +213,7 @@ func quotesAsBlockPrefixedText(ctx context.Context, lines []string) []string { submatch := nostrNoteNeventMatcher.FindStringSubmatch(matchText) nip19 := submatch[0][6:] - event, _, err := getEvent(ctx, nip19) + event, _, err := getEvent(ctx, nip19, false) if err != nil { // error case concat this to previous block blocks[b] += matchText diff --git a/main.go b/main.go index e69a7a9..57b0789 100644 --- a/main.go +++ b/main.go @@ -71,10 +71,10 @@ func main() { return } if len(relayConfig.Everything) > 0 { - sys.FallbackRelays = relayConfig.Everything + sys.FallbackRelays.URLs = relayConfig.Everything } if len(relayConfig.Profiles) > 0 { - sys.MetadataRelays = relayConfig.Profiles + sys.MetadataRelays.URLs = relayConfig.Profiles } } diff --git a/nostr.go b/nostr.go index 235bf77..b392b2b 100644 --- a/nostr.go +++ b/nostr.go @@ -5,12 +5,10 @@ import ( "fmt" "iter" "slices" - "sync" "time" "github.com/fiatjaf/eventstore/lmdb" "github.com/nbd-wtf/go-nostr" - "github.com/nbd-wtf/go-nostr/nip19" "github.com/nbd-wtf/go-nostr/sdk" cache_memory "github.com/nbd-wtf/go-nostr/sdk/cache/memory" ) @@ -58,128 +56,24 @@ func initSystem() func() { return db.Close } -func getEvent(ctx context.Context, code string) (*nostr.Event, []string, error) { - // this is for deciding what relays will go on nevent and nprofile later - priorityRelays := make(map[string]int) - - prefix, data, err := nip19.Decode(code) +func getEvent(ctx context.Context, code string, withRelays bool) (*nostr.Event, []string, error) { + evt, relays, err := sys.FetchSpecificEvent(ctx, code, true) if err != nil { - return nil, nil, fmt.Errorf("failed to decode %w", err) + return nil, nil, fmt.Errorf("couldn't find this event, did you include accurate relay or author hints in it?") } - author := "" - authorRelaysPosition := 0 - - var filter nostr.Filter - relays := make([]string, 0, 10) - - switch v := data.(type) { - case nostr.EventPointer: - author = v.Author - filter.IDs = []string{v.ID} - relays = append(relays, v.Relays...) - relays = append(relays, relayConfig.JustIds...) - authorRelaysPosition = len(v.Relays) // ensure author relays are checked after hinted relays - for _, r := range v.Relays { - priorityRelays[r] = 2 - } - case nostr.EntityPointer: - author = v.PublicKey - filter.Authors = []string{v.PublicKey} - filter.Tags = nostr.TagMap{ - "d": []string{v.Identifier}, - } - if v.Kind != 0 { - filter.Kinds = append(filter.Kinds, v.Kind) - } - relays = append(relays, v.Relays...) - authorRelaysPosition = len(v.Relays) // ensure author relays are checked after hinted relays - case string: - if prefix == "note" { - filter.IDs = []string{v} - relays = append(relays, relayConfig.JustIds...) - } + if !withRelays { + return evt, nil, nil } - // try to fetch in our internal eventstore first - if res, _ := sys.StoreRelay.QuerySync(ctx, filter); len(res) != 0 { - evt := res[0] + if relays == nil { return evt, internal.getRelaysForEvent(evt.ID), nil } - if author != "" { - // fetch relays for author - authorRelays := sys.FetchOutboxRelays(ctx, author, 3) - relays = slices.Insert(relays, authorRelaysPosition, authorRelays...) - for _, r := range authorRelays { - priorityRelays[r] = 1 - } - } - - for len(relays) < 5 { - relays = append(relays, getRandomRelay()) - } - - relays = unique(relays) - - var result *nostr.Event - var successRelays []string = nil - - { - // actually fetch the event here - subManyCtx, cancel := context.WithTimeout(ctx, time.Second*8) - defer cancel() - - // keep track of where we have actually found the event so we can show that - successRelays = make([]string, 0, len(relays)) - countdown := 7.5 - go func() { - for { - time.Sleep(500 * time.Millisecond) - if countdown <= 0 { - cancel() - break - } - countdown -= 0.5 - } - }() - - fetchProfileOnce := sync.Once{} - - for ie := range sys.Pool.SubManyEoseNonUnique( - subManyCtx, - relays, - nostr.Filters{filter}, - nostr.WithLabel("fetching-"+prefix), - ) { - fetchProfileOnce.Do(func() { - go sys.FetchProfileMetadata(ctx, ie.PubKey) - }) - - successRelays = append(successRelays, ie.Relay.URL) - if result == nil || ie.CreatedAt > result.CreatedAt { - result = ie.Event - } - countdown = min(countdown, 1) - } - } - - if result == nil { - return nil, nil, fmt.Errorf("couldn't find this %s, did you include relay or author hints in it?", prefix) - } - - // save stuff in cache and in internal store - sys.StoreRelay.Publish(ctx, *result) // save relays if we got them - allRelays := internal.attachRelaysToEvent(result.ID, successRelays...) - // put priority relays first so they get used in nevent and nprofile - slices.SortFunc(allRelays, func(a, b string) int { - vpa, _ := priorityRelays[a] - vpb, _ := priorityRelays[b] - return vpb - vpa - }) - - return result, allRelays, nil + allRelays := internal.attachRelaysToEvent(evt.ID, relays...) + + return evt, allRelays, nil } func authorLastNotes(ctx context.Context, pubkey string) []EnhancedEvent { @@ -210,7 +104,7 @@ func authorLastNotes(ctx context.Context, pubkey string) []EnhancedEvent { relays := sys.FetchOutboxRelays(ctx, pubkey, 3) for len(relays) < 3 { - relays = unique(append(relays, getRandomRelay())) + relays = unique(append(relays, sys.FallbackRelays.Next())) } ch := sys.Pool.SubManyEose(ctx, relays, nostr.Filters{filter}, nostr.WithLabel("authorlast")) diff --git a/utils.go b/utils.go index 2dc93d6..5f56778 100644 --- a/utils.go +++ b/utils.go @@ -6,7 +6,6 @@ import ( "fmt" "html" "html/template" - "math/rand" "net/http" "regexp" "slices" @@ -299,7 +298,7 @@ func renderQuotesAsHTML(ctx context.Context, input string, usingTelegramInstantV defer cancel() wg.Add(1) go func() { - event, _, err := getEvent(ctx, nip19) + event, _, err := getEvent(ctx, nip19, false) if err == nil { quotedEvent := basicFormatting(submatches[0], false, usingTelegramInstantView, false) @@ -438,14 +437,6 @@ func humanDate(createdAt nostr.Timestamp) string { } } -func getRandomRelay() string { - if serial == 0 { - serial = rand.Intn(len(sys.FallbackRelays)) - } - serial = (serial + 1) % len(sys.FallbackRelays) - return sys.FallbackRelays[serial] -} - func maxIndex(slice []int) int { maxIndex := -1 maxVal := 0