this repo has no description
1package main
2
3import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "io"
8 "net"
9 "net/http"
10 "strings"
11
12 "github.com/bluesky-social/indigo/atproto/syntax"
13)
14
15func resolveHandle(ctx context.Context, handle string) (string, error) {
16 var did string
17
18 _, err := syntax.ParseHandle(handle)
19 if err != nil {
20 return "", err
21 }
22
23 recs, err := net.LookupTXT(fmt.Sprintf("_atproto.%s", handle))
24 if err == nil {
25 for _, rec := range recs {
26 if strings.HasPrefix(rec, "did=") {
27 did = strings.Split(rec, "did=")[1]
28 break
29 }
30 }
31 }
32
33 if did == "" {
34 req, err := http.NewRequestWithContext(
35 ctx,
36 "GET",
37 fmt.Sprintf("https://%s/.well-known/atproto-did", handle),
38 nil,
39 )
40 if err != nil {
41 return "", err
42 }
43
44 resp, err := http.DefaultClient.Do(req)
45 if err != nil {
46 return "", err
47 }
48 defer resp.Body.Close()
49
50 if resp.StatusCode != http.StatusOK {
51 io.Copy(io.Discard, resp.Body)
52 return "", fmt.Errorf("unable to resolve handle")
53 }
54
55 b, err := io.ReadAll(resp.Body)
56 if err != nil {
57 return "", err
58 }
59
60 maybeDid := string(b)
61
62 if _, err := syntax.ParseDID(maybeDid); err != nil {
63 return "", fmt.Errorf("unable to resolve handle")
64 }
65
66 did = maybeDid
67 }
68
69 return did, nil
70}
71
72func resolveService(ctx context.Context, did string) (string, error) {
73 type Identity struct {
74 Service []struct {
75 ID string `json:"id"`
76 Type string `json:"type"`
77 ServiceEndpoint string `json:"serviceEndpoint"`
78 } `json:"service"`
79 }
80
81 var ustr string
82 if strings.HasPrefix(did, "did:plc:") {
83 ustr = fmt.Sprintf("https://plc.directory/%s", did)
84 } else if strings.HasPrefix(did, "did:web:") {
85 ustr = fmt.Sprintf("https://%s/.well-known/did.json", strings.TrimPrefix(did, "did:web:"))
86 } else {
87 return "", fmt.Errorf("did was not a supported did type")
88 }
89
90 req, err := http.NewRequestWithContext(ctx, "GET", ustr, nil)
91 if err != nil {
92 return "", err
93 }
94
95 resp, err := http.DefaultClient.Do(req)
96 if err != nil {
97 return "", err
98 }
99 defer resp.Body.Close()
100
101 if resp.StatusCode != 200 {
102 io.Copy(io.Discard, resp.Body)
103 return "", fmt.Errorf("could not find identity in plc registry")
104 }
105
106 var identity Identity
107 if err := json.NewDecoder(resp.Body).Decode(&identity); err != nil {
108 return "", err
109 }
110
111 var service string
112 for _, svc := range identity.Service {
113 if svc.ID == "#atproto_pds" {
114 service = svc.ServiceEndpoint
115 }
116 }
117
118 if service == "" {
119 return "", fmt.Errorf("could not find atproto_pds service in identity services")
120 }
121
122 return service, nil
123}