A vibe coded tangled fork which supports pijul.
at master 104 lines 3.2 kB view raw
1package xrpc 2 3import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "strings" 8 9 "github.com/bluesky-social/indigo/api/atproto" 10 "github.com/bluesky-social/indigo/atproto/atclient" 11 "github.com/bluesky-social/indigo/atproto/syntax" 12 "github.com/bluesky-social/indigo/xrpc" 13 "tangled.org/core/api/tangled" 14 "tangled.org/core/knotmirror/db" 15 "tangled.org/core/knotmirror/hostutil" 16 "tangled.org/core/knotmirror/models" 17) 18 19func (x *Xrpc) RequestCrawl(w http.ResponseWriter, r *http.Request) { 20 var input tangled.SyncRequestCrawl_Input 21 if err := json.NewDecoder(r.Body).Decode(&input); err != nil { 22 writeJson(w, http.StatusBadRequest, atclient.ErrorBody{Name: "BadRequest", Message: "failed to decode json body"}) 23 return 24 } 25 26 ctx := r.Context() 27 28 l := x.logger.With("input", input) 29 30 hostname, noSSL, err := hostutil.ParseHostname(input.Hostname) 31 if err != nil { 32 l.Error("invalid hostname", "err", err) 33 writeJson(w, http.StatusBadRequest, atclient.ErrorBody{Name: "BadRequest", Message: fmt.Sprintf("hostname field empty or invalid: %s", input.Hostname)}) 34 return 35 } 36 37 // TODO: check if host is Knot with knot.describeServer 38 39 // store given repoAt to db 40 // this will allow knotmirror to ingest repo creation event bypassing tap. 41 // this step won't be needed once we introduce did-for-repo 42 // TODO(boltless): remove this section 43 if input.EnsureRepo != nil { 44 repoAt, err := syntax.ParseATURI(*input.EnsureRepo) 45 if err != nil { 46 l.Error("invalid repo at-uri", "err", err) 47 writeJson(w, http.StatusBadRequest, atclient.ErrorBody{Name: "BadRequest", Message: fmt.Sprintf("repo parameter invalid: %s", *input.EnsureRepo)}) 48 return 49 } 50 owner, err := x.resolver.ResolveIdent(ctx, repoAt.Authority().String()) 51 if err != nil || owner.Handle.IsInvalidHandle() { 52 l.Error("failed to resolve ident", "err", err, "owner", repoAt.Authority().String()) 53 writeErr(w, fmt.Errorf("failed to resolve repo owner")) 54 return 55 } 56 xrpcc := xrpc.Client{Host: owner.PDSEndpoint()} 57 out, err := atproto.RepoGetRecord(ctx, &xrpcc, "", tangled.RepoNSID, repoAt.Authority().String(), repoAt.RecordKey().String()) 58 if err != nil { 59 l.Error("failed to get repo record", "err", err, "repo", repoAt) 60 writeErr(w, fmt.Errorf("failed to get repo record")) 61 return 62 } 63 record := out.Value.Val.(*tangled.Repo) 64 65 knotUrl := record.Knot 66 if !strings.Contains(record.Knot, "://") { 67 if noSSL { 68 knotUrl = "http://" + knotUrl 69 } else { 70 knotUrl = "https://" + knotUrl 71 } 72 } 73 74 repo := &models.Repo{ 75 Did: owner.DID, 76 Rkey: repoAt.RecordKey(), 77 Cid: (*syntax.CID)(out.Cid), 78 Name: record.Name, 79 KnotDomain: knotUrl, 80 State: models.RepoStatePending, 81 ErrorMsg: "", 82 RetryAfter: 0, 83 RetryCount: 0, 84 } 85 86 if err := db.UpsertRepo(ctx, x.db, repo); err != nil { 87 l.Error("failed to upsert repo", "err", err) 88 writeErr(w, err) 89 return 90 } 91 } 92 93 // subscribe to requested host 94 if !x.ks.CheckIfSubscribed(hostname) { 95 if err := x.ks.SubscribeHost(ctx, hostname, noSSL); err != nil { 96 // TODO(boltless): return HostBanned on banned hosts 97 l.Error("failed to subscribe host", "err", err) 98 writeErr(w, err) 99 return 100 } 101 } 102 103 w.WriteHeader(http.StatusOK) 104}