diff options
Diffstat (limited to 'backend/fetchers/app.bsky.actor.go')
| -rw-r--r-- | backend/fetchers/app.bsky.actor.go | 73 |
1 files changed, 42 insertions, 31 deletions
diff --git a/backend/fetchers/app.bsky.actor.go b/backend/fetchers/app.bsky.actor.go index 3c0154a..45ced77 100644 --- a/backend/fetchers/app.bsky.actor.go +++ b/backend/fetchers/app.bsky.actor.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "llostre/backend/general" + "log/slog" "net" "net/http" "strings" @@ -128,57 +129,67 @@ func FetchHandleAndPDS(did string) (string, string, error) { return handle, pds, nil } -func FetchProfile(did, pdsURL string, cache *Cache) (*general.Profile, error) { - recordURL := fmt.Sprintf("%s/xrpc/com.atproto.repo.getRecord?repo=%s&collection=app.bsky.actor.profile&rkey=self", pdsURL, did) +func FetchProfile(logger *slog.Logger, did, pdsURL, slingshotURL string, cache *Cache) (*general.Profile, error) { + // construct profile record URI + uri := fmt.Sprintf("at://%s/app.bsky.actor.profile/self", did) + + // try slingshot first + if slingshotURL != "" { + rawRecord, err := general.FetchRawRecordByURI(logger, uri, slingshotURL) + if err != nil { + logger.Warn("slingshot profile fetch failed", "did", did, "error", err) + } else { + return parseProfile(did, rawRecord, cache) + } + } - resp, err := http.Get(recordURL) + // fallback to PDS + rawRecord, err := general.FetchRawRecordByURI(logger, uri, pdsURL) if err != nil { return nil, err } - defer resp.Body.Close() - if resp.StatusCode != 200 { - return nil, fmt.Errorf("profile fetch failed: %d", resp.StatusCode) - } + return parseProfile(did, rawRecord, cache) +} - handle, err := FetchHandle(did) - if err != nil { - handle = "handle.invalid" +func FetchProfiles(logger *slog.Logger, dids []string, pdsURL, slingshotURL string, cache *Cache) map[string]general.Profile { + profiles := make(map[string]general.Profile) + for _, did := range dids { + profile, err := FetchProfile(logger, did, pdsURL, slingshotURL, cache) + if err == nil { + profiles[did] = *profile + } } + return profiles +} - var response general.ProfileRecordResponse - if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { +func parseProfile(did string, rawRecord *general.RawRecord, cache *Cache) (*general.Profile, error) { + var profileData general.ProfileRecord + if err := json.Unmarshal(rawRecord.Value, &profileData); err != nil { return nil, err } var avatarURL, bannerURL string - if response.Value.Avatar != nil { - avatarURL = fmt.Sprintf("https://cdn.bsky.app/img/avatar/plain/%s/%s@jpeg", did, response.Value.Avatar.Ref.Link) + if profileData.Avatar != nil { + avatarURL = fmt.Sprintf("https://cdn.bsky.app/img/avatar/plain/%s/%s@jpeg", did, profileData.Avatar.Ref.Link) + } + if profileData.Banner != nil { + bannerURL = fmt.Sprintf("https://cdn.bsky.app/img/banner/plain/%s/%s@jpeg", did, profileData.Banner.Ref.Link) } - if response.Value.Banner != nil { - bannerURL = fmt.Sprintf("https://cdn.bsky.app/img/banner/plain/%s/%s@jpeg", did, response.Value.Banner.Ref.Link) + + handle, err := FetchHandle(did) + if err != nil { + handle = "handle.invalid" } profile := &general.Profile{ Handle: handle, - DisplayName: response.Value.DisplayName, + DisplayName: profileData.DisplayName, AvatarURL: avatarURL, BannerURL: bannerURL, - Pronouns: response.Value.Pronouns, + Pronouns: profileData.Pronouns, } - cache.SetProfile(handle, profile) + cache.SetProfile(did, profile) return profile, nil } - -func FetchProfiles(dids []string, pdsURL string, cache *Cache) map[string]general.Profile { - profiles := make(map[string]general.Profile) - for _, did := range dids { - profile, err := FetchProfile(did, pdsURL, cache) - if err == nil { - cache.SetProfile(did, profile) - profiles[did] = *profile - } - } - return profiles -} |
