diff options
| author | Sam Anthony <sam@samanthony.xyz> | 2026-05-07 11:36:45 -0400 |
|---|---|---|
| committer | Sam Anthony <sam@samanthony.xyz> | 2026-05-07 11:36:45 -0400 |
| commit | 09c91d21b083abc976a4cc6439899fb00438a630 (patch) | |
| tree | 63ef50d67b72f847e85877ce9910b32003b63d6c /lulu.go | |
| parent | 4ee72fe36dd513bcbad227f7bdd6ed0079d2c95a (diff) | |
| download | lulu-09c91d21b083abc976a4cc6439899fb00438a630.zip | |
implement GET /cover-dimensions
Diffstat (limited to 'lulu.go')
| -rw-r--r-- | lulu.go | 105 |
1 files changed, 85 insertions, 20 deletions
@@ -9,6 +9,7 @@ import ( "io" "net/http" "net/url" + "strconv" "golang.org/x/oauth2/clientcredentials" ) @@ -33,8 +34,8 @@ type Unit string const ( Points Unit = "pt" - Millimeters = "mm" - Inches = "inch" + Millimeters Unit = "mm" + Inches Unit = "inch" ) type ValidationStatus string @@ -77,6 +78,43 @@ type InteriorValidationRecord struct { ValidPkgIds []PkgId `json:"valid_pod_package_ids"` } +// coverDimensionsReq is the json body of a /cover-dimensions/ request. +type coverDimensionsReq struct { + PkgId PkgId `json:"pod_package_id"` + NPages uint `json:"interior_page_count"` + Unit Unit `json:"unit"` +} + +type CoverDimensions struct { + Width, Height float64 + Unit Unit +} + +func (cd *CoverDimensions) UnmarshalJSON(data []byte) error { + s := string(data) + var alias struct { + Width, Height string + Unit Unit + } + if err := json.Unmarshal(data, &alias); err != nil { + return fmt.Errorf("malformed %T: %q: %w", cd, s, err) + } + + w, err := strconv.ParseFloat(alias.Width, 64) + if err != nil { + return fmt.Errorf("malformed %T.Width: %q: %w", cd, s, err) + } + h, err := strconv.ParseFloat(alias.Height, 64) + if err != nil { + return fmt.Errorf("malformed %T.Height: %q: %w", cd, s, err) + } + + cd.Width = w + cd.Height = h + cd.Unit = alias.Unit + return nil +} + type Client struct { c *http.Client } @@ -132,20 +170,12 @@ func (c *Client) validateInterior(payload any) (uint, error) { defer resp.Body.Close() if resp.StatusCode != http.StatusCreated { - body, _ := io.ReadAll(resp.Body) - return 0, fmt.Errorf("lulu: POST %s: %s: %s", url, resp.Status, body) + return 0, errResp{resp} } - buf := new(bytes.Buffer) - if _, err := io.Copy(buf, resp.Body); err != nil { - return 0, fmt.Errorf("lulu: POST %s: error reading response body: %w", url, err) - } - dec := json.NewDecoder(buf) var rec InteriorValidationRecord - if err := dec.Decode(&rec); err != nil { - return 0, fmt.Errorf("lulu: POST %s: error decoding response body %q: %w", url, buf, err) - } - return rec.Id, nil + err = decodeResponse(resp, &rec) + return rec.Id, err } // GetInteriorValidation retrieves information about an interior file @@ -164,18 +194,53 @@ func (c *Client) GetInteriorValidation(id uint) (InteriorValidationRecord, error defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - body, _ := io.ReadAll(resp.Body) - return InteriorValidationRecord{}, fmt.Errorf("lulu: GET %s: %s: %s", url, resp.Status, body) + return InteriorValidationRecord{}, errResp{resp} + } + + var rec InteriorValidationRecord + err = decodeResponse(resp, &rec) + return rec, err +} + +// CoverDimensions calculates the required dimensions of the cover for a +// book with the given manufacturing settings and number of pages. The +// returned dimensions are given in the specified units of measurement. +// +// https://api.lulu.com/docs/#tag/Files-validation/operation/Cover-Dimensions_create +func (c *Client) CoverDimensions(mfg PkgId, npages uint, unit Unit) (CoverDimensions, error) { + payload := coverDimensionsReq{mfg, npages, unit} + body, err := json.Marshal(payload) + if err != nil { + return CoverDimensions{}, fmt.Errorf("lulu: error encoding request body %v for %s: %w", payload, coverDimensionsPath, err) + } + + url, err := url.JoinPath(ApiUrl, coverDimensionsPath) + if err != nil { + return CoverDimensions{}, fmt.Errorf("lulu: %w", err) + } + resp, err := c.c.Post(url, "application/json", bytes.NewBuffer(body)) + if err != nil { + return CoverDimensions{}, fmt.Errorf("lulu: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusCreated { + return CoverDimensions{}, errResp{resp} } + var dims CoverDimensions + err = decodeResponse(resp, &dims) + return dims, err +} + +func decodeResponse(resp *http.Response, v any) error { buf := new(bytes.Buffer) if _, err := io.Copy(buf, resp.Body); err != nil { - return InteriorValidationRecord{}, fmt.Errorf("lulu: GET %s: error reading response body: %w", url, err) + return errReadResp{resp, err} } dec := json.NewDecoder(buf) - var rec InteriorValidationRecord - if err := dec.Decode(&rec); err != nil { - return rec, fmt.Errorf("lulu: GET %s: error decoding response body %q: %w", url, buf, err) + if err := dec.Decode(v); err != nil { + return errDecResp{resp, buf.Bytes(), err} } - return rec, nil + return nil } |