tangled
alpha
login
or
join now
margin.at
/
margin
90
fork
atom
Margin is an open annotation layer for the internet. Powered by the AT Protocol.
margin.at
extension
web
atproto
comments
90
fork
atom
overview
issues
4
pulls
1
pipelines
fix: do not serve user feed from PDS
Henrique Dias
1 month ago
915b40f4
b791eaab
-154
1 changed file
expand all
collapse all
unified
split
backend
internal
api
handler.go
-154
backend/internal/api/handler.go
···
11
"sort"
12
"strconv"
13
"strings"
14
-
"sync"
15
"time"
16
17
"github.com/go-chi/chi/v5"
···
172
feedType := r.URL.Query().Get("type")
173
174
viewerDID := h.getViewerDID(r)
175
-
176
-
if viewerDID != "" && (feedType == "my-feed" || creator == viewerDID) {
177
-
h.serveUserFeedFromPDS(w, r, viewerDID, tag, r.URL.Query().Get("motivation"), limit, offset)
178
-
return
179
-
}
180
181
var annotations []db.Annotation
182
var highlights []db.Highlight
···
482
"items": feed,
483
"totalItems": len(feed),
484
})
485
-
}
486
-
487
-
func (h *Handler) serveUserFeedFromPDS(w http.ResponseWriter, r *http.Request, did, tag, motivation string, limit, offset int) {
488
-
var wg sync.WaitGroup
489
-
var rawAnnos, rawHighs, rawBooks []interface{}
490
-
var errAnnos, errHighs, errBooks error
491
-
492
-
fetchLimit := limit + offset
493
-
if fetchLimit < 50 {
494
-
fetchLimit = 50
495
-
}
496
-
497
-
if motivation == "" || motivation == "commenting" {
498
-
wg.Add(1)
499
-
go func() {
500
-
defer wg.Done()
501
-
rawAnnos, errAnnos = h.FetchLatestUserRecords(r, did, xrpc.CollectionAnnotation, fetchLimit)
502
-
}()
503
-
}
504
-
if motivation == "" || motivation == "highlighting" {
505
-
wg.Add(1)
506
-
go func() {
507
-
defer wg.Done()
508
-
rawHighs, errHighs = h.FetchLatestUserRecords(r, did, xrpc.CollectionHighlight, fetchLimit)
509
-
}()
510
-
}
511
-
if motivation == "" || motivation == "bookmarking" {
512
-
wg.Add(1)
513
-
go func() {
514
-
defer wg.Done()
515
-
rawBooks, errBooks = h.FetchLatestUserRecords(r, did, xrpc.CollectionBookmark, fetchLimit)
516
-
}()
517
-
}
518
-
wg.Wait()
519
-
520
-
if errAnnos != nil {
521
-
log.Printf("PDS Fetch Error (Annos): %v", errAnnos)
522
-
}
523
-
if errHighs != nil {
524
-
log.Printf("PDS Fetch Error (Highs): %v", errHighs)
525
-
}
526
-
if errBooks != nil {
527
-
log.Printf("PDS Fetch Error (Books): %v", errBooks)
528
-
}
529
-
530
-
var annotations []db.Annotation
531
-
var highlights []db.Highlight
532
-
var bookmarks []db.Bookmark
533
-
534
-
for _, r := range rawAnnos {
535
-
if a, ok := r.(*db.Annotation); ok {
536
-
if tag == "" || containsTag(a.TagsJSON, tag) {
537
-
annotations = append(annotations, *a)
538
-
}
539
-
}
540
-
}
541
-
for _, r := range rawHighs {
542
-
if h, ok := r.(*db.Highlight); ok {
543
-
if tag == "" || containsTag(h.TagsJSON, tag) {
544
-
highlights = append(highlights, *h)
545
-
}
546
-
}
547
-
}
548
-
for _, r := range rawBooks {
549
-
if b, ok := r.(*db.Bookmark); ok {
550
-
if tag == "" || containsTag(b.TagsJSON, tag) {
551
-
bookmarks = append(bookmarks, *b)
552
-
}
553
-
}
554
-
}
555
-
556
-
go func() {
557
-
for _, a := range annotations {
558
-
h.db.CreateAnnotation(&a)
559
-
}
560
-
for _, hi := range highlights {
561
-
h.db.CreateHighlight(&hi)
562
-
}
563
-
for _, b := range bookmarks {
564
-
h.db.CreateBookmark(&b)
565
-
}
566
-
}()
567
-
568
-
collectionItems := []db.CollectionItem{}
569
-
if tag == "" && motivation == "" {
570
-
items, err := h.db.GetCollectionItemsByAuthor(did)
571
-
if err != nil {
572
-
log.Printf("Error fetching collection items for user feed: %v", err)
573
-
} else {
574
-
collectionItems = items
575
-
}
576
-
}
577
-
578
-
if len(collectionItems) > 0 {
579
-
var sembleURIs []string
580
-
for _, item := range collectionItems {
581
-
if strings.Contains(item.AnnotationURI, "network.cosmik.card") {
582
-
sembleURIs = append(sembleURIs, item.AnnotationURI)
583
-
}
584
-
}
585
-
if len(sembleURIs) > 0 {
586
-
ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
587
-
defer cancel()
588
-
ensureSembleCardsIndexed(ctx, h.db, sembleURIs)
589
-
}
590
-
}
591
-
592
-
authAnnos, _ := hydrateAnnotations(h.db, annotations, did)
593
-
authHighs, _ := hydrateHighlights(h.db, highlights, did)
594
-
authBooks, _ := hydrateBookmarks(h.db, bookmarks, did)
595
-
authCollectionItems, _ := hydrateCollectionItems(h.db, collectionItems, did)
596
-
597
-
var feed []interface{}
598
-
for _, a := range authAnnos {
599
-
feed = append(feed, a)
600
-
}
601
-
for _, h := range authHighs {
602
-
feed = append(feed, h)
603
-
}
604
-
for _, b := range authBooks {
605
-
feed = append(feed, b)
606
-
}
607
-
if motivation == "" {
608
-
for _, ci := range authCollectionItems {
609
-
feed = append(feed, ci)
610
-
}
611
-
}
612
-
613
-
sortFeed(feed)
614
-
615
-
if offset < len(feed) {
616
-
feed = feed[offset:]
617
-
} else {
618
-
feed = []interface{}{}
619
-
}
620
-
621
-
if len(feed) > limit {
622
-
feed = feed[:limit]
623
-
}
624
-
625
-
w.Header().Set("Content-Type", "application/json")
626
-
json.NewEncoder(w).Encode(map[string]interface{}{
627
-
"@context": "http://www.w3.org/ns/anno.jsonld",
628
-
"type": "Collection",
629
-
"items": feed,
630
-
"totalItems": len(feed),
631
-
})
632
-
633
}
634
635
func containsTag(tagsJSON *string, tag string) bool {
···
11
"sort"
12
"strconv"
13
"strings"
0
14
"time"
15
16
"github.com/go-chi/chi/v5"
···
171
feedType := r.URL.Query().Get("type")
172
173
viewerDID := h.getViewerDID(r)
0
0
0
0
0
174
175
var annotations []db.Annotation
176
var highlights []db.Highlight
···
476
"items": feed,
477
"totalItems": len(feed),
478
})
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
479
}
480
481
func containsTag(tagsJSON *string, tag string) bool {