aboutsummaryrefslogtreecommitdiff
path: root/backend/notes
diff options
context:
space:
mode:
Diffstat (limited to 'backend/notes')
-rw-r--r--backend/notes/app.bsky.actor.go58
-rw-r--r--backend/notes/app.bsky.feed.go150
-rw-r--r--backend/notes/author.go11
-rw-r--r--backend/notes/note.go80
4 files changed, 0 insertions, 299 deletions
diff --git a/backend/notes/app.bsky.actor.go b/backend/notes/app.bsky.actor.go
deleted file mode 100644
index 00a1ff1..0000000
--- a/backend/notes/app.bsky.actor.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package notes
-
-import (
- "fmt"
-)
-
-type AppBskyActorProfileRecord struct {
- DisplayName string `json:"displayName"`
- Avatar *struct {
- Ref struct {
- Link string `json:"$link"`
- } `json:"ref"`
- } `json:"avatar,omitempty"`
- Banner *struct {
- Ref struct {
- Link string `json:"$link"`
- } `json:"ref"`
- } `json:"banner,omitempty"`
- Pronouns string `json:"pronouns"`
- Labels *struct {
- Type string `json:"$type"`
- Values []struct {
- Val string `json:"val"`
- } `json:"values"`
- } `json:"labels,omitempty"`
-}
-
-func AuthorFromAppBskyActorProfileRecord(record AppBskyActorProfileRecord, did, handle, pds string) (*Author, error) {
- var avatarURL, bannerURL string
- if record.Avatar != nil {
- avatarURL = fmt.Sprintf("%s/xrpc/com.atproto.sync.getBlob?did=%s&cid=%s", pds, did, record.Avatar.Ref.Link)
- }
- if record.Banner != nil {
- bannerURL = fmt.Sprintf("%s/xrpc/com.atproto.sync.getBlob?did=%s&cid=%s", pds, did, record.Banner.Ref.Link)
- }
-
- // check for !no-unauthenticated label
- noUnauth := false
- if record.Labels != nil && record.Labels.Type == "com.atproto.label.defs#selfLabels" {
- for _, label := range record.Labels.Values {
- if label.Val == "!no-unauthenticated" {
- noUnauth = true
- }
- }
- }
-
- author := &Author{
- PDS: pds,
- Handle: handle,
- DisplayName: record.DisplayName,
- AvatarURL: avatarURL,
- BannerURL: bannerURL,
- Pronouns: record.Pronouns,
- NoUnauth: noUnauth,
- }
-
- return author, nil
-}
diff --git a/backend/notes/app.bsky.feed.go b/backend/notes/app.bsky.feed.go
deleted file mode 100644
index 3dd7b95..0000000
--- a/backend/notes/app.bsky.feed.go
+++ /dev/null
@@ -1,150 +0,0 @@
-package notes
-
-import (
- "fmt"
- "llostre/backend/general"
- "time"
-)
-
-type EmbedImage struct {
- Alt string `json:"alt"`
- Image struct {
- CID string `json:"$link"`
- } `json:"image"`
- AspectRatio *struct {
- Width int `json:"width"`
- Height int `json:"height"`
- } `json:"aspectRatio,omitempty"`
-}
-
-type EmbedImages struct {
- Type string `json:"$type"`
- Images []EmbedImage `json:"images,omitempty"`
-}
-
-type AppBskyFeedPostEmbed struct {
- Type string `json:"$type"`
- Images []EmbedImage `json:"images,omitempty"`
- Media *EmbedImages `json:"media,omitempty"`
-}
-
-type AppBskyFeedPostRecord struct {
- URI string `json:"uri"`
- Value struct {
- Text string `json:"text"`
- CreatedAt string `json:"createdAt"`
- Reply *struct {
- Parent struct {
- URI string `json:"uri"`
- } `json:"parent"`
- } `json:"reply,omitempty"`
- Facets []struct {
- Index struct {
- ByteStart int `json:"byteStart"`
- ByteEnd int `json:"byteEnd"`
- } `json:"index"`
- Features []struct {
- Type string `json:"$type"`
- URI string `json:"uri,omitempty"`
- DID string `json:"did,omitempty"`
- Tag string `json:"tag,omitempty"`
- } `json:"features"`
- } `json:"facets,omitempty"`
- Embed *AppBskyFeedPostEmbed `json:"embed,omitempty"`
- } `json:"value"`
-}
-
-func extractImages(embed *AppBskyFeedPostEmbed, did, pdsURL string) []Media {
- if embed == nil {
- return nil
- }
- images := embed.Images
- if embed.Media != nil {
- images = embed.Media.Images
- }
- var media []Media
- for _, img := range images {
- m := Media{
- URL: fmt.Sprintf("%s/xrpc/com.atproto.sync.getBlob?did=%s&cid=%s", pdsURL, did, img.Image.CID),
- Alt: img.Alt,
- }
- if img.AspectRatio != nil {
- m.Width = img.AspectRatio.Width
- m.Height = img.AspectRatio.Height
- }
- media = append(media, m)
- }
- return media
-}
-
-func NoteFromAppBskyFeedPostRecord(record AppBskyFeedPostRecord, author *Author) (*Note, error) {
- if record.URI == "" {
- return nil, fmt.Errorf("missing required field: uri")
- }
-
- createdAt, err := time.Parse(time.RFC3339, record.Value.CreatedAt)
- if err != nil {
- return nil, fmt.Errorf("failed to parse timestamp: %w", err)
- }
-
- var replyTo *string
- if record.Value.Reply != nil {
- replyTo = &record.Value.Reply.Parent.URI
- }
-
- var facets []Facet
- for _, f := range record.Value.Facets {
- for _, feature := range f.Features {
- var value string
- var facetType string
-
- switch feature.Type {
- case "app.bsky.richtext.facet#link":
- facetType = "link"
- value = feature.URI
- case "app.bsky.richtext.facet#mention":
- facetType = "mention"
- value = feature.DID
- case "app.bsky.richtext.facet#tag":
- facetType = "tag"
- value = feature.Tag
- default:
- continue
- }
-
- facets = append(facets, Facet{
- ByteStart: f.Index.ByteStart,
- ByteEnd: f.Index.ByteEnd,
- Type: facetType,
- Value: value,
- })
- }
- }
-
- var handle, displayName, avatarURL string
- if author != nil {
- handle = author.Handle
- displayName = author.DisplayName
- avatarURL = author.AvatarURL
- } else {
- handle = "handle.invalid"
- displayName = ""
- avatarURL = ""
- }
-
- did, _, _, err := general.ParseURI(record.URI)
-
- return &Note{
- URI: record.URI,
- AuthorDID: did,
- AuthorHandle: handle,
- AuthorName: displayName,
- AuthorNoUnauth: author.NoUnauth,
- AvatarURL: avatarURL,
- CreatedAt: createdAt,
- Text: record.Value.Text,
- ReplyTo: replyTo,
- Facets: facets,
- Media: extractImages(record.Value.Embed, did, author.PDS),
- }, nil
-}
diff --git a/backend/notes/author.go b/backend/notes/author.go
deleted file mode 100644
index faf4f7b..0000000
--- a/backend/notes/author.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package notes
-
-type Author struct {
- PDS string
- Handle string
- DisplayName string
- AvatarURL string
- BannerURL string
- Pronouns string
- NoUnauth bool
-}
diff --git a/backend/notes/note.go b/backend/notes/note.go
deleted file mode 100644
index 15f6f67..0000000
--- a/backend/notes/note.go
+++ /dev/null
@@ -1,80 +0,0 @@
-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
-}