send_wx_on_timeout.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. package crontask
  2. import (
  3. "context"
  4. "regexp"
  5. "time"
  6. "wechat-api/ent"
  7. "wechat-api/ent/contact"
  8. "wechat-api/ent/custom_types"
  9. "wechat-api/ent/labelrelationship"
  10. "wechat-api/ent/messagerecords"
  11. "wechat-api/ent/sopnode"
  12. "wechat-api/ent/sopstage"
  13. "wechat-api/ent/soptask"
  14. "wechat-api/internal/utils/dberrorhandler"
  15. )
  16. func (l *CronTask) sendWxOnTimeout() {
  17. ctx := context.Background()
  18. startTime := time.Now()
  19. sopTask, _ := l.svcCtx.DB.SopTask.Query().
  20. Where(
  21. soptask.StatusEQ(3),
  22. soptask.DeletedAtIsNil(),
  23. ).
  24. All(l.ctx)
  25. sopTasks := make([]uint64, 0)
  26. for _, st := range sopTask {
  27. sopTasks = append(sopTasks, st.ID)
  28. }
  29. sopStages, _ := l.svcCtx.DB.SopStage.Query().Where(sopstage.TaskIDIn(sopTasks...), sopstage.DeletedAtIsNil()).All(l.ctx)
  30. stageMap := make(map[uint64]*ent.SopStage)
  31. for _, stage := range sopStages {
  32. stageMap[stage.ID] = stage
  33. }
  34. // 查询所有 no_reply_condition 值非 0 的 sop_node 记录
  35. nodes, err := l.svcCtx.DB.SopNode.Query().
  36. Where(sopnode.NoReplyConditionNEQ(0)).
  37. Where(sopnode.HasSopStageWith(
  38. sopstage.StatusEQ(1),
  39. sopstage.DeletedAtIsNil(),
  40. sopstage.HasSopTaskWith(
  41. soptask.StatusEQ(3),
  42. soptask.DeletedAtIsNil(),
  43. ),
  44. )).
  45. All(ctx)
  46. if err != nil {
  47. l.Logger.Errorf("get node list failed %v", err)
  48. return
  49. }
  50. // 遍历 nodes,将其各记录 parent_id 的值存入一个新的数组 parent_nodes 中
  51. //parentNodes := make([]uint64, 0)
  52. //stages := make([]uint64, 0)
  53. messages := make([]*ent.MessageRecords, 0)
  54. for _, node := range nodes {
  55. var coef uint64 = 1
  56. switch node.NoReplyUnit {
  57. case "W":
  58. coef = 60 * 24 * 7
  59. case "D":
  60. coef = 60 * 24
  61. case "h":
  62. coef = 60
  63. }
  64. // 查询 node 对应的 stage 记录
  65. lowerBound := startTime.Add(-time.Minute * time.Duration(node.NoReplyCondition*coef+2))
  66. upperBound := startTime.Add(-time.Minute * time.Duration(node.NoReplyCondition*coef))
  67. if node.ParentID == 0 {
  68. messages, _ = l.svcCtx.DB.MessageRecords.Query().
  69. Where(messagerecords.StatusEQ(3)).
  70. Where(messagerecords.SourceTypeEQ(3)).
  71. Where(messagerecords.SourceIDEQ(node.StageID)).
  72. Where(messagerecords.SubSourceIDEQ(0)).
  73. Where(messagerecords.SendTimeGTE(lowerBound)).
  74. Where(messagerecords.SendTimeLTE(upperBound)).
  75. All(ctx)
  76. } else {
  77. messages, _ = l.svcCtx.DB.MessageRecords.Query().
  78. Where(messagerecords.StatusEQ(3)).
  79. Where(messagerecords.SourceTypeEQ(4)).
  80. Where(messagerecords.SourceIDIn(node.ParentID)).
  81. Where(messagerecords.SubSourceIDEQ(0)).
  82. Where(messagerecords.SendTimeGTE(lowerBound)).
  83. Where(messagerecords.SendTimeLTE(upperBound)).
  84. All(ctx)
  85. }
  86. for _, s := range messages {
  87. // 判断 s.Id 是否是 s.ContactID 的最新记录
  88. latest, _ := l.svcCtx.DB.MessageRecords.Query().
  89. Where(messagerecords.ContactIDEQ(s.ContactID)).
  90. Where(messagerecords.StatusEQ(3)).
  91. Order(ent.Desc(messagerecords.FieldID)).
  92. First(ctx)
  93. if latest.ID == s.ID {
  94. // 创建 MessageRecords 记录
  95. if node.ActionMessage != nil {
  96. for i, c := range node.ActionMessage {
  97. meta := custom_types.Meta{}
  98. if c.Meta != nil {
  99. meta.Filename = c.Meta.Filename
  100. }
  101. _, _ = l.svcCtx.DB.MessageRecords.Create().
  102. SetStatus(1).
  103. SetBotWxid(s.BotWxid).
  104. SetContactID(s.ContactID).
  105. SetContactType(s.ContactType).
  106. SetContactWxid(s.ContactWxid).
  107. SetContentType(c.Type).
  108. SetContent(c.Content).
  109. SetMeta(meta).
  110. SetSourceType(4).
  111. SetSourceID(node.ID).
  112. SetSubSourceID(uint64(i)).
  113. SetOrganizationID(s.OrganizationID).
  114. Save(ctx)
  115. }
  116. } else {
  117. meta := custom_types.Meta{}
  118. _, _ = l.svcCtx.DB.MessageRecords.Create().
  119. SetStatus(1).
  120. SetBotWxid(s.BotWxid).
  121. SetContactID(s.ContactID).
  122. SetContactType(s.ContactType).
  123. SetContactWxid(s.ContactWxid).
  124. SetContentType(1).
  125. SetMeta(meta).
  126. SetSourceType(4).
  127. SetSourceID(node.ID).
  128. SetSubSourceID(0).
  129. SetOrganizationID(s.OrganizationID).
  130. Save(ctx)
  131. }
  132. if node.ActionForward != nil {
  133. if node.ActionForward.Wxid != "" {
  134. forwardWxids := splitString(node.ActionForward.Wxid)
  135. for _, forwardWxid := range forwardWxids {
  136. for i, message := range node.ActionForward.Action {
  137. meta := custom_types.Meta{}
  138. if message.Meta != nil {
  139. meta.Filename = message.Meta.Filename
  140. }
  141. contactInfo, _ := l.svcCtx.DB.Contact.Query().Where(contact.WxWxidEQ(s.BotWxid), contact.WxidEQ(s.ContactWxid)).First(l.ctx)
  142. content := varReplace(message.Content, contactInfo)
  143. _, _ = l.svcCtx.DB.MessageRecords.Create().
  144. SetBotWxid(s.BotWxid).
  145. SetContactID(0).
  146. SetContactType(0).
  147. SetContactWxid(forwardWxid).
  148. SetContentType(message.Type).
  149. SetContent(content).
  150. SetMeta(meta).
  151. SetSourceType(4).
  152. SetSourceID(node.ID).
  153. SetSubSourceID(s.ContactID + uint64(i)).
  154. SetOrganizationID(s.OrganizationID).
  155. Save(l.ctx)
  156. }
  157. }
  158. }
  159. }
  160. // 查询当前联系人的标签关系
  161. currentLabelRelationships, _ := l.svcCtx.DB.LabelRelationship.Query().Where(labelrelationship.ContactID(s.ContactID)).All(l.ctx)
  162. if currentLabelRelationships == nil {
  163. continue
  164. }
  165. // 提取当前标签ID
  166. var currentLabelIds []uint64
  167. for _, relationship := range currentLabelRelationships {
  168. currentLabelIds = append(currentLabelIds, relationship.LabelID)
  169. }
  170. contact := &ent.Contact{
  171. ID: s.ContactID,
  172. Type: s.ContentType,
  173. WxWxid: s.BotWxid,
  174. Wxid: s.ContactWxid,
  175. }
  176. if node.ActionLabelAdd != nil || node.ActionLabelDel != nil {
  177. _ = l.AddLabelRelationships(stageMap, *contact, currentLabelIds, node.ActionLabelAdd, node.ActionLabelDel, s.OrganizationID)
  178. }
  179. }
  180. }
  181. }
  182. finishTime := time.Now()
  183. l.Logger.Infof("This process cost %v", finishTime.Sub(startTime).String())
  184. return
  185. }
  186. func splitString(input string) []string {
  187. // Define the regular expression pattern to match Chinese comma, English comma, and Chinese enumeration comma
  188. pattern := `[,,、]`
  189. re := regexp.MustCompile(pattern)
  190. // Split the input string based on the pattern
  191. return re.Split(input, -1)
  192. }
  193. func (l *CronTask) AddLabelRelationships(sopStages map[uint64]*ent.SopStage, contact ent.Contact, currentLabelIds []uint64, addLabelIds []uint64, delLabelIds []uint64, organizationId uint64) (err error) {
  194. //// 开始事务
  195. //tx, err := l.svcCtx.DB.Tx(context.Background())
  196. //if err != nil {
  197. // return dberrorhandler.DefaultEntError(l.Logger, err, nil)
  198. //}
  199. // 获取 addLabelIds 中不在 currentLabelIds 中的标签ID
  200. var newLabelIds []uint64
  201. var remLabelIds []uint64
  202. var finalLabelIds []uint64
  203. // 创建一个映射,用于快速查找 currentLabelIds 中的元素
  204. currentLabelIdSet := make(map[uint64]struct{})
  205. for _, id := range currentLabelIds {
  206. currentLabelIdSet[id] = struct{}{}
  207. }
  208. delLabelIdSet := make(map[uint64]struct{})
  209. for _, id := range delLabelIds {
  210. delLabelIdSet[id] = struct{}{}
  211. }
  212. if addLabelIds != nil {
  213. // 遍历 addLabelIds,找出不在 currentLabelIds 中的元素
  214. for _, id := range addLabelIds {
  215. if _, ce := currentLabelIdSet[id]; !ce {
  216. if _, re := delLabelIdSet[id]; !re {
  217. newLabelIds = append(newLabelIds, id)
  218. }
  219. }
  220. }
  221. if len(newLabelIds) > 0 {
  222. // 创建需要新增的标签关系
  223. for _, id := range newLabelIds {
  224. currentLabelIdSet[id] = struct{}{}
  225. _, err = l.svcCtx.DB.LabelRelationship.Create().
  226. SetLabelID(id).
  227. SetContactID(contact.ID).
  228. SetOrganizationID(organizationId).
  229. Save(l.ctx)
  230. if err != nil {
  231. //_ = tx.Rollback()
  232. return dberrorhandler.DefaultEntError(l.Logger, err, nil)
  233. }
  234. }
  235. // 合并 currentLabelIds 和 newLabelIds
  236. currentLabelIds = append(currentLabelIds, newLabelIds...)
  237. }
  238. }
  239. if delLabelIds != nil {
  240. // 遍历 delLabelIds,找出在 currentLabelIds 中的元素
  241. for _, id := range delLabelIds {
  242. if _, exists := currentLabelIdSet[id]; exists {
  243. remLabelIds = append(remLabelIds, id)
  244. delete(currentLabelIdSet, id)
  245. }
  246. }
  247. if len(remLabelIds) > 0 {
  248. _, err = l.svcCtx.DB.LabelRelationship.Delete().Where(labelrelationship.LabelIDIn(remLabelIds...), labelrelationship.ContactIDEQ(contact.ID), labelrelationship.OrganizationIDEQ(organizationId)).Exec(l.ctx)
  249. if err != nil {
  250. //_ = tx.Rollback()
  251. return dberrorhandler.DefaultEntError(l.Logger, err, nil)
  252. }
  253. }
  254. }
  255. if len(newLabelIds) == 0 && len(remLabelIds) == 0 {
  256. return nil
  257. }
  258. for id := range currentLabelIdSet {
  259. finalLabelIds = append(finalLabelIds, id)
  260. }
  261. // 遍历 sop_stages,找出满足条件的 stage
  262. for key, stage := range sopStages {
  263. if stage != nil && stage.ConditionType == 1 && isLabelIdListMatchFilter(finalLabelIds, stage.ConditionOperator, stage.ConditionList) {
  264. // 判断是否有 contact_wxid、source_type、source_id、sub_source_id 相同的记录
  265. _, err := l.svcCtx.DB.MessageRecords.Query().
  266. Where(
  267. messagerecords.ContactWxid(contact.Wxid),
  268. messagerecords.SourceType(3),
  269. messagerecords.SourceID(stage.ID),
  270. messagerecords.SubSourceID(0),
  271. ).
  272. Only(l.ctx)
  273. if !ent.IsNotFound(err) {
  274. continue
  275. }
  276. // 判断ActionMessage是否为空
  277. sourceType := 3
  278. if stage.ActionMessage != nil {
  279. for i, message := range stage.ActionMessage {
  280. meta := custom_types.Meta{}
  281. if message.Meta != nil {
  282. meta.Filename = message.Meta.Filename
  283. }
  284. _, _ = l.svcCtx.DB.MessageRecords.Create().
  285. SetNotNilBotWxid(&contact.WxWxid).
  286. SetNotNilContactID(&contact.ID).
  287. SetNotNilContactType(&contact.Type).
  288. SetNotNilContactWxid(&contact.Wxid).
  289. SetNotNilContentType(&message.Type).
  290. SetNotNilContent(&message.Content).
  291. SetMeta(meta).
  292. SetNotNilSourceType(&sourceType).
  293. SetNotNilSourceID(&stage.ID).
  294. SetSubSourceID(uint64(i)).
  295. SetOrganizationID(organizationId).
  296. Save(l.ctx)
  297. //if err != nil {
  298. // return dberrorhandler.DefaultEntError(l.Logger, err, nil)
  299. //}
  300. }
  301. }
  302. if stage.ActionForward != nil {
  303. if stage.ActionForward.Wxid != "" {
  304. forwardWxids := splitString(stage.ActionForward.Wxid)
  305. for _, forwardWxid := range forwardWxids {
  306. for i, message := range stage.ActionForward.Action {
  307. meta := custom_types.Meta{}
  308. if message.Meta != nil {
  309. meta.Filename = message.Meta.Filename
  310. }
  311. _, err = l.svcCtx.DB.MessageRecords.Create().
  312. SetBotWxid(contact.WxWxid).
  313. SetContactID(0).
  314. SetContactType(0).
  315. SetContactWxid(forwardWxid).
  316. SetContentType(message.Type).
  317. SetContent(message.Content).
  318. SetMeta(meta).
  319. SetSourceType(sourceType).
  320. SetSourceID(stage.ID).
  321. SetSubSourceID(contact.ID + uint64(i)).
  322. SetOrganizationID(organizationId).
  323. Save(l.ctx)
  324. }
  325. }
  326. }
  327. }
  328. if stage.ActionLabelAdd != nil || stage.ActionLabelDel != nil {
  329. // 递归调用 AddLabelRelationships
  330. sopStages[key] = nil
  331. err = l.AddLabelRelationships(sopStages, contact, finalLabelIds, stage.ActionLabelAdd, stage.ActionLabelDel, organizationId)
  332. if err != nil {
  333. //_ = tx.Rollback()
  334. return err
  335. }
  336. }
  337. }
  338. }
  339. // 所有操作成功,提交事务
  340. //err = tx.Commit()
  341. //if err != nil {
  342. // return dberrorhandler.DefaultEntError(l.Logger, err, nil)
  343. //}
  344. return nil
  345. }
  346. func isLabelIdListMatchFilter(labelIdList []uint64, conditionOperator int, conditionList []custom_types.Condition) bool {
  347. labelIdSet := make(map[uint64]struct{})
  348. for _, id := range labelIdList {
  349. labelIdSet[id] = struct{}{}
  350. }
  351. for _, condition := range conditionList {
  352. match := false
  353. for _, id := range condition.LabelIdList {
  354. if _, ok := labelIdSet[id]; ok {
  355. match = true
  356. break
  357. }
  358. }
  359. if condition.Equal == 2 {
  360. match = !match
  361. }
  362. if conditionOperator == 1 && !match {
  363. return false
  364. } else if conditionOperator == 2 && match {
  365. return true
  366. }
  367. }
  368. return conditionOperator == 1
  369. }