grain/server/handlers/kinds/kind5.go

129 lines
4.2 KiB
Go

package kinds
import (
"context"
"fmt"
"grain/server/handlers/response"
relay "grain/server/types"
"strings"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"golang.org/x/net/websocket"
)
func HandleKind5(ctx context.Context, evt relay.Event, dbClient *mongo.Client, ws *websocket.Conn) error {
for _, tag := range evt.Tags {
if len(tag) < 2 {
continue
}
if tag[0] == "e" {
eventID := tag[1]
if err := deleteEventByID(ctx, eventID, evt.PubKey, dbClient); err != nil {
response.SendOK(ws, evt.ID, false, fmt.Sprintf("error: %v", err))
return fmt.Errorf("error deleting event with ID %s: %v", eventID, err)
}
} else if tag[0] == "a" {
parts := splitTagA(tag[1])
if len(parts) == 3 {
kind := parts[0]
pubKey := parts[1]
dID := parts[2]
// Delete previous kind 5 events with the same "a" tag if they exist
if err := deletePreviousKind5Events(ctx, kind, pubKey, dID, dbClient); err != nil {
response.SendOK(ws, evt.ID, false, fmt.Sprintf("error: %v", err))
return fmt.Errorf("error deleting previous kind 5 events: %v", err)
}
// Delete target events by kind, pubKey, and dID
if err := deleteEventByKindPubKeyDID(ctx, kind, pubKey, dID, evt.CreatedAt, dbClient); err != nil {
response.SendOK(ws, evt.ID, false, fmt.Sprintf("error: %v", err))
return fmt.Errorf("error deleting events with kind %s, pubkey %s, and dID %s: %v", kind, pubKey, dID, err)
}
}
}
}
// Store the deletion event
if err := storeEvent(ctx, evt, dbClient); err != nil {
response.SendOK(ws, evt.ID, false, fmt.Sprintf("error: %v", err))
return fmt.Errorf("error storing deletion event: %v", err)
}
response.SendOK(ws, evt.ID, true, "")
return nil
}
func deletePreviousKind5Events(ctx context.Context, kind string, pubKey string, dID string, dbClient *mongo.Client) error {
collection := dbClient.Database("grain").Collection("event-kind5")
filter := bson.M{
"tags": bson.M{
"$elemMatch": bson.M{
"0": "a",
"1": fmt.Sprintf("%s:%s:%s", kind, pubKey, dID),
},
},
}
_, err := collection.DeleteMany(ctx, filter)
if err != nil {
return fmt.Errorf("error deleting previous kind 5 events from collection event-kind5: %v", err)
}
fmt.Printf("Deleted previous kind 5 events for kind %s, pubkey %s, and dID %s\n", kind, pubKey, dID)
return nil
}
func deleteEventByID(ctx context.Context, eventID string, pubKey string, dbClient *mongo.Client) error {
collections, err := dbClient.Database("grain").ListCollectionNames(ctx, bson.M{})
if err != nil {
return fmt.Errorf("error listing collections: %v", err)
}
for _, collectionName := range collections {
filter := bson.M{"id": eventID, "pubkey": pubKey}
result, err := dbClient.Database("grain").Collection(collectionName).DeleteOne(ctx, filter)
if err != nil {
return fmt.Errorf("error deleting event from collection %s: %v", collectionName, err)
}
if result.DeletedCount > 0 {
fmt.Printf("Deleted event %s from collection %s\n", eventID, collectionName)
return nil
}
}
return nil
}
func splitTagA(tagA string) []string {
return strings.Split(tagA, ":")
}
func deleteEventByKindPubKeyDID(ctx context.Context, kind string, pubKey string, dID string, createdAt int64, dbClient *mongo.Client) error {
filter := bson.M{"kind": kind, "pubkey": pubKey, "tags.d": dID, "createdat": bson.M{"$lte": createdAt}}
collections, err := dbClient.Database("grain").ListCollectionNames(ctx, bson.M{})
if err != nil {
return fmt.Errorf("error listing collections: %v", err)
}
for _, collectionName := range collections {
_, err := dbClient.Database("grain").Collection(collectionName).DeleteMany(ctx, filter)
if err != nil {
return fmt.Errorf("error deleting events from collection %s: %v", collectionName, err)
}
fmt.Printf("Deleted events with kind %s, pubkey %s, and dID %s from collection %s\n", kind, pubKey, dID, collectionName)
}
return nil
}
func storeEvent(ctx context.Context, evt relay.Event, dbClient *mongo.Client) error {
_, err := dbClient.Database("grain").Collection("event-kind5").InsertOne(ctx, evt)
if err != nil {
return fmt.Errorf("error inserting deletion event: %v", err)
}
fmt.Printf("Stored deletion event %s\n", evt.ID)
return nil
}