package notes import ( "sort" "time" ) type Note struct { URI string `json:"uri"` AuthorDID string `json:"authorDid"` AuthorHandle string `json:"authorHandle"` AuthorName string `json:"authorName"` AuthorNoUnauth bool `json:"authorNoUnauth"` // author has !no-unauthenticated label AvatarURL string `json:"avatarURL"` Text string `json:"text"` CreatedAt time.Time `json:"createdAt"` ReplyTo *string `json:"replyTo,omitempty"` Facets []Facet `json:"facets,omitempty"` Parents []string `json:"parents,omitempty"` } type Facet struct { ByteStart int `json:"byteStart"` ByteEnd int `json:"byteEnd"` Type string `json:"type"` Value string `json:"value"` // the link destination, whether url, profile or tag } func MissingNote(uri string) *Note { return &Note{ URI: uri, AuthorDID: "MISSING", Text: "This post could not be fetched. It may have been deleted.", CreatedAt: time.Time{}, } } func isChainContained(smallChain, bigChain []string) bool { if len(smallChain) > len(bigChain) { return false } // check if smallChain is a suffix of bigChain offset := len(bigChain) - len(smallChain) for i, uri := range smallChain { if bigChain[offset+i] != uri { return false } } return true } func DeduplicateThreads(posts []Note) []Note { // sort by parent chain length (longest first) sort.Slice(posts, func(i, j int) bool { return len(posts[i].Parents) > len(posts[j].Parents) }) filtered := []Note{} for _, post := range posts { isRedundant := false for _, kept := range filtered { // check if this post's chain is contained in any kept post if isChainContained(post.Parents, kept.Parents) && post.URI == kept.URI { isRedundant = true break } } if !isRedundant { filtered = append(filtered, post) } } return filtered }