bluesky appview implementation using microcosm and other services server.reddwarf.app
appview bluesky reddwarf microcosm

very basic getposts

Changed files
+119
shims
lex
app
bsky
feed
+40
main.go
··· 18 18 "tangled.org/whey.party/red-dwarf-server/microcosm/constellation" 19 19 "tangled.org/whey.party/red-dwarf-server/microcosm/slingshot" 20 20 appbskyactordefs "tangled.org/whey.party/red-dwarf-server/shims/lex/app/bsky/actor/defs" 21 + appbskyfeeddefs "tangled.org/whey.party/red-dwarf-server/shims/lex/app/bsky/feed/defs" 21 22 "tangled.org/whey.party/red-dwarf-server/shims/utils" 22 23 "tangled.org/whey.party/red-dwarf-server/sticket" 23 24 "tangled.org/whey.party/red-dwarf-server/store" ··· 367 368 368 369 c.JSON(http.StatusOK, &appbsky.FeedGetFeedGenerators_Output{ 369 370 Feeds: out, 371 + }) 372 + }) 373 + 374 + router.GET("/xrpc/app.bsky.feed.getPosts", 375 + func(c *gin.Context) { 376 + postsreq := c.QueryArray("uris") 377 + ctx := c.Request.Context() 378 + 379 + type result struct { 380 + view *appbsky.FeedDefs_PostView 381 + } 382 + 383 + results := make([]result, len(postsreq)) 384 + 385 + var wg sync.WaitGroup 386 + wg.Add(len(postsreq)) 387 + 388 + for i, raw := range postsreq { 389 + go func(i int, raw string) { 390 + defer wg.Done() 391 + 392 + post, _, _ := appbskyfeeddefs.PostView(ctx, raw, sl, BSKYIMAGECDN_URL) 393 + 394 + results[i].view = post 395 + }(i, raw) 396 + } 397 + 398 + wg.Wait() 399 + 400 + // build final slice 401 + out := make([]*appbsky.FeedDefs_PostView, 0, len(results)) 402 + for _, r := range results { 403 + if r.view != nil { 404 + out = append(out, r.view) 405 + } 406 + } 407 + 408 + c.JSON(http.StatusOK, &appbsky.FeedGetPosts_Output{ 409 + Posts: out, 370 410 }) 371 411 }) 372 412
+1
shims/lex/app/bsky/feed/defs/embed.go
··· 1 + package appbskyfeeddefs
+78
shims/lex/app/bsky/feed/defs/postview.go
··· 1 + package appbskyfeeddefs 2 + 3 + import ( 4 + "context" 5 + "encoding/json" 6 + 7 + "github.com/bluesky-social/indigo/api/agnostic" 8 + appbsky "github.com/bluesky-social/indigo/api/bsky" 9 + "github.com/bluesky-social/indigo/atproto/syntax" 10 + "tangled.org/whey.party/red-dwarf-server/microcosm" 11 + 12 + //"tangled.org/whey.party/red-dwarf-server/microcosm/constellation" 13 + //"tangled.org/whey.party/red-dwarf-server/microcosm/slingshot" 14 + "github.com/bluesky-social/indigo/lex/util" 15 + appbskyactordefs "tangled.org/whey.party/red-dwarf-server/shims/lex/app/bsky/actor/defs" 16 + "tangled.org/whey.party/red-dwarf-server/shims/utils" 17 + ) 18 + 19 + func PostView(ctx context.Context, postaturi string, sl *microcosm.MicrocosmClient, imgcdn string) (*appbsky.FeedDefs_PostView, *appbsky.FeedPost, error) { 20 + aturi, err := syntax.ParseATURI(postaturi) 21 + if err != nil { 22 + return nil, nil, err 23 + } 24 + 25 + did := aturi.Authority().String() 26 + rkey := aturi.RecordKey().String() 27 + repoDID, err := utils.NewDID(did) 28 + if err != nil { 29 + return nil, nil, err 30 + } 31 + 32 + postRecordResponse, err_r := agnostic.RepoGetRecord(ctx, sl, "", "app.bsky.feed.post", string(did), rkey) 33 + if err_r != nil { 34 + return nil, nil, err_r 35 + } 36 + 37 + var postRecord appbsky.FeedPost 38 + if err := json.Unmarshal(*postRecordResponse.Value, &postRecord); err != nil { 39 + return nil, nil, err 40 + } 41 + 42 + profile, _, _ := appbskyactordefs.ProfileViewBasic(ctx, repoDID, sl, imgcdn) 43 + 44 + lexicontypedecoder := &util.LexiconTypeDecoder{Val: &postRecord} 45 + 46 + fakecount := int64(-1) 47 + 48 + return &appbsky.FeedDefs_PostView{ 49 + // LexiconTypeID string `json:"$type" cborgen:"$type,const=app.bsky.feed.defs#postView"` 50 + LexiconTypeID: "app.bsky.feed.defs#postView", 51 + // Author *ActorDefs_ProfileViewBasic `json:"author" cborgen:"author"` 52 + Author: profile, 53 + // BookmarkCount *int64 `json:"bookmarkCount,omitempty" cborgen:"bookmarkCount,omitempty"` 54 + // Cid string `json:"cid" cborgen:"cid"` 55 + Cid: *postRecordResponse.Cid, 56 + // // debug: Debug information for internal development 57 + // Debug *interface{} `json:"debug,omitempty" cborgen:"debug,omitempty"` 58 + // Embed *FeedDefs_PostView_Embed `json:"embed,omitempty" cborgen:"embed,omitempty"` 59 + // IndexedAt string `json:"indexedAt" cborgen:"indexedAt"` 60 + IndexedAt: postRecord.CreatedAt, 61 + // Labels []*comatproto.LabelDefs_Label `json:"labels,omitempty" cborgen:"labels,omitempty"` 62 + // LikeCount *int64 `json:"likeCount,omitempty" cborgen:"likeCount,omitempty"` 63 + LikeCount: &fakecount, 64 + // QuoteCount *int64 `json:"quoteCount,omitempty" cborgen:"quoteCount,omitempty"` 65 + QuoteCount: &fakecount, 66 + // Record *lexutil.LexiconTypeDecoder `json:"record" cborgen:"record"` 67 + Record: lexicontypedecoder, 68 + // ReplyCount *int64 `json:"replyCount,omitempty" cborgen:"replyCount,omitempty"` 69 + ReplyCount: &fakecount, 70 + // RepostCount *int64 `json:"repostCount,omitempty" cborgen:"repostCount,omitempty"` 71 + RepostCount: &fakecount, 72 + // Threadgate *FeedDefs_ThreadgateView `json:"threadgate,omitempty" cborgen:"threadgate,omitempty"` 73 + // Uri string `json:"uri" cborgen:"uri"` 74 + Uri: postRecordResponse.Uri, 75 + // Viewer *FeedDefs_ViewerState `json:"viewer,omitempty" cborgen:"viewer,omitempty"` 76 + 77 + }, &postRecord, nil 78 + }