this repo has no description
0
fork

Configure Feed

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

at main 115 lines 3.3 kB view raw
1package main 2 3import ( 4 "context" 5 "fmt" 6 "log/slog" 7 "strconv" 8 "strings" 9 10 "github.com/willdot/bskyfeedgen/store" 11) 12 13type repliesStore interface { 14 GetUsersReplies(usersDID string, cursor int64, limit int) ([]store.ReplyPost, error) 15 GetBookmarksForUserWithPaging(userDID string, cursor int64, limit int) ([]store.Bookmark, error) 16 AddRepliedPost(replyPost store.ReplyPost) error 17} 18 19type FeedGenerator struct { 20 store repliesStore 21} 22 23func NewFeedGenerator(store repliesStore) *FeedGenerator { 24 return &FeedGenerator{ 25 store: store, 26 } 27} 28 29func (f *FeedGenerator) GetFeed(ctx context.Context, userDID, feed, cursor string, limit int) (FeedReponse, error) { 30 switch { 31 case strings.Contains(feed, "bookmark-replies"): 32 return f.getBookmarkRepliesFeed(ctx, userDID, cursor, limit) 33 case strings.Contains(feed, "bookmarks"): 34 return f.getBookmarksFeed(ctx, userDID, cursor, limit) 35 36 default: 37 return FeedReponse{ 38 Feed: make([]FeedItem, 0), 39 }, fmt.Errorf("invalid feed requested") 40 } 41} 42 43func (f *FeedGenerator) getBookmarkRepliesFeed(ctx context.Context, userDID, cursor string, limit int) (FeedReponse, error) { 44 resp := FeedReponse{ 45 Feed: make([]FeedItem, 0), 46 } 47 48 cursorInt, err := strconv.Atoi(cursor) 49 if err != nil && cursor != "" { 50 slog.Error("convert cursor to int", "error", err, "cursor value", cursor) 51 } 52 if cursorInt == 0 { 53 // if no cursor provided use a date waaaaay in the future to start the less than query 54 cursorInt = 9999999999999 55 } 56 57 usersReplies, err := f.store.GetUsersReplies(userDID, int64(cursorInt), limit) 58 if err != nil { 59 return resp, fmt.Errorf("get users replies from DB: %w", err) 60 } 61 62 feedItems := make([]FeedItem, 0, len(usersReplies)) 63 for _, post := range usersReplies { 64 feedItems = append(feedItems, FeedItem{ 65 Post: post.ReplyURI, 66 }) 67 } 68 69 resp.Feed = feedItems 70 71 // only set the return cursor if there was a record returned and that the len of records 72 // being returned is the same as the limit 73 if len(usersReplies) > 0 && len(usersReplies) == limit { 74 lastFeedItem := usersReplies[len(usersReplies)-1] 75 resp.Cursor = fmt.Sprintf("%d", lastFeedItem.CreatedAt) 76 } 77 return resp, nil 78} 79 80func (f *FeedGenerator) getBookmarksFeed(ctx context.Context, userDID, cursor string, limit int) (FeedReponse, error) { 81 resp := FeedReponse{ 82 Feed: make([]FeedItem, 0), 83 } 84 85 cursorInt, err := strconv.Atoi(cursor) 86 if err != nil && cursor != "" { 87 slog.Error("convert cursor to int", "error", err, "cursor value", cursor) 88 } 89 if cursorInt == 0 { 90 // if no cursor provided use a date waaaaay in the future to start the less than query 91 cursorInt = 9999999999999 92 } 93 94 usersBookmarks, err := f.store.GetBookmarksForUserWithPaging(userDID, int64(cursorInt), limit) 95 if err != nil { 96 return resp, fmt.Errorf("get users bookmarks from DB: %w", err) 97 } 98 99 feedItems := make([]FeedItem, 0, len(usersBookmarks)) 100 for _, bookmark := range usersBookmarks { 101 feedItems = append(feedItems, FeedItem{ 102 Post: bookmark.PostATURI, 103 }) 104 } 105 106 resp.Feed = feedItems 107 108 // only set the return cursor if there was a record returned and that the len of records 109 // being returned is the same as the limit 110 if len(usersBookmarks) > 0 && len(usersBookmarks) == limit { 111 lastFeedItem := usersBookmarks[len(usersBookmarks)-1] 112 resp.Cursor = fmt.Sprintf("%d", lastFeedItem.CreatedAt) 113 } 114 return resp, nil 115}