A collection of Custom Bluesky Feeds, including Fresh Feeds, all under one roof
1package static
2
3import (
4 "context"
5 "fmt"
6 "strconv"
7
8 appbsky "github.com/bluesky-social/indigo/api/bsky"
9)
10
11type StaticFeed struct {
12 FeedActorDID string
13 FeedName string
14 StaticPostURIs []string
15}
16
17// NewStaticFeed returns a new StaticFeed, a list of aliases for the feed, and an error
18// StaticFeed is a trivial implementation of the Feed interface, so its aliases are just the input feedName
19func NewStaticFeed(ctx context.Context, feedActorDID string, feedName string, staticPostURIs []string) (*StaticFeed, []string, error) {
20 return &StaticFeed{
21 FeedActorDID: feedActorDID,
22 FeedName: feedName,
23 StaticPostURIs: staticPostURIs,
24 }, []string{feedName}, nil
25}
26
27// GetPage returns a list of FeedDefs_SkeletonFeedPost, a new cursor, and an error
28// It takes a feed name, a user DID, a limit, and a cursor
29// The feed name can be used to produce different feeds from the same feed generator
30func (sf *StaticFeed) GetPage(ctx context.Context, feed string, userDID string, limit int64, cursor string) ([]*appbsky.FeedDefs_SkeletonFeedPost, *string, error) {
31 cursorAsInt := int64(0)
32 var err error
33
34 if cursor != "" {
35 cursorAsInt, err = strconv.ParseInt(cursor, 10, 64)
36 if err != nil {
37 return nil, nil, fmt.Errorf("cursor is not an integer: %w", err)
38 }
39 }
40
41 posts := []*appbsky.FeedDefs_SkeletonFeedPost{}
42
43 for i, postURI := range sf.StaticPostURIs {
44 if int64(i) < cursorAsInt {
45 continue
46 }
47
48 if int64(len(posts)) >= limit {
49 break
50 }
51
52 posts = append(posts, &appbsky.FeedDefs_SkeletonFeedPost{
53 Post: postURI,
54 })
55 }
56
57 cursorAsInt += int64(len(posts))
58
59 var newCursor *string
60
61 if cursorAsInt < int64(len(sf.StaticPostURIs)) {
62 newCursor = new(string)
63 *newCursor = strconv.FormatInt(cursorAsInt, 10)
64 }
65
66 return posts, newCursor, nil
67}
68
69// Describe returns a list of FeedDescribeFeedGenerator_Feed, and an error
70// StaticFeed is a trivial implementation of the Feed interface, so it returns a single FeedDescribeFeedGenerator_Feed
71// For a more complicated feed, this function would return a list of FeedDescribeFeedGenerator_Feed with the URIs of aliases
72// supported by the feed
73func (sf *StaticFeed) Describe(ctx context.Context) ([]appbsky.FeedDescribeFeedGenerator_Feed, error) {
74 return []appbsky.FeedDescribeFeedGenerator_Feed{
75 {
76 Uri: "at://" + sf.FeedActorDID + "/app.bsky.feed.generator/" + sf.FeedName,
77 },
78 }, nil
79}