diff --git a/backend/internal/api/hydration.go b/backend/internal/api/hydration.go index 80e36a9..b09c6bb 100644 --- a/backend/internal/api/hydration.go +++ b/backend/internal/api/hydration.go @@ -1023,6 +1023,7 @@ func hydrateCollectionItemsWithData(database *db.DB, items []db.CollectionItem, b := APIBookmark{ ID: n.URI, Type: "Bookmark", + Motivation: "bookmarking", Author: profiles[n.AuthorDID], Source: n.TargetSource, Title: title, diff --git a/backend/internal/api/notes.go b/backend/internal/api/notes.go index 6b4abbc..576131e 100644 --- a/backend/internal/api/notes.go +++ b/backend/internal/api/notes.go @@ -51,6 +51,7 @@ type NoteIndexDB interface { SaveEditHistory(uri, recordType, previousContent string, previousCID *string) error HashURL(rawURL string) string CommunityBookmarkExists(authorDID, targetHash, tagsJSON string) (bool, error) + GetCommunityBookmarkURI(authorDID, targetHash string) (string, error) } type dbAdapter struct{ d *db.DB } @@ -130,6 +131,9 @@ func (a *dbAdapter) HashURL(rawURL string) string { return db.HashURL(rawURL) } func (a *dbAdapter) CommunityBookmarkExists(did, hash, tags string) (bool, error) { return a.d.CommunityBookmarkExists(did, hash, tags) } +func (a *dbAdapter) GetCommunityBookmarkURI(did, hash string) (string, error) { + return a.d.GetCommunityBookmarkURI(did, hash) +} type NoteWriteService struct { db NoteIndexDB @@ -1126,13 +1130,16 @@ func (s *NoteWriteService) DeleteBookmark(w http.ResponseWriter, r *http.Request did := session.DID collection := xrpc.CollectionNote + var targetHash string for _, col := range []string{xrpc.CollectionNote, xrpc.CollectionBookmark, xrpc.CollectionCommunityBookmark} { uri := "at://" + did + "/" + col + "/" + rkey if note, dbErr := s.db.GetNoteByURI(uri); dbErr == nil && note != nil { collection = col + targetHash = note.TargetHash break - } else if _, dbErr := s.db.GetBookmarkByURI(uri); dbErr == nil { + } else if bm, dbErr := s.db.GetBookmarkByURI(uri); dbErr == nil && bm != nil { collection = col + targetHash = bm.SourceHash break } } @@ -1148,6 +1155,19 @@ func (s *NoteWriteService) DeleteBookmark(w http.ResponseWriter, r *http.Request s.db.DeleteBookmark(uri) s.db.DeleteNote(uri) + if collection != xrpc.CollectionCommunityBookmark && targetHash != "" { + if communityURI, err := s.db.GetCommunityBookmarkURI(did, targetHash); err == nil && communityURI != "" { + parts := strings.Split(communityURI, "/") + if len(parts) == 5 { + communityRkey := parts[4] + _ = s.refresher.ExecuteWithAutoRefresh(r, session, func(client *xrpc.Client, did string) error { + return client.DeleteRecord(r.Context(), did, xrpc.CollectionCommunityBookmark, communityRkey) + }) + } + s.db.DeleteNote(communityURI) + } + } + WriteSuccess(w, map[string]bool{"success": true}) } diff --git a/backend/internal/db/queries_notes.go b/backend/internal/db/queries_notes.go index 2e23cac..54958b6 100644 --- a/backend/internal/db/queries_notes.go +++ b/backend/internal/db/queries_notes.go @@ -75,6 +75,21 @@ func (db *DB) MarginNoteBookmarkExists(authorDID, targetHash string) (bool, erro return true, nil } +func (db *DB) GetCommunityBookmarkURI(authorDID, targetHash string) (string, error) { + var uri string + err := db.QueryRow(` + SELECT uri FROM notes + WHERE author_did = $1 + AND target_hash = $2 + AND uri LIKE 'at://%/community.lexicon.bookmarks.bookmark/%' + LIMIT 1 + `, authorDID, targetHash).Scan(&uri) + if err == sql.ErrNoRows { + return "", nil + } + return uri, err +} + func (db *DB) CommunityBookmarkExists(authorDID, targetHash, tagsJSON string) (bool, error) { query := ` SELECT 1 FROM notes