Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ func runRestore(ctx context.Context) {
func startPeriodicCloudBackups(ctx context.Context) {
cloudProvider, err := getCloudProvider()
if err != nil {
log.Printf("⚠️ Cloud backup disabled: %v", err)
log.Printf("⚠️ Cloud backup disabled: %v", err)
return
}

Expand Down
2 changes: 1 addition & 1 deletion blastr.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ func blast(ctx context.Context, ev *nostr.Event) {
}
cancel()
}
slog.Info("🔫 blasted event", "id", ev.ID, "relays", successCount)
slog.Info("🔫 blasted event", "kind", ev.Kind, "id", ev.ID, "relays", successCount)
}
18 changes: 11 additions & 7 deletions import.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ func ensureImportRelays() {
slog.Error("🚫 Unable to connect to any import relays, check your connectivity and relays_import.json file")
os.Exit(1)
} else {
slog.Warn("⚠️ Some relays failed to connect, proceeding, but this may cause issues")
slog.Info("ℹ️ If you always see this message during startup, consider removing the relays that are not working from your relays_import.json file")
slog.Warn("⚠️ Some relays failed to connect, proceeding, but this may cause issues")
slog.Info("ℹ️ If you always see this message during startup, consider removing the relays that are not working from your relays_import.json file")
}
}

Expand Down Expand Up @@ -221,12 +221,18 @@ func subscribeInboxAndChat(ctx context.Context) {

for ev := range pool.SubscribeMany(ctx, config.ImportSeedRelays, filter, nostr.SubscriptionOptions{}) {
if _, ok := config.BlacklistedPubKeys[ev.PubKey.Hex()]; ok {
slog.Debug("🚫discarding imported note from blacklisted pubkey", "pubkey", ev.PubKey, "id", ev.ID)
slog.Debug("🚫 discarding imported note from blacklisted pubkey", "pubkey", ev.PubKey, "id", ev.ID)
continue
}
if !wot.GetInstance().Has(ctx, ev.PubKey.Hex()) && ev.Kind != nostr.KindGiftWrap {
continue
}

// Discard follow list events since they are not relevant for the inbox or chat
if ev.Kind == nostr.KindFollowList {
continue
}

for tag := range ev.Tags.FindAll("p") {
if len(tag) < 2 {
continue
Expand All @@ -237,10 +243,10 @@ func subscribeInboxAndChat(ctx context.Context) {
dbToPublish = chatDB
}

slog.Debug("ℹ️ importing event", "kind", ev.Kind, "id", ev.ID, "relay", ev.Relay.URL)
slog.Debug("ℹ️ importing event", "kind", ev.Kind, "id", ev.ID, "relay", ev.Relay.URL)

if isDuplicate(ctx, dbToPublish, ev.Event) {
slog.Debug("ℹ️ skipping duplicate event", "id", ev.ID)
slog.Debug("ℹ️ skipping duplicate event", "id", ev.ID)
break // Avoid re-importing duplicates
}

Expand All @@ -262,8 +268,6 @@ func subscribeInboxAndChat(ctx context.Context) {
log.Println("🎁🔒️✉️ new gift-wrapped message in your chat relay")
case nostr.KindRepost:
log.Println("🔁 new repost in your inbox")
case nostr.KindFollowList:
// do nothing
default:
log.Println("📦 new event kind", ev.Kind, "event in your inbox")
}
Expand Down
9 changes: 9 additions & 0 deletions init.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ func initRelays(ctx context.Context) {
)(ctx, event); reject {
return reject, msg
}
if reject, msg := EventMustBeLatest(ctx, &event, privateDB); reject {
return reject, msg
}
return MustBeWhitelistedToPost(ctx, &event)
}

Expand Down Expand Up @@ -296,6 +299,9 @@ func initRelays(ctx context.Context) {
)(ctx, event); reject {
return reject, msg
}
if reject, msg := EventMustBeLatest(ctx, &event, outboxDB); reject {
return reject, msg
}
return MustBeWhitelistedToPost(ctx, &event)
}

Expand Down Expand Up @@ -405,6 +411,9 @@ func initRelays(ctx context.Context) {
if reject, msg := OnlyGiftWrappedDMs(ctx, &event); reject {
return reject, msg
}
if reject, msg := EventMustNotBeFollowList(ctx, &event); reject {
return reject, msg
}
if reject, msg := MustNotBeBlacklistedToPost(ctx, &event); reject {
return reject, msg
}
Expand Down
12 changes: 6 additions & 6 deletions pkg/wot/simple_in_memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func (wt *SimpleInMemory) Refresh(ctx context.Context) {
filter.Authors = append(filter.Authors, nostr.MustPubKeyFromHex(pubkeyHex))
}

slog.Info("🛜 fetching Nostr events to build WoT")
slog.Info("🛜 fetching Nostr events to build WoT")

events := wt.Pool.FetchMany(timeoutCtx, wt.SeedRelays, filter, nostr.SubscriptionOptions{})
for ev := range latestEventByKindAndPubkey(timeoutCtx, events, &eventsAnalysed) {
Expand All @@ -118,13 +118,13 @@ func (wt *SimpleInMemory) Refresh(ctx context.Context) {
}

if wt.WotDepth == 2 {
slog.Info("🕸️ analysed Nostr events", "count", eventsAnalysed.Load())
slog.Info("🕸️ analysed Nostr events", "count", eventsAnalysed.Load())
slog.Info("📈 direct followers in import relays", "🫂pubkeys", len(newWot), "🔗relays", len(wt.SeedRelays))
wt.pubkeys.Store(&newWot)
return
}

slog.Info("🕸️ analysing Nostr events", "count", eventsAnalysed.Load())
slog.Info("🕸️ analysing Nostr events", "count", eventsAnalysed.Load())

processBatch := func(pubkeys []string) {
timeoutCtx, cancel := context.WithTimeout(ctx, timeout)
Expand Down Expand Up @@ -160,7 +160,7 @@ func (wt *SimpleInMemory) Refresh(ctx context.Context) {

select {
case <-done:
slog.Info("🕸️ analysing Nostr events", "count", eventsAnalysed.Load())
slog.Info("🕸️ analysing Nostr events", "count", eventsAnalysed.Load())
case <-timeoutCtx.Done():
slog.Error("🚫 timeout while fetching events, moving to the next batch")
}
Expand All @@ -172,7 +172,7 @@ func (wt *SimpleInMemory) Refresh(ctx context.Context) {
processBatch(batch)
}

slog.Info("📈 totals", "🫂pubkeys", pubkeyFollowers.Size(), "🔗relays", relaysDiscovered.Size())
slog.Info("📈 totals", "🫂 pubkeys", pubkeyFollowers.Size(), "🔗 relays", relaysDiscovered.Size())

// Log Top N pubkeys by follower count for debugging purposes
if slog.Default().Enabled(ctx, slog.LevelDebug) {
Expand Down Expand Up @@ -228,7 +228,7 @@ func (wt *SimpleInMemory) Refresh(ctx context.Context) {
return true
})

slog.Info("🫥 pruned pubkeys without minimum common followers", "🚧minimum", minimumFollowers, "🫂kept", len(newWot), "🗑️eliminated", pubkeyFollowers.Size()-len(newWot))
slog.Info("🫥 pruned pubkeys without minimum common followers", "🚧 minimum", minimumFollowers, "🫂 kept", len(newWot), "🗑️ eliminated", pubkeyFollowers.Size()-len(newWot))

wt.pubkeys.Store(&newWot)
}
Expand Down
40 changes: 40 additions & 0 deletions policies.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"fiatjaf.com/nostr"
"fiatjaf.com/nostr/khatru"
"fiatjaf.com/nostr/eventstore"
"github.com/barrydeen/haven/pkg/wot"
)

Expand Down Expand Up @@ -113,6 +114,45 @@ func EventMustBeChatRelated(_ context.Context, event *nostr.Event) (bool, string
return true, "only chat related events are allowed"
}

func EventMustNotBeFollowList(_ context.Context, event *nostr.Event) (bool, string) {
if event.Kind == nostr.KindFollowList {
return true, "blocked: follow list events are not allowed"
}
return false, ""
}

func EventMustBeLatest(_ context.Context, event *nostr.Event, db eventstore.Store) (bool, string) {
// if event is not replaceable or addressable kind, we don't need to check for latest
if !event.Kind.IsReplaceable() && !event.Kind.IsAddressable() {
return false, ""
}

// prepare filter with kind and author
filter := nostr.Filter{
Kinds: []nostr.Kind{event.Kind},
Authors: []nostr.PubKey{event.PubKey},
Limit: 10, // could be just 1
}

// when addressable, add the "d" tag to the filter
if event.Kind.IsAddressable() {
filter.Tags = nostr.TagMap{"d": []string{event.Tags.GetD()}}
}

// query the latest events of the same kind and pubkey (and "d" tag if applicable)
savedEvents := db.QueryEvents(filter, filter.Limit)

// check if there is a stored event that is newer (or same precedence) than this incoming event
for savedEvent := range savedEvents {
if !nostr.IsOlder(savedEvent, *event) {
slog.Debug("🚫 event rejected: there is a newer event", "kind", event.Kind, "pubkey", event.PubKey)
return true, "replaced: there is a newer event"
}
}

return false, ""
}

func OnlyGiftWrappedDMs(_ context.Context, event *nostr.Event) (bool, string) {
if event.Kind == nostr.KindEncryptedDirectMessage {
return true, "only gift wrapped DMs are supported"
Expand Down
Loading