initial commit

This commit is contained in:
Gitea
2024-01-24 16:12:16 +03:00
commit 5b5dc2165c
23 changed files with 1846 additions and 0 deletions

View 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
}