diff --git a/_const/enum/cp_e/cp_relation.go b/_const/enum/cp_e/cp_relation.go new file mode 100644 index 0000000000000000000000000000000000000000..86bd635e83a87d8504076cb35583ff298f9e019c --- /dev/null +++ b/_const/enum/cp_e/cp_relation.go @@ -0,0 +1,23 @@ +package cp_e + +import "git.hilo.cn/hilo-common/resource/mysql" + +type CpInviteStatus mysql.Type +type CpCancelStatus mysql.Type + +const ( + //新用户 + CpRelationInviteDiamond = 18888 + + //1.未接受2.已接受3.拒接导致退费4.过期导致退费 + CpInvite CpInviteStatus = 1 + CpInviteAccept CpInviteStatus = 2 + CpInviteRefuse CpInviteStatus = 3 + CpInviteExpired CpInviteStatus = 4 + + //1.未处理2.发起者已撤销3.对方已确认4.到期自动确认 + CpCancel CpCancelStatus = 1 + CpCancelRevoke CpCancelStatus = 2 + CpCancelAccept CpCancelStatus = 3 + CpCancelAcceptAuto CpCancelStatus = 4 +) diff --git a/corn/cp_corn/cp.go b/corn/cp_corn/cp.go new file mode 100644 index 0000000000000000000000000000000000000000..aed68b3893ad4c736c4f548f19c44615482b480b --- /dev/null +++ b/corn/cp_corn/cp.go @@ -0,0 +1,93 @@ +package cp_corn + +import ( + "git.hilo.cn/hilo-common/_const/enum/diamond_e" + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/mylogrus" + "git.hilo.cn/hilo-common/resource/config" + "git.hilo.cn/hilo-common/utils" + "github.com/robfig/cron" + "hilo-user/_const/enum/cp_e" + "hilo-user/domain/model/cp_m" + "hilo-user/domain/model/diamond_m" + "time" +) + +// cp邀请、解除到期结算 +func CpInviteCancelInit() { + if !config.IsMaster() { + return + } + mylogrus.MyLog.Infof("CpInviteCancelInit") + + // 每2min监测一次 + c := cron.New() + spec := "0 */2 * * * *" + if !config.AppIsRelease() { + spec = "0 */1 * * * ?" // 测服每1分钟 + } + _ = c.AddFunc(spec, func() { + defer utils.CheckGoPanic() + model := domain.CreateModelNil() + // 获取超过24小时没被处理的cp邀请 + inviteList, err := cp_m.GetCpInviteByTime(model, time.Now().AddDate(0, 0, -1)) + if err != nil { + model.Log.Errorf("CpInviteCancelInit err:%v", err) + return + } + for _, v := range inviteList { + model.Log.Infof("CpInviteCancelInit invite:%+v", v) + err = model.Transaction(func(model *domain.Model) error { + // 更新邀请记录 + err = cp_m.UpdateStatusCpInvite(model, v.Id, cp_e.CpInviteExpired) + if err != nil { + model.Log.Errorf("CpInviteCancelInit Id:%d, err:%v", v.Id, err) + return err + } + // 退费 + err = diamond_m.ChangeDiamondAccountDetail(model, diamond_e.CpInviteRefund, v.Id, v.UserId, v.DiamondNum) + if err != nil { + model.Log.Errorf("CpInviteCancelInit Id:%d, err:%v", v.Id, err) + return err + } + return nil + }) + if err != nil { + model.Log.Errorf("CpInviteCancelInit invite:%+v, err:%v", v, err) + return + } + time.Sleep(time.Millisecond * 10) + } + + // 获取超过24小时没被处理的cp解除申请 + cancelList, err := cp_m.GetCpCancelByTime(model, time.Now().AddDate(0, 0, -1)) + if err != nil { + model.Log.Errorf("CpInviteCancelInit err:%v", err) + return + } + for _, v := range cancelList { + model.Log.Infof("CpInviteCancelInit cancel:%+v", v) + err = model.Transaction(func(model *domain.Model) error { + // 更新解除记录 + err = cp_m.UpdateStatusCpCancel(model, v.Id, cp_e.CpCancelAcceptAuto) + if err != nil { + model.Log.Errorf("CpInviteCancelInit Id:%d, err:%v", v.Id, err) + return err + } + // 删除cp关系表的记录 + err = cp_m.DelCpRelation(model, v.UserId, v.RecUserId) + if err != nil { + model.Log.Errorf("CpInviteCancelInit Id:%d, err:%v", v.Id, err) + return err + } + return nil + }) + if err != nil { + model.Log.Errorf("CpInviteCancelInit cancel:%+v, err:%v", v, err) + return + } + time.Sleep(time.Millisecond * 10) + } + }) + c.Start() +} diff --git a/corn/cron.go b/corn/cron.go new file mode 100644 index 0000000000000000000000000000000000000000..09bf09f3ca6f8a9de1d56bc2d53d69ed4486e3d0 --- /dev/null +++ b/corn/cron.go @@ -0,0 +1,7 @@ +package cron + +import "hilo-user/corn/cp_corn" + +func Init() { + cp_corn.CpInviteCancelInit() +} diff --git a/cv/cp_cv/cp_relation.go b/cv/cp_cv/cp_relation.go new file mode 100644 index 0000000000000000000000000000000000000000..b5df88cc0150d0c817848dbd2c4eae1cf664cf65 --- /dev/null +++ b/cv/cp_cv/cp_relation.go @@ -0,0 +1,5 @@ +package cp_cv + +type CheckCpRelationRes struct { + NoBind bool `json:"isBind"` +} diff --git a/cv/user_cv/user.go b/cv/user_cv/user.go index f493554f42759ae0a38af2ac2655985f077557f4..993abad9cb2f8cc7d005606a26b2fd72c44adb03 100644 --- a/cv/user_cv/user.go +++ b/cv/user_cv/user.go @@ -326,3 +326,18 @@ func GetUserBaseMap(userIds []mysql.ID, myUserId mysql.ID) (map[mysql.ID]*CvUser } return mapIdUser, nil } + +type CvUserTiny struct { + Id uint64 `json:"id,omitempty"` + ExternalId string `json:"externalId"` + Avatar string `json:"avatar"` + Nick string `json:"nick"` + Sex uint8 `json:"sex"` + Code string `json:"code"` + Country string `json:"country"` + CountryIcon string `json:"countryIcon"` + IsPrettyCode bool `json:"isPrettyCode"` // 是否靓号 + IsLogout bool `json:"isLogout"` //是否注销 true:已经注销, false:没有注销 + //生日,如果是其它人用户信息,年龄则按照是否展示显示,如果是本人,年龄则按照是否存在展示 + Birthday *uint64 `json:"birthday"` +} diff --git a/domain/model/cp_m/cp_relation.go b/domain/model/cp_m/cp_relation.go new file mode 100644 index 0000000000000000000000000000000000000000..fc5300392c968a256c2c15b2dbee33b903aa612a --- /dev/null +++ b/domain/model/cp_m/cp_relation.go @@ -0,0 +1,241 @@ +package cp_m + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/utils" + "gorm.io/gorm" + "hilo-user/_const/enum/cp_e" + "hilo-user/domain/model/user_m" + "hilo-user/myerr/bizerr" + "time" +) + +type CpRelation struct { + Id uint64 `json:"id"` + UserId1 uint64 `json:"userId1"` + UserId2 uint64 `json:"userId2"` + CreatedTime time.Time `json:"createdTime"` +} + +type CpInvite struct { + Id uint64 `json:"id"` + UserId uint64 `json:"userId"` + InviteUserId uint64 `json:"inviteUserId"` + DiamondNum uint32 `json:"diamondNum"` + Status cp_e.CpInviteStatus `json:"status"` +} + +// 发送私信-发起邀请 +type CpInviteMessage struct { + Identifier string `json:"identifier"` + Msg string `json:"msg"` + Sender *user_m.UserTiny `json:"sender"` +} + +// 发送私信-接受邀请 +type CpAcceptInviteMessage struct { + Identifier string `json:"identifier"` + Msg string `json:"msg"` + Sender *user_m.UserTiny `json:"sender"` + Receiver *user_m.UserTiny `json:"receiver"` +} + +// 发送私信-拒绝邀请 +type CpDenyInviteMessage struct { + Identifier string `json:"identifier"` + Msg string `json:"msg"` + Sender *user_m.UserTiny `json:"sender"` +} + +type CpCancel struct { + Id uint64 `json:"id"` + UserId uint64 `json:"userId"` + RecUserId uint64 `json:"recUserId"` + Status cp_e.CpCancelStatus `json:"status"` +} + +// 发送私信(解除) +type CpCancelMessage struct { + Identifier string `json:"identifier"` + Msg string `json:"msg"` + Status uint8 `json:"status"` //1.发起解除2.撤销解除3.接受解除 +} + +type Cp struct { + Id uint64 `json:"id"` + UserId1 uint64 `json:"userId1"` + UserId2 uint64 `json:"userId2"` + DisconnectSecond int64 `json:"disconnectSecond"` + Score int32 `json:"score"` + DayScore int32 `json:"dayScore"` + PeriodDay string `json:"periodDay"` + WeekScore int32 `json:"weekScore"` + PeriodWeek string `json:"periodWeek"` + MonthScore int32 `json:"monthScore"` + PeriodMonth string `json:"periodMonth"` + Status int8 `json:"status"` + CreatedTime time.Time `json:"createdTime"` +} + +func CreateCp(model *domain.Model, userId1, userId2 uint64) error { + userIds := []uint64{userId1, userId2} + oldCp := make([]*Cp, 0) + // 这两个人以前是否有旧的cp关系 + err := model.DB().Model(Cp{}).Where("status = 1 and user_id1 in (?) and user_id2 in (?)", userIds, userIds).Find(&oldCp).Error + if err != nil { + model.Log.Errorf("CreateCp user1:%d, user2:%d, err:%v", userId1, userId2, err) + return err + } + createdTime := time.Now() + if len(oldCp) > 0 { + // 旧的cp关系,有效的时间给他加回去 + oldSecond := time.Duration(time.Now().Unix() - oldCp[0].CreatedTime.Unix() - oldCp[0].DisconnectSecond) + if oldSecond > 0 { + createdTime = createdTime.Add(-1 * time.Second * time.Duration(time.Now().Unix()-oldCp[0].CreatedTime.Unix()-oldCp[0].DisconnectSecond)) + } + } + + result := model.DB().Exec("insert into cp_relation(user_id1, user_id2, created_time) select ?,?,? where not exists (select user_id1 from cp_relation where user_id1 in (?) or user_id2 in (?));", userId1, userId2, createdTime.Format(utils.DATETIME_FORMAT), userIds, userIds) + if result.Error != nil { + model.Log.Errorf("CreateCp user1:%d, user2:%d, err:%v", userId1, userId2, result.Error) + return result.Error + } + if result.RowsAffected <= 0 { + model.Log.Errorf("CreateCp user1:%d, user2:%d, err:%v", userId1, userId2, bizerr.TransactionFailed) + return bizerr.TransactionFailed + } + return nil +} + +func GetCp(model *domain.Model, userId uint64) (*CpRelation, error) { + res := new(CpRelation) + err := model.DB().Model(CpRelation{}).Where("user_id1 = ? or user_id2 = ?", userId, userId).First(&res).Error + if err != nil { + if err == gorm.ErrRecordNotFound { + return res, nil + } + model.Log.Errorf("CreateCp userId:%d, err:%v", userId, err) + return nil, err + } + return res, nil +} + +func GetCpInvite(model *domain.Model, userId, userIdInvite uint64, status cp_e.CpInviteStatus) (*CpInvite, error) { + res := new(CpInvite) + err := model.DB().Model(CpInvite{}).Where(CpInvite{UserId: userId, InviteUserId: userIdInvite, Status: status}).First(&res).Error + if err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + model.Log.Errorf("GetCpInvite user1:%d, user2:%d, err:%v", userId, userIdInvite, err) + return nil, err + } + return res, nil +} + +func CreateCpInvite(model *domain.Model, userId, userIdInvite uint64, diamondNum uint32) (uint64, error) { + cpInvite := CpInvite{UserId: userId, InviteUserId: userIdInvite, DiamondNum: diamondNum, Status: cp_e.CpInvite} + err := model.DB().Model(CpInvite{}).Create(&cpInvite).Error + if err != nil { + model.Log.Errorf("CreateCpInvite user1:%d, user2:%d, diamondNum:%d, err:%v", userId, userIdInvite, diamondNum, err) + return 0, err + } + return cpInvite.Id, nil +} + +// userId:发起邀请者 +func UpdateStatusCpInvite(model *domain.Model, id uint64, status cp_e.CpInviteStatus) error { + result := model.DB().Exec("update cp_invite set status=? where id=? and status=? limit 1", status, id, cp_e.CpInvite) + if result.Error != nil { + model.Log.Errorf("UpdateStatusCpInvite id:%d, status:%d, err:%v", id, status, result.Error) + return result.Error + } + if result.RowsAffected <= 0 { + model.Log.Errorf("UpdateStatusCpInvite id:%d, status:%d, err:%v", id, status, bizerr.TransactionFailed) + return bizerr.TransactionFailed + } + return nil +} + +func CreateCpCancel(model *domain.Model, userId, recUserId uint64) (uint64, error) { + cpCancel := CpCancel{UserId: userId, RecUserId: recUserId, Status: cp_e.CpCancel} + err := model.DB().Model(CpCancel{}).Create(&cpCancel).Error + if err != nil { + model.Log.Errorf("CreateCpCancel user1:%d, user2:%d, err:%v", userId, recUserId, err) + return 0, err + } + return cpCancel.Id, nil +} + +func GetCpCancel(model *domain.Model, userIds []uint64, status cp_e.CpCancelStatus) (*CpCancel, error) { + res := new(CpCancel) + err := model.DB().Model(CpCancel{}).Where("status = ? and user_id in (?) and rec_user_id in (?)", status, userIds, userIds).First(&res).Error + if err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + model.Log.Errorf("GetCpCancel users:%d, err:%v", userIds, err) + return nil, err + } + return res, nil +} + +func GetCpCancelWithMe(model *domain.Model, userId uint64, status cp_e.CpCancelStatus) (*CpCancel, error) { + res := new(CpCancel) + err := model.DB().Model(CpCancel{}).Where("status = ? and (user_id = ? or rec_user_id = ?)", status, userId, userId).First(&res).Error + if err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + model.Log.Errorf("GetCpCancel user1:%d, err:%v", userId, err) + return nil, err + } + return res, nil +} + +func UpdateStatusCpCancel(model *domain.Model, id uint64, status cp_e.CpCancelStatus) error { + result := model.DB().Exec("update cp_cancel set status=? where id=? and status=? limit 1", status, id, cp_e.CpCancel) + if result.Error != nil { + model.Log.Errorf("UpdateStatusCpCancel id:%d, status:%d, err:%v", id, status, result.Error) + return result.Error + } + if result.RowsAffected <= 0 { + model.Log.Errorf("UpdateStatusCpCancel id:%d, status:%d, err:%v", id, status, bizerr.TransactionFailed) + return bizerr.TransactionFailed + } + return nil +} + +func DelCpRelation(model *domain.Model, userId1, userId2 uint64) error { + userIds := []uint64{userId1, userId2} + result := model.DB().Exec("delete from cp_relation where user_id1 in (?) and user_id2 in (?) limit 1;", userIds, userIds) + if result.Error != nil { + model.Log.Errorf("DelCpRelation user1:%d, user2:%d, err:%v", userId1, userId2, result.Error) + return result.Error + } + if result.RowsAffected <= 0 { + model.Log.Errorf("DelCpRelation user1:%d, user2:%d, err:%v", userId1, userId2, bizerr.TransactionFailed) + return bizerr.TransactionFailed + } + return nil +} + +func GetCpInviteByTime(model *domain.Model, expTime time.Time) ([]*CpInvite, error) { + res := make([]*CpInvite, 0) + err := model.DB().Model(CpInvite{}).Where("status = ? and created_time <= ?", cp_e.CpInvite, expTime.Format(utils.DATETIME_FORMAT)).Find(&res).Error + if err != nil { + model.Log.Errorf("GetCpInviteByTime err:%v", err) + return nil, err + } + return res, nil +} + +func GetCpCancelByTime(model *domain.Model, expTime time.Time) ([]*CpCancel, error) { + res := make([]*CpCancel, 0) + err := model.DB().Model(CpCancel{}).Where("status = ? and created_time <= ?", cp_e.CpCancel, expTime.Format(utils.DATETIME_FORMAT)).Find(&res).Error + if err != nil { + model.Log.Errorf("GetCpCancelByTime err:%v", err) + return nil, err + } + return res, nil +} diff --git a/domain/model/diamond_m/diamond.go b/domain/model/diamond_m/diamond.go new file mode 100644 index 0000000000000000000000000000000000000000..22b63b09cd28aa404b98abfea955265d4b46d48e --- /dev/null +++ b/domain/model/diamond_m/diamond.go @@ -0,0 +1,190 @@ +package diamond_m + +import ( + "git.hilo.cn/hilo-common/_const/enum/diamond_e" + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" + "git.hilo.cn/hilo-common/utils" + "hilo-user/myerr" + "hilo-user/myerr/bizerr" + "strconv" + "time" +) + +type DiamondAccount struct { + mysql.Entity + *domain.Model `gorm:"-"` + UserId mysql.ID + DiamondNum mysql.Num + PinkDiamondNum mysql.Num + Status diamond_e.StatusAccount +} + +//账号详情 +type DiamondAccountDetail struct { + mysql.Entity + *domain.Model `gorm:"-"` + UserId mysql.ID + DiamondAccountId mysql.ID + OperateId mysql.ID + OperateType diamond_e.OperateType + OriginId mysql.ID + AddReduce mysql.AddReduce + Num mysql.Num + Remark mysql.Str + BefNum mysql.Num + AftNum mysql.Num + diamondAccount *DiamondAccount `gorm:"-"` +} + +// 粉钻详情 +type DiamondPinkAccountDetail struct { + mysql.Entity + *domain.Model `gorm:"-"` + UserId mysql.ID + DiamondAccountId mysql.ID + OperateId mysql.ID + OperateType diamond_e.OperateType + OriginId mysql.ID + AddReduce mysql.AddReduce + Num mysql.Num + Remark mysql.Str + BefNum mysql.Num + AftNum mysql.Num + diamondAccount *DiamondAccount `gorm:"-"` +} + +//账号操作配置 +type DiamondOperateSet struct { + mysql.Entity + *domain.Model `gorm:"-"` + DiamondNum mysql.NumAll + FrequencyNum mysql.NumAll + FrequencyDay mysql.NumAll + DiamondMaxNum mysql.NumAll + AddReduce mysql.AddReduce + Type diamond_e.OperateType + Name mysql.Str + Status mysql.UserYesNo + DiamondType diamond_e.OperateType +} + +//通过userId获取帐号 +func GetDiamondAccountByUserId(model *domain.Model, userId mysql.ID) (*DiamondAccount, error) { + var diamondAccount DiamondAccount + if err := model.Db.WithContext(model).Where(&DiamondAccount{ + UserId: userId, + }).First(&diamondAccount).Error; err != nil { + return nil, myerr.WrapErr(err) + } + diamondAccount.Model = model + return &diamondAccount, nil +} + +//匹配条件扣费 +func (diamondAccount *DiamondAccount) ChangeDiamondAccountDetail(operateType diamond_e.OperateType, originId mysql.ID, diamondNum mysql.Num) (*DiamondAccountDetail, error) { + return diamondAccount.addDiamondAccountDetail(operateType, originId, diamondNum) +} + +//钻石操作记录, +func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamond_e.OperateType, originId mysql.ID, diamondNum mysql.Num) (*DiamondAccountDetail, error) { + var diamondOperateSet DiamondOperateSet + var err error + if err = diamondAccount.Db.Where(&DiamondOperateSet{ + Type: operateType, + Status: mysql.USER, + DiamondType: mysql.DiamondYellow, + }).First(&diamondOperateSet).Error; err != nil { + return nil, myerr.WrapErr(err) + } + + //判断是增加,账号是否被冻结 + if diamondAccount.Status == diamond_e.Frozen && diamondOperateSet.AddReduce == mysql.REDUCE { + return nil, bizerr.DiamondAccountFrozen + } + + //无限,检查次数 + var count int64 + if diamondOperateSet.FrequencyDay == -1 { + if diamondOperateSet.FrequencyNum != -1 { + diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{ + UserId: diamondAccount.UserId, + OperateType: operateType, + }).Count(&count) + if count >= int64(diamondOperateSet.FrequencyNum) { + return nil, bizerr.DiamondFrequency + //return nil, myerr.NewSysError("钻石操作次数多大, userId:" + mysql.IdToStr(diamondAccount.UserId) + " diamondOperateSetId" + mysql.IdToStr(diamondOperateSet.ID)) + } + } + } else if diamondOperateSet.FrequencyDay == 1 { + beginTime, err := time.ParseInLocation("2006-01-02", time.Now().Format("2006-01-02"), time.Local) + if err != nil { + return nil, myerr.WrapErr(err) + } + //一天的次数 + diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{ + UserId: diamondAccount.UserId, + OperateType: operateType, + }).Where("created_time >= ? ", beginTime).Count(&count) + if count >= int64(diamondOperateSet.FrequencyNum) { + return nil, bizerr.DiamondFrequency + } + //终极拦截,利用 + diamondAccount.SetCheckUpdateCondition(" EXISTS (SELECT * from (SELECT COUNT(1) as n from diamond_account_detail d where d.user_id = " + strconv.FormatUint(diamondAccount.UserId, 10) + " and d.operate_type = " + strconv.FormatUint(uint64(operateType), 10) + " and d.created_time >= from_unixtime(" + strconv.FormatInt(utils.GetZeroTime(time.Now()).Unix(), 10) + ")) t where t.n < " + strconv.Itoa(diamondOperateSet.FrequencyNum) + " )") + } + + //-1,代表值无效,由参数给与 + var upateDiamondNum mysql.Num + if diamondOperateSet.DiamondNum == -1 { + upateDiamondNum = diamondNum + } else { + upateDiamondNum = mysql.Num(diamondOperateSet.DiamondNum) + } + + var afterNum mysql.Num + if diamondOperateSet.AddReduce == mysql.ADD { + afterNum = diamondAccount.DiamondNum + upateDiamondNum + } else if diamondOperateSet.AddReduce == mysql.REDUCE { + if diamondAccount.DiamondNum < upateDiamondNum { + return nil, bizerr.DiamondNoEnough + } + afterNum = diamondAccount.DiamondNum - upateDiamondNum + } else { + return nil, myerr.NewSysError("AddReduce 值错误:" + mysql.TypeToString(mysql.Type(diamondOperateSet.AddReduce))) + } + + diamondAccountDetail := &DiamondAccountDetail{ + Model: diamondAccount.Model, + UserId: diamondAccount.UserId, + DiamondAccountId: diamondAccount.ID, + OperateId: diamondOperateSet.ID, + OperateType: diamondOperateSet.Type, + OriginId: originId, + AddReduce: diamondOperateSet.AddReduce, + Num: upateDiamondNum, + Remark: diamondOperateSet.Name, + BefNum: diamondAccount.DiamondNum, + AftNum: afterNum, + diamondAccount: diamondAccount, + } + return diamondAccountDetail, err +} + +// 此方法必须要在事务里面调用 +func ChangeDiamondAccountDetail(model *domain.Model, operateType diamond_e.OperateType, originId mysql.ID, userId mysql.ID, diamondNum mysql.Num) error { + diamondAccount, err := GetDiamondAccountByUserId(model, userId) + if err != nil { + model.Log.Errorf("ChangeDiamondAccountDetail operateType:%v, originId:%v, userId:%v, diamondNum:%v, err:%v", operateType, originId, userId, diamondNum, err) + return err + } + diamondAccountDetail, err := diamondAccount.ChangeDiamondAccountDetail(operateType, originId, diamondNum) + if err != nil { + model.Log.Errorf("ChangeDiamondAccountDetail operateType:%v, originId:%v, userId:%v, diamondNum:%v, err:%v", operateType, originId, userId, diamondNum, err) + return err + } + if err := diamondAccountDetail.PersistentNoInTransactional(); err != nil { + model.Log.Errorf("ChangeDiamondAccountDetail operateType:%v, originId:%v, userId:%v, diamondNum:%v, err:%v", operateType, originId, userId, diamondNum, err) + return err + } + return nil +} diff --git a/domain/model/diamond_m/repo.go b/domain/model/diamond_m/repo.go new file mode 100755 index 0000000000000000000000000000000000000000..7b48c1552015245e4cd901f46563f4ac861f1645 --- /dev/null +++ b/domain/model/diamond_m/repo.go @@ -0,0 +1,52 @@ +package diamond_m + +import ( + "git.hilo.cn/hilo-common/resource/mysql" + "gorm.io/gorm" + "hilo-user/domain/model" + "hilo-user/myerr" + "strconv" +) + +func (diamondAccountDetail *DiamondAccountDetail) PersistentNoInTransactional() error { + //fixme: 这里有点奇怪, diamondAccount持久化动作在diamondAccountDetail持久化之后,RowsAffected 就一定是0 + txDiamondAccount := diamondAccountDetail.Db.Model(diamondAccountDetail.diamondAccount) + if diamondAccountDetail.diamondAccount.CheckUpdateCondition() { + txDiamondAccount = txDiamondAccount.Where(diamondAccountDetail.diamondAccount.GetUpdateCondition()) + } + if diamondAccountDetail.AddReduce == mysql.ADD { + //增加 + txDiamondAccount.UpdateColumn("diamond_num", gorm.Expr("diamond_num + ?", diamondAccountDetail.Num)) + } else if diamondAccountDetail.AddReduce == mysql.REDUCE { + //减少,保证不能扣成负数 + txDiamondAccount.Where("diamond_num >= ?", diamondAccountDetail.Num).UpdateColumn("diamond_num", gorm.Expr("diamond_num - ?", diamondAccountDetail.Num)) + } else { + myerr.NewSysError("addReduce 枚举错误 value:" + mysql.TypeToString(mysql.Type(diamondAccountDetail.AddReduce))) + } + if err := txDiamondAccount.Error; err != nil { + return myerr.WrapErr(err) + } + if txDiamondAccount.RowsAffected == 0 { + diamondAccountDetail.Log.Errorf("gorm condition update.RowsAffected = 0,AddReduce:%v", diamondAccountDetail.AddReduce) + return myerr.NewWaring("gorm condition update.RowsAffected = 0") + } + + //持久化diamondAccountDetail + if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil { + return myerr.WrapErr(err) + } + //改变diamondAccount值 + if diamondAccountDetail.diamondAccount == nil { + return myerr.NewSysError("持久化错误, 模型:DiamondAccountDetail 中没有diamondAccount, DiamondAccountDetail.Id =" + strconv.Itoa(int(diamondAccountDetail.ID))) + } + + var newDiamondAccount DiamondAccount + if err := diamondAccountDetail.Db.First(&newDiamondAccount, diamondAccountDetail.diamondAccount.ID).Error; err != nil { + return myerr.WrapErr(err) + } + + if newDiamondAccount.DiamondNum < 0 { + return myerr.NewSysError("diamond_account表中,diamond_num 不能小于0, diamondAccount.id = " + strconv.Itoa(int(newDiamondAccount.ID))) + } + return nil +} diff --git a/domain/model/user_m/user.go b/domain/model/user_m/user.go index a7491317afeb74a2523a57d39563600552c80710..2e938253c5426233226e6497d0df089ca5c0d759 100755 --- a/domain/model/user_m/user.go +++ b/domain/model/user_m/user.go @@ -6,6 +6,7 @@ import ( "hilo-user/_const/enum/user_e" "hilo-user/myerr" "hilo-user/myerr/bizerr" + "time" ) //用户信息 @@ -106,3 +107,31 @@ func GetUserByExtId(model *domain.Model, externalId string) (*User, error) { user.Model = model return &user, nil } + +func ToUserTiny(user *User) *UserTiny { + return &UserTiny{ + ID: user.ID, + ExternalId: user.ExternalId, + Avatar: user.Avatar, + Nick: user.Nick, + Sex: user.Sex, + Code: user.Code, + Description: user.Description, + Country: user.Country, + CountryIcon: user.CountryIcon, + IsPrettyCode: user.IsPrettyCode(), + IsLogout: IfLogout(user.LogoutTime), + Birthday: BirthdayToUint64(&user.Birthday), + } +} + +func IfLogout(logoutTime int64) bool { + return logoutTime > 0 && time.Now().Unix() > logoutTime +} + +func BirthdayToUint64(birthday *mysql.Timestamp) *uint64 { + if *birthday == 0 { + return nil + } + return (*uint64)(birthday) +} diff --git a/domain/service/cp_s/cp_relation.go b/domain/service/cp_s/cp_relation.go new file mode 100644 index 0000000000000000000000000000000000000000..9d3fe3ca2e90d5b9d162a1f18703fb58b052efb5 --- /dev/null +++ b/domain/service/cp_s/cp_relation.go @@ -0,0 +1,163 @@ +package cp_s + +import ( + "encoding/json" + "git.hilo.cn/hilo-common/_const/enum/diamond_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/rpc" + "git.hilo.cn/hilo-common/sdk/tencentyun" + "git.hilo.cn/hilo-common/txop/msg" + "hilo-user/_const/enum/cp_e" + "hilo-user/domain/model/cp_m" + "hilo-user/domain/model/diamond_m" + "hilo-user/domain/model/user_m" + "hilo-user/myerr/bizerr" +) + +func InviteCpRelation(myCtx *mycontext.MyContext, myUserId uint64, externalId, lang string) error { + model := domain.CreateModelContext(myCtx) + user, err := user_m.GetUser(model, myUserId) + if err != nil { + return err + } + userInvite, err := user_m.GetUserByExtId(model, externalId) + if err != nil { + return err + } + + if userInvite.ID == myUserId { + return bizerr.InvalidParameter + } + + // 自己是否有cp了 + myCp, err := cp_m.GetCp(model, myUserId) + if err != nil { + return err + } + if myCp.Id > 0 { + return msg.GetErrByLanguage(model, 0, lang, comerr.InvalidParameter) + } + // 对方是否已经有cp了 + inviCp, err := cp_m.GetCp(model, userInvite.ID) + if err != nil { + return err + } + if inviCp.Id > 0 { + return msg.GetErrByLanguage(model, 0, lang, comerr.InvalidParameter) + } + + // 我是否发起过cp邀请,且还未被处理 + myInvite, err := cp_m.GetCpInvite(model, user.ID, 0, cp_e.CpInvite) + if err != nil { + model.Log.Errorf("InviteCpRelation myUserId:%d, err:%v", myUserId, err) + return err + } + if myInvite != nil && myInvite.Id > 0 { + return bizerr.CpAlreadyInvite + } + + err = model.Transaction(func(model *domain.Model) error { + // 创建邀请记录 + cpInvId, err := cp_m.CreateCpInvite(model, myUserId, userInvite.ID, cp_e.CpRelationInviteDiamond) + if err != nil { + model.Log.Errorf("InviteCpRelation myUserId:%d, err:%v", myUserId, err) + return err + } + // 扣费 + err = diamond_m.ChangeDiamondAccountDetail(model, diamond_e.CpInvite, cpInvId, myUserId, cp_e.CpRelationInviteDiamond) + if err != nil { + model.Log.Errorf("InviteCpRelation myUserId:%d, err:%v", myUserId, err) + return err + } + // 发送私信-邀请 + data, _ := json.Marshal(cp_m.CpInviteMessage{ + Identifier: "CpInviteMessage", + Msg: "Do you want to be CP with me?", + Sender: user_m.ToUserTiny(user), + }) + if err := tencentyun.BatchSendCustomMsg(model, 1, user.ExternalId, []string{userInvite.ExternalId}, string(data), "cp邀请"); err != nil { + model.Log.Errorf("BatchSendCustomMsg fail:%v", err) + return err + } + return nil + }) + if err != nil { + model.Log.Errorf("InviteCpRelation myUserId:%d, err:%v", myUserId, err) + return err + } + // socket 推送弹窗 + go rpc.SendCpInviteNotice(userInvite.ID, user.Code, user.Nick, user.Avatar, "Do you want to be CP with me?") + + return nil +} + +func CancelCpRelation(myCtx *mycontext.MyContext, myUserId uint64, externalId, lang string) error { + model := domain.CreateModelContext(myCtx) + user, err := user_m.GetUser(model, myUserId) + if err != nil { + return err + } + userRec, err := user_m.GetUserByExtId(model, externalId) + if err != nil { + return err + } + + if userRec.ID == myUserId { + return bizerr.InvalidParameter + } + + // 自己没有cp了 + myCp, err := cp_m.GetCp(model, myUserId) + if err != nil { + return err + } + if myCp.Id == 0 { + return msg.GetErrByLanguage(model, 0, lang, comerr.InvalidParameter) + } + // 对方没有cp了 + inviCp, err := cp_m.GetCp(model, userRec.ID) + if err != nil { + return err + } + if inviCp.Id == 0 { + return msg.GetErrByLanguage(model, 0, lang, comerr.InvalidParameter) + } + + // 是否有关于我的cp解除申请,且还未被处理 + myCancel, err := cp_m.GetCpCancelWithMe(model, user.ID, cp_e.CpCancel) + if err != nil { + model.Log.Errorf("InviteCpRelation myUserId:%d, err:%v", myUserId, err) + return err + } + if myCancel != nil && myCancel.Id > 0 { + return bizerr.CpHaveCancelNoDeal + } + + err = model.Transaction(func(model *domain.Model) error { + // 创建邀请记录 + _, err = cp_m.CreateCpCancel(model, myUserId, userRec.ID) + if err != nil { + model.Log.Errorf("CancelCpRelation myUserId:%d, err:%v", myUserId, err) + return err + } + // 发送私信 + data, _ := json.Marshal(cp_m.CpCancelMessage{ + Identifier: "CpCancelMessage", + Msg: "I want to unbind the CP relationship", + Status: 1, + }) + if err := tencentyun.BatchSendCustomMsg(model, 1, user.ExternalId, []string{userRec.ExternalId}, string(data), "cp解除"); err != nil { + model.Log.Errorf("CancelCpRelation BatchSendCustomMsg fail:%v", err) + return err + } + return nil + }) + if err != nil { + model.Log.Errorf("CancelCpRelation myUserId:%d, err:%v", myUserId, err) + return err + } + + return nil +} diff --git a/go.mod b/go.mod index 9492f43b55a2857a96efe9c4bc033358605ae32e..d2948d45e9a1bad60f15ae1348f3c1a90c30b802 100644 --- a/go.mod +++ b/go.mod @@ -19,13 +19,22 @@ require ( gorm.io/gorm v1.23.8 ) +require ( + github.com/jonboulle/clockwork v0.3.0 // indirect + github.com/robfig/cron v1.2.0 +) + +require ( + github.com/bluele/gcache v0.0.2 + github.com/jinzhu/now v1.1.5 +) + require ( github.com/KyleBanks/depth v1.2.1 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/aliyun/alibaba-cloud-sdk-go v1.61.1274 // indirect github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect - github.com/bluele/gcache v0.0.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/fatih/color v1.9.0 // indirect @@ -38,7 +47,8 @@ require ( github.com/go-playground/universal-translator v0.17.0 // indirect github.com/go-playground/validator/v10 v10.2.0 // indirect github.com/go-sql-driver/mysql v1.7.0 // indirect - github.com/golang/protobuf v1.5.0 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/go-cmp v0.5.8 // indirect github.com/hashicorp/consul/api v1.7.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.1 // indirect github.com/hashicorp/go-hclog v0.12.0 // indirect @@ -48,11 +58,10 @@ require ( github.com/hashicorp/golang-lru v0.5.0 // indirect github.com/hashicorp/serf v0.9.3 // indirect github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/joho/godotenv v1.3.0 // indirect - github.com/jonboulle/clockwork v0.3.0 // indirect github.com/json-iterator/go v1.1.9 // indirect + github.com/kr/pretty v0.3.0 // indirect github.com/leodido/go-urn v1.2.0 // indirect github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect github.com/lestrrat-go/strftime v1.0.6 // indirect @@ -64,7 +73,6 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 // indirect - github.com/robfig/cron v1.2.0 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.479 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ims v1.0.479 // indirect github.com/tencentyun/tls-sig-api-v2-golang v1.0.0 // indirect @@ -72,7 +80,7 @@ require ( golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect golang.org/x/text v0.3.6 // indirect - golang.org/x/tools v0.0.0-20190907020128-2ca718005c18 // indirect + golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e // indirect google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect google.golang.org/grpc v1.42.0 // indirect google.golang.org/protobuf v1.28.1 // indirect diff --git a/go.sum b/go.sum index 43ebc57ad82cf6a6fa673f5e65703b9102544d32..a4bdf02cfc01e41f262c44d9cb87d12f8894fe6c 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,6 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/AgoraIO/Tools/DynamicKey/AgoraDynamicKey/go/src v0.0.0-20200910100525-12b7f1b63a6a/go.mod h1:4bXIK0ntDk9CqAXobmomWd7dedbfNv/aaIpmpqqzt+A= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= @@ -18,6 +19,28 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aws/aws-sdk-go-v2 v1.16.2/go.mod h1:ytwTPBG6fXTZLxxeeCCWj2/EMYp/xDUgX+OET6TLNNU= +github.com/aws/aws-sdk-go-v2 v1.16.12/go.mod h1:C+Ym0ag2LIghJbXhfXZ0YEEp49rBWowxKzJLUoob0ts= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.1/go.mod h1:n8Bs1ElDD2wJ9kCRTczA83gYbBmjSwZp3umc6zF4EeM= +github.com/aws/aws-sdk-go-v2/config v1.15.3/go.mod h1:9YL3v07Xc/ohTsxFXzan9ZpFpdTOFl4X65BAKYaz8jg= +github.com/aws/aws-sdk-go-v2/credentials v1.11.2/go.mod h1:j8YsY9TXTm31k4eFhspiQicfXPLZ0gYXA50i4gxPE8g= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.3/go.mod h1:uk1vhHHERfSVCUnqSqz8O48LBYDSC+k6brng09jcMOk= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.9/go.mod h1:AnVH5pvai0pAF4lXRq0bmhbes1u9R8wTE+g+183bZNM= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.19/go.mod h1:llxE6bwUZhuCas0K7qGiu5OgMis3N7kdWtFSxoHmJ7E= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.3/go.mod h1:ssOhaLpRlh88H3UmEcsBoVKq309quMvm3Ds8e9d4eJM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.13/go.mod h1:lB12mkZqCSo5PsdBFLNqc2M/OOYgNAy8UtaktyuWvE8= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.10/go.mod h1:8DcYQcz0+ZJaSxANlHIsbbi6S+zMwjwdDqwW3r9AzaE= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.0/go.mod h1:Nf3QiqrNy2sj3Rku+9z4nN/bThI97gQmR7YxG3s+ez8= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.1/go.mod h1:GeUru+8VzrTXV/83XyMJ80KpH8xO89VPoUileyNQ+tc= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.3/go.mod h1:Seb8KNmD6kVTjwRjVEgOT5hPin6sq+v4C2ycJQDwuH8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.3/go.mod h1:wlY6SVjuwvh3TVRpTqdy4I1JpBFLX4UGeKZdWntaocw= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.3/go.mod h1:Bm/v2IaN6rZ+Op7zX+bOUMdL4fsrYZiD0dsjLhNKwZc= +github.com/aws/aws-sdk-go-v2/service/rekognition v1.20.1/go.mod h1:JziF+gVo2UhFc4A52j/0Zcjpba2oxoMp/TyJ+0tZkIg= +github.com/aws/aws-sdk-go-v2/service/s3 v1.26.5/go.mod h1:qFKU5d+PAv+23bi9ZhtWeA+TmLUz7B/R59ZGXQ1Mmu4= +github.com/aws/aws-sdk-go-v2/service/sso v1.11.3/go.mod h1:7UQ/e69kU7LDPtY40OyoHYgRmgfGM4mgsLYtcObdveU= +github.com/aws/aws-sdk-go-v2/service/sts v1.16.3/go.mod h1:bfBj0iVmsUyUg4weDB4NxktD9rDGeKSVWnjTnwbx9b8= +github.com/aws/smithy-go v1.11.2/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM= +github.com/aws/smithy-go v1.13.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw= github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0= @@ -25,6 +48,9 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -33,6 +59,7 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -49,7 +76,10 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/gzip v0.0.1 h1:ezvKOL6jH+jlzdHNE4h9h8q8uMpDQjyl0NN0Jd7jozc= github.com/gin-contrib/gzip v0.0.1/go.mod h1:fGBJBCdt6qCZuCAOwWuFhBB4OOq9EFqlo5dEaFhhu5w= @@ -90,6 +120,7 @@ github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -105,8 +136,9 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -114,9 +146,12 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -155,6 +190,8 @@ github.com/hashicorp/memberlist v0.2.2 h1:5+RffWKwqJ71YPu9mWsF7ZOscZmwfasdA8kbdC github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.9.3 h1:AVF6JDQQens6nMHT9OGERBvK0f8rPrAGILnsKLr6lzM= github.com/hashicorp/serf v0.9.3/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= @@ -177,12 +214,14 @@ github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGn github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= @@ -224,9 +263,20 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -242,6 +292,8 @@ github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5H github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= @@ -253,6 +305,7 @@ github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -267,6 +320,7 @@ github.com/swaggo/gin-swagger v1.2.0/go.mod h1:qlH2+W7zXGZkczuL+r2nEBR2JTT+/lX05 github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y= github.com/swaggo/swag v1.6.7 h1:e8GC2xDllJZr3omJkm9YfmK0Y56+rMO3cg0JBKNz09s= github.com/swaggo/swag v1.6.7/go.mod h1:xDhTyuFIujYiN3DKWC/H/83xcfHp+UE/IzWWampG7Zc= +github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.479 h1:3kwDb6p1J3LxmwnNgSSEheemPffo+vMewoDzKysYdig= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.479/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ims v1.0.479 h1:xDmo1rBmSJ7Hw3iOa6DQ/++z1d7pgsEVKrZno35zR7w= @@ -275,6 +329,7 @@ github.com/tencentyun/tls-sig-api-v2-golang v1.0.0 h1:NavMw9XO2iCLv8hTKaJW2kTaGR github.com/tencentyun/tls-sig-api-v2-golang v1.0.0/go.mod h1:u7WiArmCTXTaQAHJwAOaLgpJ5e2xdY5/cgMEy3ubL60= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI= @@ -282,19 +337,24 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -308,7 +368,9 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -317,8 +379,10 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -326,21 +390,29 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -352,11 +424,14 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18 h1:xFbv3LvlvQAmbNJFCBKRv1Ccvnh9FVsW0FX2kTWWowE= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e h1:4nW4NLDYnU28ojHaHO8OVxFHk/aQ33U01a9cjED+pzE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -383,22 +458,28 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.63.2 h1:tGK/CyBg7SMzb60vP1M03vNZ3VDu3wGQJwn7Sxi9r3c= gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/myerr/bizerr/bizCode.go b/myerr/bizerr/bizCode.go index 3912d54e790b75515c5a5894123458bb099a9e07..e8f79c51197138e234dfcb17e1f94bb97c859f9d 100755 --- a/myerr/bizerr/bizCode.go +++ b/myerr/bizerr/bizCode.go @@ -23,4 +23,9 @@ var ( ResPropertyDiamondNoUse = myerr.NewBusinessCode(5004, "Property can not buy", myerr.BusinessData{}) //头饰不能买 CpNotRelation = myerr.NewBusinessCode(6000, "cp not relation", myerr.BusinessData{}) + // 群组 + GroupNotFound = myerr.NewBusinessCode(14001, "Group not found", myerr.BusinessData{}) // 找不到该群 + + CpAlreadyInvite = myerr.NewBusinessCode(50120, "Already invited", myerr.BusinessData{}) // 已经发送过邀请了 + CpHaveCancelNoDeal = myerr.NewBusinessCode(50121, "You have a cancel apply", myerr.BusinessData{}) // 有接触申请需要处理 ) diff --git a/mysql/3.9.0.sql b/mysql/3.9.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..c2bcac8db685fefb6a7f7741878dc7c57a9da94a --- /dev/null +++ b/mysql/3.9.0.sql @@ -0,0 +1,44 @@ +CREATE TABLE `cp_relation` ( + `id` bigint unsigned AUTO_INCREMENT NOT NULL, + `user_id1` bigint NOT NULL COMMENT 'user_id1', + `user_id2` bigint NOT NULL COMMENT 'user_id2', + `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uid1_idx` (`user_id1`) USING BTREE, + UNIQUE KEY `uid2_idx` (`user_id2`) USING BTREE, + KEY `ctime_idx` (`created_time`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='cp关系表'; + +INSERT INTO hilo.diamond_operate_set (diamond_num, frequency_num, frequency_day, diamond_max_num, add_reduce, `type`, name, status, diamond_type) +VALUES (-1, -1, -1, -1, 2, 94, 'cp邀请扣费', 1, 1), + (-1, -1, -1, -1, 1, 95, 'cp邀请退费', 1, 1); + +CREATE TABLE `cp_invite` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `user_id` bigint NOT NULL COMMENT '发起邀请者', + `invite_user_id` bigint NOT NULL COMMENT '被邀请的人', + `diamond_num` int unsigned NOT NULL COMMENT '邀请者花费的钻石', + `status` tinyint unsigned NOT NULL COMMENT '状态1.未接受2.已接受3.拒接导致退费4.过期导致退费', + `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + KEY `uid_idx` (`user_id`) USING BTREE, + KEY `uid2_idx` (`invite_user_id`) USING BTREE, + KEY `status_idx` (`status`) USING BTREE, + KEY `created_time` (`created_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='cp邀请发起记录'; + +CREATE TABLE `cp_cancel` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `user_id` bigint NOT NULL COMMENT '发起者', + `rec_user_id` bigint NOT NULL COMMENT '接收者', + `status` tinyint unsigned NOT NULL COMMENT '状态1.未处理2.发起者已撤销3.对方已确认4.到期自动确认', + `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + KEY `uid_idx` (`user_id`) USING BTREE, + KEY `uid2_idx` (`rec_user_id`) USING BTREE, + KEY `status_idx` (`status`) USING BTREE, + KEY `created_time` (`created_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='cp解除发起记录'; \ No newline at end of file diff --git a/req/request.go b/req/request.go index 106f559e16240696a1cdc8bcb048fd28712dab32..84af386701f830120082ea8fe3ab13c62c8a20cd 100755 --- a/req/request.go +++ b/req/request.go @@ -30,6 +30,20 @@ func GetUserId(c *gin.Context) (mysql.ID, error) { return 0, bizerr.ParaMissing } +func ToUserId(myContext *mycontext.MyContext, externalId mysql.Str) (mysql.ID, error) { + return user_c.ToUserId(domain.CreateModelContext(myContext), externalId) + //if externalId == "" { + // return 0, myerr.NewSysError("externalId 不能为空") + //} + //var user user_m.User + //if err := mysql.Db.Where(&user_m.User{ + // ExternalId: externalId, + //}).First(&user).Error; err != nil { + // return 0, bizerr.ExternalIdNoExist + //} + //return user.ID, nil +} + // 获取userId和externalId func GetUserIdAndExtId(c *gin.Context, myContext *mycontext.MyContext) (mysql.ID, string, error) { if userIdStr, ok := c.Keys[mycontext.USERID]; ok { diff --git a/route/cp_r/cp_relation.go b/route/cp_r/cp_relation.go new file mode 100644 index 0000000000000000000000000000000000000000..00a90650cef83e1f6bc9244f6932b30f97508c83 --- /dev/null +++ b/route/cp_r/cp_relation.go @@ -0,0 +1,380 @@ +package cp_r + +import ( + "encoding/json" + "fmt" + "git.hilo.cn/hilo-common/_const/enum/diamond_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/sdk/tencentyun" + "git.hilo.cn/hilo-common/txop/msg" + "github.com/gin-gonic/gin" + "hilo-user/_const/enum/cp_e" + "hilo-user/cv/cp_cv" + "hilo-user/domain/cache/user_c" + "hilo-user/domain/model/cp_m" + "hilo-user/domain/model/diamond_m" + "hilo-user/domain/model/user_m" + "hilo-user/domain/service/cp_s" + "hilo-user/myerr/bizerr" + "hilo-user/req" + "hilo-user/resp" + "strconv" +) + +// @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") + + _, 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, msg.GetErrByLanguage(model, 0, lang, comerr.InvalidParameter) // cwj---- + } + + resp.ResponseOk(c, cp_cv.CheckCpRelationRes{}) + 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") + + 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") + 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) + 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, 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, bizerr.InvalidParameter + } + + if optType == 1 { // 接受的时候 + // 自己是否有cp了 + myCp, err := cp_m.GetCp(model, myUserId) + if err != nil { + return myCtx, err + } + if myCp.Id > 0 { + return myCtx, msg.GetErrByLanguage(model, 0, lang, comerr.InvalidParameter) + } + // 对方是否已经有cp了 + senderCp, err := cp_m.GetCp(model, userSender.ID) + if err != nil { + return myCtx, err + } + if senderCp.Id > 0 { + return myCtx, msg.GetErrByLanguage(model, 0, lang, comerr.InvalidParameter) + } + } + 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关系表 + 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 + } + // 发放告白礼物 cwj---- + //if _, err = bag_tx.SendUserBag(model, userSender.ID, 1, award.GiftId, award.GiftN, 3, "告白礼物"); err != nil { + // model.Log.Errorf("ReplyCpInvite userSender:%d, user:%d, status:%d, err:%v", userSender.ID, user.ID, updateStatus, err) + // return err + //} + // 发放头饰 cwj---- + //if err = headwear_tx.SendHeadwear(model, userSender.ID, 1, 3); err != nil { + // model.Log.Errorf("ReplyCpInvite userSender:%d, user:%d, status:%d, err:%v", userSender.ID, user.ID, updateStatus, err) + // return err + //} + //if err = headwear_tx.SendHeadwear(model, user.ID, 1, 3); err != nil { + // model.Log.Errorf("ReplyCpInvite userSender:%d, user:%d, status:%d, err:%v", userSender.ID, user.ID, updateStatus, err) + // return err + //} + // 私信-接受 + msgData, _ = json.Marshal(cp_m.CpAcceptInviteMessage{ + Identifier: "CpAcceptInviteMessage", + Msg: "We are already CP!", + Sender: user_m.ToUserTiny(userSender), + Receiver: user_m.ToUserTiny(user), + }) + } else { // 拒绝 + // 退费 + err = diamond_m.ChangeDiamondAccountDetail(model, diamond_e.CpInviteRefund, cpRecord.Id, cpRecord.UserId, cpRecord.DiamondNum) + if err != nil { + model.Log.Errorf("ReplyCpInvite UserId:%d, err:%v", cpRecord.UserId, err) + return err + } + // 私信-拒绝 + msgData, _ = json.Marshal(cp_m.CpDenyInviteMessage{ + Identifier: "CpDenyInviteMessage", + Msg: fmt.Sprintf("%s have declined the CP invitation", 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") + optType, err := strconv.Atoi(c.PostForm("type")) + if err != nil || optType > 2 || optType < 1 { + return myCtx, bizerr.InvalidParameter + } + + myUserId, _, 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, bizerr.InvalidParameter + } + + 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 { // 撤销解除 + // 私信 + msgData, _ = json.Marshal(cp_m.CpCancelMessage{ + Identifier: "CpCancelMessage", + Msg: fmt.Sprintf("%s withdrew my application to lift CP", myUser.Nick), + Status: 2, + }) + } 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 + } + // 私信 + msgData, _ = json.Marshal(cp_m.CpCancelMessage{ + Identifier: "CpCancelMessage", + Msg: "The CP relationship has been unbound, the CP value has been cleared, and the CP privilege has disappeared", + Status: 3, + }) + } + 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 { + Avatar1 string `json:"avatar1"` + Avatar2 string `json:"avatar2"` + Nick1 string `json:"nick1"` + Nick2 string `json:"nick2"` + Grade int `json:"grade"` // 等级 + GradeName string `json:"gradeName"` // 等级称号 + CreatedTime int64 `json:"createdTime"` // 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") + + 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 { + res = new(CpDetail) + if cp.UserId1 == user.ID { + res.Avatar1 = user.Avatar + res.Nick1 = user.Nick + user2, err := user_c.GetUserTinyById(model, cp.UserId2) + if err != nil { + return myCtx, err + } + res.Avatar2 = user2.Avatar + res.Nick2 = user2.Nick + + res.CreatedTime = cp.CreatedTime.Unix() + } + } + + resp.ResponseOk(c, res) + return myCtx, nil +} diff --git a/route/router.go b/route/router.go index d37c5fdae4d3ee24ed24d65a7722b77a8e895d15..1fb17495e08c6b0e7f802f404228b14d667d99df 100755 --- a/route/router.go +++ b/route/router.go @@ -42,6 +42,12 @@ func InitRouter() *gin.Engine { cp.PUT("/anniversary/:id", wrapper(cp_r.PutAnniversary)) cp.GET("/anniversary", wrapper(cp_r.PageAnniversary)) cp.DELETE("/anniversary/:id", wrapper(cp_r.DelAnniversary)) + + cp.GET("/relation/check", wrapper(cp_r.CheckUserCpRelation)) + cp.POST("/relation", wrapper(cp_r.CpRelation)) + cp.POST("/relation/invite/reply", wrapper(cp_r.ReplyCpInvite)) + cp.POST("/relation/cancel/reply", wrapper(cp_r.ReplyCpCancel)) + cp.GET("/relation/detail", wrapper(cp_r.CpDetailPage)) } inner := r.Group("/inner") inner.Use(ExceptionHandle, LoggerHandle)