aboutsummaryrefslogtreecommitdiff
path: root/backend/fetchers/app.bsky.actor.go
diff options
context:
space:
mode:
authorGuillermo Serrahima <dev@vylion.com>2026-04-11 07:40:30 +0200
committerGuillermo Serrahima <dev@vylion.com>2026-04-11 23:39:19 +0200
commit9f0a9a6779f00786e4728ad5c3fad36814a293b0 (patch)
tree4b16d535c5d41ef46980608a88b7581be3c2bfd0 /backend/fetchers/app.bsky.actor.go
parentf6d60077b7cfc0d589fa7961e2bb59aea9f993a3 (diff)
downloadllostre-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.go184
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
-}