amocrm/pkg/amoClient/amo.go

847 lines
27 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package amoClient
import (
"amocrm/internal/models"
"amocrm/internal/workers/limiter"
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/model"
"strings"
"sync"
"time"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
type Amo struct {
fiberClient *fiber.Client
logger *zap.Logger
redirectionURL string
integrationID string
integrationSecret string
rateLimiter *limiter.RateLimiter
fileMutex sync.Mutex
}
type AmoDeps struct {
FiberClient *fiber.Client
Logger *zap.Logger
RedirectionURL string
IntegrationID string
IntegrationSecret string
RateLimiter *limiter.RateLimiter
}
func NewAmoClient(deps AmoDeps) *Amo {
if deps.FiberClient == nil {
deps.FiberClient = fiber.AcquireClient()
}
return &Amo{
fiberClient: deps.FiberClient,
logger: deps.Logger,
redirectionURL: deps.RedirectionURL,
integrationSecret: deps.IntegrationSecret,
integrationID: deps.IntegrationID,
rateLimiter: deps.RateLimiter,
}
}
// токен должен быть с правами администратора
// https://www.amocrm.ru/developers/content/crm_platform/users-api#users-list
func (a *Amo) GetUserList(req models.RequestGetListUsers, accesToken string, domain string) (*models.ResponseGetListUsers, error) {
for {
if a.rateLimiter.Check() {
uri := fmt.Sprintf("https://%s/ajax/v3/users?with=rights&page=%d&limit=%d", domain, req.Page, req.Limit)
agent := a.fiberClient.Get(uri)
agent.Set("Authorization", "Bearer "+accesToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err := range errs {
a.logger.Error("error sending request in GetUserList", zap.Error(err))
}
return nil, fmt.Errorf("request GetUserList failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
switch statusCode {
case fiber.StatusForbidden:
errorMessage := fmt.Sprintf("error GetUserList StatusForbidden - %d", statusCode)
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
case fiber.StatusUnauthorized:
errorMessage := fmt.Sprintf("error GetUserList StatusUnauthorized - %d", statusCode)
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
default:
errorMessage := fmt.Sprintf("error GetUserList statusCode - %d", statusCode)
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
}
var userListResponse models.ResponseGetListUsers
err := json.Unmarshal(resBody, &userListResponse)
if err != nil {
a.logger.Error("error unmarshal ResponseGetListUsers:", zap.Error(err))
return nil, err
}
return &userListResponse, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}
// https://www.amocrm.ru/developers/content/oauth/step-by-step
// POST /oauth2/access_token
// тут и создание по коду и обновление по рефрешу в этом клиенте
func (a *Amo) CreateWebHook(req models.WebHookRequest, domain string) (*models.CreateWebHookResp, error) {
for {
if a.rateLimiter.Check() {
req.SetClientID(a.integrationID)
req.SetClientSecret(a.integrationSecret)
req.SetRedirectURL(a.redirectionURL)
bodyBytes, err := json.Marshal(req)
if err != nil {
a.logger.Error("error marshal req in CreateWebHook:", zap.Error(err))
return nil, err
}
agent := a.fiberClient.Post("https://" + domain + "/oauth2/access_token")
agent.Set("Content-Type", "application/json").Body(bodyBytes)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err = range errs {
a.logger.Error("error sending request in CreateWebHook for create or update tokens", zap.Error(err))
}
return nil, fmt.Errorf("request failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from CreateWebHook: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var tokens models.CreateWebHookResp
err = json.Unmarshal(resBody, &tokens)
if err != nil {
a.logger.Error("error unmarshal CreateWebHookResp:", zap.Error(err))
return nil, err
}
return &tokens, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}
// https://www.amocrm.ru/developers/content/crm_platform/leads_pipelines#%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D1%81%D1%82%D0%B0%D1%82%D1%83%D1%81%D0%BE%D0%B2-%D0%B2%D0%BE%D1%80%D0%BE%D0%BD%D0%BA%D0%B8-%D1%81%D0%B4%D0%B5%D0%BB%D0%BE%D0%BA
// GET /api/v4/leads/pipelines/{pipeline_id}/statuses
func (a *Amo) GetListSteps(pipelineID int, accessToken string, domain string) (*models.ResponseGetListSteps, error) {
for {
if a.rateLimiter.Check() {
uri := fmt.Sprintf("https://%s/api/v4/leads/pipelines/%d/statuses", domain, pipelineID)
agent := a.fiberClient.Get(uri)
agent.Set("Authorization", "Bearer "+accessToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err := range errs {
a.logger.Error("error sending request in GetListSteps", zap.Error(err))
}
return nil, fmt.Errorf("request GetListSteps failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from GetListSteps: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var listSteps models.ResponseGetListSteps
err := json.Unmarshal(resBody, &listSteps)
if err != nil {
a.logger.Error("error unmarshal ResponseGetListSteps:", zap.Error(err))
return nil, err
}
return &listSteps, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}
// https://www.amocrm.ru/developers/content/crm_platform/custom-fields#%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D0%BF%D0%BE%D0%BB%D0%B5%D0%B9-%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D0%B8
// GET /api/v4/leads/custom_fields
// GET /api/v4/contacts/custom_fields
// GET /api/v4/companies/custom_fields
// GET /api/v4/customers/custom_fields
// пока без этих двух
// GET /api/v4/customers/segments/custom_fields
// GET /api/v4/catalogs/{catalog_id}/custom_fields
// эти методы все относятся к одному и тому же, поэтому на вход будет урл и рек стуктура, выход у них один и тот же
func (a *Amo) GetListFields(req models.GetListFieldsReq, accessToken string, domain string) (*models.ResponseGetListFields, error) {
for {
if a.rateLimiter.Check() {
fullURL := fmt.Sprintf("https://%s/api/v4/%s/custom_fields?limit=%d&page=%d", domain, req.EntityType, req.Limit, req.Page)
agent := a.fiberClient.Get(fullURL)
agent.Set("Authorization", "Bearer "+accessToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err := range errs {
a.logger.Error("error sending request in GetListFields", zap.Error(err))
}
return nil, fmt.Errorf("request GetListFields failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from GetListFields: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var listFields models.ResponseGetListFields
err := json.Unmarshal(resBody, &listFields)
if err != nil {
a.logger.Error("error unmarshal ResponseGetListFields:", zap.Error(err))
return nil, err
}
return &listFields, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}
// https://www.amocrm.ru/developers/content/crm_platform/tags-api#%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D1%82%D0%B5%D0%B3%D0%BE%D0%B2-%D0%B4%D0%BB%D1%8F-%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D0%B8
// GET /api/v4/{entity_type:leads|contacts|companies|customers}/tags
func (a *Amo) GetListTags(req models.GetListTagsReq, accessToken string, domain string) (*models.ResponseGetListTags, error) {
for {
if a.rateLimiter.Check() {
fullURL := fmt.Sprintf("https://%s/api/v4/%s/tags?", domain, req.EntityType)
if req.Filter.Name != "" {
fullURL += "&filter[name]=" + url.QueryEscape(req.Filter.Name)
}
if len(req.Filter.ID) > 0 {
for _, id := range req.Filter.ID {
fullURL += fmt.Sprintf("&filter[id][]=%d", id)
}
}
if req.Filter.Query != "" {
fullURL += "&filter[query]=" + url.QueryEscape(req.Filter.Query)
}
fullURL += fmt.Sprintf("&page=%d&limit=%d", req.Page, req.Limit)
agent := a.fiberClient.Get(fullURL)
agent.Set("Authorization", "Bearer "+accessToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err := range errs {
a.logger.Error("error sending request in GetListTags", zap.Error(err))
}
return nil, fmt.Errorf("request GetListTags failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from GetListTags: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var listTags models.ResponseGetListTags
err := json.Unmarshal(resBody, &listTags)
if err != nil {
a.logger.Error("error unmarshal ResponseGetListTags:", zap.Error(err))
return nil, err
}
return &listTags, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}
// https://www.amocrm.ru/developers/content/crm_platform/account-info
// GET /api/v4/account
func (a *Amo) GetUserInfo(accessToken string, domain string) (*models.AmocrmUserInformation, error) {
for {
if a.rateLimiter.Check() {
url := fmt.Sprintf("https://%s/api/v4/account?with=drive_url", domain)
agent := a.fiberClient.Get(url)
agent.Set("Authorization", "Bearer "+accessToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err := range errs {
a.logger.Error("error sending request in GetUserInfo", zap.Error(err))
}
return nil, fmt.Errorf("request GetUserInfo failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from GetUserInfo: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var userInfo models.AmocrmUserInformation
err := json.Unmarshal(resBody, &userInfo)
if err != nil {
a.logger.Error("error unmarshal AmocrmUserInformation:", zap.Error(err))
return nil, err
}
return &userInfo, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}
// https://www.amocrm.ru/developers/content/crm_platform/leads_pipelines#%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D0%B2%D0%BE%D1%80%D0%BE%D0%BD%D0%BE%D0%BA-%D1%81%D0%B4%D0%B5%D0%BB%D0%BE%D0%BA
// GET /api/v4/leads/pipelines
func (a *Amo) GetListPipelines(accessToken string, domain string) (*models.PipelineResponse, error) {
for {
if a.rateLimiter.Check() {
uri := fmt.Sprintf("https://%s/api/v4/leads/pipelines", domain)
agent := a.fiberClient.Get(uri)
agent.Set("Authorization", "Bearer "+accessToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err := range errs {
a.logger.Error("error sending request in GetListPipelines", zap.Error(err))
}
return nil, fmt.Errorf("request GetListPipelines failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from GetListPipelines: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var userInfo models.PipelineResponse
err := json.Unmarshal(resBody, &userInfo)
if err != nil {
a.logger.Error("error unmarshal PipelineResponse:", zap.Error(err))
return nil, err
}
return &userInfo, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}
// токен должен быть с правами администратора
// https://www.amocrm.ru/developers/content/crm_platform/users-api#user-detail
// GET /api/v4/users/{id
func (a *Amo) GetUserByID(id int32, accessToken string, domain string) (*models.OneUserInfo, error) {
for {
if a.rateLimiter.Check() {
uri := fmt.Sprintf("https://%s/api/v4/users/%d?with=role,uuid", domain, id)
agent := a.fiberClient.Get(uri)
agent.Set("Authorization", "Bearer "+accessToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err := range errs {
a.logger.Error("error sending request in GetUserByID", zap.Error(err))
}
return nil, fmt.Errorf("request GetUserByID failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from Get User By ID:%s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var userInfo models.OneUserInfo
err := json.Unmarshal(resBody, &userInfo)
if err != nil {
a.logger.Error("error unmarshal response body in Get User By ID:", zap.Error(err))
return nil, err
}
return &userInfo, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}
func (a *Amo) AddFields(req []models.AddLeadsFields, entity model.EntityType, accessToken string, domain string) (*models.ResponseGetListFields, error) {
for {
if a.rateLimiter.Check() {
uri := fmt.Sprintf("https://%s/api/v4/%s/custom_fields", domain, entity)
bodyBytes, err := json.Marshal(req)
if err != nil {
a.logger.Error("error marshal req in Add Fields:", zap.Error(err))
return nil, err
}
agent := a.fiberClient.Post(uri)
agent.Set("Content-Type", "application/json").Body(bodyBytes)
agent.Set("Authorization", "Bearer "+accessToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err = range errs {
a.logger.Error("error sending request in Add Fields for add fields", zap.Error(err))
}
return nil, fmt.Errorf("request failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from Add Fields: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var fields models.ResponseGetListFields
err = json.Unmarshal(resBody, &fields)
if err != nil {
a.logger.Error("error unmarshal response body in Add Fields:", zap.Error(err))
return nil, err
}
return &fields, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}
func (a *Amo) CreatingDeal(req []models.DealReq, accessToken string, domain string) ([]models.DealResp, error) {
for {
if a.rateLimiter.Check() {
uri := fmt.Sprintf("https://%s/api/v4/leads/complex", domain)
bodyBytes, err := json.Marshal(req)
if err != nil {
a.logger.Error("error marshal req in Creating Deal:", zap.Error(err))
return nil, err
}
agent := a.fiberClient.Post(uri)
agent.Set("Content-Type", "application/json").Body(bodyBytes)
agent.Set("Authorization", "Bearer "+accessToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err = range errs {
a.logger.Error("error sending request in Creating Deal for creating deals", zap.Error(err))
}
return nil, fmt.Errorf("request failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from Creating Deal: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var resp []models.DealResp
err = json.Unmarshal(resBody, &resp)
if err != nil {
a.logger.Error("error unmarshal response body in Creating Deal:", zap.Error(err))
return nil, err
}
return resp, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}
func (a *Amo) UpdatingDeal(req []models.UpdateDealReq, accessToken string, domain string) (*models.UpdateDealResp, error) {
for {
if a.rateLimiter.Check() {
uri := fmt.Sprintf("https://%s/api/v4/leads", domain)
bodyBytes, err := json.Marshal(req)
if err != nil {
a.logger.Error("error marshal req in Updating Deal:", zap.Error(err))
return nil, err
}
agent := a.fiberClient.Patch(uri)
agent.Set("Content-Type", "application/json").Body(bodyBytes)
agent.Set("Authorization", "Bearer "+accessToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err = range errs {
a.logger.Error("error sending request in Updating Deal for updating deals", zap.Error(err))
}
return nil, fmt.Errorf("request failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from Updating Deal: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode), zap.String("domain", domain), zap.String("token", accessToken))
return nil, fmt.Errorf(errorMessage)
}
var resp models.UpdateDealResp
err = json.Unmarshal(resBody, &resp)
if err != nil {
a.logger.Error("error unmarshal response body in Updating Deal:", zap.Error(err))
return nil, err
}
return &resp, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}
func (a *Amo) CreatingCustomer(req []models.Customer, accessToken string, domain string) (*models.CustomerResp, error) {
for {
if a.rateLimiter.Check() {
uri := fmt.Sprintf("https://%s/api/v4/customers", domain)
bodyBytes, err := json.Marshal(req)
if err != nil {
a.logger.Error("error marshal req in Creating Customer:", zap.Error(err))
return nil, err
}
agent := a.fiberClient.Post(uri)
agent.Set("Content-Type", "application/json").Body(bodyBytes)
agent.Set("Authorization", "Bearer "+accessToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err = range errs {
a.logger.Error("error sending request in Creating Customer for creating customers", zap.Error(err))
}
return nil, fmt.Errorf("request failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from Creating Customer: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var resp models.CustomerResp
err = json.Unmarshal(resBody, &resp)
if err != nil {
a.logger.Error("error unmarshal response body in Creating Customer:", zap.Error(err))
return nil, err
}
return &resp, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}
// todo подумать на счет хранилища в амо
func (a *Amo) downloadFile(urlFile string) (*os.File, error) {
var err error
agent := a.fiberClient.Get(urlFile)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err = range errs {
a.logger.Error("error sending request for getting file by url", zap.Error(err))
}
return nil, fmt.Errorf("request failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from getting file by url: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
fileName := strings.Split(urlFile, "/")
tmpFile, err := os.Create(fileName[len(fileName)-1])
if err != nil {
return nil, err
}
_, err = io.Copy(tmpFile, bytes.NewReader(resBody))
if err != nil {
return nil, err
}
return tmpFile, nil
}
func (a *Amo) UploadFileToAmo(urlFile string, accessToken string, driveURL string) (*models.ValuesFile, error) {
a.fileMutex.Lock()
defer a.fileMutex.Unlock()
localFile, err := a.downloadFile(urlFile)
if err != nil {
return nil, err
}
defer os.Remove(localFile.Name())
fileInfo, err := os.Stat(localFile.Name())
if err != nil {
return nil, err
}
fileSize := fileInfo.Size()
createSessionData := &models.CreateSession{
FileName: localFile.Name(),
FileSize: fileSize,
}
uri := fmt.Sprintf("%s/v1.0/sessions", driveURL)
bodyBytes, err := json.Marshal(createSessionData)
if err != nil {
a.logger.Error("error marshal create session data:", zap.Error(err))
return nil, err
}
agent := a.fiberClient.Post(uri)
agent.Set("Content-Type", "application/json").Body(bodyBytes)
agent.Set("Authorization", "Bearer "+accessToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err = range errs {
a.logger.Error("error sending request to create session for upload file in amo", zap.Error(err))
}
return nil, fmt.Errorf("request failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from creating upload file session: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var resp models.UploadSession
err = json.Unmarshal(resBody, &resp)
if err != nil {
a.logger.Error("error unmarshal response body in creating upload file session:", zap.Error(err))
return nil, err
}
response, err := a.createPart(resp, localFile)
if err != nil {
a.logger.Error("error create part file sending to amo:", zap.Error(err))
return nil, err
}
return &models.ValuesFile{
Value: models.ValueFile{
FileUUID: response.UUID,
VersionUUID: response.VersionUUID,
FileName: response.Name,
FileSize: response.Size,
},
}, nil
}
func (a *Amo) createPart(uploadData models.UploadSession, file *os.File) (*models.UploadedFile, error) {
defer file.Close()
fileInfo, err := file.Stat()
if err != nil {
return nil, err
}
fileSize := fileInfo.Size()
var uploadedFile models.UploadedFile
maxSize := uploadData.MaxPartSize
var remainingSize = fileSize
var start int64 = 0
for remainingSize > 0 {
end := start + maxSize
if end > fileSize {
end = fileSize
}
partSize := end - start
partFile, err := os.OpenFile(file.Name(), os.O_RDONLY, 0644)
if err != nil {
return nil, err
}
defer partFile.Close()
_, err = partFile.Seek(start, io.SeekStart)
if err != nil {
return nil, err
}
buffer := make([]byte, partSize)
_, err = partFile.Read(buffer)
if err != nil {
return nil, err
}
agent := a.fiberClient.Post(uploadData.UploadURL).Body(buffer)
if err != nil {
return nil, err
}
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err = range errs {
a.logger.Error("error sending request to upload part file to amo", zap.Error(err))
}
return nil, fmt.Errorf("request failed: %v", errs[0])
}
if statusCode != http.StatusOK && statusCode != http.StatusAccepted {
return nil, fmt.Errorf("failed to upload part file to amo, status: %d, respBody: %s", statusCode, string(resBody))
}
start = end
remainingSize -= partSize
if statusCode == http.StatusAccepted {
var next struct {
NextUrl string `json:"next_url"`
SessionID int `json:"session_id"`
}
if err := json.Unmarshal(resBody, &next); err != nil {
return nil, err
}
uploadData.UploadURL = next.NextUrl
continue
}
if err := json.Unmarshal(resBody, &uploadedFile); err != nil {
return nil, err
}
return &uploadedFile, nil
}
return nil, nil
}
func (a *Amo) CreateContact(req []models.CreateContactReq, domain, accessToken string) (*models.ContactResponse, error) {
for {
if a.rateLimiter.Check() {
uri := fmt.Sprintf("https://%s/api/v4/contacts", domain)
bodyBytes, err := json.Marshal(req)
if err != nil {
a.logger.Error("error marshal req in Creating Contact:", zap.Error(err))
return nil, err
}
agent := a.fiberClient.Post(uri)
agent.Set("Content-Type", "application/json").Body(bodyBytes)
agent.Set("Authorization", "Bearer "+accessToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err = range errs {
a.logger.Error("error sending request in Creating Contact", zap.Error(err))
}
return nil, fmt.Errorf("request failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from Creating Contact: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var resp models.ContactResponse
err = json.Unmarshal(resBody, &resp)
if err != nil {
a.logger.Error("error unmarshal response body in Creating Contact:", zap.Error(err))
return nil, err
}
return &resp, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}
func (a *Amo) UpdateContact(req models.CreateContactReq, domain, accessToken string, idContact int32) (*models.ContactResponse, error) {
for {
if a.rateLimiter.Check() {
uri := fmt.Sprintf("https://%s/api/v4/contacts/%d", domain, idContact)
bodyBytes, err := json.Marshal(req)
if err != nil {
a.logger.Error("error marshal req in Update Contact:", zap.Error(err))
return nil, err
}
agent := a.fiberClient.Patch(uri)
agent.Set("Content-Type", "application/json").Body(bodyBytes)
agent.Set("Authorization", "Bearer "+accessToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err = range errs {
a.logger.Error("error sending request in Update Contact", zap.Error(err))
}
return nil, fmt.Errorf("request failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from Update Contact: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var resp models.ContactResponse
err = json.Unmarshal(resBody, &resp)
if err != nil {
a.logger.Error("error unmarshal response body in Update Contact:", zap.Error(err))
return nil, err
}
return &resp, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}
func (a *Amo) LinkedContactToContact(req []models.LinkedContactReq, domain, accessToken string, id int32) (*models.LinkedContactResponse, error) {
for {
if a.rateLimiter.Check() {
uri := fmt.Sprintf("https://%s/api/v4/contacts/%d/link", domain, id)
bodyBytes, err := json.Marshal(req)
if err != nil {
a.logger.Error("error marshal req in Linked Contact To Contact:", zap.Error(err))
return nil, err
}
agent := a.fiberClient.Post(uri)
agent.Set("Content-Type", "application/json").Body(bodyBytes)
agent.Set("Authorization", "Bearer "+accessToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err = range errs {
a.logger.Error("error sending request in Linked Contact To Contact", zap.Error(err))
}
return nil, fmt.Errorf("request failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from Linked Contact To Contact: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var resp models.LinkedContactResponse
err = json.Unmarshal(resBody, &resp)
if err != nil {
a.logger.Error("error unmarshal response body in Linked Contact To Contact:", zap.Error(err))
return nil, err
}
return &resp, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}