Diffdown is a real-time collaborative Markdown editor/previewer built on the AT Protocol diffdown.com
at main 62 lines 1.5 kB view raw
1package atproto 2 3import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7) 8 9// Profile holds resolved ATProto profile information fetched at runtime 10type Profile struct { 11 DID string `json:"did"` 12 Handle string `json:"handle"` 13 DisplayName string `json:"displayName"` 14 Avatar string `json:"avatar"` 15 PDSURL string `json:"pdsUrl"` 16} 17 18const bskyAppViewURL = "https://public.api.bsky.app" 19 20// ResolveProfile fetches a user's profile from the Bluesky public AppView. 21func ResolveProfile(did string) (*Profile, error) { 22 url := fmt.Sprintf("%s/xrpc/app.bsky.actor.getProfile?actor=%s", bskyAppViewURL, did) 23 24 resp, err := httpClient.Get(url) 25 if err != nil { 26 return nil, err 27 } 28 defer resp.Body.Close() 29 30 if resp.StatusCode != http.StatusOK { 31 return nil, fmt.Errorf("profile fetch failed: %d", resp.StatusCode) 32 } 33 34 var result struct { 35 DID string `json:"did"` 36 Handle string `json:"handle"` 37 DisplayName string `json:"displayName"` 38 Avatar string `json:"avatar"` 39 } 40 41 if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { 42 return nil, err 43 } 44 45 return &Profile{ 46 DID: result.DID, 47 Handle: result.Handle, 48 DisplayName: result.DisplayName, 49 Avatar: result.Avatar, 50 }, nil 51} 52 53// GetDisplayName returns the best available name for a user 54func (p *Profile) GetDisplayName() string { 55 if p.DisplayName != "" { 56 return p.DisplayName 57 } 58 if p.Handle != "" && p.Handle != p.DID { 59 return p.Handle 60 } 61 return p.DID 62}