contact_form.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. package crontask
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "github.com/google/uuid"
  7. "github.com/zeromicro/go-zero/core/logx"
  8. "net/http"
  9. "strconv"
  10. "time"
  11. "wechat-api/ent/contact"
  12. "wechat-api/ent/contactfield"
  13. "wechat-api/ent/contactfieldtemplate"
  14. "wechat-api/ent/custom_types"
  15. "wechat-api/ent/predicate"
  16. "wechat-api/ent/usagedetail"
  17. )
  18. type ResponseItem struct {
  19. DataIndex string `json:"dataIndex"`
  20. Value []string `json:"value"`
  21. }
  22. type FieldPropsOptions struct {
  23. Label string `json:"label"`
  24. Value string `json:"value"`
  25. }
  26. type FieldProps struct {
  27. Options []FieldPropsOptions `json:"options"`
  28. }
  29. type FormData struct {
  30. Title string `json:"title"`
  31. DataIndex string `json:"dataIndex"`
  32. ValueType string `json:"valueType"`
  33. FieldProps FieldProps `json:"fieldProps"`
  34. }
  35. func (l *CronTask) analyze() {
  36. usageDetails := make(map[string]map[string]string)
  37. contactFieldTemplates := make(map[string][]custom_types.ContactFieldTemplate)
  38. template_type_text := "text"
  39. template_type_radio := "radio"
  40. //template_type_date := "date"
  41. template_sex_id := "sex"
  42. template_sex_label := "性别"
  43. template_sex_options_man_label := "男"
  44. template_sex_options_man_value := "男"
  45. template_sex_options_woman_label := "女"
  46. template_sex_options_woman_value := "男"
  47. template_phone_id := "phone"
  48. template_phone_label := "手机号"
  49. //template_name_id := "name"
  50. //template_name_label := "姓名"
  51. //
  52. //template_age_id := "age"
  53. //template_age_label := "年龄(以字符串形式返回阿拉伯数字)"
  54. //
  55. //template_area_id := "area"
  56. //template_area_label := "地区"
  57. //
  58. //template_birthday_id := "birthday"
  59. //template_birthday_label := "出生日期"
  60. //
  61. //template_birtharea_id := "birtharea"
  62. //template_birtharea_label := "出生地"
  63. //
  64. //template_idcard_no_id := "idcard_no"
  65. //template_idcard_no_label := "身份证号"
  66. //
  67. //template_title_id := "title"
  68. //template_title_label := "称呼"
  69. contactBasicFieldTemplates := []custom_types.ContactFieldTemplate{
  70. {
  71. Label: &template_sex_label,
  72. Id: &template_sex_id,
  73. Type: &template_type_radio,
  74. Options: []custom_types.ContactFieldTemplateOptions{
  75. {
  76. Label: &template_sex_options_man_label,
  77. Value: &template_sex_options_man_value,
  78. }, {
  79. Label: &template_sex_options_woman_label,
  80. Value: &template_sex_options_woman_value,
  81. },
  82. },
  83. },
  84. {
  85. Label: &template_phone_label,
  86. Id: &template_phone_id,
  87. Type: &template_type_text,
  88. },
  89. //{
  90. // Label: &template_name_label,
  91. // Id: &template_name_id,
  92. // Type: &template_type_text,
  93. //}, {
  94. // Label: &template_age_label,
  95. // Id: &template_age_id,
  96. // Type: &template_type_text,
  97. //}, {
  98. // Label: &template_area_label,
  99. // Id: &template_area_id,
  100. // Type: &template_type_text,
  101. //}, {
  102. // Label: &template_birthday_label,
  103. // Id: &template_birthday_id,
  104. // Type: &template_type_date,
  105. //}, {
  106. // Label: &template_birtharea_label,
  107. // Id: &template_birtharea_id,
  108. // Type: &template_type_text,
  109. //}, {
  110. // Label: &template_idcard_no_label,
  111. // Id: &template_idcard_no_id,
  112. // Type: &template_type_text,
  113. //}, {
  114. // Label: &template_title_label,
  115. // Id: &template_title_id,
  116. // Type: &template_type_text,
  117. //},
  118. }
  119. var predicates []predicate.UsageDetail
  120. predicates = append(predicates, usagedetail.TypeIn(1, 3, 4, 6))
  121. predicates = append(predicates, usagedetail.AppIn(1, 3, 4, 5))
  122. //yesterdayStart := time.Now().AddDate(0, 0, -1).Truncate(24 * time.Hour)
  123. //yesterdayEnd := yesterdayStart.Add(24 * time.Hour)
  124. //yesterdayEnd := time.Now().Truncate(24 * time.Hour)
  125. //yesterdayStart := yesterdayEnd.AddDate(0, 0, -1)
  126. //predicates = append(predicates, usagedetail.CreatedAtGTE(yesterdayStart))
  127. //predicates = append(predicates, usagedetail.CreatedAtLT(yesterdayEnd))
  128. //logx.Info("yesterdayEnd: ", yesterdayEnd)
  129. //logx.Info("yesterdayStart: ", yesterdayStart)
  130. todayStart := time.Now().AddDate(0, 0, 0).Truncate(24 * time.Hour)
  131. todayEnd := todayStart.Add(24 * time.Hour)
  132. predicates = append(predicates, usagedetail.CreatedAtGTE(todayStart))
  133. predicates = append(predicates, usagedetail.CreatedAtLT(todayEnd))
  134. logx.Info("todayStart: ", todayStart)
  135. logx.Info("todayEnd: ", todayEnd)
  136. data, err := l.svcCtx.DB.UsageDetail.Query().Where(predicates...).All(l.ctx)
  137. logx.Info("usageDetails: ", data)
  138. if err != nil {
  139. return
  140. }
  141. for _, u := range data {
  142. if _, ok := contactFieldTemplates[u.BotID]; !ok {
  143. c, _ := l.svcCtx.DB.ContactFieldTemplate.Query().Where(contactfieldtemplate.OrganizationID(u.OrganizationID)).First(l.ctx)
  144. if c != nil {
  145. contactFieldTemplates[u.BotID] = c.Template
  146. } else {
  147. contactFieldTemplates[u.BotID] = nil
  148. }
  149. }
  150. if contactFieldTemplates[u.BotID] == nil {
  151. continue
  152. }
  153. if _, ok := usageDetails[u.BotID]; !ok {
  154. usageDetails[u.BotID] = make(map[string]string)
  155. }
  156. usageDetails[u.BotID][u.ReceiverID] += fmt.Sprintf("用户:%s\n机器人:%s\n", u.Request, u.Response)
  157. }
  158. logx.Info("usageDetails: ", usageDetails)
  159. for botID, template := range contactFieldTemplates {
  160. if template == nil {
  161. template = contactBasicFieldTemplates
  162. } else {
  163. template = append(template, contactBasicFieldTemplates...)
  164. }
  165. for receiverID, messages := range usageDetails[botID] {
  166. logx.Info("messages: ", messages)
  167. logx.Info("template: ", template)
  168. result, _ := l.openaiRequest(messages, template)
  169. logx.Info("result: ", result)
  170. if result == nil {
  171. continue
  172. }
  173. _ = l.UpdateContactFields(botID, receiverID, result)
  174. }
  175. }
  176. }
  177. func (l *CronTask) openaiRequest(messages string, template []custom_types.ContactFieldTemplate) ([]ResponseItem, error) {
  178. //formData := ConvertFormData(template)
  179. //jsonBytes, err := json.Marshal(formData)
  180. //if err != nil {
  181. // return nil, err
  182. //}
  183. //jsonStr := string(jsonBytes)
  184. //logx.Info("contactFieldTemplates: ", jsonStr)
  185. //req := &types.CompApiReq{
  186. // types.CompCtlReq{
  187. // "form",
  188. // "",
  189. // false,
  190. // "",
  191. // },
  192. // types.StdCompApiReq{
  193. // "gpt-4o",
  194. // []types.StdCompMessage{},
  195. // false,
  196. // nil,
  197. // },
  198. // types.FastGptSpecReq{
  199. // "",
  200. // "",
  201. // "",
  202. // false,
  203. // map[string]string{
  204. // "form_data": jsonStr,
  205. // "chat_history": messages,
  206. // "external_id": uuid.New().String(),
  207. // },
  208. // },
  209. //}
  210. //resp, err := compapi.NewClient(l.ctx, compapi.WithApiBase("http://new-api.gkscrm.com/v1/"),
  211. // compapi.WithApiKey("sk-wwttAtdLcTfeF7F2Eb9d3592Bd4c487f8e8fA544D6C4BbA9")).
  212. // Chat(req)
  213. //if err == nil && resp != nil && len(resp.Choices) > 0 {
  214. // //logx.Info("resp.Choices: ", resp.Choices[0].Message.Content)
  215. // var items []ResponseItem
  216. // err = json.Unmarshal([]byte(resp.Choices[0].Message.Content), &items)
  217. // if err != nil {
  218. // return nil, err
  219. // }
  220. // return items, nil
  221. //} else if resp != nil && len(resp.Choices) == 0 {
  222. // return nil, err
  223. //}
  224. url := "https://toolsapi-debug.gkscrm.com/call_center/form/extract"
  225. bodyData := map[string]interface{}{
  226. "form_data": ConvertFormData(template),
  227. "chat_history": messages,
  228. "external_id": uuid.New().String(),
  229. }
  230. logx.Info("bodyData: %+v", bodyData)
  231. bodyBytes, err := json.Marshal(bodyData)
  232. if err != nil {
  233. return nil, err
  234. }
  235. req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes))
  236. if err != nil {
  237. return nil, err
  238. }
  239. req.Header.Set("Content-Type", "application/json")
  240. req.Header.Set("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIn0.ZS9jnsLPCnmc8L_lu4yaQFp34vwWF1mHlHSBYrY5JVs")
  241. client := &http.Client{}
  242. resp, err := client.Do(req)
  243. if err != nil || resp == nil || resp.Body == nil {
  244. logx.Error("read body error: ", err)
  245. return nil, err
  246. }
  247. logx.Info("err: ", err)
  248. if err != nil {
  249. return nil, err
  250. }
  251. defer resp.Body.Close()
  252. if resp.StatusCode != http.StatusOK {
  253. return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
  254. }
  255. //var result []ResponseItem
  256. var fullResp struct {
  257. Data []ResponseItem `json:"data"`
  258. }
  259. err = json.NewDecoder(resp.Body).Decode(&fullResp)
  260. if err != nil {
  261. return nil, err
  262. }
  263. return fullResp.Data, nil
  264. //return nil, err
  265. }
  266. func (l *CronTask) UpdateContactFields(botID string, receiverID string, fields []ResponseItem) error {
  267. basic_ids := []string{"sex", "phone", "name", "age", "area", "birthday", "birtharea", "idcard_no", "title"}
  268. c, _ := l.svcCtx.DB.Contact.Query().Where(contact.WxWxidEQ(botID), contact.WxidEQ(receiverID)).First(l.ctx)
  269. if c == nil {
  270. return fmt.Errorf("Contact not find")
  271. }
  272. for _, field := range fields {
  273. if contains(basic_ids, field.DataIndex) {
  274. if len(field.Value) == 0 {
  275. continue
  276. }
  277. value := 0
  278. if field.DataIndex == "sex" && c.Sex == 0 {
  279. if field.Value[0] == "男" {
  280. value = 1
  281. } else if field.Value[0] == "女" {
  282. value = 2
  283. }
  284. _, err := l.svcCtx.DB.Contact.Update().
  285. Where(contact.WxidEQ(receiverID)).
  286. SetSex(value).
  287. Save(l.ctx)
  288. if err != nil {
  289. continue
  290. }
  291. } else if field.DataIndex == "phone" && c.Phone == "" {
  292. _, err := l.svcCtx.DB.Contact.Update().
  293. Where(contact.WxidEQ(receiverID)).
  294. SetPhone(field.Value[0]).
  295. Save(l.ctx)
  296. if err != nil {
  297. continue
  298. }
  299. } else if field.DataIndex == "name" && c.Cname == "" {
  300. _, err := l.svcCtx.DB.Contact.Update().
  301. Where(contact.WxidEQ(receiverID)).
  302. SetCname(field.Value[0]).
  303. Save(l.ctx)
  304. if err != nil {
  305. continue
  306. }
  307. } else if field.DataIndex == "age" && c.Cage == 0 {
  308. num, err := strconv.Atoi(field.Value[0])
  309. if err != nil {
  310. continue
  311. }
  312. _, err = l.svcCtx.DB.Contact.Update().
  313. Where(contact.WxidEQ(receiverID)).
  314. SetCage(num).
  315. Save(l.ctx)
  316. if err != nil {
  317. continue
  318. }
  319. } else if field.DataIndex == "area" && c.Carea == "" {
  320. _, err := l.svcCtx.DB.Contact.Update().
  321. Where(contact.WxidEQ(receiverID)).
  322. SetCarea(field.Value[0]).
  323. Save(l.ctx)
  324. if err != nil {
  325. continue
  326. }
  327. } else if field.DataIndex == "birthday" && c.Cbirthday == "" {
  328. _, err := l.svcCtx.DB.Contact.Update().
  329. Where(contact.WxidEQ(receiverID)).
  330. SetCbirthday(field.Value[0]).
  331. Save(l.ctx)
  332. if err != nil {
  333. continue
  334. }
  335. } else if field.DataIndex == "birtharea" && c.Cbirtharea == "" {
  336. _, err := l.svcCtx.DB.Contact.Update().
  337. Where(contact.WxidEQ(receiverID)).
  338. SetCbirtharea(field.Value[0]).
  339. Save(l.ctx)
  340. if err != nil {
  341. continue
  342. }
  343. } else if field.DataIndex == "idcard_no" && c.CidcardNo == "" {
  344. _, err := l.svcCtx.DB.Contact.Update().
  345. Where(contact.WxidEQ(receiverID)).
  346. SetCidcardNo(field.Value[0]).
  347. Save(l.ctx)
  348. if err != nil {
  349. continue
  350. }
  351. } else if field.DataIndex == "title" && c.Ctitle == "" {
  352. _, err := l.svcCtx.DB.Contact.Update().
  353. Where(contact.WxidEQ(receiverID)).
  354. SetCtitle(field.Value[0]).
  355. Save(l.ctx)
  356. if err != nil {
  357. continue
  358. }
  359. }
  360. } else {
  361. f, _ := l.svcCtx.DB.ContactField.Query().Where(contactfield.ContactID(c.ID), contactfield.FormID(field.DataIndex)).First(l.ctx)
  362. if f == nil {
  363. if field.Value != nil && len(field.Value) > 0 && field.Value[0] != "" {
  364. _, err := l.svcCtx.DB.ContactField.Create().
  365. SetContactID(c.ID).
  366. SetFormID(field.DataIndex).
  367. SetValue(field.Value).
  368. Save(l.ctx)
  369. if err != nil {
  370. continue
  371. }
  372. }
  373. } else {
  374. if field.Value != nil {
  375. if len(field.Value) == 0 || field.Value[0] == "" {
  376. continue
  377. }
  378. _, err := l.svcCtx.DB.ContactField.UpdateOneID(f.ID).
  379. SetValue(field.Value).
  380. Save(l.ctx)
  381. if err != nil {
  382. continue
  383. }
  384. }
  385. }
  386. }
  387. }
  388. return nil
  389. }
  390. func ConvertFormData(input []custom_types.ContactFieldTemplate) []FormData {
  391. result := make([]FormData, len(input))
  392. for i, item := range input {
  393. options := make([]FieldPropsOptions, len(item.Options))
  394. for j, opt := range item.Options {
  395. options[j] = FieldPropsOptions{
  396. Label: *opt.Label,
  397. Value: *opt.Value,
  398. }
  399. }
  400. result[i] = FormData{
  401. Title: *item.Label,
  402. DataIndex: *item.Id,
  403. ValueType: *item.Type,
  404. FieldProps: FieldProps{
  405. Options: options,
  406. },
  407. }
  408. }
  409. return result
  410. }
  411. func contains(strs []string, target string) bool {
  412. for _, s := range strs {
  413. if s == target {
  414. return true
  415. }
  416. }
  417. return false
  418. }