friend_push_notice.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. package MessageHandlers
  2. import (
  3. "context"
  4. "encoding/json"
  5. "entgo.io/ent/dialect/sql"
  6. "github.com/zeromicro/go-zero/core/logx"
  7. "strconv"
  8. "strings"
  9. "sync"
  10. "time"
  11. "wechat-api/ent"
  12. "wechat-api/ent/label"
  13. "wechat-api/ent/labellog"
  14. "wechat-api/ent/labelrelationship"
  15. "wechat-api/ent/wx"
  16. "wechat-api/internal/lock"
  17. "wechat-api/internal/pkg/wechat_ws"
  18. "wechat-api/internal/svc"
  19. "wechat-api/workphone"
  20. )
  21. type FriendPushNoticeHandler struct {
  22. svcCtx *svc.ServiceContext
  23. }
  24. func NewFriendPushNoticeHandler(svcCtx *svc.ServiceContext) *FriendPushNoticeHandler {
  25. return &FriendPushNoticeHandler{
  26. svcCtx: svcCtx,
  27. }
  28. }
  29. func (f *FriendPushNoticeHandler) Handler(msg *wechat_ws.MsgJsonObject) error {
  30. if msg.MsgType == "FriendPushNotice" {
  31. message := workphone.FriendPushNoticeMessage{}
  32. err := json.Unmarshal([]byte(msg.Message), &message)
  33. if err != nil {
  34. return err
  35. }
  36. // 拿到租户 id
  37. wx_info, err := f.svcCtx.DB.Wx.Query().
  38. Where(
  39. wx.WxidEQ(message.WeChatId), // Additional filter by organizationId
  40. ).
  41. Only(context.TODO())
  42. //hookClient := hook.NewHook("", "", "")
  43. for _, friend := range message.Friends {
  44. friendType := 1
  45. //if friend.Type == 1 {
  46. // friendType = 2
  47. // _ = hookClient.RequestChatRoomInfo(friend.FriendId, message.WeChatId)
  48. //} else {
  49. // friendType = 1
  50. //}
  51. _, err = f.svcCtx.DB.Contact.Create().
  52. SetWxWxid(message.WeChatId).
  53. SetType(friendType).
  54. SetWxid(friend.FriendId).
  55. SetAccount(friend.FriendNo).
  56. SetNickname(friend.FriendNick).
  57. SetMarkname(friend.Memo).
  58. SetHeadimg(friend.Avatar).
  59. //SetSex(cast.ToInt(friend.Gender)).
  60. SetOrganizationID(wx_info.OrganizationID).
  61. OnConflict().
  62. UpdateNewValues().
  63. SetType(friendType).
  64. SetOrganizationID(wx_info.OrganizationID).
  65. ID(context.TODO())
  66. if err != nil {
  67. logx.Error("Contact.Create: ", wx_info.OrganizationID)
  68. return err
  69. }
  70. }
  71. }
  72. return nil
  73. }
  74. type FriendPushNoticeTypeHandler struct {
  75. svcCtx *svc.ServiceContext
  76. lockMap sync.Map // 微信号 -> *sync.Mutex
  77. }
  78. func NewFriendPushNoticeTypeHandler(svcCtx *svc.ServiceContext) *FriendPushNoticeTypeHandler {
  79. return &FriendPushNoticeTypeHandler{
  80. svcCtx: svcCtx,
  81. }
  82. }
  83. // Handle 实现 MessageHandlerStrategy 接口
  84. func (f *FriendPushNoticeTypeHandler) Handle(ctx context.Context, msg *wechat_ws.MsgJsonObject, svcCtx *svc.ServiceContext) error {
  85. message := workphone.FriendPushNoticeMessage{}
  86. err := json.Unmarshal([]byte(msg.Message), &message)
  87. logx.Infof("msg.Message 的内容是:%s", msg.Message)
  88. if err != nil {
  89. logx.Errorf("Unmarshal.fail")
  90. return err
  91. }
  92. // 拿到租户 id
  93. wxInfo, err := svcCtx.DB.Wx.Query().
  94. Where(
  95. wx.WxidEQ(message.WeChatId), // Additional filter by organizationId
  96. ).Only(ctx)
  97. if err != nil {
  98. return err
  99. }
  100. var labelRelationshipCreates []*ent.LabelRelationshipCreate
  101. for _, friend := range message.Friends {
  102. var friendId uint64
  103. friendType := 1
  104. if friend.Type == 1 {
  105. friendType = 4
  106. } else {
  107. friendType = 1
  108. }
  109. //修改拉黑后的状态被重置
  110. friendId, err = svcCtx.DB.Contact.Create().
  111. SetWxWxid(message.WeChatId).
  112. SetType(friendType).
  113. SetWxid(friend.FriendId).
  114. SetAccount(friend.FriendNo).
  115. SetNickname(friend.FriendNick).
  116. SetMarkname(friend.Memo).
  117. SetHeadimg(friend.Avatar).
  118. SetOrganizationID(wxInfo.OrganizationID).
  119. OnConflict().
  120. UpdateWxWxid().
  121. UpdateWxid().
  122. UpdateType().
  123. UpdateAccount().
  124. UpdateNickname().
  125. UpdateMarkname().
  126. UpdateHeadimg().
  127. UpdateOrganizationID().
  128. ID(ctx)
  129. if err != nil {
  130. logx.Errorf("Contact.Create 失败, OrgID=%d, err=%v", wxInfo.OrganizationID, err)
  131. return err
  132. }
  133. //判断friend里的labelId="1,2,3,4,5"为空就不处理了,不为空的时候就查下label表里有没有这个labelId,没有就插入,有就跳过
  134. if friend.LabelIds == "" {
  135. logx.Infof("没有labelIds 失败, wx_wxId=%v", message.WeChatId)
  136. continue
  137. }
  138. //获取labelId,并且按照逗号去分割成数组
  139. labelIdsStr := friend.LabelIds
  140. var ids []int
  141. ids, err = ParseCSVToIntSlice(labelIdsStr)
  142. if err != nil {
  143. logx.Infof("labelstring切割失败, labelIds=%v", labelIdsStr)
  144. continue
  145. }
  146. //转换成labelIds的切片,去labelLog里 用labelId in 查下一下数据。
  147. //labelIds := strings.Split(labelIdsStr, ",")
  148. //ids, _ = ParseCSVToIntSlice(labelIdsStr)
  149. LabelLogs, err := svcCtx.DB.LabelLog.Query().
  150. Where(labellog.LabelIDIn(ids...)).
  151. Where(labellog.WxID(message.WeChatId)).
  152. All(ctx)
  153. if err != nil || len(LabelLogs) == 0 {
  154. logx.Error("labelLog.Query.fail: 跳过 || 或者查询失败", wxInfo.OrganizationID)
  155. continue
  156. }
  157. //映射本地的name + type + model + organization_id
  158. currentOrgID := wxInfo.OrganizationID
  159. for _, remoteLabel := range LabelLogs {
  160. labelInfo, err := svcCtx.DB.Label.Query().Where(
  161. label.NameEQ(remoteLabel.LabelName),
  162. //label.StatusEQ(remoteLabel.LabelName),
  163. label.OrganizationID(currentOrgID),
  164. ).Only(ctx)
  165. if err != nil || ent.IsNotFound(err) {
  166. logx.Error("label not found.fail: ", wxInfo.OrganizationID)
  167. continue
  168. }
  169. labelRelationshipCreates = append(labelRelationshipCreates,
  170. svcCtx.DB.LabelRelationship.Create().
  171. //SetID(int(label.LabelId)).
  172. SetOrganizationID(wxInfo.OrganizationID).
  173. SetContactID(friendId).
  174. SetStatus(1).
  175. SetLabelID(labelInfo.ID).
  176. SetCreatedAt(time.Now()).
  177. SetUpdatedAt(time.Now()),
  178. )
  179. //
  180. }
  181. }
  182. if len(labelRelationshipCreates) > 0 {
  183. lock.GetWxIdLockManager().RunWithLock(message.WeChatId, func() {
  184. errShip := svcCtx.DB.LabelRelationship.CreateBulk(labelRelationshipCreates...).
  185. OnConflict(
  186. sql.ConflictColumns(labelrelationship.FieldLabelID, labelrelationship.FieldContactID),
  187. ).DoNothing().Exec(ctx)
  188. if errShip != nil {
  189. logx.Error("label_relationship.create.fail: ", wxInfo.OrganizationID, labelRelationshipCreates)
  190. }
  191. })
  192. }
  193. return nil
  194. }
  195. func ParseCSVToIntSlice(csv string) ([]int, error) {
  196. if csv == "" {
  197. return nil, nil
  198. }
  199. parts := strings.Split(csv, ",")
  200. var result []int
  201. for _, p := range parts {
  202. trimmed := strings.TrimSpace(p)
  203. if trimmed == "" {
  204. continue // 忽略空字符串
  205. }
  206. n, err := strconv.Atoi(trimmed)
  207. if err != nil {
  208. logx.Error("无法将 %s 转换为整数: %v", trimmed, err)
  209. continue // 忽略无效字符
  210. }
  211. result = append(result, n)
  212. }
  213. return result, nil
  214. }
  215. func (f *FriendPushNoticeTypeHandler) getWxLock(wxid string) *sync.Mutex {
  216. actual, _ := f.lockMap.LoadOrStore(wxid, &sync.Mutex{})
  217. return actual.(*sync.Mutex)
  218. }