initial commit
This commit is contained in:
228
internal/interconnect/eway/client.go
Normal file
228
internal/interconnect/eway/client.go
Normal file
@ -0,0 +1,228 @@
|
||||
package eway
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.loyso.art/frx/eway/internal/entity"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type client struct {
|
||||
http *resty.Client
|
||||
log zerolog.Logger
|
||||
}
|
||||
|
||||
func NewClientWithSession(sessionid, sessionuser string, log zerolog.Logger) client {
|
||||
cookies := []*http.Cookie{
|
||||
{
|
||||
Name: "session_id",
|
||||
Value: sessionid,
|
||||
Domain: "eway.elevel.ru",
|
||||
HttpOnly: true,
|
||||
},
|
||||
{
|
||||
Name: "session_user",
|
||||
Value: sessionuser,
|
||||
Domain: "eway.elevel.ru",
|
||||
HttpOnly: true,
|
||||
},
|
||||
{
|
||||
Name: "contract",
|
||||
Value: "6101",
|
||||
Domain: "eway.elevel.ru",
|
||||
HttpOnly: true,
|
||||
},
|
||||
}
|
||||
|
||||
httpclient := resty.New().
|
||||
SetDebug(false).
|
||||
SetCookies(cookies).
|
||||
SetBaseURL("https://eway.elevel.ru/api")
|
||||
|
||||
return client{
|
||||
http: httpclient,
|
||||
log: log.With().Str("client", "eway").Logger(),
|
||||
}
|
||||
}
|
||||
|
||||
type getGoodsNewOrder struct {
|
||||
Column int
|
||||
Dir string
|
||||
}
|
||||
|
||||
type GetGoodsNewParams struct {
|
||||
Draw int
|
||||
Order getGoodsNewOrder
|
||||
Start int
|
||||
// 100 is max
|
||||
Length int
|
||||
SearchInStocks bool
|
||||
RemmantsAtleast int
|
||||
}
|
||||
|
||||
type getGoodsNewResponse struct {
|
||||
Draw string `json:"draw"`
|
||||
RecordsFiltered int `json:"recordsFiltered"`
|
||||
RecordsTotal int `json:"recordsTotal"`
|
||||
Data [][]any `json:"data"`
|
||||
Replacement bool `json:"replacement"`
|
||||
}
|
||||
|
||||
type goodRemnant [4]int
|
||||
|
||||
func parseGoodItem(items []any) (out entity.GoodsItemRaw) {
|
||||
valueOf := reflect.ValueOf(&out).Elem()
|
||||
typeOf := valueOf.Type()
|
||||
numField := valueOf.NumField()
|
||||
|
||||
for i := 0; i < numField; i++ {
|
||||
field := valueOf.Field(i)
|
||||
fieldType := typeOf.Field(i)
|
||||
if fieldType.Type.Kind() == reflect.Slice &&
|
||||
field.Type().Elem().Kind() != reflect.String {
|
||||
continue
|
||||
}
|
||||
|
||||
itemValue := reflect.ValueOf(items[i])
|
||||
if items[i] == nil ||
|
||||
(itemValue.CanAddr() && itemValue.IsNil()) ||
|
||||
itemValue.IsZero() {
|
||||
continue
|
||||
}
|
||||
|
||||
if field.Type().Kind() != itemValue.Type().Kind() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Dirty hack that accepts only strings.
|
||||
if field.Type().Kind() == reflect.Slice {
|
||||
values := items[i].([]any)
|
||||
elemSlice := reflect.MakeSlice(typeOf.Field(i).Type, 0, field.Len())
|
||||
for _, value := range values {
|
||||
valueStr, ok := value.(string)
|
||||
if ok {
|
||||
elemSlice = reflect.Append(elemSlice, reflect.ValueOf(valueStr))
|
||||
}
|
||||
}
|
||||
|
||||
field.Set(elemSlice)
|
||||
continue
|
||||
}
|
||||
|
||||
field.Set(itemValue)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func mapResponseByOrder(response getGoodsNewResponse) (items []entity.GoodsItemRaw) {
|
||||
for _, columns := range response.Data {
|
||||
gi := parseGoodItem(columns)
|
||||
items = append(items, gi)
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
func (c client) GetGoodsRemnants(
|
||||
ctx context.Context,
|
||||
productIDs []int,
|
||||
) (out entity.MappedGoodsRemnants, err error) {
|
||||
if len(productIDs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
productsStr := make([]string, 0, len(productIDs))
|
||||
for _, sku := range productIDs {
|
||||
productsStr = append(productsStr, strconv.Itoa(sku))
|
||||
}
|
||||
|
||||
resp, err := c.http.R().
|
||||
SetFormData(map[string]string{
|
||||
"products": strings.Join(productsStr, ","),
|
||||
}).
|
||||
SetDoNotParseResponse(true).
|
||||
Post("/goods_remnants")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting goods new: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
err = resp.RawBody().Close()
|
||||
if err != nil {
|
||||
c.log.Error().Err(err).Msg("unable to close body")
|
||||
}
|
||||
}()
|
||||
|
||||
if resp.IsError() {
|
||||
return nil, errors.New("request was not successful")
|
||||
}
|
||||
|
||||
data, err := io.ReadAll(resp.RawBody())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("reading raw body: %w", err)
|
||||
}
|
||||
|
||||
c.log.Debug().RawJSON("response", data).Msg("body prepared")
|
||||
|
||||
out = make(entity.MappedGoodsRemnants, len(productIDs))
|
||||
err = json.NewDecoder(bytes.NewReader(data)).Decode(&out)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decoding body: %w", err)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c client) GetGoodsNew(
|
||||
ctx context.Context,
|
||||
params GetGoodsNewParams,
|
||||
) (items []entity.GoodsItemRaw, total int, err error) {
|
||||
var response getGoodsNewResponse
|
||||
resp, err := c.http.R().
|
||||
SetFormData(map[string]string{
|
||||
"draw": strconv.Itoa(params.Draw),
|
||||
"start": strconv.Itoa(params.Start),
|
||||
"length": strconv.Itoa(params.Length),
|
||||
"order[0][column]": "14",
|
||||
"order[0][dir]": "desc",
|
||||
"search[value]": "",
|
||||
"search[regex]": "false",
|
||||
"search_in_stocks": "on",
|
||||
"remnants_atleast": "5",
|
||||
}).
|
||||
SetQueryParam("category_id", "0").
|
||||
SetQueryParam("own", "26476"). // user id?
|
||||
SetDoNotParseResponse(true).
|
||||
Post("/goods_new")
|
||||
if err != nil {
|
||||
return nil, -1, fmt.Errorf("getting goods new: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
err = resp.RawBody().Close()
|
||||
if err != nil {
|
||||
c.log.Error().Err(err).Msg("unable to close body")
|
||||
}
|
||||
}()
|
||||
|
||||
if resp.IsError() {
|
||||
return nil, -1, errors.New("request was not successful")
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.RawBody()).Decode(&response)
|
||||
if err != nil {
|
||||
return nil, -1, fmt.Errorf("decoding body: %w", err)
|
||||
}
|
||||
|
||||
return mapResponseByOrder(response), response.RecordsTotal, nil
|
||||
}
|
||||
Reference in New Issue
Block a user