add_friend_by_phone_logic.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. package chat
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "wechat-api/ent"
  7. "wechat-api/ent/predicate"
  8. "wechat-api/ent/wx"
  9. "wechat-api/internal/service/addfriend"
  10. "wechat-api/internal/svc"
  11. "wechat-api/internal/types"
  12. "wechat-api/internal/utils/typekit"
  13. "github.com/go-sql-driver/mysql"
  14. "github.com/suyuan32/simple-admin-common/enum/errorcode"
  15. "github.com/suyuan32/simple-admin-common/msg/errormsg"
  16. "github.com/zeromicro/go-zero/core/errorx"
  17. "github.com/zeromicro/go-zero/core/logx"
  18. )
  19. type AddFriendByPhoneLogic struct {
  20. logx.Logger
  21. ctx context.Context
  22. svcCtx *svc.ServiceContext
  23. }
  24. func NewAddFriendByPhoneLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddFriendByPhoneLogic {
  25. return &AddFriendByPhoneLogic{
  26. Logger: logx.WithContext(ctx),
  27. ctx: ctx,
  28. svcCtx: svcCtx}
  29. }
  30. func GetListRandOne(strList []string) string {
  31. one := ""
  32. if len(strList) > 0 {
  33. typekit.ShuffleList(strList)
  34. one = strList[0]
  35. }
  36. return one
  37. }
  38. func (l *AddFriendByPhoneLogic) getWxInfoList(preds ...predicate.Wx) ([]*ent.Wx, error) {
  39. preds = append(preds, wx.StatusEQ(1))
  40. return l.svcCtx.DB.Wx.Query().Where(preds...).All(l.ctx)
  41. }
  42. func (l *AddFriendByPhoneLogic) getWxIdListByOid(Oid uint64, Type uint64) ([]string, error) {
  43. preds := []predicate.Wx{}
  44. preds = append(preds, wx.OrganizationIDEQ(Oid))
  45. if Type == 1 || Type == 3 {
  46. preds = append(preds, wx.CtypeEQ(Type))
  47. }
  48. wxIdList := []string{}
  49. wxInfoList, err := l.getWxInfoList(preds...)
  50. if err == nil {
  51. for _, wxInfo := range wxInfoList {
  52. wxIdList = append(wxIdList, wxInfo.Wxid)
  53. }
  54. }
  55. return wxIdList, err
  56. }
  57. type AddFriendByPhoneInfo struct {
  58. Type int `json:"type"`
  59. WeChatId string `json:"wechat_id"`
  60. Oid int64 `json:"oid"`
  61. Phone string `json:"phone"`
  62. Message string `json:"message"`
  63. CallbackURL string `json:"callback_url"`
  64. }
  65. func (l *AddFriendByPhoneLogic) rebuildAddFriendByPhoneInfos(req *types.AddFriendByPhoneReq,
  66. Oid uint64) ([]AddFriendByPhoneInfo, error) {
  67. var err error
  68. _, req.WeChatIds, req.Phones, err = l.alignWxidsAndPhones(Oid,
  69. uint64(req.Type), req.WeChatIds, req.Phones)
  70. if err != nil {
  71. return nil, err
  72. }
  73. infos := []AddFriendByPhoneInfo{}
  74. for idx, phone := range req.Phones { //以phones为主,逐一绑定wxid,多余的wxid忽略
  75. info := AddFriendByPhoneInfo{Type: req.Type, WeChatId: req.WeChatIds[idx],
  76. Phone: phone, Message: req.Message, CallbackURL: req.CallbackURL, Oid: int64(Oid)}
  77. infos = append(infos, info)
  78. }
  79. return infos, nil
  80. }
  81. /*
  82. 1.手机号是必传的,至少有1个
  83. 2.微信号可以不传为空,这种情况拿当前登录者同租户OID的微信ID随机绑定传入的每个手机号
  84. 3.微信号数量等于或者大于手机号数量,则按输入前后顺序逐一绑定,多出来的微信号忽略
  85. 4.当微信号数量小于手机号数量,多出来的手机号则从输入的微信号中随机找1个绑定
  86. */
  87. func (l *AddFriendByPhoneLogic) alignWxidsAndPhones(Oid uint64, CType uint64,
  88. weChatIds []string, phones []string) (bool, []string, []string, error) {
  89. lenWechatIds := len(weChatIds)
  90. lenPhones := len(phones)
  91. if lenPhones == 0 {
  92. return false, nil, nil, errors.New("phones empty")
  93. }
  94. if lenWechatIds == 0 { //输入wxids为空,从当前库中同Oid的Wxid里随机选1个
  95. allWxIds, err := l.getWxIdListByOid(Oid, CType)
  96. if err != nil {
  97. return false, weChatIds, phones, err
  98. }
  99. if len(allWxIds) == 0 {
  100. return false, weChatIds, phones, fmt.Errorf("wxids empty(%d)", Oid)
  101. }
  102. for range lenPhones {
  103. weChatIds = append(weChatIds, GetListRandOne(allWxIds))
  104. }
  105. } else if lenWechatIds < lenPhones { //当wxids数量小于phones数量,从已输入wxids随机选1个对齐phones
  106. for range lenPhones - lenWechatIds {
  107. weChatIds = append(weChatIds, GetListRandOne(weChatIds))
  108. }
  109. }
  110. //剩下的case就是wxids数量等于或大于phones
  111. return true, weChatIds, phones, nil
  112. }
  113. /*
  114. func (l *AddFriendByPhoneLogic) alignWxidsAndPhones(Oid uint64, CType uint64,
  115. weChatIds []string, phones []string) (bool, []string, []string, error) {
  116. lenWechatIds := len(weChatIds)
  117. lenPhones := len(phones)
  118. //case1: 输入的wxids和phones大小一样,不需要对齐
  119. if lenWechatIds == lenPhones {
  120. return true, weChatIds, phones, nil
  121. }
  122. //case2: 输入的wxids比phones小或者空
  123. if lenWechatIds < lenPhones {
  124. allWxIds, err := l.getWxIdListByOid(Oid, CType)
  125. if err != nil {
  126. return false, weChatIds, phones, err
  127. }
  128. if len(allWxIds) == 0 {
  129. if len(weChatIds) == 0 {
  130. err = errors.New("db wxIds empty")
  131. }
  132. return false, weChatIds, phones, err
  133. }
  134. for i := 0; i < lenPhones-lenWechatIds; i++ {
  135. weChatIds = append(weChatIds, GetRandWxid(allWxIds))
  136. }
  137. } else { //case 3: 输入的wxids比phones大
  138. // for i := 0; i < lenWechatIds-lenPhones; i++ {
  139. // phones = append(phones, GetRandWxid(phones))
  140. // }
  141. }
  142. return true, weChatIds, phones, nil
  143. }
  144. */
  145. func (l *AddFriendByPhoneLogic) AddFriendByPhone(req *types.AddFriendByPhoneReq) (resp *types.BaseMsgResp, err error) {
  146. // todo: add your logic here and delete this line
  147. if len(req.Phones) == 0 {
  148. return nil, errors.New("miss phone")
  149. }
  150. orgID, ok := l.ctx.Value("organizationId").(uint64)
  151. if !ok || orgID == 0 {
  152. return nil, errors.New("content get oid info err")
  153. }
  154. //fmt.Println("before weChatIds:", req.WeChatIds)
  155. //fmt.Println("before phones:", req.Phones)
  156. //apiKeyObj.OrganizationID = 1
  157. if req.Type != 3 {
  158. req.Type = 1
  159. }
  160. infos, err := l.rebuildAddFriendByPhoneInfos(req, orgID)
  161. if err != nil {
  162. return nil, err
  163. }
  164. //fmt.Println("after weChatIds:", req.WeChatIds)
  165. //fmt.Println("after phones:", req.Phones)
  166. //fmt.Println(typekit.PrettyPrint(infos))
  167. var id int64
  168. for _, info := range infos {
  169. id, err = l.AppendWechaFriendAddInfo(&info)
  170. if err != nil {
  171. logx.Errorf("chat.AppendWechaFriendAddLog err : %s", err)
  172. return nil, err
  173. }
  174. logx.Infof("chat.AppendWechaFriendAddLog succ,get id:%d", id)
  175. continue
  176. if req.Type != 1 {
  177. continue //企微忽略后面
  178. }
  179. ret := addfriend.NewAddWechatFriendService(l.ctx, l.svcCtx).
  180. FindFriendByContent(info.WeChatId, info.Phone)
  181. retStr := "fail"
  182. if ret {
  183. retStr = "succ"
  184. }
  185. logx.Infof("call addfriend.NewAddWechatFriendService.FindFriendByContent('%s','%s') maybe %s", info.WeChatId, info.Phone, retStr)
  186. }
  187. return &types.BaseMsgResp{Msg: errormsg.Success, Code: errorcode.OK}, nil
  188. }
  189. func isDuplicateEntry(err error) bool {
  190. var mysqlErr *mysql.MySQLError
  191. if errors.As(err, &mysqlErr) {
  192. return mysqlErr.Number == 1062
  193. }
  194. return false
  195. }
  196. func (l *AddFriendByPhoneLogic) AppendWechaFriendAddInfo(addInfo *AddFriendByPhoneInfo) (int64, error) {
  197. isCanAdd := 0
  198. if addInfo.Type != 1 {
  199. isCanAdd = 1
  200. }
  201. isCanAdd = 1
  202. res, err := l.svcCtx.DB.AddWechatFriendLog.Create().
  203. SetNotNilOwnerWxID(&addInfo.WeChatId).
  204. SetNotNilOwnerWxType(&addInfo.Type).
  205. SetNotNilFindContent(&addInfo.Phone).
  206. SetNotNilMessage(&addInfo.Message).
  207. SetIsCanAdd(isCanAdd).
  208. SetNotNilOrganizationID(&addInfo.Oid).
  209. Save(l.ctx)
  210. id := int64(0)
  211. if err == nil {
  212. id = res.ID
  213. } else {
  214. if isDuplicateEntry(err) {
  215. err = errorx.NewDefaultError("手机号不能重复绑定")
  216. }
  217. }
  218. return id, err
  219. }