contact_form.go 10 KB

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