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) resp, err := http.Get(recordURL) if err != nil { return nil, err } defer resp.Body.Close() 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 } 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 }