package storage import ( "context" "fmt" pb "northwest.io/muxstr/api/nostr/v1" ) const KindDeletion = 5 // ProcessDeletion handles kind 5 deletion events by hard deleting the referenced events. // Only events authored by the same pubkey as the deletion event can be deleted. func (s *Storage) ProcessDeletion(ctx context.Context, deletionEvent *pb.Event) error { if deletionEvent.Kind != KindDeletion { return fmt.Errorf("not a deletion event") } // Extract event IDs to delete from "e" tags var eventIDsToDelete []string for _, tag := range deletionEvent.Tags { if len(tag.Values) >= 2 && tag.Values[0] == "e" { eventIDsToDelete = append(eventIDsToDelete, tag.Values[1]) } } if len(eventIDsToDelete) == 0 { return nil } tx, err := s.db.BeginTx(ctx, nil) if err != nil { return fmt.Errorf("failed to begin transaction: %w", err) } defer tx.Rollback() // Hard delete each referenced event (only if authored by same pubkey) for _, eventID := range eventIDsToDelete { // Verify the event exists and was authored by the same pubkey var eventPubkey string err := tx.QueryRowContext(ctx, "SELECT pubkey FROM events WHERE id = ?", eventID, ).Scan(&eventPubkey) if err != nil { // Event doesn't exist, skip continue } // Only delete if pubkeys match if eventPubkey != deletionEvent.Pubkey { continue } // Hard delete the event _, err = tx.ExecContext(ctx, "DELETE FROM events WHERE id = ?", eventID, ) if err != nil { return fmt.Errorf("failed to delete event: %w", err) } } return tx.Commit() }