This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / appview / migration / migrate_add_repo_did.go
5.8 kB 194 lines
1package migration 2 3import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "strings" 8 9 comatproto "github.com/bluesky-social/indigo/api/atproto" 10 "github.com/bluesky-social/indigo/atproto/atclient" 11 "github.com/bluesky-social/indigo/atproto/syntax" 12 lexutil "github.com/bluesky-social/indigo/lex/util" 13 "tangled.org/core/api/tangled" 14 "tangled.org/core/appview/db" 15) 16 17func (s *Migration) migrateAddRepoDid(ctx context.Context, client *atclient.APIClient, did syntax.DID, record syntax.ATURI) error { 18 if record.Collection().String() == tangled.FeedStarNSID { 19 return s.migrateAddRepoDidStar(ctx, client, did, record) 20 } 21 22 ex, err := comatproto.RepoGetRecord(ctx, client, "", record.Collection().String(), did.String(), record.RecordKey().String()) 23 if err != nil { 24 return fmt.Errorf("pds: %w", err) 25 } 26 27 val := ex.Value.Val 28 29 switch record.Collection().String() { 30 case tangled.RepoNSID: 31 rec, ok := val.(*tangled.Repo) 32 if !ok { 33 return fmt.Errorf("unexpected type for repo record") 34 } 35 repo, err := db.GetRepoByAtUri(s.db, record.String()) 36 if err != nil { 37 return fmt.Errorf("db: failed to query repo: %w", err) 38 } 39 rec.RepoDid = &repo.RepoDid 40 41 case tangled.RepoIssueNSID: 42 rec, ok := val.(*tangled.RepoIssue) 43 if !ok { 44 return fmt.Errorf("unexpected type for issue record") 45 } 46 if strings.HasPrefix(rec.Repo, "did:") { 47 return nil 48 } 49 repo, err := db.GetRepoByAtUri(s.db, rec.Repo) 50 if err != nil { 51 return fmt.Errorf("db: failed to query repo by at_uri %q: %w", rec.Repo, err) 52 } 53 rec.Repo = repo.RepoDid 54 55 case tangled.RepoPullNSID: 56 rec, ok := val.(*tangled.RepoPull) 57 if !ok { 58 return fmt.Errorf("unexpected type for pull record") 59 } 60 if rec.Target == nil { 61 return fmt.Errorf("pull record has nil target") 62 } 63 if !strings.HasPrefix(rec.Target.Repo, "did:") { 64 repo, err := db.GetRepoByAtUri(s.db, rec.Target.Repo) 65 if err != nil { 66 return fmt.Errorf("db: failed to query target repo by at_uri %q: %w", rec.Target.Repo, err) 67 } 68 rec.Target.Repo = repo.RepoDid 69 } 70 if rec.Source != nil && rec.Source.Repo != nil && !strings.HasPrefix(*rec.Source.Repo, "did:") { 71 sourceRepo, srcErr := db.GetRepoByAtUri(s.db, *rec.Source.Repo) 72 if srcErr == nil && sourceRepo.RepoDid != "" { 73 rec.Source.Repo = &sourceRepo.RepoDid 74 } 75 } 76 77 case tangled.RepoCollaboratorNSID: 78 rec, ok := val.(*tangled.RepoCollaborator) 79 if !ok { 80 return fmt.Errorf("unexpected type for collaborator record") 81 } 82 if strings.HasPrefix(rec.Repo, "did:") { 83 return nil 84 } 85 repo, err := db.GetRepoByAtUri(s.db, rec.Repo) 86 if err != nil { 87 return fmt.Errorf("db: failed to query repo by at_uri %q: %w", rec.Repo, err) 88 } 89 rec.Repo = repo.RepoDid 90 91 case tangled.RepoArtifactNSID: 92 rec, ok := val.(*tangled.RepoArtifact) 93 if !ok { 94 return fmt.Errorf("unexpected type for artifact record") 95 } 96 if rec.Repo != nil { 97 repo, err := db.GetRepoByAtUri(s.db, *rec.Repo) 98 if err != nil { 99 return fmt.Errorf("db: failed to query repo by at_uri %q: %w", *rec.Repo, err) 100 } 101 rec.RepoDid = &repo.RepoDid 102 } 103 104 case tangled.ActorProfileNSID: 105 rec, ok := val.(*tangled.ActorProfile) 106 if !ok { 107 return fmt.Errorf("unexpected type for profile record") 108 } 109 rewritten := make([]string, 0, len(rec.PinnedRepositories)) 110 for _, pin := range rec.PinnedRepositories { 111 if strings.HasPrefix(pin, "did:") { 112 rewritten = append(rewritten, pin) 113 continue 114 } 115 repo, repoErr := db.GetRepoByAtUri(s.db, pin) 116 if repoErr != nil || repo.RepoDid == "" { 117 rewritten = append(rewritten, pin) 118 continue 119 } 120 rewritten = append(rewritten, repo.RepoDid) 121 } 122 rec.PinnedRepositories = rewritten 123 124 default: 125 return fmt.Errorf("unexpected collection: '%s'", record.Collection()) 126 } 127 128 _, err = comatproto.RepoPutRecord(ctx, client, &comatproto.RepoPutRecord_Input{ 129 Repo: did.String(), 130 Collection: record.Collection().String(), 131 Rkey: record.RecordKey().String(), 132 SwapRecord: ex.Cid, 133 Record: &lexutil.LexiconTypeDecoder{Val: val}, 134 }) 135 if err != nil { 136 return fmt.Errorf("put record: %w", err) 137 } 138 139 return nil 140} 141 142func (s *Migration) migrateAddRepoDidStar(ctx context.Context, client *atclient.APIClient, did syntax.DID, record syntax.ATURI) error { 143 var raw struct { 144 Cid *string `json:"cid,omitempty"` 145 Uri string `json:"uri"` 146 Value json.RawMessage `json:"value"` 147 } 148 params := map[string]any{ 149 "collection": record.Collection().String(), 150 "repo": did.String(), 151 "rkey": record.RecordKey().String(), 152 } 153 if err := client.LexDo(ctx, lexutil.Query, "", "com.atproto.repo.getRecord", params, nil, &raw); err != nil { 154 return fmt.Errorf("get record: %w", err) 155 } 156 157 var legacy struct { 158 CreatedAt string `json:"createdAt"` 159 Subject *string `json:"subject,omitempty"` 160 } 161 if err := json.Unmarshal(raw.Value, &legacy); err != nil { 162 return fmt.Errorf("decode old star fields: %w", err) 163 } 164 if legacy.Subject == nil { 165 return fmt.Errorf("star record has no subject field") 166 } 167 168 repo, err := db.GetRepoByAtUri(s.db, *legacy.Subject) 169 if err != nil { 170 return fmt.Errorf("db: failed to query repo by at_uri %q: %w", *legacy.Subject, err) 171 } 172 if repo.RepoDid == "" { 173 return fmt.Errorf("repo has no repoDid: %s", *legacy.Subject) 174 } 175 176 newRecord := &tangled.FeedStar{ 177 CreatedAt: legacy.CreatedAt, 178 Subject: &tangled.FeedStar_Subject{ 179 FeedStar_Repo: &tangled.FeedStar_Repo{Did: repo.RepoDid}, 180 }, 181 } 182 183 _, err = comatproto.RepoPutRecord(ctx, client, &comatproto.RepoPutRecord_Input{ 184 Repo: did.String(), 185 Collection: record.Collection().String(), 186 Rkey: record.RecordKey().String(), 187 SwapRecord: raw.Cid, 188 Record: &lexutil.LexiconTypeDecoder{Val: newRecord}, 189 }) 190 if err != nil { 191 return fmt.Errorf("put record: %w", err) 192 } 193 return nil 194}