package caps import ( "context" "encoding/json" "time" abiv1 "git.dev.alexdunmow.com/block/pluginsdk/abi/v1" "git.dev.alexdunmow.com/block/pluginsdk/content" "github.com/google/uuid" ) // contentStub implements content.Content over content.* capability calls. type contentStub struct{ base } var _ content.Content = (*contentStub)(nil) func (s *contentStub) GetAuthorProfile(ctx context.Context, id uuid.UUID) (*content.AuthorProfile, error) { resp := &abiv1.ContentGetAuthorProfileResponse{} if err := s.invoke(ctx, "get_author_profile", &abiv1.ContentGetAuthorProfileRequest{Id: id.String()}, resp); err != nil { return nil, err } a := resp.GetAuthor() if a == nil { return nil, nil } return &content.AuthorProfile{ ID: parseUUID(a.GetId()), Name: a.GetName(), Slug: a.GetSlug(), Bio: a.GetBio(), AvatarURL: a.GetAvatarUrl(), Website: a.GetWebsite(), SocialLinks: a.GetSocialLinks(), }, nil } func (s *contentStub) GetPage(ctx context.Context, slug string) (*content.PageInfo, error) { resp := &abiv1.ContentGetPageResponse{} if err := s.invoke(ctx, "get_page", &abiv1.ContentGetPageRequest{Slug: slug}, resp); err != nil { return nil, err } p := resp.GetPage() if p == nil { return nil, nil } return &content.PageInfo{ID: parseUUID(p.GetId()), Slug: p.GetSlug(), Title: p.GetTitle()}, nil } func (s *contentStub) GetPost(ctx context.Context, slug string) (*content.PostInfo, error) { resp := &abiv1.ContentGetPostResponse{} if err := s.invoke(ctx, "get_post", &abiv1.ContentGetPostRequest{Slug: slug}, resp); err != nil { return nil, err } p := resp.GetPost() if p == nil { return nil, nil } info := postInfoFromProto(p) return &info, nil } func (s *contentStub) ListPosts(ctx context.Context, params content.ListPostsParams) ([]content.PostInfo, error) { req := &abiv1.ContentListPostsRequest{ Limit: int32(params.Limit), Offset: int32(params.Offset), Category: params.Category, PublishedOnly: params.PublishedOnly, IncludeBody: params.IncludeBody, IncludeExcerpt: params.IncludeExcerpt, } resp := &abiv1.ContentListPostsResponse{} if err := s.invoke(ctx, "list_posts", req, resp); err != nil { return nil, err } out := make([]content.PostInfo, 0, len(resp.GetPosts())) for _, p := range resp.GetPosts() { out = append(out, postInfoFromProto(p)) } return out, nil } // postInfoFromProto decodes an abiv1.PostInfo into the SDK content.PostInfo, // shared by GetPost and ListPosts. func postInfoFromProto(p *abiv1.PostInfo) content.PostInfo { var publishedAt time.Time if ts := p.GetPublishedAt(); ts != nil { publishedAt = ts.AsTime() } return content.PostInfo{ ID: parseUUID(p.GetId()), Slug: p.GetSlug(), Title: p.GetTitle(), Excerpt: p.GetExcerpt(), Body: p.GetBody(), FeaturedImageURL: p.GetFeaturedImageUrl(), AuthorID: parseUUID(p.GetAuthorId()), AuthorName: p.GetAuthorName(), AuthorSlug: p.GetAuthorSlug(), PublishedAt: publishedAt, } } // Slugify has no error channel in the interface; a transport failure degrades // to the empty string (the caller treats an empty slug as "unavailable"). func (s *contentStub) Slugify(text string) string { resp := &abiv1.ContentSlugifyResponse{} if err := s.invoke(context.Background(), "slugify", &abiv1.ContentSlugifyRequest{Text: text}, resp); err != nil { return "" } return resp.GetSlug() } func (s *contentStub) BlockNoteToHTML(ctx context.Context, doc map[string]any) string { docJSON, err := json.Marshal(doc) if err != nil { return "" } resp := &abiv1.ContentBlockNoteToHtmlResponse{} if err := s.invoke(ctx, "block_note_to_html", &abiv1.ContentBlockNoteToHtmlRequest{DocJson: docJSON}, resp); err != nil { return "" } return resp.GetHtml() } func (s *contentStub) GenerateExcerpt(html string, maxLen int) string { resp := &abiv1.ContentGenerateExcerptResponse{} req := &abiv1.ContentGenerateExcerptRequest{Html: html, MaxLen: int32(maxLen)} if err := s.invoke(context.Background(), "generate_excerpt", req, resp); err != nil { return "" } return resp.GetExcerpt() } func (s *contentStub) StripHTML(str string) string { resp := &abiv1.ContentStripHtmlResponse{} if err := s.invoke(context.Background(), "strip_html", &abiv1.ContentStripHtmlRequest{Html: str}, resp); err != nil { return "" } return resp.GetText() }