166 lines
3.5 KiB
Go
166 lines
3.5 KiB
Go
package facepp
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"mime/multipart"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
func (c *Client) SkinAnalyze(opts SkinAnalyzeOptions) (*SkinAnalyzeResponse, error) {
|
|
if opts.ImageFile != "" {
|
|
return c.skinAnalyzeFile(opts)
|
|
}
|
|
|
|
values := url.Values{}
|
|
switch {
|
|
case opts.ImageBase64 != "":
|
|
values.Set("image_base64", opts.ImageBase64)
|
|
case opts.ImageURL != "":
|
|
values.Set("image_url", opts.ImageURL)
|
|
default:
|
|
return nil, errors.New("facepp: image is required")
|
|
}
|
|
|
|
applyOptionalParams(values, opts)
|
|
|
|
return decodeSkinAnalyzeResult(c.postForm(values))
|
|
}
|
|
|
|
func (c *Client) SkinAnalyzeFromFile(path string, opts ...SkinAnalyzeOptions) (*SkinAnalyzeResponse, error) {
|
|
raw, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req := SkinAnalyzeOptions{}
|
|
if len(opts) > 0 {
|
|
req = opts[0]
|
|
}
|
|
req.ImageBase64 = base64.StdEncoding.EncodeToString(raw)
|
|
req.ImageFile = ""
|
|
req.ImageURL = ""
|
|
|
|
return c.SkinAnalyze(req)
|
|
}
|
|
|
|
func (c *Client) skinAnalyzeFile(opts SkinAnalyzeOptions) (*SkinAnalyzeResponse, error) {
|
|
if c.apiKey == "" || c.apiSecret == "" {
|
|
return nil, errors.New("facepp: api_key or api_secret is empty")
|
|
}
|
|
|
|
file, err := os.Open(opts.ImageFile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer file.Close()
|
|
|
|
var buf bytes.Buffer
|
|
writer := multipart.NewWriter(&buf)
|
|
|
|
if err := writer.WriteField("api_key", c.apiKey); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := writer.WriteField("api_secret", c.apiSecret); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := writeOptionalFields(writer, opts); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
part, err := writer.CreateFormFile("image_file", filepath.Base(opts.ImageFile))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if _, err := io.Copy(part, file); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := writer.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req, err := http.NewRequest(http.MethodPost, c.endpoint, &buf)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
|
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := checkAPIError(body); err != nil {
|
|
return decodeSkinAnalyzeResult(body, err)
|
|
}
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return decodeSkinAnalyzeResult(body, fmt.Errorf("facepp: http %d: %s", resp.StatusCode, strings.TrimSpace(string(body))))
|
|
}
|
|
|
|
return decodeSkinAnalyzeResult(body, nil)
|
|
}
|
|
|
|
func applyOptionalParams(values url.Values, opts SkinAnalyzeOptions) {
|
|
if opts.ReturnMaps != "" {
|
|
values.Set("return_maps", opts.ReturnMaps)
|
|
}
|
|
if opts.ReturnMarks != "" {
|
|
values.Set("return_marks", opts.ReturnMarks)
|
|
}
|
|
}
|
|
|
|
func writeOptionalFields(writer *multipart.Writer, opts SkinAnalyzeOptions) error {
|
|
if opts.ReturnMaps != "" {
|
|
if err := writer.WriteField("return_maps", opts.ReturnMaps); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if opts.ReturnMarks != "" {
|
|
return writer.WriteField("return_marks", opts.ReturnMarks)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func decodeSkinAnalyzeResult(body []byte, reqErr error) (*SkinAnalyzeResponse, error) {
|
|
if len(body) == 0 {
|
|
return nil, reqErr
|
|
}
|
|
|
|
resp, err := decodeSkinAnalyze(body)
|
|
if err != nil {
|
|
if reqErr != nil {
|
|
return nil, reqErr
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
if reqErr != nil {
|
|
return resp, reqErr
|
|
}
|
|
|
|
return resp, nil
|
|
}
|
|
|
|
func decodeSkinAnalyze(body []byte) (*SkinAnalyzeResponse, error) {
|
|
var result SkinAnalyzeResponse
|
|
if err := json.Unmarshal(body, &result); err != nil {
|
|
return nil, err
|
|
}
|
|
return &result, nil
|
|
}
|