contact_form.go 12 KB

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