diff options
Diffstat (limited to 'backend/fetchers/app.bsky.go')
| -rw-r--r-- | backend/fetchers/app.bsky.go | 83 |
1 files changed, 81 insertions, 2 deletions
diff --git a/backend/fetchers/app.bsky.go b/backend/fetchers/app.bsky.go index 6b25f0b..069a183 100644 --- a/backend/fetchers/app.bsky.go +++ b/backend/fetchers/app.bsky.go @@ -3,7 +3,9 @@ package fetchers import ( "encoding/json" "fmt" + "io" "llostre/backend/auth" + "llostre/backend/general" "llostre/backend/notes" "log/slog" "net/http" @@ -28,7 +30,7 @@ func FetchAppBskyFeedPosts(logger *slog.Logger, did, pdsURL, accessToken string, if err != nil { return nil, err } - req.Header.Set("Authorization", "Bearer " + accessToken) + req.Header.Set("Authorization", "Bearer "+accessToken) req.Header.Set("DPoP", dpopProof) resp, err := http.DefaultClient.Do(req) @@ -42,7 +44,7 @@ func FetchAppBskyFeedPosts(logger *slog.Logger, did, pdsURL, accessToken string, return nil, err } - profile, err := FetchProfile(did, pdsURL) + profile, err := FetchProfile(did, pdsURL, notesCache) if err != nil { logger.Error("profile fetch failed", "did", did, "error", err) } else { @@ -62,3 +64,80 @@ func FetchAppBskyFeedPosts(logger *slog.Logger, did, pdsURL, accessToken string, return posts, nil } + +func FetchPostByURI(uri, accessToken string, keypair *auth.DPoPKeyPair, cache *Cache) (*notes.Note, error) { + // check cache + if cached, found := cache.Get(uri); found { + return cached, nil + } + + repo, collection, rkey, err := general.ParseURI(uri) + + // need to resolve DID to PDS + pds, err := FetchPDS(repo) + if err != nil { + return nil, err + } + + url := fmt.Sprintf("%s/xrpc/com.atproto.repo.getRecord?repo=%s&collection=%s&rkey=%s", + pds, repo, collection, rkey) + + // fetch with DPoP + dpopProof, err := keypair.GenerateDPoPProof("GET", url, "") + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + req.Header.Set("Authorization", "Bearer "+accessToken) + req.Header.Set("DPoP", dpopProof) + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != 200 { + body, _ := io.ReadAll(resp.Body) + return nil, fmt.Errorf("PDS returned status %d: %s", resp.StatusCode, string(body)) + } + + var result struct { + URI string `json:"uri"` + Value json.RawMessage `json:"value"` + } + if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { + return nil, err + } + + // convert to AppBskyFeedPostRecord + record := notes.AppBskyFeedPostRecord{ + URI: result.URI, + } + if err := json.Unmarshal(result.Value, &record.Value); err != nil { + return nil, err + } + + // get author of the note + profile, found := cache.GetProfile(repo) + if !found { + profile, err = FetchProfile(repo, pds, cache) + } + if err != nil { + return nil, err + } + + note, err := notes.AppBskyFeedPostFromRecord(record, profile) + if err != nil { + return nil, err + } + + // cache it + cache.Set(note.URI, note) + + return note, nil +} |
