Live video on the AT Protocol
at eli/lexicon-dev 69 lines 2.3 kB view raw
1package model 2 3import ( 4 "context" 5 "errors" 6 "fmt" 7 8 "github.com/bluesky-social/indigo/api/bsky" 9 "github.com/bluesky-social/indigo/atproto/syntax" 10 lexutil "github.com/bluesky-social/indigo/lex/util" 11 "gorm.io/gorm" 12 "gorm.io/gorm/clause" 13 "stream.place/streamplace/pkg/spid" 14) 15 16type BskyProfile struct { 17 URI string `json:"uri" gorm:"primaryKey;column:uri"` 18 CID string `json:"cid" gorm:"column:cid"` 19 RepoDID string `json:"repoDID" gorm:"column:repo_did"` 20 Repo *Repo `json:"repo,omitempty" gorm:"foreignKey:DID;references:RepoDID"` 21 Record *[]byte `json:"record" gorm:"column:record"` 22 WasStreamplace bool `json:"wasStreamplace" gorm:"primaryKey;column:was_streamplace"` 23} 24 25func (m *DBModel) UpsertBskyProfile(ctx context.Context, aturi syntax.ATURI, recBs []byte, wasStreamplace bool) error { 26 cid, err := spid.GetCIDFromBytes(recBs) 27 if err != nil { 28 return fmt.Errorf("failed to get cid: %w", err) 29 } 30 dbProfile := &BskyProfile{ 31 URI: aturi.String(), 32 CID: cid.String(), 33 RepoDID: aturi.Authority().String(), 34 Record: &recBs, 35 WasStreamplace: wasStreamplace, 36 } 37 38 // Use GORM's OnConflict to handle unique/primary conflicts 39 // If a conflict (same PK), then update the relevant fields 40 return m.DB. 41 Clauses( 42 // Conflict columns: uri, was_streamplace (matching primaryKey in struct) 43 clause.OnConflict{ 44 Columns: []clause.Column{{Name: "uri"}, {Name: "was_streamplace"}}, 45 DoUpdates: clause.AssignmentColumns([]string{"cid", "repo_did", "record"}), 46 }, 47 ). 48 Create(dbProfile).Error 49} 50 51func (m *DBModel) GetBskyProfile(ctx context.Context, did string, wasStreamplace bool) (*bsky.ActorProfile, error) { 52 var profile BskyProfile 53 err := m.DB.Where("uri = ? AND was_streamplace = ?", fmt.Sprintf("at://%s/app.bsky.actor.profile/self", did), wasStreamplace).First(&profile).Error 54 if errors.Is(err, gorm.ErrRecordNotFound) { 55 return nil, nil 56 } 57 if err != nil { 58 return nil, err 59 } 60 rec, err := lexutil.CborDecodeValue(*profile.Record) 61 if err != nil { 62 return nil, fmt.Errorf("failed to decode profile record: %w", err) 63 } 64 bskyProfile, ok := rec.(*bsky.ActorProfile) 65 if !ok { 66 return nil, fmt.Errorf("invalid profile record") 67 } 68 return bskyProfile, nil 69}