add filters to cli and client

This commit is contained in:
Aleksandr Trushkin
2023-12-14 20:40:35 +03:00
parent 30c361eb34
commit e80d5145cf
3 changed files with 181 additions and 18 deletions

View File

@ -29,7 +29,11 @@ type Client interface {
ListEducationalProducts(
ctx context.Context,
params ListEducationProductsParams,
) (result ListEducationProductsResponse, err error)
) (result listEducationProductsResponse, err error)
ListEducationalProductsFilterCount(
ctx context.Context,
params ListEducationProductsParams,
) (result ProductsFilterCount, err error)
}
func NewClient(ctx context.Context, log *slog.Logger, debug bool) (c *client, err error) {
@ -75,7 +79,12 @@ func (c *client) GetMainPageState() (*PageState, error) {
type ListEducationProductsParams struct {
LearningType string
CoursesThematics string
CoursesThematics []string
CourseGraphics []string
CourseLevels []string
CourseFormats []string
CourseDurations []string
CourseTypes []string
SortBy string
Limit int
@ -125,7 +134,7 @@ const (
FilterGraphicTerm FilterGraphic = "courseTimeTermNew"
)
type ListEducationProductsRequest struct {
type listEducationProductsRequest struct {
Fingerprint string `json:"fingerPrint,omitempty"`
ProductName string `json:"productName,omitempty"`
Location string `json:"location"`
@ -163,7 +172,7 @@ type ListEducationProductsRequest struct {
SortDirection string `json:"sortDirection"`
}
type ListEducationProductsResponse struct {
type listEducationProductsResponse struct {
Items []Course `json:"items"`
Organizations map[string]Organization `json:"organizations"`
@ -174,7 +183,7 @@ type ListEducationProductsResponse struct {
func (c *client) ListEducationalProducts(
ctx context.Context,
params ListEducationProductsParams,
) (result ListEducationProductsResponse, err error) {
) (result listEducationProductsResponse, err error) {
const urlPath = "/v1/education/products"
const defaultLimit = 1
const defaultSortProp = "advertising.position"
@ -186,15 +195,17 @@ func (c *client) ListEducationalProducts(
}
if !c.validLearningTypes.hasValue(params.LearningType) {
return result, errors.NewValidationError("learning_type", "bad value")
return result, errors.NewValidationError("learning_type", "unknown value")
}
if params.CoursesThematics != "" && !c.validCourseThematics.hasValue(params.CoursesThematics) {
return result, errors.NewValidationError("courses_thematics", "bad value")
for _, ct := range params.CoursesThematics {
if !c.validCourseThematics.hasValue(ct) {
return result, errors.NewValidationError("courses_thematics", "unknown value "+ct)
}
}
reqParams := ListEducationProductsRequest{
reqParams := listEducationProductsRequest{
LearningType: valueAsArray(params.LearningType),
CoursesThematics: valueAsArray(params.CoursesThematics),
CoursesThematics: params.CoursesThematics,
ProductName: productName,
Fields: defaultProductFields,
SortProperty: defaultSortProp, // mayber sort by price?
@ -212,12 +223,11 @@ func (c *client) ListEducationalProducts(
Offset: params.Offset,
}
req := c.http.R().
resp, err := c.http.R().
SetBody(reqParams).
SetResult(&result).
EnableTrace()
resp, err := req.Post(c.makeEducationURL(urlPath))
EnableTrace().
Post(c.makeEducationURL(urlPath))
if err != nil {
return result, fmt.Errorf("making request: %w", err)
}
@ -229,6 +239,88 @@ func (c *client) ListEducationalProducts(
return result, nil
}
type educationProductFilterCountRequest struct {
Filters educationProductFilter `json:"filters"`
}
type educationProductFilter struct {
AdvertisingOnly bool `json:"advertisingOnly"`
Location string `json:"location"`
LearningTypes []string `json:"learningTypes"`
CoursesThematics []string `json:"coursesThematics"`
CourseGraphics []string `json:"courseGraphics"`
CourseLevels []string `json:"courseLevels"`
CourseFormats []string `json:"courseFormats"`
CourseDurations []string `json:"courseDurations"`
CourseTypes []string `json:"courseTypes"`
}
type boolableDict map[int]int
type nameableDict map[string]int
type ProductsFilterCount struct {
IsCourseProfession boolableDict `json:"isCourseProfession"` // 0: count, 1: count eq to false + true
CourseLevels nameableDict `json:"courseLevels"`
CourseGraphics nameableDict `json:"courseGraphics"`
OrganizationIDs nameableDict `json:"organizationIds"`
HasTrialPeriod boolableDict `json:"hasTrialPeriod"`
HasMentor boolableDict `json:"hasMentor"`
HasJobGuarantee boolableDict `json:"hasJobGuarantee"`
CourseFormats nameableDict `json:"courseFormats"`
CourseDurations nameableDict `json:"courseDurations"`
CoursesThematics nameableDict `json:"coursesThematics"`
LearningTypes nameableDict `json:"learningTypes"`
}
func (c *client) ListEducationalProductsFilterCount(
ctx context.Context,
params ListEducationProductsParams,
) (result ProductsFilterCount, err error) {
const urlPath = "/v2/education/prodicts/fitter/count"
if err = c.checkClientInited(); err != nil {
return result, err
}
if !c.validLearningTypes.hasValue(params.LearningType) {
return result, errors.NewValidationError("learning_type", "unknown value")
}
for _, ct := range params.CoursesThematics {
if !c.validCourseThematics.hasValue(ct) {
return result, errors.NewValidationError("courses_thematics", "unknown value "+ct)
}
}
reqParams := educationProductFilterCountRequest{
Filters: educationProductFilter{
AdvertisingOnly: false,
Location: "",
LearningTypes: valueAsArray(params.LearningType),
CoursesThematics: params.CoursesThematics,
CourseGraphics: params.CourseGraphics,
CourseLevels: params.CourseLevels,
CourseFormats: params.CourseFormats,
CourseDurations: params.CourseDurations,
CourseTypes: params.CourseTypes,
},
}
var respData DataContainer[ProductsFilterCount]
resp, err := c.http.R().
SetBody(reqParams).
SetResult(&result).
EnableTrace().
Post(c.makeEducationURL(urlPath))
if err != nil {
return result, fmt.Errorf("making request: %w", err)
}
if resp.IsError() {
return result, fmt.Errorf("bad status code %d: %w", resp.StatusCode(), errors.ErrUnexpectedStatus)
}
return respData.Data, nil
}
func (c *client) makeEducationURL(path string) string {
if c.cachedMainPageInfo == nil {
return ""

View File

@ -12,6 +12,6 @@ func (NoopClient) GetMainPageState() (*PageState, error) {
return nil, errors.ErrNotImplemented
}
func (NoopClient) ListEducationalProducts(context.Context, ListEducationProductsParams) (ListEducationProductsResponse, error) {
return ListEducationProductsResponse{}, errors.ErrNotImplemented
func (NoopClient) ListEducationalProducts(context.Context, ListEducationProductsParams) (listEducationProductsResponse, error) {
return listEducationProductsResponse{}, errors.ErrNotImplemented
}