Live video on the AT Protocol
at eli/windows-selftest-github 140 lines 4.4 kB view raw
1package model 2 3import ( 4 "context" 5 "errors" 6 "fmt" 7 "time" 8 9 "github.com/bluesky-social/indigo/api/bsky" 10 lexutil "github.com/bluesky-social/indigo/lex/util" 11 "gorm.io/gorm" 12) 13 14type FeedPost struct { 15 CID string `json:"cid" gorm:"primaryKey;column:cid"` 16 URI string `json:"uri"` 17 CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;index:recent_replies"` 18 FeedPost *[]byte `json:"feedPost"` 19 RepoDID string `json:"repoDID" gorm:"column:repo_did"` 20 Repo *Repo `json:"repo,omitempty" gorm:"foreignKey:DID;references:RepoDID"` 21 Type string `json:"type" gorm:"column:type"` 22 ReplyRootCID *string `json:"replyRootCID,omitempty" gorm:"column:reply_root_cid"` 23 ReplyRoot *FeedPost `json:"replyRoot,omitempty" gorm:"foreignKey:cid;references:ReplyRootCID"` 24 ReplyRootRepoDID *string `json:"replyRootRepoDID,omitempty" gorm:"column:reply_root_repo_did;index:recent_replies"` 25 ReplyRootRepo *Repo `json:"replyRootRepo,omitempty" gorm:"foreignKey:DID;references:ReplyRootRepoDID"` 26 IndexedAt *time.Time `json:"indexedAt,omitempty" gorm:"column:indexed_at"` 27} 28 29func (fp *FeedPost) ToBskyPostView() (*bsky.FeedDefs_PostView, error) { 30 rec, err := lexutil.CborDecodeValue(*fp.FeedPost) 31 if err != nil { 32 return nil, fmt.Errorf("error decoding feed post: %w", err) 33 } 34 postView := bsky.FeedDefs_PostView{ 35 LexiconTypeID: "app.bsky.feed.defs#postView", 36 Cid: fp.CID, 37 Uri: fp.URI, 38 Author: &bsky.ActorDefs_ProfileViewBasic{ 39 Did: fp.RepoDID, 40 Handle: fp.Repo.Handle, 41 }, 42 Record: &lexutil.LexiconTypeDecoder{Val: rec}, 43 IndexedAt: fp.IndexedAt.UTC().Format(time.RFC3339Nano), 44 } 45 return &postView, nil 46} 47 48func (m *DBModel) CreateFeedPost(ctx context.Context, post *FeedPost) error { 49 return m.DB.Create(post).Error 50} 51 52func (m *DBModel) ListFeedPosts() ([]FeedPost, error) { 53 posts := []FeedPost{} 54 err := m.DB.Find(&posts).Error 55 if err != nil { 56 return nil, fmt.Errorf("error retrieving chat posts: %w", err) 57 } 58 return posts, nil 59} 60func (m *DBModel) ListFeedPostsByType(feedType string, limit int, after int64) ([]FeedPost, error) { 61 if after == 0 { 62 after = time.Now().Add(48 * time.Hour).UnixMilli() 63 } 64 time := time.UnixMilli(after) 65 posts := []FeedPost{} 66 // exclude scumb.ag for now (so my dev streams don't show up) 67 err := m.DB.Where("type = ? AND created_at < ? AND repo_did != ?", feedType, time.UTC(), "did:plc:dkh4rwafdcda4ko7lewe43ml"). 68 Order("created_at DESC"). 69 Group("uri"). 70 Limit(limit). 71 Find(&posts).Error 72 if err != nil { 73 return nil, fmt.Errorf("error retrieving feed posts: %w", err) 74 } 75 return posts, nil 76} 77 78func (m *DBModel) GetFeedPost(cid string) (*FeedPost, error) { 79 post := FeedPost{} 80 err := m.DB.Where("CID = ?", cid).First(&post).Error 81 if errors.Is(err, gorm.ErrRecordNotFound) { 82 return nil, nil 83 } 84 if err != nil { 85 return nil, fmt.Errorf("error retrieving feed post: %w", err) 86 } 87 return &post, nil 88} 89 90func (m *DBModel) GetReplies(repoDID string) ([]*bsky.FeedDefs_PostView, error) { 91 posts := []FeedPost{} 92 err := m.DB. 93 Preload("Repo"). 94 Where("reply_root_repo_did = ? AND type = ?", repoDID, "reply"). 95 Limit(100). 96 Order("created_at DESC"). 97 Find(&posts).Error 98 if err != nil { 99 return nil, fmt.Errorf("error retrieving replies: %w", err) 100 } 101 bskyPosts := []*bsky.FeedDefs_PostView{} 102 for _, post := range posts { 103 bskyPost, err := post.ToBskyPostView() 104 if err != nil { 105 return nil, fmt.Errorf("error converting feed post to bsky post view: %w", err) 106 } 107 bskyPosts = append(bskyPosts, bskyPost) 108 } 109 return bskyPosts, nil 110} 111 112type StreamplaceFeedPostLivestream struct { 113 URL string `json:"url"` 114 Title string `json:"title"` 115} 116 117func (m *DBModel) GetLatestLivestream(repoDID string) (*bsky.FeedDefs_PostView, error) { 118 posts := []FeedPost{} 119 err := m.DB. 120 Preload("Repo"). 121 Where("type = ?", "livestream"). 122 Where("repo_did = ?", repoDID). 123 Limit(1). 124 Order("created_at DESC"). 125 Find(&posts).Error 126 if err != nil { 127 return nil, fmt.Errorf("error retrieving livestream: %w", err) 128 } 129 130 if len(posts) == 0 { 131 return nil, nil 132 } 133 134 view, err := posts[0].ToBskyPostView() 135 if err != nil { 136 return nil, fmt.Errorf("error converting feed post to bsky post view: %w", err) 137 } 138 139 return view, nil 140}