package wecom import ( "context" "encoding/json" "entgo.io/ent/dialect/sql" "fmt" "github.com/zeromicro/go-zero/core/logx" "strconv" "sync" "time" "wechat-api/ent" "wechat-api/ent/label" "wechat-api/ent/labellog" "wechat-api/ent/labelrelationship" "wechat-api/ent/wx" "wechat-api/internal/lock" "wechat-api/internal/pkg/wechat_ws" "wechat-api/internal/svc" "wechat-api/workphone/wecom" ) type CustomerPushNoticeHandler struct { svcCtx *svc.ServiceContext lockMap sync.Map // 微信号 -> *sync.Mutex } func NewCustomerPushNoticeHandler(svcCtx *svc.ServiceContext) *CustomerPushNoticeHandler { return &CustomerPushNoticeHandler{ svcCtx: svcCtx, } } // Handle 实现 MessageHandlerStrategy 接口 func (f *CustomerPushNoticeHandler) Handle(ctx context.Context, msg *wechat_ws.MsgJsonObject, svcCtx *svc.ServiceContext) error { message := wecom.CustomerPushNoticeMessage{} err := json.Unmarshal([]byte(msg.Message), &message) logx.Infof("CustomerPushNotice.Message 的内容是:%s", msg.Message) if err != nil { logx.Errorf("Unmarshal.fail") return err } wxInfo, err := svcCtx.DB.Wx.Query(). Where( wx.WxidEQ(message.WxId), // Additional filter by organizationId ).Only(ctx) if err != nil { return err } var labelRelationshipCreates []*ent.LabelRelationshipCreate var ctype uint64 ctype = 3 for _, friend := range message.Contacts { var friendId uint64 //Wxid := strconv.FormatInt(friend.RemoteId, 10) friendType := 1 if friend.Suffix == "微信" { friendType = 1 } else { friendType = 4 } list := friend.PhoneRemark var phone string if len(list) > 0 { phone = list[0] } var sex int if friend.Gender == "Male" { sex = 1 } else if friend.Gender == "Female" { sex = 2 } else { sex = 0 } //修改拉黑后的状态被重置 friendId, err = svcCtx.DB.Contact.Create(). SetWxWxid(message.WxId). SetType(friendType). SetWxid(friend.RemoteId). SetNickname(friend.Name). SetMarkname(friend.Remark). SetHeadimg(friend.Avatar). SetPhone(phone). SetSex(sex). SetCtype(ctype). SetOrganizationID(wxInfo.OrganizationID). OnConflict(). UpdateWxWxid(). UpdateWxid(). UpdateType(). UpdateAccount(). UpdateNickname(). UpdateMarkname(). UpdateHeadimg(). UpdateOrganizationID(). UpdatePhone(). UpdateSex(). UpdateCtype(). ID(ctx) if err != nil { logx.Errorf("Contact.Create 失败, OrgID=%d, err=%v", wxInfo.OrganizationID, err) return err } //判断friend里的labelId="1,2,3,4,5"为空就不处理了,不为空的时候就查下label表里有没有这个labelId,没有就插入,有就跳过 if friend.LabelIds == nil || len(friend.LabelIds) == 0 { logx.Infof("没有labelIds 失败, wx_wxId=%v", message.WxId) continue } labelIdsStr := friend.LabelIds var ids []uint64 ids, err = stringSliceToUint64Slice(labelIdsStr) if err != nil { logx.Infof("labelstring切割失败, labelIds=%v", labelIdsStr) continue } LabelLogs, err := svcCtx.DB.LabelLog.Query(). Where(labellog.LabelIDIn(ids...)). Where(labellog.WxID(message.WxId)). All(ctx) if err != nil || len(LabelLogs) == 0 { logx.Infof("labelLog.Query.fail: 跳过 || 或者查询失败 组织id:%d", wxInfo.OrganizationID) continue } //映射本地的name + type + model + organization_id currentOrgID := wxInfo.OrganizationID for _, remoteLabel := range LabelLogs { labelInfo, err := svcCtx.DB.Label.Query().Where( label.NameEQ(remoteLabel.LabelName), //label.StatusEQ(remoteLabel.LabelName), label.OrganizationID(currentOrgID), ).Only(ctx) if err != nil || ent.IsNotFound(err) { logx.Infof("label id %d not found.fail: ", wxInfo.OrganizationID) continue } //labelId, err := strconv.ParseUint(strconv.FormatUint(labelInfo.ID, 10), 10, 64) if err != nil { fmt.Println("转换出错:", err) continue } _, err = svcCtx.DB.LabelRelationship.Query().Where( labelrelationship.LabelIDEQ(labelInfo.ID), //label.StatusEQ(remoteLabel.LabelName), labelrelationship.ContactIDEQ(friendId), ).Only(ctx) if err != nil || ent.IsNotFound(err) { labelRelationshipCreates = append(labelRelationshipCreates, svcCtx.DB.LabelRelationship.Create(). //SetID(int(label.LabelId)). SetOrganizationID(wxInfo.OrganizationID). SetContactID(friendId). SetStatus(1). SetLabelID(labelInfo.ID). SetCreatedAt(time.Now()). SetUpdatedAt(time.Now()), ) } } } if len(labelRelationshipCreates) > 0 { lock.GetWxIdLockManager().RunWithLock(message.WxId, func() { errShip := svcCtx.DB.LabelRelationship.CreateBulk(labelRelationshipCreates...). OnConflict( sql.ConflictColumns(labelrelationship.FieldLabelID, labelrelationship.FieldContactID), ).DoNothing().Exec(ctx) if errShip != nil { logx.Error("label_relationship.create.fail: ", wxInfo.OrganizationID, labelRelationshipCreates) } }) } return nil } func stringSliceToUint64Slice(strSlice []string) ([]uint64, error) { uintSlice := make([]uint64, 0, len(strSlice)) for _, s := range strSlice { n, err := strconv.ParseUint(s, 10, 64) if err != nil { fmt.Printf("转换失败: %v\n", err) continue // 你可以选择跳过或直接 return 报错 } uintSlice = append(uintSlice, n) } return uintSlice, nil } func (f *CustomerPushNoticeHandler) getWxLock(wxid string) *sync.Mutex { actual, _ := f.lockMap.LoadOrStore(wxid, &sync.Mutex{}) return actual.(*sync.Mutex) }