package caps import ( "context" "encoding/json" "fmt" abiv1 "git.dev.alexdunmow.com/block/pluginsdk/abi/v1" "git.dev.alexdunmow.com/block/pluginsdk/content" "github.com/google/uuid" ) // authorStub implements content.Author over the content.* write capability // calls (WO-WZ-019). Same family as contentStub; split so the read surface // stays untouched. type authorStub struct{ base } var _ content.Author = (*authorStub)(nil) func (s *authorStub) CreatePage(ctx context.Context, params content.CreatePageParams) (content.CreatePageResult, error) { req := &abiv1.ContentCreatePageRequest{ Slug: params.Slug, ParentSlug: params.ParentSlug, Title: params.Title, TemplateKey: params.TemplateKey, MasterPageKey: params.MasterPageKey, } resp := &abiv1.ContentCreatePageResponse{} if err := s.invoke(ctx, "create_page", req, resp); err != nil { return content.CreatePageResult{}, err } id, err := uuid.Parse(resp.GetPageId()) if err != nil { return content.CreatePageResult{}, fmt.Errorf("content.create_page: bad page_id %q: %w", resp.GetPageId(), err) } return content.CreatePageResult{PageID: id, Created: resp.GetCreated()}, nil } func (s *authorStub) SetPageBlocks(ctx context.Context, pageID uuid.UUID, blocks []content.PageBlock) error { req := &abiv1.ContentSetPageBlocksRequest{PageId: pageID.String()} for _, b := range blocks { pb, err := pageBlockToProto(b) if err != nil { return fmt.Errorf("content.set_page_blocks: block %q: %w", b.BlockKey, err) } req.Blocks = append(req.Blocks, pb) } return s.invoke(ctx, "set_page_blocks", req, &abiv1.ContentSetPageBlocksResponse{}) } func (s *authorStub) PublishPage(ctx context.Context, pageID uuid.UUID) error { req := &abiv1.ContentPublishPageRequest{PageId: pageID.String()} return s.invoke(ctx, "publish_page", req, &abiv1.ContentPublishPageResponse{}) } func (s *authorStub) SetPageSEO(ctx context.Context, pageID uuid.UUID, seo content.PageSEO) error { req := &abiv1.ContentSetPageSeoRequest{ PageId: pageID.String(), MetaTitle: seo.MetaTitle, MetaDescription: seo.MetaDescription, OgTitle: seo.OGTitle, OgDescription: seo.OGDescription, OgImage: seo.OGImage, FocusKeyphrase: seo.FocusKeyphrase, CanonicalUrl: seo.CanonicalURL, RobotsDirective: seo.RobotsDirective, TwitterTitle: seo.TwitterTitle, TwitterDescription: seo.TwitterDescription, TwitterImage: seo.TwitterImage, } return s.invoke(ctx, "set_page_seo", req, &abiv1.ContentSetPageSeoResponse{}) } func (s *authorStub) UpsertPost(ctx context.Context, params content.UpsertPostParams) (content.UpsertPostResult, error) { docJSON, err := json.Marshal(params.Document) if err != nil { return content.UpsertPostResult{}, fmt.Errorf("content.upsert_post: marshal document: %w", err) } req := &abiv1.ContentUpsertPostRequest{ Slug: params.Slug, Title: params.Title, DocumentJson: docJSON, Excerpt: params.Excerpt, Publish: params.Publish, IsFeatured: params.IsFeatured, } if params.AuthorProfileID != nil { v := params.AuthorProfileID.String() req.AuthorProfileId = &v } if params.FeaturedImageID != nil { v := params.FeaturedImageID.String() req.FeaturedImageId = &v } resp := &abiv1.ContentUpsertPostResponse{} if err := s.invoke(ctx, "upsert_post", req, resp); err != nil { return content.UpsertPostResult{}, err } id, err := uuid.Parse(resp.GetPostId()) if err != nil { return content.UpsertPostResult{}, fmt.Errorf("content.upsert_post: bad post_id %q: %w", resp.GetPostId(), err) } return content.UpsertPostResult{PostID: id, Created: resp.GetCreated()}, nil } // pageBlockToProto converts one content.PageBlock to its wire form. func pageBlockToProto(b content.PageBlock) (*abiv1.PageBlock, error) { contentJSON, err := json.Marshal(b.Content) if err != nil { return nil, err } return &abiv1.PageBlock{ BlockKey: b.BlockKey, Title: b.Title, ContentJson: contentJSON, HtmlContent: b.HTMLContent, Slot: b.Slot, SortOrder: b.SortOrder, }, nil }