aboutsummaryrefslogtreecommitdiff
path: root/backend/fetchers/app.bsky.feed.go
diff options
context:
space:
mode:
Diffstat (limited to 'backend/fetchers/app.bsky.feed.go')
-rw-r--r--backend/fetchers/app.bsky.feed.go57
1 files changed, 53 insertions, 4 deletions
diff --git a/backend/fetchers/app.bsky.feed.go b/backend/fetchers/app.bsky.feed.go
index 2a38d5a..1b9acc1 100644
--- a/backend/fetchers/app.bsky.feed.go
+++ b/backend/fetchers/app.bsky.feed.go
@@ -26,7 +26,7 @@ func FetchAppBskyFeedPosts(logger *slog.Logger, did, pdsURL, slingshotURL string
if err != nil {
logger.Error("Fetching from slingshot failed")
} else {
- return parseAppBskyFeedPostCollection(logger, records, author, cache)
+ return parseAppBskyFeedPostCollection(logger, slingshotURL, session, records, author, cache)
}
}
@@ -35,7 +35,7 @@ func FetchAppBskyFeedPosts(logger *slog.Logger, did, pdsURL, slingshotURL string
return nil, err
}
- return parseAppBskyFeedPostCollection(logger, records, author, cache)
+ return parseAppBskyFeedPostCollection(logger, slingshotURL, session, records, author, cache)
}
func GetAppBskyFeedPostByURI(logger *slog.Logger, uri, slingshotURL string, session *auth.OAuthState, cache *Cache) (*notes.Note, error) {
@@ -114,7 +114,7 @@ func parseAppBskyFeedPostRecord(rawRecord *general.RawRecord, author *notes.Auth
return note, nil
}
-func parseAppBskyFeedPostCollection(logger *slog.Logger, records []general.RawRecord, author *notes.Author, cache *Cache) ([]notes.Note, error) {
+func parseAppBskyFeedPostCollection(logger *slog.Logger, slingshotURL string, session *auth.OAuthState, records []general.RawRecord, author *notes.Author, cache *Cache) ([]notes.Note, error) {
posts := make([]notes.Note, 0, len(records))
for _, record := range records {
note, err := parseAppBskyFeedPostRecord(&record, author, cache)
@@ -122,9 +122,58 @@ func parseAppBskyFeedPostCollection(logger *slog.Logger, records []general.RawRe
logger.Error("failed to parse post record", "error", err)
continue
}
+ if note.ReplyTo != nil {
+ parents, err := FetchParents(logger, *note.ReplyTo, slingshotURL, session, cache, 10)
+ if err != nil {
+ logger.Warn("failed to fetch parent chain", "uri", note.URI, "error", err)
+ }
+ note.Parents = parents
+ }
cache.Set(note.URI, note)
posts = append(posts, *note)
}
- return posts, nil
+ return notes.DeduplicateThreads(posts), nil
+}
+
+func FetchParents(logger *slog.Logger, replyToURI string, slingshotURL string, session *auth.OAuthState, cache *Cache, maxDepth int) ([]string, error) {
+ parents := []string{}
+ seen := make(map[string]bool)
+ currentURI := replyToURI
+
+ for currentURI != "" {
+ // check for circular reference
+ if seen[currentURI] {
+ logger.Warn("circular reference detected in thread", "uri", currentURI)
+ break
+ }
+ seen[currentURI] = true
+
+ note, err := GetAppBskyFeedPostByURI(logger, currentURI, slingshotURL, session, cache)
+ if err != nil {
+ logger.Warn("failed to fetch parent", "uri", currentURI, "error", err)
+ break
+ }
+
+ // preemptively fetch posts from author to avoid hammering servers if there's a back and forth
+ if _, found := cache.GetProfile(note.AuthorDID); !found {
+ logger.Debug("caching posts from thread participant", "did", note.AuthorDID)
+ authorPDS, err := FetchPDS(note.AuthorDID)
+ if err != nil {
+ logger.Warn("failed to fetch parent", "uri", currentURI, "error", err)
+ break
+ }
+ go FetchAppBskyFeedPosts(logger, note.AuthorDID, authorPDS, slingshotURL, session, cache)
+ }
+
+ parents = append(parents, currentURI)
+
+ if note.ReplyTo == nil {
+ break
+ }
+
+ currentURI = *note.ReplyTo
+ }
+
+ return parents, nil
}