
- Добавлена проверка токенов при запросе /amo/state - Исправлена работа с amo oauth-токенами - Добавлены примеры шаблонизатора - Добавлена возможность генерации и создания шаблонов из примеров - В ответ генератора добавлены ссылки для скачивания сгенерированных файлов - Вернул очиску temp после загрузки файла в Яндекс.Диск - yadisk.UploadResources - добавлено ожидание окончания отправки файла и таймаут в 5 секунд для отправки файла - Добавлены эндпоинты для загрузки файлов в хранилища - Актуализирован генератор по вебхуку - Обновлены генератор по данным - Обновлен генератор по лиду
346 lines
9.4 KiB
Go
346 lines
9.4 KiB
Go
package handlers
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"github.com/Pena-Co-Ltd/amocrm_templategen_back/amo"
|
|
"github.com/Pena-Co-Ltd/amocrm_templategen_back/templategen"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type ReqGeneratorByAmoLead struct {
|
|
File string `json:"file"` // Путь до файла в Yandex Disk, либо ID файла в Google Disk
|
|
StorageID string `json:"storage_id"`
|
|
StorageType string `json:"storage_type"`
|
|
LeadId int64 `json:"lead_id"` // Required.
|
|
}
|
|
|
|
type RespGenerated struct {
|
|
DownloadUrl string `json:"download_url"`
|
|
}
|
|
|
|
// GeneratorByAmoLead - сгенерировать файл по lead_id и указанному файлу если он установлен,
|
|
// или по шаблону если файл не указан
|
|
func (h *Handlers) GeneratorByAmoLead(w http.ResponseWriter, r *http.Request) {
|
|
var req ReqGeneratorByAmoLead
|
|
|
|
amoData := getAmoByJwt(r)
|
|
|
|
if amoData == nil {
|
|
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
err := decodePost(&req, r)
|
|
if err != nil {
|
|
h.reportError(w, err, http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
leadId := strconv.FormatInt(req.LeadId, 10)
|
|
|
|
if leadId == "" {
|
|
h.reportError(w, errors.New("lead_id required"), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// Получить данные по лиду
|
|
amoClient, err := h.Amo.NewClient(r.Context(), amoData.Referer, amoData.Token(), "")
|
|
|
|
if err != nil {
|
|
h.reportError(w, err, http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
lead, err := amoClient.GetLeadById(leadId)
|
|
if err != nil {
|
|
h.reportError(w, err, http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if lead.Id == 0 {
|
|
fmt.Println("Lead empty")
|
|
}
|
|
|
|
dataTemplate := map[string]interface{}{}
|
|
|
|
// Добавляем Инфо Лида
|
|
for k, v := range templategen.AmoLeadFieldsToRuMap(lead) {
|
|
dataTemplate[k] = v
|
|
}
|
|
|
|
// Добавляем инфо контактов
|
|
contacts := []amo.Contact{}
|
|
for _, data := range lead.Embedded.Contacts {
|
|
contact, err := amoClient.GetContactById(strconv.Itoa(data.Id))
|
|
if err == nil {
|
|
contacts = append(contacts, *contact)
|
|
} else {
|
|
fmt.Println("Something Wrong1:", err)
|
|
}
|
|
}
|
|
|
|
dataTemplate["Контакты"] = templategen.AmoContactsFieldsToRuMap(contacts)
|
|
|
|
// Добавляем инфо компаний
|
|
companies := []amo.Company{}
|
|
for _, data := range lead.Embedded.Companies {
|
|
company, err := amoClient.GetCompanyById(strconv.Itoa(data.Id))
|
|
if err == nil {
|
|
companies = append(companies, *company)
|
|
} else {
|
|
fmt.Println("Something Wrong2:", err)
|
|
}
|
|
}
|
|
|
|
dataTemplate["Компании"] = templategen.AmoCompaniesFieldsToRuMap(companies)
|
|
|
|
var file, storageType, storageID, name string
|
|
if req.File != "" {
|
|
if req.StorageType == "" {
|
|
h.reportError(w, errors.New("storage required"), http.StatusBadRequest)
|
|
return
|
|
}
|
|
if req.StorageID == "" {
|
|
h.reportError(w, errors.New("storage_id required"), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
file = req.File
|
|
storageType = req.StorageType
|
|
storageID = req.StorageID
|
|
name = lead.Name
|
|
} else {
|
|
template, err := h.dal.Template.GetByLeadId(r.Context(), leadId)
|
|
if err != nil {
|
|
h.reportError(w, err, http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if template == nil {
|
|
h.reportError(w, err, http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
file = template.File
|
|
storageType = template.StorageType
|
|
storageID = template.StorageID
|
|
name = template.Name
|
|
}
|
|
|
|
exportUrl, err := h.generate(w, r, file, name, storageID, storageType, amoData.UserID, dataTemplate)
|
|
|
|
sendResponse(w, http.StatusOK, RespGenerated{DownloadUrl: exportUrl})
|
|
}
|
|
|
|
type ReqGeneratorByData struct {
|
|
File string `json:"file"`
|
|
StorageID string `json:"storage_id"`
|
|
StorageType string `json:"storage_type"`
|
|
TemplateID string `json:"template_id"`
|
|
Name string `json:"name"`
|
|
Data map[string]any `json:"data"`
|
|
}
|
|
|
|
// GeneratorByData - сгенерировать файл по данным и указанному файлу или шаблону
|
|
func (h *Handlers) GeneratorByData(w http.ResponseWriter, r *http.Request) {
|
|
var req ReqGeneratorByData
|
|
|
|
amoData := getAmoByJwt(r)
|
|
|
|
if amoData == nil {
|
|
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
err := decodePost(&req, r)
|
|
if err != nil {
|
|
h.reportError(w, err, http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if req.StorageType == "" {
|
|
h.reportError(w, errors.New("storage required"), http.StatusBadRequest)
|
|
return
|
|
}
|
|
if req.StorageID == "" {
|
|
h.reportError(w, errors.New("storage_id required"), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
exportUrl, err := h.generate(w, r, req.File, req.Name, req.StorageID, req.StorageType, amoData.UserID, req.Data)
|
|
|
|
sendResponse(w, http.StatusOK, RespGenerated{DownloadUrl: exportUrl})
|
|
}
|
|
|
|
// GeneratorByAmoWebhook - эндпоинт для вебхука amo. Генерирует файл по ранее заданному шаблону
|
|
func (h *Handlers) GeneratorByAmoWebhook(w http.ResponseWriter, r *http.Request) {
|
|
reqBody, err := io.ReadAll(r.Body)
|
|
|
|
if err != nil {
|
|
h.reportError(w, err, http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
body := string(reqBody)
|
|
|
|
fmt.Println()
|
|
bodyUnescaped, err := url.QueryUnescape(body)
|
|
fmt.Println("WEBHOOK BODY:", bodyUnescaped)
|
|
fmt.Println()
|
|
|
|
p, err := url.ParseQuery(body)
|
|
if err != nil {
|
|
h.reportError(w, err, http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
leadId := p.Get("event[data][id]")
|
|
//subdomain := p.Get("subdomain")
|
|
accId := p.Get("account_id")
|
|
templateId := p.Get("action[settings][widget][settings][template_id]")
|
|
// pipelineId := p.Get("event[data][pipeline_id]")
|
|
|
|
// Запрашиваем данные по аккаунту
|
|
amoData, err := h.dal.Amo.GetByAccountID(r.Context(), accId)
|
|
if err != nil {
|
|
h.reportError(w, err, http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
amoClient, err := h.Amo.NewClient(r.Context(), amoData.Referer, amoData.Token(), "")
|
|
|
|
if err != nil {
|
|
h.reportError(w, err, http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
lead, err := amoClient.GetLeadById(leadId)
|
|
if err != nil {
|
|
h.reportError(w, err, http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if lead != nil {
|
|
// fmt.Printf("Lead RESP:%+v\r\n", lead)
|
|
} else {
|
|
fmt.Println("Lead empty")
|
|
}
|
|
|
|
dataTemplate := map[string]interface{}{}
|
|
|
|
// Добавляем Инфо Лида
|
|
for k, v := range templategen.AmoLeadFieldsToRuMap(lead) {
|
|
dataTemplate[k] = v
|
|
}
|
|
|
|
// Добавялем инфо контактов
|
|
contacts := []amo.Contact{}
|
|
for _, data := range lead.Embedded.Contacts {
|
|
contact, err := amoClient.GetContactById(strconv.Itoa(data.Id))
|
|
if err == nil {
|
|
contacts = append(contacts, *contact)
|
|
} else {
|
|
fmt.Println("Something Wrong1:", err)
|
|
}
|
|
}
|
|
|
|
dataTemplate["Контакты"] = templategen.AmoContactsFieldsToRuMap(contacts)
|
|
|
|
// Добавляем инфо компаний
|
|
companies := []amo.Company{}
|
|
for _, data := range lead.Embedded.Companies {
|
|
company, err := amoClient.GetCompanyById(strconv.Itoa(data.Id))
|
|
if err == nil {
|
|
companies = append(companies, *company)
|
|
} else {
|
|
fmt.Println("Something Wrong2:", err)
|
|
}
|
|
}
|
|
|
|
dataTemplate["Компании"] = templategen.AmoCompaniesFieldsToRuMap(companies)
|
|
|
|
//template, err := h.dal.Template.GetByLeadId(r.Context(), leadId)
|
|
//if err != nil {
|
|
// h.reportError(w, err, http.StatusInternalServerError)
|
|
// return
|
|
//}
|
|
|
|
template, err := h.dal.Template.GetByID(r.Context(), templateId)
|
|
if template == nil {
|
|
h.reportError(w, err, http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
exportUrl, err := h.generate(w, r, template.File, template.Name, template.StorageID, template.StorageType,
|
|
amoData.UserID, dataTemplate)
|
|
|
|
sendResponse(w, 200, RespGenerated{DownloadUrl: exportUrl})
|
|
}
|
|
|
|
// generate - локальная функция, для генерации файла, возвращает ссылку для скачивания сгенерированного файла
|
|
func (h *Handlers) generate(w http.ResponseWriter, r *http.Request, file, name, storageID, storageType, userID string,
|
|
data any,
|
|
) (string, error) {
|
|
var exportUrl string
|
|
|
|
// Генерируем файл и загружаем в хранилище
|
|
switch storageType {
|
|
case "gdisk":
|
|
gdiskData, err := h.dal.GDisk.GetByID(r.Context(), storageID)
|
|
if err != nil {
|
|
h.reportError(w, err, http.StatusInternalServerError)
|
|
return "", nil
|
|
}
|
|
|
|
if gdiskData == nil {
|
|
h.reportError(w, err, http.StatusInternalServerError)
|
|
return "", nil
|
|
}
|
|
|
|
client, err := h.GDisk.NewClient(r.Context(), gdiskData.Token())
|
|
|
|
exportUrl, err = templategen.GDiskGenerateDoc(file, name, userID, gdiskData.SaveFolderID, client,
|
|
data)
|
|
if err != nil {
|
|
h.reportError(w, err, http.StatusInternalServerError)
|
|
return "", nil
|
|
}
|
|
case "yadisk":
|
|
yaDiskData, err := h.dal.YaDisk.GetByID(r.Context(), storageID)
|
|
if err != nil {
|
|
h.reportError(w, err, http.StatusInternalServerError)
|
|
return "", nil
|
|
}
|
|
|
|
client, err := h.YaDisk.NewClient(r.Context(), yaDiskData.Token(), "")
|
|
|
|
exportUrl, err = templategen.YaDiskGenerateDoc(file, name, userID, yaDiskData.SaveFolder, client,
|
|
data)
|
|
|
|
if err != nil {
|
|
h.reportError(w, err, http.StatusInternalServerError)
|
|
return "", nil
|
|
}
|
|
case "example":
|
|
generatedFile, err := templategen.ExampleGenerate(file, data)
|
|
if err != nil {
|
|
h.reportError(w, err, http.StatusInternalServerError)
|
|
}
|
|
|
|
generatedFile = strings.TrimPrefix(generatedFile, "./")
|
|
exportUrl = fmt.Sprintf("https://%v/%v", h.opts.Domain, generatedFile)
|
|
default:
|
|
h.reportError(w, errors.New("got unknown storage"), http.StatusInternalServerError)
|
|
return "", nil
|
|
}
|
|
|
|
// Обновляем счетчик генераций
|
|
|
|
return exportUrl, nil
|
|
}
|