Write on the margins of the internet. Powered by the AT Protocol.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Retrieve and merge annotations, highlights, and bookmarks using both normalized and raw URL hashes

scanash00 bb297394 5345691c

+88 -18
+65
backend/internal/api/handler.go
··· 895 895 offset := parseIntParam(r, "offset", 0) 896 896 897 897 urlHash := db.HashURL(source) 898 + rawHash := db.HashString(source) 898 899 899 900 annotations, _ := h.db.GetAnnotationsByTargetHash(urlHash, limit, offset) 900 901 highlights, _ := h.db.GetHighlightsByTargetHash(urlHash, limit, offset) 901 902 bookmarks, _ := h.db.GetBookmarksByTargetHash(urlHash, limit, offset) 903 + 904 + if rawHash != urlHash { 905 + rawAnnotations, _ := h.db.GetAnnotationsByTargetHash(rawHash, limit, offset) 906 + rawHighlights, _ := h.db.GetHighlightsByTargetHash(rawHash, limit, offset) 907 + rawBookmarks, _ := h.db.GetBookmarksByTargetHash(rawHash, limit, offset) 908 + 909 + annotations = mergeAnnotations(annotations, rawAnnotations) 910 + highlights = mergeHighlights(highlights, rawHighlights) 911 + bookmarks = mergeBookmarks(bookmarks, rawBookmarks) 912 + } 902 913 903 914 enrichedAnnotations, _ := hydrateAnnotations(h.db, annotations, h.getViewerDID(r)) 904 915 enrichedHighlights, _ := hydrateHighlights(h.db, highlights, h.getViewerDID(r)) ··· 1569 1580 } 1570 1581 return filtered 1571 1582 } 1583 + 1584 + func mergeAnnotations(a, b []db.Annotation) []db.Annotation { 1585 + seen := make(map[string]bool) 1586 + var result []db.Annotation 1587 + for _, item := range a { 1588 + if !seen[item.URI] { 1589 + seen[item.URI] = true 1590 + result = append(result, item) 1591 + } 1592 + } 1593 + for _, item := range b { 1594 + if !seen[item.URI] { 1595 + seen[item.URI] = true 1596 + result = append(result, item) 1597 + } 1598 + } 1599 + return result 1600 + } 1601 + 1602 + func mergeHighlights(a, b []db.Highlight) []db.Highlight { 1603 + seen := make(map[string]bool) 1604 + var result []db.Highlight 1605 + for _, item := range a { 1606 + if !seen[item.URI] { 1607 + seen[item.URI] = true 1608 + result = append(result, item) 1609 + } 1610 + } 1611 + for _, item := range b { 1612 + if !seen[item.URI] { 1613 + seen[item.URI] = true 1614 + result = append(result, item) 1615 + } 1616 + } 1617 + return result 1618 + } 1619 + 1620 + func mergeBookmarks(a, b []db.Bookmark) []db.Bookmark { 1621 + seen := make(map[string]bool) 1622 + var result []db.Bookmark 1623 + for _, item := range a { 1624 + if !seen[item.URI] { 1625 + seen[item.URI] = true 1626 + result = append(result, item) 1627 + } 1628 + } 1629 + for _, item := range b { 1630 + if !seen[item.URI] { 1631 + seen[item.URI] = true 1632 + result = append(result, item) 1633 + } 1634 + } 1635 + return result 1636 + }
+3 -3
backend/internal/db/queries.go
··· 43 43 func HashURL(rawURL string) string { 44 44 parsed, err := url.Parse(rawURL) 45 45 if err != nil || parsed.Host == "" { 46 - return hashString(rawURL) 46 + return HashString(rawURL) 47 47 } 48 48 49 49 host := strings.ToLower(parsed.Host) ··· 55 55 } 56 56 normalized = strings.TrimSuffix(normalized, "/") 57 57 58 - return hashString(normalized) 58 + return HashString(normalized) 59 59 } 60 60 61 - func hashString(s string) string { 61 + func HashString(s string) string { 62 62 h := sha256.New() 63 63 h.Write([]byte(s)) 64 64 return hex.EncodeToString(h.Sum(nil))
+20 -15
lexicons/at/margin/annotation.json
··· 49 49 "maxLength": 10 50 50 }, 51 51 "generator": { 52 - "type": "object", 53 - "description": "The client/agent that created this record", 54 - "properties": { 55 - "id": { 56 - "type": "string", 57 - "format": "uri" 58 - }, 59 - "name": { 60 - "type": "string" 61 - }, 62 - "homepage": { 63 - "type": "string", 64 - "format": "uri" 65 - } 66 - } 52 + "type": "ref", 53 + "ref": "#generator", 54 + "description": "The client/agent that created this record" 67 55 }, 68 56 "rights": { 69 57 "type": "string", ··· 79 67 "type": "string", 80 68 "format": "datetime" 81 69 } 70 + } 71 + } 72 + }, 73 + "generator": { 74 + "type": "object", 75 + "description": "The client/agent that created this record", 76 + "properties": { 77 + "id": { 78 + "type": "string", 79 + "format": "uri" 80 + }, 81 + "name": { 82 + "type": "string" 83 + }, 84 + "homepage": { 85 + "type": "string", 86 + "format": "uri" 82 87 } 83 88 } 84 89 },