package main import ( "context" "fmt" "log/slog" "strconv" "git.loyso.art/frx/kurious/internal/common/client/sravni" "git.loyso.art/frx/kurious/internal/common/errors" "github.com/teris-io/cli" ) const ( learningTypeOptName = "learning-type" courseThematicOptName = "course-thematic" ) func setupAPICommand(ctx context.Context) cli.Command { learningTypeOpt := cli.NewOption(learningTypeOptName, "Specify learning type"). WithChar('l'). WithType(cli.TypeString) courseThematic := cli.NewOption(courseThematicOptName, "Specify course thematic"). WithChar('t'). WithType(cli.TypeString) apiEducationListProducts := buildCLICommand(func() cli.Command { return cli.NewCommand("list_products", "List products by some filters"). WithOption(learningTypeOpt). WithOption(courseThematic). WithOption(limitOption). WithOption(offsetOption). WithAction(newListProductAction(ctx)) }) apiEducation := cli.NewCommand("education", "Education related category"). WithCommand(apiEducationListProducts) return cli.NewCommand("api", "Interaction with API"). WithCommand(apiEducation) } type action interface { context() context.Context parse(args []string, options map[string]string) error handle() error } func asCLIAction(a action) cli.Action { return func(args []string, options map[string]string) int { ctx := a.context() log := makeLogger(options) err := a.parse(args, options) if err != nil { log.ErrorContext(ctx, "unable to parse args and opts", slog.Any("err", err)) return -1 } err = a.handle() if err != nil { log.ErrorContext(ctx, "unable to handle action", slog.Any("err", err)) return -1 } return 0 } } type listProductsActionParams struct { learningType string courseThematic string limit int offset int } type listProductsAction struct { *baseAction client sravni.Client params listProductsActionParams } func newListProductAction(ctx context.Context) cli.Action { action := &listProductsAction{ baseAction: newBaseAction(ctx), } return asCLIAction(action) } func (a *listProductsAction) parse(args []string, options map[string]string) error { err := a.baseAction.parse(args, options) if err != nil { return err } var ok bool a.params.learningType, ok = options[learningTypeOptName] if !ok { return errors.SimpleError(learningTypeOptName + " is empty") } a.params.courseThematic = options[courseThematicOptName] if value, ok := options[limitOption.Key()]; ok { a.params.limit, _ = strconv.Atoi(value) } if value, ok := options[offsetOption.Key()]; ok { a.params.offset, _ = strconv.Atoi(value) } client, err := makeSravniClient(a.ctx, a.log, options) if err != nil { return fmt.Errorf("making sravni client: %w", err) } a.client = client return nil } func (a *listProductsAction) handle() error { params := sravni.ListEducationProductsParams{ LearningType: a.params.learningType, CoursesThematics: a.params.courseThematic, Limit: a.params.limit, Offset: a.params.offset, } result, err := a.client.ListEducationalProducts(a.ctx, params) if err != nil { return fmt.Errorf("listing education products: %w", err) } a.log.InfoContext(a.ctx, "list education products result", slog.Any("result", result)) return nil }