this repo has no description
1package photocopy 2 3import ( 4 "context" 5 "fmt" 6 "time" 7 8 "github.com/araddon/dateparse" 9 "github.com/bluesky-social/indigo/api/bsky" 10 "github.com/bluesky-social/indigo/atproto/syntax" 11) 12 13func (p *Photocopy) handleCreate(ctx context.Context, recb []byte, indexedAt, rev, did, collection, rkey, cid string) error { 14 _, err := dateparse.ParseAny(indexedAt) 15 if err != nil { 16 return err 17 } 18 19 switch collection { 20 } 21 22 return nil 23} 24 25// func (p *Photocopy) handleCreatePost(ctx context.Context, rev string, recb []byte, uri, did, collection, rkey, cid string, indexedAt time.Time) error { 26// var rec bsky.FeedPost 27// if err := rec.UnmarshalCBOR(bytes.NewReader(recb)); err != nil { 28// return err 29// } 30// 31// jb, err := json.Marshal(rec) 32// if err != nil { 33// return err 34// } 35// 36// cat, err := parseTimeFromRecord(rec, rkey) 37// if err != nil { 38// return err 39// } 40// 41// bqrec := &BigQueryRecord{ 42// Uri: uri, 43// AuthorDid: did, 44// Collection: collection, 45// Rkey: rkey, 46// CreatedAt: *cat, 47// IndexedAt: indexedAt, 48// Raw: recb, 49// Json: string(jb), 50// Cid: cid, 51// Rev: rev, 52// } 53// 54// if rec.Reply != nil { 55// if rec.Reply.Parent != nil { 56// bqrec.ReplyToUri = rec.Reply.Parent.Uri 57// } 58// if rec.Reply.Root != nil { 59// bqrec.InThreadUri = rec.Reply.Root.Uri 60// } 61// } 62// 63// if err := p.inserters.genericInserter.Insert(ctx, bqrec); err != nil { 64// return err 65// } 66// 67// return nil 68// } 69 70// func (p *Photocopy) handleCreateFollow(ctx context.Context, recb []byte, uri, did, rkey string, indexedAt time.Time) error { 71// var rec bsky.GraphFollow 72// if err := rec.UnmarshalCBOR(bytes.NewReader(recb)); err != nil { 73// return err 74// } 75// 76// cat, err := parseTimeFromRecord(rec, rkey) 77// if err != nil { 78// return err 79// } 80// 81// bqrec := &BigQueryFollow{ 82// Uri: uri, 83// AuthorDid: did, 84// Rkey: rkey, 85// CreatedAt: *cat, 86// IndexedAt: indexedAt, 87// SubjectDid: rec.Subject, 88// } 89// 90// if err := p.inserters.followsInserter.Insert(ctx, bqrec); err != nil { 91// return err 92// } 93// 94// return nil 95// } 96// 97// func (p *Photocopy) handleCreateInteraction(ctx context.Context, recb []byte, uri, did, collection, rkey string, indexedAt time.Time) error { 98// colPts := strings.Split(collection, ".") 99// if len(colPts) < 4 { 100// return fmt.Errorf("invalid collection type %s", collection) 101// } 102// 103// bqi := &BigQueryInteraction{ 104// Uri: uri, 105// Kind: colPts[3], 106// AuthorDid: did, 107// Rkey: rkey, 108// IndexedAt: indexedAt, 109// } 110// 111// switch collection { 112// case "app.bsky.feed.like": 113// var rec bsky.FeedLike 114// if err := rec.UnmarshalCBOR(bytes.NewReader(recb)); err != nil { 115// return err 116// } 117// 118// cat, err := parseTimeFromRecord(rec, rkey) 119// if err != nil { 120// return err 121// } 122// 123// if rec.Subject == nil { 124// return fmt.Errorf("invalid subject in like") 125// } 126// 127// bqi.SubjectUri = rec.Subject.Uri 128// bqi.CreatedAt = *cat 129// case "app.bsky.feed.repost": 130// var rec bsky.FeedRepost 131// if err := rec.UnmarshalCBOR(bytes.NewReader(recb)); err != nil { 132// return err 133// } 134// 135// cat, err := parseTimeFromRecord(rec, rkey) 136// if err != nil { 137// return err 138// } 139// 140// if rec.Subject == nil { 141// return fmt.Errorf("invalid subject in repost") 142// } 143// 144// bqi.SubjectUri = rec.Subject.Uri 145// bqi.CreatedAt = *cat 146// } 147// 148// if err := p.inserters.interactionsInserter.Insert(ctx, bqi); err != nil { 149// return err 150// } 151// 152// return nil 153// } 154 155func parseTimeFromRecord(rec any, rkey string) (*time.Time, error) { 156 var rkeyTime time.Time 157 if rkey != "self" { 158 rt, err := syntax.ParseTID(rkey) 159 if err == nil { 160 rkeyTime = rt.Time() 161 } 162 } 163 switch rec := rec.(type) { 164 case *bsky.FeedPost: 165 t, err := dateparse.ParseAny(rec.CreatedAt) 166 if err != nil { 167 return nil, err 168 } 169 170 if inRange(t) { 171 return &t, nil 172 } 173 174 if rkeyTime.IsZero() || !inRange(rkeyTime) { 175 return timePtr(time.Now()), nil 176 } 177 178 return &rkeyTime, nil 179 case *bsky.FeedRepost: 180 t, err := dateparse.ParseAny(rec.CreatedAt) 181 if err != nil { 182 return nil, err 183 } 184 185 if inRange(t) { 186 return timePtr(t), nil 187 } 188 189 if rkeyTime.IsZero() { 190 return nil, fmt.Errorf("failed to get a useful timestamp from record") 191 } 192 193 return &rkeyTime, nil 194 case *bsky.FeedLike: 195 t, err := dateparse.ParseAny(rec.CreatedAt) 196 if err != nil { 197 return nil, err 198 } 199 200 if inRange(t) { 201 return timePtr(t), nil 202 } 203 204 if rkeyTime.IsZero() { 205 return nil, fmt.Errorf("failed to get a useful timestamp from record") 206 } 207 208 return &rkeyTime, nil 209 case *bsky.ActorProfile: 210 // We can't really trust the createdat in the profile record anyway, and its very possible its missing. just use iat for this one 211 return timePtr(time.Now()), nil 212 case *bsky.FeedGenerator: 213 if !rkeyTime.IsZero() && inRange(rkeyTime) { 214 return &rkeyTime, nil 215 } 216 return timePtr(time.Now()), nil 217 default: 218 if !rkeyTime.IsZero() && inRange(rkeyTime) { 219 return &rkeyTime, nil 220 } 221 return timePtr(time.Now()), nil 222 } 223} 224 225func inRange(t time.Time) bool { 226 now := time.Now() 227 if t.Before(now) { 228 return now.Sub(t) <= time.Hour*24*365*5 229 } 230 return t.Sub(now) <= time.Hour*24*200 231} 232 233func timePtr(t time.Time) *time.Time { 234 return &t 235}