aboutsummaryrefslogtreecommitdiff
path: root/backend/fetchers/profiles.go
diff options
context:
space:
mode:
Diffstat (limited to 'backend/fetchers/profiles.go')
-rw-r--r--backend/fetchers/profiles.go106
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
+}