this repo has no description
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}