diff options
Diffstat (limited to 'backend/fetchers/profiles.go')
| -rw-r--r-- | backend/fetchers/profiles.go | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/backend/fetchers/profiles.go b/backend/fetchers/profiles.go new file mode 100644 index 0000000..c25dd97 --- /dev/null +++ b/backend/fetchers/profiles.go @@ -0,0 +1,106 @@ +package fetchers + +import ( + "encoding/json" + "fmt" + "io" + "llostre/backend/general" + "net/http" + "strings" +) + +func FetchHandle(did string) (string, error) { + didDocURL := fmt.Sprintf("https://plc.directory/%s", did) + + resp, err := http.Get(didDocURL) + if err != nil { + return "", err + } + defer resp.Body.Close() + + if resp.StatusCode != 200 { + return "", fmt.Errorf("DID resolution failed: %d", resp.StatusCode) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return "", err + } + + var didDoc struct { + AlsoKnownAs []string `json:"alsoKnownAs"` + } + + err = json.Unmarshal(body, &didDoc) + if err != nil { + return "", err + } + + if len(didDoc.AlsoKnownAs) == 0 { + return "", fmt.Errorf("no handle found") + } + + handle := strings.TrimPrefix(didDoc.AlsoKnownAs[0], "at://") + return handle, nil +} + +func FetchProfile(did string, pdsURL string) (*general.Profile, error) { + recordURL := fmt.Sprintf("%s/xrpc/com.atproto.repo.getRecord?repo=%s&collection=app.bsky.actor.profile&rkey=self", pdsURL, did) + + fmt.Printf("Fetching profile from: %s\n", recordURL) + resp, err := http.Get(recordURL) + if err != nil { + return nil, err + } + defer resp.Body.Close() + fmt.Printf("Response status: %d\n", resp.StatusCode) + + if resp.StatusCode != 200 { + return nil, fmt.Errorf("profile fetch failed: %d", resp.StatusCode) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + handle, err := FetchHandle(did) + if err != nil { + handle = "handle.invalid" + } + + var response general.ProfileRecordResponse + + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + fmt.Printf("Unmarshaled value: %+v\n", response.Value) + + 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 response.Value.Banner != nil { + bannerURL = fmt.Sprintf("https://cdn.bsky.app/img/banner/plain/%s/%s@jpeg", did, response.Value.Banner.Ref.Link) + } + + return &general.Profile{ + Handle: handle, + DisplayName: response.Value.DisplayName, + AvatarURL: avatarURL, + BannerURL: bannerURL, + Pronouns: response.Value.Pronouns, + }, nil +} + +func FetchProfiles(dids []string, pdsURL string) map[string]general.Profile { + profiles := make(map[string]general.Profile) + for _, did := range dids { + profile, err := FetchProfile(did, pdsURL) + if err == nil { + profiles[did] = *profile + } + } + return profiles +} |
