1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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
}
|