package cp_r import ( "encoding/json" "fmt" "git.hilo.cn/hilo-common/_const/common" "git.hilo.cn/hilo-common/_const/enum/diamond_e" "git.hilo.cn/hilo-common/_const/enum/msg_e" "git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/myerr/comerr" "git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/sdk/tencentyun" "git.hilo.cn/hilo-common/txop/bag_tx" "git.hilo.cn/hilo-common/txop/diamond_tx" "git.hilo.cn/hilo-common/txop/headwear_tx" "git.hilo.cn/hilo-common/txop/msg" "git.hilo.cn/hilo-common/utils" "github.com/gin-gonic/gin" "hilo-user/_const/enum/cp_e" "hilo-user/cv/cp_cv" "hilo-user/cv/user_cv" "hilo-user/domain/cache/user_c" "hilo-user/domain/model/cp_m" "hilo-user/domain/model/user_m" "hilo-user/domain/service/cp_s" "hilo-user/myerr" "hilo-user/myerr/bizerr" "hilo-user/req" "hilo-user/resp" "strconv" "time" ) // @Tags cp关系 // @Summary 检查用户是否绑定了cp // @Param externalId query string true "用户的externalId" // @Success 200 {object} cp_cv.CheckCpRelationRes // @Router /v2/cp/relation/check [get] func CheckUserCpRelation(c *gin.Context) (*mycontext.MyContext, error) { myCtx := mycontext.CreateMyContext(c.Keys) externalId := c.Query("externalId") if externalId == "" { return myCtx, bizerr.InvalidParameter } _, lang, err := req.GetUserIdLang(c, myCtx) if err != nil { return myCtx, err } if externalId == "" { return myCtx, bizerr.InvalidParameter } model := domain.CreateModelContext(myCtx) user, err := user_m.GetUserByExtId(model, externalId) if err != nil { return myCtx, err } cp, err := cp_m.GetCp(model, user.ID) if err != nil { return myCtx, err } if cp.Id > 0 { return myCtx, myerr.ToLocal(msg.GetErrByLanguage(model, common.MSG_ID_ALREADY_HAS_CP, lang, comerr.AlreadyHasCp)) } msg, err := msg.GetResMultiTextBy(model, common.MSG_ID_INVITE_CP, lang) if err != nil { return myCtx, err } resp.ResponseOk(c, cp_cv.CheckCpRelationRes{Diamond: cp_e.CpRelationInviteDiamond, Msg: msg}) return myCtx, nil } // @Tags cp关系 // @Summary 发送cp邀请/发起解除cp // @Param externalId formData string true "对方的externalId" // @Param type formData int true "类型1.发起邀请2.发起解除" // @Success 200 // @Router /v2/cp/relation [post] func CpRelation(c *gin.Context) (*mycontext.MyContext, error) { myCtx := mycontext.CreateMyContext(c.Keys) externalId := c.PostForm("externalId") if externalId == "" { return myCtx, bizerr.InvalidParameter } myUserId, lang, err := req.GetUserIdLang(c, myCtx) if err != nil { return myCtx, err } optType, err := strconv.Atoi(c.PostForm("type")) if err != nil || optType > 2 || optType < 1 { return myCtx, bizerr.InvalidParameter } if optType == 1 { // 邀请 err = cp_s.InviteCpRelation(myCtx, myUserId, externalId, lang) if err != nil { myCtx.Log.Errorf("InviteCpRelation myUserId:%d, err:%v", myUserId, err) return myCtx, err } } else { // 发起解除 err = cp_s.CancelCpRelation(myCtx, myUserId, externalId, lang) if err != nil { myCtx.Log.Errorf("CancelCpRelation myUserId:%d, err:%v", myUserId, err) return myCtx, err } } resp.ResponseOk(c, nil) return myCtx, nil } // @Tags cp关系 // @Summary 回应cp邀请 // @Param externalId formData string true "对方用户的externalId" // @Param type formData int true "类型1.接受2.拒绝" // @Success 200 // @Router /v2/cp/relation/invite/reply [post] func ReplyCpInvite(c *gin.Context) (*mycontext.MyContext, error) { myCtx := mycontext.CreateMyContext(c.Keys) externalId := c.PostForm("externalId") if externalId == "" { return myCtx, myerr.WrapErr(bizerr.InvalidParameter) } optType, err := strconv.Atoi(c.PostForm("type")) if err != nil || optType > 2 || optType < 1 { return myCtx, myerr.WrapErr(bizerr.InvalidParameter) } myUserId, lang, err := req.GetUserIdLang(c, myCtx) if err != nil { return myCtx, err } model := domain.CreateModelContext(myCtx) user, err := user_m.GetUser(model, myUserId) if err != nil { return myCtx, err } userSender, err := user_m.GetUserByExtId(model, externalId) if err != nil { return myCtx, err } if userSender.ID == myUserId { return myCtx, myerr.WrapErr(bizerr.InvalidParameter) } cpRecord, err := cp_m.GetCpInvite(model, userSender.ID, user.ID, cp_e.CpInvite) if err != nil { model.Log.Errorf("ReplyCpInvite userSender:%d, user:%d, err:%v", userSender.ID, user.ID, err) return myCtx, err } if cpRecord == nil || cpRecord.Id == 0 { return myCtx, myerr.ToLocal(msg.GetErrByLanguage(model, common.MSG_ID_ALREADY_EXPIRED, lang, comerr.AlreadyExpired)) } if optType == 1 { // 接受的时候 // 自己是否有cp了 myCp, err := cp_m.GetCp(model, myUserId) if err != nil { return myCtx, err } if myCp.Id > 0 { return myCtx, myerr.ToLocal(msg.GetErrByLanguage(model, common.MSG_ID_ALREADY_HAS_CP, lang, comerr.AlreadyHasCp)) } // 对方是否已经有cp了 senderCp, err := cp_m.GetCp(model, userSender.ID) if err != nil { return myCtx, err } if senderCp.Id > 0 { return myCtx, myerr.ToLocal(msg.GetErrByLanguage(model, common.MSG_ID_ALREADY_HAS_CP, lang, comerr.AlreadyHasCp)) } } err = model.Transaction(func(model *domain.Model) error { // 更新邀请状态 updateStatus := cp_e.CpInviteAccept if optType == 2 { // 拒接 updateStatus = cp_e.CpInviteRefuse } err = cp_m.UpdateStatusCpInvite(model, cpRecord.Id, updateStatus) if err != nil { model.Log.Errorf("ReplyCpInvite userSender:%d, user:%d, status:%d, err:%v", userSender.ID, user.ID, updateStatus, err) return err } var msgData []byte if optType == 1 { // 接受 // 写入cp关系表 cpId, err := cp_m.CreateCp(model, userSender.ID, user.ID) if err != nil { model.Log.Errorf("ReplyCpInvite userSender:%d, user:%d, status:%d, err:%v", userSender.ID, user.ID, updateStatus, err) return err } // 初始化cp等级 if err := cp_m.InitCpLevel(model, mysql.ID(cpId), userSender.ID, user.ID); err != nil { model.Log.Errorf("ReplyCpInvite InitCpLevel fail:%v-%v-%v", userSender.ID, user.ID, err) return err } // 初始化cp纪念日 if err := cp_m.InitCpAnniversary(model, cp_m.CpRelation{ Id: mysql.ID(cpId), UserId1: userSender.ID, UserId2: user.ID, }, lang); err != nil { model.Log.Errorf("ReplyCpInvite InitCpAnniversary fail:%v-%v-%v", userSender.ID, user.ID, err) return err } // 发放告白礼物 if _, err = bag_tx.SendUserBag(model, userSender.ID, 1, cp_e.CpConfessionGiftId, 1, 3, "告白礼物"); err != nil { model.Log.Errorf("ReplyCpInvite userSender:%d, user:%d, status:%d, err:%v", userSender.ID, user.ID, updateStatus, err) return err } // 发放头饰 for _, u := range []*user_m.User{userSender, user} { headwearId := cp_e.CpMaleHeadwearId if u.Sex == mysql.WOMAN { headwearId = cp_e.CpFemaleHeadwearId } if err = headwear_tx.SendHeadwear(model, u.ID, mysql.ID(headwearId), 9999); err != nil { model.Log.Errorf("ReplyCpInvite user:%d, headwearId:%d, err:%v", u.ID, headwearId, err) return err } } // 私信-接受 content, err := msg.GetResMultiTextBy(model, common.MSG_ID_BIND_CP_SUCCEED, lang) if err != nil { return err } tip, err := msg.GetResMultiTextBy(model, common.MSG_ID_SEND_CP_GIFT, lang) if err != nil { return err } msgData, _ = json.Marshal(cp_m.CpAcceptInviteMessage{ Identifier: "CpAcceptInviteMessage", Msg: content, Tip: fmt.Sprintf(tip, userSender.Code), Sender: user_m.ToUserTiny(userSender), Receiver: user_m.ToUserTiny(user), }) } else { // 拒绝 // 退费 err = diamond_tx.SendDiamond(model, cpRecord.UserId, diamond_e.CpInviteRefund, cpRecord.Id, cpRecord.DiamondNum, msg_e.MgrSendDiamondProperty) if err != nil { model.Log.Errorf("ReplyCpInvite UserId:%d, err:%v", cpRecord.UserId, err) return err } // 私信-拒绝 content, err := msg.GetResMultiTextBy(model, common.MSG_ID_REJECTED_CP_INVITE, lang) if err != nil { return err } msgData, _ = json.Marshal(cp_m.CpDenyInviteMessage{ Identifier: "CpDenyInviteMessage", Msg: fmt.Sprintf(content, user.Nick), Sender: user_m.ToUserTiny(user), }) } if err := tencentyun.BatchSendCustomMsg(model, 1, userSender.ExternalId, []string{user.ExternalId}, string(msgData), "cp邀请"); err != nil { model.Log.Errorf("BatchSendCustomMsg fail:%v", err) return err } return nil }) if err != nil { model.Log.Errorf("ReplyCpInvite myUserId:%d, err:%v", myUserId, err) return myCtx, err } resp.ResponseOk(c, nil) return myCtx, nil } // @Tags cp关系 // @Summary 回应cp解除 // @Param externalId formData string true "对方的externalId" // @Param type formData int true "类型1.撤销2.接受" // @Success 200 // @Router /v2/cp/relation/cancel/reply [post] func ReplyCpCancel(c *gin.Context) (*mycontext.MyContext, error) { myCtx := mycontext.CreateMyContext(c.Keys) externalId := c.PostForm("externalId") if externalId == "" { return myCtx, bizerr.InvalidParameter } optType, err := strconv.Atoi(c.PostForm("type")) if err != nil || optType > 2 || optType < 1 { return myCtx, bizerr.InvalidParameter } myUserId, lang, err := req.GetUserIdLang(c, myCtx) if err != nil { return myCtx, err } model := domain.CreateModelContext(myCtx) myUser, err := user_m.GetUser(model, myUserId) if err != nil { return myCtx, err } user2, err := user_m.GetUserByExtId(model, externalId) if err != nil { return myCtx, err } if user2.ID == myUserId { return myCtx, bizerr.InvalidParameter } cpCancel, err := cp_m.GetCpCancel(model, []uint64{myUser.ID, user2.ID}, cp_e.CpCancel) if err != nil { model.Log.Errorf("ReplyCpCancel myUser:%d, user2:%d, err:%v", myUser.ID, user2.ID, err) return myCtx, err } if cpCancel == nil || cpCancel.Id == 0 { return myCtx, myerr.ToLocal(msg.GetErrByLanguage(model, common.MSG_ID_ALREADY_EXPIRED, lang, comerr.AlreadyExpired)) } if optType == 1 { // 撤销,只有自己能撤销自己的申请 if cpCancel.UserId != myUserId { return myCtx, bizerr.InvalidParameter } } else { // 接受,只有对方能接受 if cpCancel.RecUserId != myUserId { return myCtx, bizerr.InvalidParameter } } err = model.Transaction(func(model *domain.Model) error { // 更新邀请状态 updateStatus := cp_e.CpCancelRevoke if optType == 2 { // 接受 updateStatus = cp_e.CpCancelAccept } err = cp_m.UpdateStatusCpCancel(model, cpCancel.Id, updateStatus) if err != nil { model.Log.Errorf("ReplyCpCancel myUser:%d, user2:%d, status:%d, err:%v", myUser.ID, user2.ID, updateStatus, err) return err } var msgData []byte if optType == 1 { // 撤销解除 // 私信 content, err := msg.GetResMultiTextBy(model, common.MSG_ID_CANCEL_UNBIND_CP, lang) if err != nil { return err } msgData, _ = json.Marshal(cp_m.CpDealCancelMessage{ Identifier: "CpDealCancelMessage", Msg: fmt.Sprintf(content, myUser.Nick), Status: 1, }) } else { // 接受解除 // 删除cp关系表的记录 err = cp_m.DelCpRelation(model, myUser.ID, user2.ID) if err != nil { model.Log.Errorf("ReplyCpCancel myUser:%d, user2:%d, status:%d, err:%v", myUser.ID, user2.ID, updateStatus, err) return err } // 私信-接受解除 content, err := msg.GetResMultiTextBy(model, common.MSG_ID_UNBIND_CP_SUCCEED, lang) if err != nil { return err } msgData, _ = json.Marshal(cp_m.CpDealCancelMessage{ Identifier: "CpDealCancelMessage", Msg: content, Status: 2, }) } if err := tencentyun.BatchSendCustomMsg(model, 1, myUser.ExternalId, []string{user2.ExternalId}, string(msgData), "cp解除"); err != nil { model.Log.Errorf("ReplyCpCancel BatchSendCustomMsg fail:%v", err) return err } return nil }) if err != nil { model.Log.Errorf("ReplyCpCancel myUserId:%d, err:%v", myUserId, err) return myCtx, err } resp.ResponseOk(c, cp_cv.CheckCpRelationRes{}) return myCtx, nil } type CpDetail struct { CpInfo cp_cv.CvCpInfo `json:"cpInfo"` // cp信息 CpLevel cp_cv.CvCpLevel `json:"cpLevel"` // cp等级 } // @Tags cp关系 // @Summary 详情页cp数据 // @Param externalId query string true "用户的externalId" // @Success 200 {object} CpDetail // @Router /v2/cp/relation/detail [get] func CpDetailPage(c *gin.Context) (*mycontext.MyContext, error) { myCtx := mycontext.CreateMyContext(c.Keys) externalId := c.Query("externalId") if externalId == "" { return myCtx, bizerr.InvalidParameter } model := domain.CreateModelContext(myCtx) user, err := user_m.GetUserByExtId(model, externalId) if err != nil { return myCtx, err } cp, err := cp_m.GetCp(model, user.ID) if err != nil { return myCtx, err } var res *CpDetail if cp.Id > 0 { userIds := []uint64{cp.UserId1, cp.UserId2} userMap, err := user_c.GetUserTinyMap(model, userIds, false) if err != nil { return myCtx, err } res = new(CpDetail) // 返回值 level := cp_m.GetCpLevel(model, cp.Id) res.CpLevel = cp_cv.CvCpLevel{ Level: level.Level, Points: cp_e.CpLevelPoints[level.Level] + level.Points, StartPoints: cp_e.CpLevelPoints[level.Level], ExpireAtUnix: level.ExpireAt.Unix(), SettlementDate: level.ExpireAt.Format(utils.DATE_FORMAT), } if res.CpLevel.Level != cp_e.CpLevelMax { res.CpLevel.EndPoints = cp_e.CpLevelPoints[res.CpLevel.Level+1] } res.CpInfo = cp_cv.CvCpInfo{ UserInfo: user_cv.UserTinyToCvTiny(userMap[cp.UserId1]), CpUserInfo: user_cv.UserTinyToCvTiny(userMap[cp.UserId2]), CpDays: int(time.Now().Sub(cp.CreatedTime).Hours()/24) + 1, CreatedUnix: cp.CreatedTime.Unix(), } } resp.ResponseOk(c, res) return myCtx, nil } // @Tags cp关系 // @Summary 检查cp的im是否失效 // @Param msgType query int true "类型" // @Param msgId query int true "消息id" // @Success 200 {object} cp_cv.CheckCpImRes // @Router /v2/cp/im/check [get] func CheckCpImExpire(c *gin.Context) (*mycontext.MyContext, error) { myCtx := mycontext.CreateMyContext(c.Keys) userId, lang, err := req.GetUserIdLang(c, myCtx) if err != nil { return myCtx, err } msgType, err := strconv.Atoi(c.Query("msgType")) if err != nil { return myCtx, err } if msgType < 1 || msgType > 2 { return myCtx, bizerr.InvalidParameter } msgId, err := strconv.ParseUint(c.Query("msgId"), 10, 64) if err != nil { return myCtx, err } if msgId <= 0 { return myCtx, bizerr.InvalidParameter } model := domain.CreateModelContext(myCtx) var resId common.MsgIdType switch msgType { case 1: // 邀请的消息im检查是否过期 cpRecord, err := cp_m.GetCpInviteById(model, msgId, userId) if err != nil { model.Log.Errorf("CheckCpImExpire userId:%d, msgType:%d, msgId:%d, err:%v", userId, msgType, msgId, err) return myCtx, err } if cpRecord == nil || cpRecord.Id == 0 { model.Log.Errorf("CheckCpImExpire userId:%d, msgType:%d, msgId:%d, err:%v", userId, msgType, msgId, bizerr.InvalidParameter) return myCtx, bizerr.InvalidParameter } switch cpRecord.Status { case cp_e.CpInvite: if userId == cpRecord.UserId { // 发起人 resId = common.MSG_ID_WAITING_ACCEPTED // 等待对方接受 } case cp_e.CpInviteAccept: resId = common.MSG_ID_INVITATION_ACCEPTED // 已接受 case cp_e.CpInviteRefuse: resId = common.MSG_ID_INVITATION_REFUSED // 已拒绝 case cp_e.CpInviteExpired: resId = common.MSG_ID_ALREADY_EXPIRED } case 2: // 解除的消息im检查是否过期 cpCancel, err := cp_m.GetCpCancelById(model, msgId, userId) if err != nil { model.Log.Errorf("CheckCpImExpire userId:%d, msgType:%d, msgId:%d, err:%v", userId, msgType, msgId, err) return myCtx, err } if cpCancel == nil || cpCancel.Id == 0 { model.Log.Errorf("CheckCpImExpire userId:%d, msgType:%d, msgId:%d, err:%v", userId, msgType, msgId, bizerr.InvalidParameter) return myCtx, bizerr.InvalidParameter } switch cpCancel.Status { case cp_e.CpCancel: if userId == cpCancel.UserId { // 发起人 resId = common.MSG_ID_WAITING_ACCEPTED // 等待对方接受 } case cp_e.CpCancelRevoke: resId = common.MSG_ID_HAS_BEEN_CANCELED // 已被取消 case cp_e.CpCancelAccept, cp_e.CpCancelAcceptAuto: resId = common.MSG_ID_CP_UNBOUND // 已解绑 } } if resId > 0 { return myCtx, myerr.ToLocal(msg.GetErrByLanguage(model, resId, lang, comerr.AlreadyExpired)) } resp.ResponseOk(c, cp_cv.CheckCpImRes{}) return myCtx, nil }