Live video on the AT Protocol
79
fork

Configure Feed

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

at v0.8.5 142 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 URI string `json:"uri" gorm:"primaryKey;column:uri"` 16 CID string `json:"cid" gorm:"column:cid"` 17 CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;index:recent_replies"` 18 FeedPost *[]byte `json:"feedPost" gorm:"column:feed_post"` 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 ReplyRootURI *string `json:"replyRootURI,omitempty" gorm:"column:reply_root_uri"` 23 ReplyRoot *FeedPost `json:"replyRoot,omitempty" gorm:"foreignKey:uri;references:ReplyRootURI"` 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 }, 41 Record: &lexutil.LexiconTypeDecoder{Val: rec}, 42 IndexedAt: fp.IndexedAt.UTC().Format(time.RFC3339Nano), 43 } 44 if fp.Repo != nil { 45 postView.Author.Handle = fp.Repo.Handle 46 } 47 return &postView, nil 48} 49 50func (m *DBModel) CreateFeedPost(ctx context.Context, post *FeedPost) error { 51 return m.DB.Create(post).Error 52} 53 54func (m *DBModel) ListFeedPosts() ([]FeedPost, error) { 55 posts := []FeedPost{} 56 err := m.DB.Find(&posts).Error 57 if err != nil { 58 return nil, fmt.Errorf("error retrieving chat posts: %w", err) 59 } 60 return posts, nil 61} 62func (m *DBModel) ListFeedPostsByType(feedType string, limit int, after int64) ([]FeedPost, error) { 63 if after == 0 { 64 after = time.Now().Add(48 * time.Hour).UnixMilli() 65 } 66 time := time.UnixMilli(after) 67 posts := []FeedPost{} 68 // exclude scumb.ag for now (so my dev streams don't show up) 69 err := m.DB.Where("type = ? AND created_at < ? AND repo_did != ?", feedType, time.UTC(), "did:plc:dkh4rwafdcda4ko7lewe43ml"). 70 Order("created_at DESC"). 71 Group("uri"). 72 Limit(limit). 73 Find(&posts).Error 74 if err != nil { 75 return nil, fmt.Errorf("error retrieving feed posts: %w", err) 76 } 77 return posts, nil 78} 79 80func (m *DBModel) GetFeedPost(uri string) (*FeedPost, error) { 81 post := FeedPost{} 82 err := m.DB.Where("uri = ?", uri).First(&post).Error 83 if errors.Is(err, gorm.ErrRecordNotFound) { 84 return nil, nil 85 } 86 if err != nil { 87 return nil, fmt.Errorf("error retrieving feed post: %w", err) 88 } 89 return &post, nil 90} 91 92func (m *DBModel) GetReplies(repoDID string) ([]*bsky.FeedDefs_PostView, error) { 93 posts := []FeedPost{} 94 err := m.DB. 95 Preload("Repo"). 96 Where("reply_root_repo_did = ? AND type = ?", repoDID, "reply"). 97 Limit(100). 98 Order("created_at DESC"). 99 Find(&posts).Error 100 if err != nil { 101 return nil, fmt.Errorf("error retrieving replies: %w", err) 102 } 103 bskyPosts := []*bsky.FeedDefs_PostView{} 104 for _, post := range posts { 105 bskyPost, err := post.ToBskyPostView() 106 if err != nil { 107 return nil, fmt.Errorf("error converting feed post to bsky post view: %w", err) 108 } 109 bskyPosts = append(bskyPosts, bskyPost) 110 } 111 return bskyPosts, nil 112} 113 114type StreamplaceFeedPostLivestream struct { 115 URL string `json:"url"` 116 Title string `json:"title"` 117} 118 119func (m *DBModel) GetLatestLivestream(repoDID string) (*bsky.FeedDefs_PostView, error) { 120 posts := []FeedPost{} 121 err := m.DB. 122 Preload("Repo"). 123 Where("type = ?", "livestream"). 124 Where("repo_did = ?", repoDID). 125 Limit(1). 126 Order("created_at DESC"). 127 Find(&posts).Error 128 if err != nil { 129 return nil, fmt.Errorf("error retrieving livestream: %w", err) 130 } 131 132 if len(posts) == 0 { 133 return nil, nil 134 } 135 136 view, err := posts[0].ToBskyPostView() 137 if err != nil { 138 return nil, fmt.Errorf("error converting feed post to bsky post view: %w", err) 139 } 140 141 return view, nil 142}