package caps import ( "context" abiv1 "git.dev.alexdunmow.com/block/pluginsdk/abi/v1" "git.dev.alexdunmow.com/block/pluginsdk/gating" "github.com/google/uuid" ) // gatingStub implements gating.Gating over gating.* capability calls. type gatingStub struct{ base } var _ gating.Gating = (*gatingStub)(nil) func (s *gatingStub) GetSubscriberTierLevel(ctx context.Context, userID uuid.UUID) (int, error) { resp := &abiv1.GatingGetSubscriberTierLevelResponse{} req := &abiv1.GatingGetSubscriberTierLevelRequest{UserId: userID.String()} if err := s.invoke(ctx, "get_subscriber_tier_level", req, resp); err != nil { return 0, err } return int(resp.GetLevel()), nil } // EvaluateAccess mirrors the host's decision. The rule evaluation is a pure, // deterministic function (gating.EvaluateAccess) so the interface exposes no // error channel; the call still crosses the boundary to keep host and guest // on identical logic, and falls back to the local pure function if the // transport is unavailable. func (s *gatingStub) EvaluateAccess(userTierLevel int, rule *gating.AccessRule) gating.AccessResult { req := &abiv1.GatingEvaluateAccessRequest{UserTierLevel: int32(userTierLevel)} if rule != nil { req.Rule = &abiv1.AccessRule{ MinTierLevel: int32(rule.MinTierLevel), OverrideTierId: rule.OverrideTierID, TeaserMode: rule.TeaserMode, TeaserPercent: int32(rule.TeaserPercent), } } resp := &abiv1.GatingEvaluateAccessResponse{} if err := s.invoke(context.Background(), "evaluate_access", req, resp); err != nil { return gating.EvaluateAccess(userTierLevel, rule) } r := resp.GetResult() return gating.AccessResult{ HasAccess: r.GetHasAccess(), TeaserMode: r.GetTeaserMode(), TeaserPercent: int(r.GetTeaserPercent()), RequiredLevel: int(r.GetRequiredLevel()), } }