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 }