diff options
| author | Guillermo Serrahima <dev@vylion.com> | 2026-04-11 07:40:30 +0200 |
|---|---|---|
| committer | Guillermo Serrahima <dev@vylion.com> | 2026-04-11 23:39:19 +0200 |
| commit | 9f0a9a6779f00786e4728ad5c3fad36814a293b0 (patch) | |
| tree | 4b16d535c5d41ef46980608a88b7581be3c2bfd0 /backend/fetchers/app.bsky.actor.go | |
| parent | f6d60077b7cfc0d589fa7961e2bb59aea9f993a3 (diff) | |
| download | llostre-9f0a9a6779f00786e4728ad5c3fad36814a293b0.tar.xz llostre-9f0a9a6779f00786e4728ad5c3fad36814a293b0.zip | |
project restructure
Diffstat (limited to 'backend/fetchers/app.bsky.actor.go')
| -rw-r--r-- | backend/fetchers/app.bsky.actor.go | 184 |
1 files changed, 0 insertions, 184 deletions
diff --git a/backend/fetchers/app.bsky.actor.go b/backend/fetchers/app.bsky.actor.go deleted file mode 100644 index 41a9c17..0000000 --- a/backend/fetchers/app.bsky.actor.go +++ /dev/null @@ -1,184 +0,0 @@ -package fetchers - -import ( - "encoding/json" - "fmt" - "io" - "llostre/backend/auth" - "llostre/backend/general" - "llostre/backend/notes" - "net" - "net/http" - "strings" - "time" -) - -type DIDDocument struct { - AlsoKnownAs []string `json:"alsoKnownAs"` - Service []struct { - ID string `json:"id"` - Type string `json:"type"` - ServiceEndpoint string `json:"serviceEndpoint"` - } `json:"service"` -} - -func FetchDID(handle string) (string, error) { - // return if it's a DID already - if strings.HasPrefix(handle, "did:") { - return handle, nil - } - - // resolve DNS record first - txtRecords, err := net.LookupTXT("_atproto." + handle) - if err == nil { - for _, txt := range txtRecords { - if after, ok := strings.CutPrefix(txt, "did="); ok { - return after, nil - } - } - } - - // fallback to HTTPS well-known - resp, err := http.Get(fmt.Sprintf("https://%s/.well-known/atproto-did", handle)) - if err != nil { - return "", err - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return "", err - } - - did := strings.TrimSpace(string(body)) - if !strings.HasPrefix(did, "did:") { - return "", fmt.Errorf("invalid DID returned: %s", did) - } - - return did, nil -} - -func FetchDidDoc(did string) (*DIDDocument, error) { - didDocURL := fmt.Sprintf("https://plc.directory/%s", did) - - resp, err := http.Get(didDocURL) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return nil, fmt.Errorf("DID resolution failed: %d", resp.StatusCode) - } - - var didDoc DIDDocument - if err := json.NewDecoder(resp.Body).Decode(&didDoc); err != nil { - return nil, err - } - - return &didDoc, nil -} - -func FetchHandle(did string) (string, error) { - var didDoc, err = FetchDidDoc(did) - 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 FetchPDS(did string) (string, error) { - var didDoc, err = FetchDidDoc(did) - if err != nil { - return "", err - } - - for _, svc := range didDoc.Service { - if svc.Type == "AtprotoPersonalDataServer" { - return svc.ServiceEndpoint, nil - } - } - - return "", fmt.Errorf("no PDS found for DID %s", did) -} - -func FetchHandleAndPDS(did string) (string, string, error) { - var didDoc, err = FetchDidDoc(did) - if err != nil { - return "", "", err - } - - if len(didDoc.AlsoKnownAs) == 0 { - return "", "", fmt.Errorf("no handle found") - } - - var pds string - for _, svc := range didDoc.Service { - if svc.Type == "AtprotoPersonalDataServer" { - pds = svc.ServiceEndpoint - break - } - } - - handle := strings.TrimPrefix(didDoc.AlsoKnownAs[0], "at://") - - return handle, pds, nil -} - -func FetchAppBskyActorProfile(conf *Config, did, pdsURL string, session *auth.OAuthState) (*notes.Author, error) { - // construct profile record URI - uri := fmt.Sprintf("at://%s/app.bsky.actor.profile/self", did) - - // try slingshot first - if conf.SlingshotURL != "" && general.SlingshotAvailable() { - rawRecord, err := general.FetchRawRecordByURI(conf.Logger, uri, conf.SlingshotURL, session) - if err != nil { - conf.Logger.Warn("slingshot profile fetch failed", "did", did, "error", err) - general.SetSlingshotBackoff(5 * time.Minute) - } else { - return parseAppBskyActorProfile(did, pdsURL, rawRecord, conf.Cache) - } - } - - // fallback to PDS - rawRecord, err := general.FetchRawRecordByURI(conf.Logger, uri, pdsURL, session) - if err != nil { - return nil, err - } - - return parseAppBskyActorProfile(did, pdsURL, rawRecord, conf.Cache) -} - -func FetchAppBskyActorProfiles(conf *Config, dids []string, pdsURL string, session *auth.OAuthState) map[string]notes.Author { - authors := make(map[string]notes.Author) - for _, did := range dids { - author, err := FetchAppBskyActorProfile(conf, did, pdsURL, session) - if err == nil { - authors[did] = *author - } - } - return authors -} - -func parseAppBskyActorProfile(did, pds string, rawRecord *general.RawRecord, cache *Cache) (*notes.Author, error) { - var profile notes.AppBskyActorProfileRecord - if err := json.Unmarshal(rawRecord.Value, &profile); err != nil { - return nil, err - } - - handle, err := FetchHandle(did) - if err != nil { - handle = "handle.invalid" - } - - author, err := notes.AuthorFromAppBskyActorProfileRecord(profile, did, handle, pds) - - cache.SetAuthor(did, author) - return author, nil -} |
