cleanup-kind3.go raw

   1  //go:build !(js && wasm)
   2  
   3  package database
   4  
   5  import (
   6  	"context"
   7  	"time"
   8  
   9  	"next.orly.dev/pkg/nostr/encoders/filter"
  10  	"next.orly.dev/pkg/nostr/encoders/kind"
  11  	"next.orly.dev/pkg/lol/chk"
  12  	"next.orly.dev/pkg/lol/log"
  13  )
  14  
  15  // CleanupKind3WithoutPTags scans for kind 3 follow list events that have no p tags
  16  // and deletes them. This cleanup is needed because the directory spider may have
  17  // saved malformed events that lost their tags during serialization.
  18  func (d *D) CleanupKind3WithoutPTags(ctx context.Context) error {
  19  	log.I.F("database: starting cleanup of kind 3 events without p tags")
  20  
  21  	startTime := time.Now()
  22  
  23  	// Query for all kind 3 events
  24  	f := &filter.F{
  25  		Kinds: kind.NewS(kind.FollowList),
  26  	}
  27  
  28  	events, err := d.QueryEvents(ctx, f)
  29  	if chk.E(err) {
  30  		return err
  31  	}
  32  
  33  	deletedCount := 0
  34  
  35  	// Check each event for p tags
  36  	for _, ev := range events {
  37  		hasPTag := false
  38  
  39  		if ev.Tags != nil && ev.Tags.Len() > 0 {
  40  			// Look for at least one p tag
  41  			for _, tag := range *ev.Tags {
  42  				if tag != nil && tag.Len() >= 2 {
  43  					key := tag.Key()
  44  					if len(key) == 1 && key[0] == 'p' {
  45  						hasPTag = true
  46  						break
  47  					}
  48  				}
  49  			}
  50  		}
  51  
  52  		// Delete events without p tags
  53  		if !hasPTag {
  54  			log.W.F("database: deleting kind 3 event without p tags from pubkey %x", ev.Pubkey)
  55  			if err := d.DeleteEvent(ctx, ev.ID); chk.E(err) {
  56  				log.E.F("database: failed to delete kind 3 event %x: %v", ev.ID, err)
  57  				continue
  58  			}
  59  			deletedCount++
  60  		}
  61  	}
  62  
  63  	duration := time.Since(startTime)
  64  
  65  	if deletedCount > 0 {
  66  		log.I.F("database: cleanup completed in %v - deleted %d kind 3 events without p tags (scanned %d total)",
  67  			duration, deletedCount, len(events))
  68  	} else {
  69  		log.I.F("database: cleanup completed in %v - no kind 3 events needed deletion (scanned %d total)",
  70  			duration, len(events))
  71  	}
  72  
  73  	return nil
  74  }
  75