|
@@ -0,0 +1,208 @@
|
|
|
|
+package crontask
|
|
|
|
+
|
|
|
|
+import (
|
|
|
|
+ "bytes"
|
|
|
|
+ "encoding/json"
|
|
|
|
+ "fmt"
|
|
|
|
+ "github.com/google/uuid"
|
|
|
|
+ "github.com/zeromicro/go-zero/core/logx"
|
|
|
|
+ "net/http"
|
|
|
|
+ "time"
|
|
|
|
+ "wechat-api/ent/contact"
|
|
|
|
+ "wechat-api/ent/contactfield"
|
|
|
|
+ "wechat-api/ent/contactfieldtemplate"
|
|
|
|
+ "wechat-api/ent/custom_types"
|
|
|
|
+ "wechat-api/ent/predicate"
|
|
|
|
+ "wechat-api/ent/usagedetail"
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+type ResponseItem struct {
|
|
|
|
+ DataIndex string `json:"dataIndex"`
|
|
|
|
+ Value []string `json:"value"`
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type FieldPropsOptions struct {
|
|
|
|
+ Label string `json:"label"`
|
|
|
|
+ Value string `json:"value"`
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type FieldProps struct {
|
|
|
|
+ Options []FieldPropsOptions `json:"options"`
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type FormData struct {
|
|
|
|
+ Title string `json:"title"`
|
|
|
|
+ DataIndex string `json:"dataIndex"`
|
|
|
|
+ ValueType string `json:"valueType"`
|
|
|
|
+ FieldProps FieldProps `json:"fieldProps"`
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (l *CronTask) analyze() {
|
|
|
|
+ usageDetails := make(map[string]map[string]string)
|
|
|
|
+ contactFieldTemplates := make(map[string][]custom_types.ContactFieldTemplate)
|
|
|
|
+
|
|
|
|
+ var predicates []predicate.UsageDetail
|
|
|
|
+ predicates = append(predicates, usagedetail.TypeIn(1, 3))
|
|
|
|
+ predicates = append(predicates, usagedetail.AppIn(1, 3, 4, 5))
|
|
|
|
+ yesterdayStart := time.Now().AddDate(0, 0, -1).Truncate(24 * time.Hour)
|
|
|
|
+ yesterdayEnd := yesterdayStart.Add(24 * time.Hour)
|
|
|
|
+ predicates = append(predicates, usagedetail.CreatedAtGTE(yesterdayStart))
|
|
|
|
+ predicates = append(predicates, usagedetail.CreatedAtLT(yesterdayEnd))
|
|
|
|
+
|
|
|
|
+ //todayStart := time.Now().AddDate(0, 0, 0).Truncate(24 * time.Hour)
|
|
|
|
+ //todayEnd := todayStart.Add(24 * time.Hour)
|
|
|
|
+ //predicates = append(predicates, usagedetail.CreatedAtGTE(todayStart))
|
|
|
|
+ //predicates = append(predicates, usagedetail.CreatedAtLT(todayEnd))
|
|
|
|
+
|
|
|
|
+ data, err := l.svcCtx.DB.UsageDetail.Query().Where(predicates...).All(l.ctx)
|
|
|
|
+ logx.Info("todayStart: ", todayStart)
|
|
|
|
+ logx.Info("todayEnd: ", todayEnd)
|
|
|
|
+ logx.Info("usageDetails: ", data)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for _, u := range data {
|
|
|
|
+ if _, ok := contactFieldTemplates[u.BotID]; !ok {
|
|
|
|
+ c, _ := l.svcCtx.DB.ContactFieldTemplate.Query().Where(contactfieldtemplate.OrganizationID(u.OrganizationID)).First(l.ctx)
|
|
|
|
+ if c != nil {
|
|
|
|
+ contactFieldTemplates[u.BotID] = c.Template
|
|
|
|
+ } else {
|
|
|
|
+ contactFieldTemplates[u.BotID] = nil
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if contactFieldTemplates[u.BotID] == nil {
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+ if _, ok := usageDetails[u.BotID]; !ok {
|
|
|
|
+ usageDetails[u.BotID] = make(map[string]string)
|
|
|
|
+ }
|
|
|
|
+ usageDetails[u.BotID][u.ReceiverID] += fmt.Sprintf("用户:%s\n机器人:%s\n", u.Request, u.Response)
|
|
|
|
+ }
|
|
|
|
+ logx.Info("contactFieldTemplates: ", contactFieldTemplates)
|
|
|
|
+ logx.Info("usageDetails: ", usageDetails)
|
|
|
|
+ for botID, template := range contactFieldTemplates {
|
|
|
|
+ if template == nil {
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+ for receiverID, messages := range usageDetails[botID] {
|
|
|
|
+ result, _ := openaiRequest(messages, template)
|
|
|
|
+ logx.Info("result: ", result)
|
|
|
|
+ if result == nil {
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+ _ = l.UpdateContactFields(botID, receiverID, result)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func openaiRequest(messages string, template []custom_types.ContactFieldTemplate) ([]ResponseItem, error) {
|
|
|
|
+ url := "https://toolsapi-debug.gkscrm.com/call_center/form/extract"
|
|
|
|
+ bodyData := map[string]interface{}{
|
|
|
|
+ "form_data": ConvertFormData(template),
|
|
|
|
+ "chat_history": messages,
|
|
|
|
+ "external_id": uuid.New().String(),
|
|
|
|
+ }
|
|
|
|
+ logx.Infof("bodyData: %+v", bodyData)
|
|
|
|
+ bodyBytes, err := json.Marshal(bodyData)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes))
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ req.Header.Set("Content-Type", "application/json")
|
|
|
|
+ req.Header.Set("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIn0.ZS9jnsLPCnmc8L_lu4yaQFp34vwWF1mHlHSBYrY5JVs")
|
|
|
|
+
|
|
|
|
+ client := &http.Client{}
|
|
|
|
+ resp, err := client.Do(req)
|
|
|
|
+ if err != nil || resp == nil || resp.Body == nil {
|
|
|
|
+ logx.Error("read body error: ", err)
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ logx.Info("err: ", err)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ defer resp.Body.Close()
|
|
|
|
+
|
|
|
|
+ if resp.StatusCode != http.StatusOK {
|
|
|
|
+ return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //var result []ResponseItem
|
|
|
|
+ var fullResp struct {
|
|
|
|
+ Data []ResponseItem `json:"data"`
|
|
|
|
+ }
|
|
|
|
+ err = json.NewDecoder(resp.Body).Decode(&fullResp)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return fullResp.Data, nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (l *CronTask) UpdateContactFields(botID string, receiverID string, fields []ResponseItem) error {
|
|
|
|
+ logx.Infof("botID: ", botID)
|
|
|
|
+ logx.Infof("receiverID: ", receiverID)
|
|
|
|
+ logx.Infof("fields: ", fields)
|
|
|
|
+ c, _ := l.svcCtx.DB.Contact.Query().Where(contact.WxWxidEQ(botID), contact.WxidEQ(receiverID)).First(l.ctx)
|
|
|
|
+ logx.Infof("c: ", c)
|
|
|
|
+ if c == nil {
|
|
|
|
+ return fmt.Errorf("Contact not find")
|
|
|
|
+ }
|
|
|
|
+ for _, field := range fields {
|
|
|
|
+ f, _ := l.svcCtx.DB.ContactField.Query().Where(contactfield.ContactID(c.ID), contactfield.FormID(field.DataIndex)).First(l.ctx)
|
|
|
|
+ if f == nil {
|
|
|
|
+ if field.Value != nil && len(field.Value) > 0 {
|
|
|
|
+ _, err := l.svcCtx.DB.ContactField.Create().
|
|
|
|
+ SetContactID(c.ID).
|
|
|
|
+ SetFormID(field.DataIndex).
|
|
|
|
+ SetValue(field.Value).
|
|
|
|
+ Save(l.ctx)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ if field.Value != nil {
|
|
|
|
+ if len(field.Value) == 0 {
|
|
|
|
+ field.Value = []string{""}
|
|
|
|
+ }
|
|
|
|
+ _, err := l.svcCtx.DB.ContactField.UpdateOneID(f.ID).
|
|
|
|
+ SetValue(field.Value).
|
|
|
|
+ Save(l.ctx)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func ConvertFormData(input []custom_types.ContactFieldTemplate) []FormData {
|
|
|
|
+ result := make([]FormData, len(input))
|
|
|
|
+ for i, item := range input {
|
|
|
|
+ options := make([]FieldPropsOptions, len(item.Options))
|
|
|
|
+ for j, opt := range item.Options {
|
|
|
|
+ options[j] = FieldPropsOptions{
|
|
|
|
+ Label: *opt.Label,
|
|
|
|
+ Value: *opt.Value,
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ result[i] = FormData{
|
|
|
|
+ Title: *item.Label,
|
|
|
|
+ DataIndex: *item.Id,
|
|
|
|
+ ValueType: *item.Type,
|
|
|
|
+ FieldProps: FieldProps{
|
|
|
|
+ Options: options,
|
|
|
|
+ },
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return result
|
|
|
|
+}
|