aboutsummaryrefslogtreecommitdiff
path: root/notes/note.go
diff options
context:
space:
mode:
Diffstat (limited to 'notes/note.go')
-rw-r--r--notes/note.go80
1 files changed, 80 insertions, 0 deletions
diff --git a/notes/note.go b/notes/note.go
new file mode 100644
index 0000000..15f6f67
--- /dev/null
+++ b/notes/note.go
@@ -0,0 +1,80 @@
+package notes
+
+import (
+ "time"
+)
+
+type Media struct {
+ URL string `json:"url"`
+ Alt string `json:"alt"`
+ Width int `json:"width,omitempty"`
+ Height int `json:"height,omitempty"`
+}
+
+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 []Note `json:"parents,omitempty"`
+ Media []Media `json:"media,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(smallChainPost, bigChainPost Note) bool {
+ if len(smallChainPost.Parents) > len(bigChainPost.Parents) {
+ return false
+ }
+
+ // if the thread is going to differ at any post, it's going to be at the end
+ // thus if the posts match their parents MUST match too
+ // (not that I expect to ever compare a post to itself but this way it won't break if I do. And technically a thread contains itself)
+ if len(smallChainPost.Parents) == len(bigChainPost.Parents) {
+ return smallChainPost.URI == bigChainPost.URI
+ }
+
+ // check if the last post of the smaller chain is the (n+1)-th post of the bigger chain
+ // where n is the number of parents in the smaller reply chain
+ offset := len(bigChainPost.Parents) - len(smallChainPost.Parents)
+ return smallChainPost.URI == bigChainPost.Parents[offset-1].URI
+}
+
+func DeduplicateThreads(posts []Note) []Note {
+ 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, kept) {
+ isRedundant = true
+ break
+ }
+ }
+ if !isRedundant {
+ filtered = append(filtered, post)
+ }
+ }
+
+ return filtered
+}