A locally focused bluesky appview
at master 3.2 kB view raw
1package views 2 3import ( 4 "fmt" 5 6 "github.com/bluesky-social/indigo/api/bsky" 7 "github.com/bluesky-social/indigo/lex/util" 8 "github.com/whyrusleeping/konbini/hydration" 9) 10 11// PostView builds a post view (app.bsky.feed.defs#postView) 12func PostView(post *hydration.PostInfo, author *hydration.ActorInfo) *bsky.FeedDefs_PostView { 13 view := &bsky.FeedDefs_PostView{ 14 LexiconTypeID: "app.bsky.feed.defs#postView", 15 Uri: post.URI, 16 Cid: post.Cid, 17 Author: ProfileViewBasic(author), 18 Record: &util.LexiconTypeDecoder{ 19 Val: post.Post, 20 }, 21 IndexedAt: post.Post.CreatedAt, // Using createdAt as indexedAt for now 22 } 23 24 // Add engagement counts 25 if post.LikeCount > 0 { 26 lc := int64(post.LikeCount) 27 view.LikeCount = &lc 28 } 29 if post.RepostCount > 0 { 30 rc := int64(post.RepostCount) 31 view.RepostCount = &rc 32 } 33 if post.ReplyCount > 0 { 34 rpc := int64(post.ReplyCount) 35 view.ReplyCount = &rpc 36 } 37 38 // Add viewer state 39 if post.ViewerLike != "" { 40 view.Viewer = &bsky.FeedDefs_ViewerState{ 41 Like: &post.ViewerLike, 42 } 43 } 44 45 // Add embed if it was hydrated 46 if post.EmbedInfo != nil { 47 view.Embed = post.EmbedInfo 48 } 49 50 return view 51} 52 53// FeedViewPost builds a feed view post (app.bsky.feed.defs#feedViewPost) 54func FeedViewPost(post *hydration.PostInfo, author *hydration.ActorInfo) *bsky.FeedDefs_FeedViewPost { 55 return &bsky.FeedDefs_FeedViewPost{ 56 Post: PostView(post, author), 57 } 58} 59 60// ThreadViewPost builds a thread view post (app.bsky.feed.defs#threadViewPost) 61func ThreadViewPost(post *hydration.PostInfo, author *hydration.ActorInfo, parent, replies any) *bsky.FeedDefs_ThreadViewPost { 62 view := &bsky.FeedDefs_ThreadViewPost{ 63 LexiconTypeID: "app.bsky.feed.defs#threadViewPost", 64 Post: PostView(post, author), 65 } 66 67 // TODO: Type parent and replies properly as union types 68 // For now leaving them as interface{} to be handled by handlers 69 70 return view 71} 72 73// GeneratorView builds a feed generator view (app.bsky.feed.defs#generatorView) 74func GeneratorView(uri, cid string, record *bsky.FeedGenerator, creator *hydration.ActorInfo, likeCount int64, viewerLike string, indexedAt string) *bsky.FeedDefs_GeneratorView { 75 view := &bsky.FeedDefs_GeneratorView{ 76 LexiconTypeID: "app.bsky.feed.defs#generatorView", 77 Uri: uri, 78 Cid: cid, 79 Did: record.Did, 80 Creator: ProfileView(creator), 81 DisplayName: record.DisplayName, 82 Description: record.Description, 83 IndexedAt: indexedAt, 84 } 85 86 // Add optional fields 87 if record.Avatar != nil { 88 avatarURL := fmt.Sprintf("https://cdn.bsky.app/img/avatar/plain/%s/%s@jpeg", creator.DID, record.Avatar.Ref.String()) 89 view.Avatar = &avatarURL 90 } 91 92 if record.DescriptionFacets != nil && len(record.DescriptionFacets) > 0 { 93 view.DescriptionFacets = record.DescriptionFacets 94 } 95 96 if record.AcceptsInteractions != nil { 97 view.AcceptsInteractions = record.AcceptsInteractions 98 } 99 100 if record.ContentMode != nil { 101 view.ContentMode = record.ContentMode 102 } 103 104 // Add like count if present 105 if likeCount > 0 { 106 view.LikeCount = &likeCount 107 } 108 109 // Add viewer state if viewer has liked 110 if viewerLike != "" { 111 view.Viewer = &bsky.FeedDefs_GeneratorViewerState{ 112 Like: &viewerLike, 113 } 114 } 115 116 return view 117}