package service import ( "joybuywork/internal/app" "joybuywork/internal/consts" "joybuywork/internal/consts/ckey" "joybuywork/internal/plugins/jsonm" "joybuywork/internal/repository/cache" "joybuywork/internal/repository/dbcheck" "joybuywork/internal/repository/finder" "joybuywork/internal/repository/model" "joybuywork/internal/repository/mtype" "joybuywork/internal/repository/withdefault" "joybuywork/internal/service/cmm" containers "joybuywork/internal/service/containers/campaignuser" "joybuywork/internal/service/notify" "joybuywork/internal/service/provider" "joybuywork/internal/service/provider/award" "joybuywork/internal/service/provider/cachecurd" "joybuywork/internal/service/provider/fissionaction" "joybuywork/internal/service/provider/players" "joybuywork/internal/service/provider/projectuser" "joybuywork/internal/service/queue/producer" "joybuywork/internal/service/queue/types" "joybuywork/internal/utils" "joybuywork/internal/utils/blink" "joybuywork/internal/utils/logic" "joybuywork/internal/utils/timez" "joybuywork/internal/utils/verify" pb "joybuywork/proto/go_proto/w_campaign_user" "joybuywork/proto/go_proto/workerr" "errors" "fmt" "strings" "time" grds "github.com/go-redis/redis/v8" "github.com/golang-module/carbon/v2" deventpb "gits.branchcn.com/backend/deeplink/proto/go_proto/devent" bi_fission_actionpb "gits.branchcn.com/backend/fissionbi/proto/go_proto/bi_fission_action" "gits.branchcn.com/backend/microcode/plugins/derivative/lock" "gorm.io/gen" "gorm.io/gen/field" ) type WCampaignUser struct { Service } // List 用户列表 func (s *WCampaignUser) List(req *pb.ListReq, res *pb.ListRes) (err error) { defer s.checkErr() *res = pb.ListRes{} container := new(containers.List) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // Reward 用户奖励 func (s *WCampaignUser) Reward(req *pb.RewardReq, res *pb.RewardRes) (err error) { defer s.checkErr() *res = pb.RewardRes{} container := new(containers.Reward) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // Visit 访问活动 func (s *WCampaignUser) Visit(req *pb.VisitReq, res *pb.VisitRes) (err error) { defer s.checkErr() *res = pb.VisitRes{} container := new(containers.Visit) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // Play 用户活动数据 func (s *WCampaignUser) Play(req *pb.PlayReq, res *pb.PlayRes) (err error) { defer s.checkErr() *res = pb.PlayRes{} container := new(containers.Play) { container.Init(s.ctx, logic.WithOnce(ckey.FissionUserPlayOnce(req.GetId())), logic.WithErrData(req)) container.Req = req container.Res = res } return container.Run() } // RewardUser 中奖用户列表 func (s *WCampaignUser) RewardUser(req *pb.RewardUserReq, res *pb.RewardUserRes) (err error) { defer s.checkErr() *res = pb.RewardUserRes{} container := new(containers.RewardUser) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // Info 用户信息 func (s *WCampaignUser) Info(req *pb.InfoReq, res *pb.InfoRes) (err error) { defer s.checkErr() cpn, err := finder.Campaign(s.ctx, req.GetCampaignId(), req.GetCampaignHashId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.IsDel == mtype.Yes { err = workerr.NotFound("not found cpn") return } user, err := cache.NewFissionUser(s.ctx, cpn.ID).FindBySubUserId(req.GetSubUserId()) if err != nil { return s.BE().CacheError(err) } if user == nil { err = workerr.NotFound("not found user") return } var psuId string if user.ParentID != 0 { var parent *model.FissionUser parent, err = finder.FissionUser(s.ctx, cpn.ID, user.ParentID) if err != nil { err = s.BE().CacheError(err) return } psuId = parent.SubUserID } statM := s.GetDao().FissionUserStat stat, err := statM.WithContext(s.ctx).Where(statM.UserID.Eq(user.ID)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } rewardM := s.GetDao().FissionRewardRecord.SubTable(cpn.ID) list, err := rewardM.WithContext(s.ctx).Where(rewardM.UserID.Eq(user.ID), rewardM.Status.Eq(mtype.FissionRewardRecordStatusSuccess)).Find() if err != nil { return s.BE().MysqlError(err) } *res = pb.InfoRes{ SubUserId: user.SubUserID, PsuId: psuId, DirectNum: 0, IndirectNum: 0, Rewards: make([]*pb.InfoRes_Reward, 0, len(list)), } if stat != nil { res.DirectNum = stat.DirectNum res.IndirectNum = stat.IndirectNum } for _, v := range list { res.Rewards = append(res.Rewards, &pb.InfoRes_Reward{ CreatedTime: v.CreatedAt, Title: v.Title, }) } return } // Rank 排行榜 func (s *WCampaignUser) Rank(req *pb.RankReq, res *pb.RankRes) (err error) { defer s.checkErr() cpn, err := finder.Campaign(s.ctx, req.GetCampaignId(), req.GetCampaignHashId()) if err != nil { return s.BE().CacheError(err) } if cpn == nil || cpn.IsDel == mtype.Yes { err = workerr.NotFound("not found cpn") return } conf, err := cache.NewCampaignConfig(s.ctx).FindByCampaignId(cpn.ID) if err != nil { return s.BE().CacheError(err) } m := s.GetDao().FissionUserStat var order []field.Expr var cond = []gen.Condition{ m.CampaignID.Eq(cpn.ID), m.IsDel.Eq(mtype.No), } var t int32 = consts.FissionRankTypeSelfTask switch cpn.FissionID { case consts.IdSignIn: t = consts.FissionRankTypeSign order = append(order, m.SignNum.Desc(), m.SignRewardNum.Desc(), m.ID) cond = append(cond, m.SignNum.Gt(0)) case consts.IdGrow: t = consts.FissionRankTypeGrow order = append(order, m.GrowNum.Desc(), m.GrowRewardNum.Desc(), m.ID) cond = append(cond, m.GrowNum.Gt(0)) default: switch conf.Option { case mtype.FissionCampaignConfigTargetOptionApp: t = utils.Ternary[int32](conf.AppEvent == mtype.FissionCampaignConfigTargetAppEventRegister, consts.FissionRankTypeRegister, consts.FissionRankTypeInstall) case mtype.FissionCampaignConfigTargetOptionFriend: t = consts.FissionRankTypeFriendTarget } if conf.Target == mtype.FissionCampaignConfigTargetUp || conf.Option == mtype.FissionCampaignConfigTargetOptionTask { order = append(order, m.TargetNum.Desc(), m.IndirectTargetNum.Desc(), m.ID) cond = append(cond, m.TargetNum.Gt(0)) } else { order = append(order, m.EffectiveNum.Desc(), m.IndirectEffectiveNum.Desc(), m.ID) cond = append(cond, m.EffectiveNum.Gt(0)) } } offset, limit := utils.PpDbLo(req.GetPage(), req.GetPerPage()) list, total, err := m.WithContext(s.ctx).Where(cond...).Order(order...).FindByPage(offset, limit) if err != nil { return s.BE().MysqlError(err) } *res = pb.RankRes{ List: make([]*pb.RankRes_One, 0, len(list)), Total: total, Type: t, } if total == 0 { return } var userIds []int64 for _, v := range list { userIds = append(userIds, v.UserID) } um := s.GetDao().FissionUser.SubTable(cpn.ID) ul, err := um.WithContext(s.ctx).Where(um.ID.In(userIds...)).Find() if err != nil { return s.BE().MysqlError(err) } var uMap = make(map[int64]string) for _, v := range ul { uMap[v.ID] = v.UserMark } var condMap = make(map[int64][]*pb.RankRes_Cond) if t == consts.FissionRankTypeSelfTask { var userConds []*model.FissionUserCond userCondM := s.GetDao().FissionUserCond userConds, err = userCondM.WithContext(s.ctx).Where(userCondM.UserID.In(userIds...)).Find() if err != nil { err = s.BE().MysqlError(err) return } var userCondMap = make(map[int64]map[int64]int64) for _, v := range userConds { if _, ok := userCondMap[v.UserID]; !ok { userCondMap[v.UserID] = map[int64]int64{v.CondID: v.Num} } else { userCondMap[v.UserID][v.CondID] = v.Num } } var conds []*model.FissionCampaignCond condM := s.GetDao().FissionCampaignCond conds, err = condM.WithContext(s.ctx).Where(condM.CampaignID.Eq(cpn.ID)). Where( condM.WithContext(s.ctx). Or(condM.IsDel.Eq(mtype.No)). Or(condM.IsDel.Eq(mtype.Yes), condM.DelUse.Eq(mtype.Yes)), ).Find() if err != nil { err = s.BE().MysqlError(err) return } for _, id := range userIds { for _, v := range conds { one := &pb.RankRes_Cond{ Desc: v.Desc, Num: 0, } if num, ok := userCondMap[id][v.ID]; ok { one.Num = num } condMap[id] = append(condMap[id], one) } } } for _, v := range list { one := &pb.RankRes_One{ SubUserId: uMap[v.UserID], Conds: condMap[v.UserID], } switch cpn.FissionID { case consts.IdSignIn: one.DirectNum = v.SignRewardNum one.IndirectNum = v.SignNum case consts.IdGrow: one.DirectNum = v.GrowNum one.IndirectNum = v.GrowRewardNum default: if conf.Target == mtype.FissionCampaignConfigTargetUp || conf.Option == mtype.FissionCampaignConfigTargetOptionTask { one.DirectNum = v.TargetNum one.IndirectNum = v.IndirectTargetNum } else { one.DirectNum = v.EffectiveNum one.IndirectNum = v.IndirectEffectiveNum } } res.List = append(res.List, one) } return } // Lottery 活动抽奖 func (s *WCampaignUser) Lottery(req *pb.LotteryReq, res *pb.LotteryRes) (err error) { defer s.checkErr() *res = pb.LotteryRes{} container := new(containers.Lottery) { container.Init(s.ctx, logic.WithOnce(ckey.FissionUserLotteryOnce(req.GetUserId()))) container.Req = req container.Res = res } err = container.Run() return } // Answer 活动答题 func (s *WCampaignUser) Answer(req *pb.AnswerReq, res *pb.AnswerRes) (err error) { defer s.checkErr() *res = pb.AnswerRes{} container := new(containers.Answer) { container.Init(s.ctx, logic.WithOnce(ckey.FissionUserAnswerOnce(req.GetUserId())), logic.WithBp()) container.Req = req container.Res = res } return container.Run() } // Vote 活动投票 func (s *WCampaignUser) Vote(req *pb.VoteReq, res *pb.VoteRes) (err error) { defer s.checkErr() *res = pb.VoteRes{} container := new(containers.Vote) { container.Init(s.ctx, logic.WithOnce(ckey.FissionUserVoteOnce(req.GetUserId()))) container.Req = req container.Res = res } return container.Run() } // Notify 客户端回调 func (s *WCampaignUser) Notify(req *pb.NotifyReq, res *pb.NotifyRes) (err error) { defer s.checkErr() *res = pb.NotifyRes{} cpn, err := finder.Campaign(s.ctx, req.GetCampaignId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.IsDel == mtype.Yes { err = workerr.NotFound("not found cpn") return } user, err := finder.FissionUser(s.ctx, cpn.ID, req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { err = workerr.NotFound("not found user") return } m := s.GetDao().FissionRewardRecord.SubTable(cpn.ID) record, err := m.WithContext(s.ctx).Where(m.UserID.Eq(user.ID), m.HashID.Eq(req.GetRewardHashId())).Take() if err = dbcheck.DbError(err); err != nil { return s.BE().MysqlError(err) } if record == nil { return workerr.NotFound("reward not found") } // 不是待发送的就不用发送 if record.Status != mtype.FissionRewardRecordStatusWait { return } _, err = m.WithContext(s.ctx).Where(m.ID.Eq(record.ID)).UpdateSimple(m.Status.Value(mtype.FissionRewardRecordStatusSuccess)) if err != nil { return s.BE().MysqlError(err) } ntfM := s.GetDao().FissionNotify ntf := withdefault.FissionNotify(&model.FissionNotify{ CampaignID: user.CampaignID, RecordID: record.ID, NotifyType: mtype.FissionNotifyTypeClient, NotifyURL: "", Token: "", Body: req.GetBody(), PushNum: record.RewardNum, IsOk: mtype.Yes, }) err = ntfM.WithContext(s.ctx).Create(ntf) if err != nil { return s.BE().MysqlError(err) } respM := s.GetDao().FissionNotifyResp err = respM.WithContext(s.ctx).Create(withdefault.FissionNotifyResp(&model.FissionNotifyResp{ NotifyID: ntf.ID, Resp: req.GetResp(), })) if err != nil { return s.BE().MysqlError(err) } return } // AcceptReward 领取奖品 func (s *WCampaignUser) AcceptReward(req *pb.AcceptRewardReq, res *pb.AcceptRewardRes) (err error) { defer s.checkErr() *res = pb.AcceptRewardRes{} cpn, err := finder.Campaign(s.ctx, req.GetCampaignId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.IsDel == mtype.Yes { err = workerr.NotFound("not found cpn") return } m := s.GetDao().FissionRewardRecord.SubTable(cpn.ID) reward, err := m.WithContext(s.ctx).Where(m.HashID.Eq(req.GetRewardHashId()), m.CampaignID.Eq(cpn.ID)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if reward == nil { err = workerr.NotFound("not found reward") return } // 不是待发送的就不用发送 if reward.Status != mtype.FissionRewardRecordStatusWait { return } userId, userRewardId := reward.UserID, reward.ID // 没有回调就通知回调 producer.NewCampaignNotice(s.ctx).CampaignRewardNotify(types.CampaignRewardNotify{ CampaignId: cpn.ID, UserId: userId, UserRewardId: userRewardId, }) return } // TargetRule 达标规则 func (s *WCampaignUser) TargetRule(req *pb.TargetRuleReq, res *pb.TargetRuleRes) (err error) { defer s.checkErr() m := s.GetDao().FissionUser.SubTable(req.GetCampaignId()) offset, limit := utils.PpDbLo(req.GetPage(), req.GetPerPage()) list, total, err := m.WithContext(s.ctx).Where( m.CampaignID.Eq(req.GetCampaignId()), m.ParentID.Eq(req.GetUserId()), m.ParentID.Gt(0), ).FindByPage(offset, limit) if err != nil { return s.BE().MysqlError(err) } if total == 0 { return } var userIds []int64 var userCondMap = make(map[int64]map[int64]int64) for _, v := range list { if _, ok := userCondMap[v.ID]; !ok { userIds = append(userIds, v.ID) userCondMap[v.ID] = map[int64]int64{} } } userCondM := s.GetDao().FissionUserCond userConds, err := userCondM.WithContext(s.ctx).Where(userCondM.UserID.In(userIds...)).Find() if err != nil { return s.BE().MysqlError(err) } for _, v := range userConds { userCondMap[v.UserID][v.CondID] = v.Num } statM := s.GetDao().FissionUserStat stat, err := statM.WithContext(s.ctx).Where(statM.UserID.Eq(req.GetUserId())).Take() if err = dbcheck.DbError(err); err != nil { return s.BE().MysqlError(err) } *res = pb.TargetRuleRes{ List: make([]*pb.TargetRuleRes_One, 0, len(list)), Total: total, TargetNum: 0, } if stat != nil { var cpn *model.FissionCampaign cpn, err = finder.Campaign(s.ctx, req.GetCampaignId()) if err != nil { err = s.BE().CacheError(err) return } switch cpn.FissionID { case consts.IdReferral, consts.IdWinTogether: res.TargetNum = stat.EffectiveNum default: res.TargetNum = stat.TargetNum } } condM := s.GetDao().FissionCampaignCond conds, err := condM.WithContext(s.ctx).Where(condM.CampaignID.Eq(req.GetCampaignId())).Find() if err != nil { return s.BE().MysqlError(err) } for _, v := range list { one := &pb.TargetRuleRes_One{ SubUserId: utils.Ternary(v.SubUserID == "", v.DeviceID, v.SubUserID), Cond: make([]*pb.TargetRuleRes_Cond, 0, len(conds)), } for _, cond := range conds { one.Cond = append(one.Cond, &pb.TargetRuleRes_Cond{ Desc: cond.Desc, Num: userCondMap[v.ID][cond.ID], CondId: cond.ID, }) } res.List = append(res.List, one) } return } // Task 我的任务 func (s *WCampaignUser) Task(req *pb.TaskReq, res *pb.TaskRes) (err error) { defer s.checkErr() *res = pb.TaskRes{} container := new(containers.Task) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // Resend 补发奖品 func (s *WCampaignUser) Resend(req *pb.ResendReq, res *pb.ResendRes) (err error) { defer s.checkErr() lc := app.NewRedisLock(s.ctx, ckey.FissionRewardResendOnce(req.GetRewardHashId()), lock.SetExpire(20*time.Second)) if !lc.SoftLock() { return workerr.BusyError } defer lc.Release() cpn, err := finder.Campaign(s.ctx, req.GetCampaignHashId()) if err != nil { return s.BE().CacheError(err) } m := s.GetDao().FissionRewardRecord.SubTable(cpn.ID) record, err := m.WithContext(s.ctx).Where(m.HashID.Eq(req.GetRewardHashId())).Take() if err = dbcheck.DbError(err); err != nil { return s.BE().MysqlError(err) } if record == nil { return workerr.NotFound("not found record") } if record.Status != mtype.FissionRewardRecordStatusFail { switch record.Status { case mtype.FissionRewardRecordStatusWait: if record.CreatedAt+consts.DaySec > time.Now().Unix() { return s.BE().VerifyError("can not resend") } default: return s.BE().VerifyError("can not resend") } } reward, err := cache.NewReward(s.ctx).FindById(record.BaseRewardID) if err != nil { return s.BE().CacheError(err) } if reward == nil || reward.ReceiveType != mtype.RewardReceiveTypeNotify { return } url, err := cache.NewNotifyURL(s.ctx).FindById(reward.URLID) if err != nil { return } user, err := finder.FissionUser(s.ctx, cpn.ID, record.UserID) if err != nil { return s.BE().CacheError(err) } var parentSubUserId string if user.ParentID > 0 { var parent *model.FissionUser parent, err = finder.FissionUser(s.ctx, cpn.ID, user.ParentID) if err != nil { return s.BE().CacheError(err) } parentSubUserId = parent.SubUserID } project, err := finder.Project(s.ctx, cpn.ProjectID) if err != nil { return s.BE().CacheError(err) } _ = notify.Reward{ CampaignId: record.CampaignID, RewardId: record.ID, UserId: user.ID, ParentId: user.ParentID, CampaignHashId: cpn.HashID, RewardHashId: record.HashID, KvData: reward.GetJustKvData(), RewardType: record.RewardType, RewardTitle: record.Title, RewardNum: record.RewardNum, SubUserId: user.SubUserID, ParentSubUserId: parentSubUserId, Lang: utils.STernary[string](user.UserLang, "", user.LangMark), Title: cpn.Title, MallRecordId: record.MallRecordID, }.Send(s.ctx, url.URL, project.NotifyToken, project.PushLadder, url.GetHeaders()) record, err = m.WithContext(s.ctx).Where(m.HashID.Eq(req.GetRewardHashId())).Take() if err = dbcheck.DbError(err); err != nil { return s.BE().MysqlError(err) } *res = pb.ResendRes{ Status: int32(record.Status), FailType: record.FailType, FailMsg: record.FailMsg, } return } // DynamicLink 获取用户动态链接 func (s *WCampaignUser) DynamicLink(req *pb.DynamicLinkReq, res *pb.DynamicLinkRes) (err error) { defer s.checkErr() *res = pb.DynamicLinkRes{} container := new(containers.DynamicLink) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // DylinkShow 获取用户动态链接详情 func (s *WCampaignUser) DylinkShow(req *pb.DylinkShowReq, res *pb.DylinkShowRes) (err error) { defer s.checkErr() m := s.GetDao().FissionUserDylink lk, err := m.WithContext(s.ctx).Where(m.HashID.Eq(req.GetHashId())).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } params := lk.GetParams() *res = pb.DylinkShowRes{ MediaType: params.MediaType, ImageText: nil, } switch params.MediaType { case mtype.FissionUserDyLinkMediaTypeImgText: for _, text := range params.ImageText { res.ImageText = append(res.ImageText, &pb.DylinkShowRes_ImageText{ NickName: text.NickName, Avatar: text.Avatar, Title: text.Title, Desc: text.Desc, Image: text.Image, }) } } return } // SignIn 我的签到板 func (s *WCampaignUser) SignIn(req *pb.SignInReq, res *pb.SignInRes) (err error) { defer s.checkErr() *res = pb.SignInRes{} cpn, user, err := s.CpnAndUser(req.GetCampaignId(), req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { err = workerr.NotFound("not found user") return } player, err := players.NewSign(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } playerData, err := player.SignBoard(req.GetPageType(), req.GetNowMouth()) if err != nil { return } *res = pb.SignInRes{ SignDate: make([]*pb.SignInRes_SignDate, 0, len(playerData.SignDate)), NowMouth: playerData.NowMouth, CycleDate: make([]*pb.SignInRes_CycleDate, 0, len(playerData.CycleDate)), } for _, v := range playerData.SignDate { res.SignDate = append(res.SignDate, &pb.SignInRes_SignDate{ Y: v.Y, M: v.M, D: v.D, SignIn: v.SignIn, Ban: v.Ban, RewardId: v.RewardId, Open: v.Open, NowWeek: v.NowWeek, NowDay: v.NowDay, LastMiss: v.LastMiss, NowMouth: v.NowMouth, }) } for _, v := range playerData.CycleDate { res.CycleDate = append(res.CycleDate, &pb.SignInRes_CycleDate{ SignTime: v.SignTime, SignIn: v.SignIn, NowDay: v.NowDay, RewardId: v.RewardId, RewardImg: v.RewardImg, RewardTitle: v.RewardTitle, IsSuper: v.IsSuper, Y: v.Y, M: v.M, D: v.D, }) } return } // Sign 签到 func (s *WCampaignUser) Sign(req *pb.SignReq, res *pb.SignRes) (err error) { defer s.checkErr() lc := app.NewRedisLock(s.ctx, ckey.FissionUserSignOnce(req.GetUserId())) defer lc.Release() if !lc.SoftLock() { err = workerr.OnceLockError return } cpn, user, err := s.CpnAndUser(req.GetCampaignId(), req.GetUserId()) if err != nil { return } sign, err := players.NewSign(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } status, reward, err := sign.SignIn(req.GetSignDate()) if err != nil { return } *res = pb.SignRes{ FailType: status, } if reward != nil { *res = pb.SignRes{ FailType: status, HasReward: true, RewardTitle: reward.RewardTitle, RewardNum: reward.RewardNum, ImgUrl: reward.ImgUrl, RewardId: reward.RewardId, ReceiveType: reward.ReceiveType, KvData: make([]*pb.SignRes_KV, 0, len(reward.KvData)), Contact: reward.Contact, } for _, v := range reward.KvData { res.KvData = append(res.KvData, &pb.SignRes_KV{ Key: v.Key, Value: v.Value, }) } } return } // DiceMap 大富翁地图 func (s *WCampaignUser) DiceMap(req *pb.DiceMapReq, res *pb.DiceMapRes) (err error) { defer s.checkErr() cpn, err := finder.Campaign(s.ctx, req.GetCampaignId()) if err != nil { err = s.BE().CacheError(err) return } user, err := finder.FissionUser(s.ctx, cpn.ID, req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { err = workerr.NotFound("please login") return } dice, err := players.NewDice(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } maps, err := dice.DiceMap(req.GetMapHashId(), req.GetGoShowStep(), req.GetPrefixStep()) if err != nil { return } *res = pb.DiceMapRes{ List: make([]*pb.DiceMapRes_One, 0, len(maps)), } for _, v := range maps { res.List = append(res.List, &pb.DiceMapRes_One{ MapHashId: v.MapHashId, MarkType: v.MarkType, RewardTitle: v.RewardTitle, ImgUrl: v.ImgUrl, RewardId: v.RewardId, }) } return } // Dice 大富翁骰子 func (s *WCampaignUser) Dice(req *pb.DiceReq, res *pb.DiceRes) (err error) { defer s.checkErr() lc := app.NewRedisLock(s.ctx, ckey.FissionDiceOnce(req.GetUserId())) defer lc.Release() if !lc.SoftLock() { return workerr.OnceLockError } cpn, user, err := s.CpnAndUser(req.GetCampaignId(), req.GetUserId()) if err != nil { return } dice, err := players.NewDice(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } var rollRes players.RollRes switch req.GetMark() { case mtype.FissionDicePropMarkFixedRoll: rollRes, err = dice.FixRoll(req.GetVal()) if err != nil { return } default: rollRes, err = dice.Roll() if err != nil { return } } *res = pb.DiceRes{ FailType: rollRes.FailType, MapHashId: rollRes.MapHashId, RollNum: rollRes.RollNum, MarkType: rollRes.MarkType, RewardTitle: rollRes.RewardTitle, ImgUrl: rollRes.ImgUrl, IsIntact: rollRes.IsIntact, Lack: rollRes.Lack, RewardId: rollRes.RewardId, } return } // Grow 成长生命体 func (s *WCampaignUser) Grow(req *pb.GrowReq, res *pb.GrowRes) (err error) { defer s.checkErr() lifeM := s.GetDao().FissionGrowLife life, err := lifeM.WithContext(s.ctx).Where(lifeM.UserID.Eq(req.GetUserId()), lifeM.IsGrow.Eq(mtype.Yes)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if life == nil { *res = pb.GrowRes{ GetGrow: true, } return } cpn, err := cache.NewCampaign(s.ctx).FindById(req.GetCampaignId()) if err != nil { err = s.BE().CacheError(err) return } tz := provider.NewCampaignTZ(s.ctx, cpn, req.GetLangMark()) now, die := timez.GMTTime(tz.GetTz()), timez.GMTTime(tz.GetTz(), life.DieTime) if life.IsDie == mtype.No && die.Before(now) { err = cmm.NewCMM(s.ctx, s.GetDao()).LifeStatus(life, true, 0) if err != nil { return } life.IsDie = mtype.Yes } *res = pb.GrowRes{ GetGrow: false, Title: life.Title, Step: life.Step, Num: life.Num, WillDie: die.Before(now.AddDate(0, 0, 1)), IsDie: life.IsDie == mtype.Yes, MaxLv: false, RewardTitle: "", RewardUrl: "", RewardId: 0, } stepM := s.GetDao().FissionCampaignGrowStep step, err := stepM.WithContext(s.ctx).Where(stepM.CampaignID.Eq(life.CampaignID), stepM.Step.Eq(life.Step+1), stepM.IsDel.Eq(mtype.No)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if step != nil { res.LvUpNum = step.Num res.DiffP = utils.PercentNoZero(life.Num, step.Num) return } recordM := s.GetDao().FissionRewardRecord.SubTable(cpn.ID) record, err := recordM.WithContext(s.ctx).Where( recordM.ID.Eq(life.RecordID), ).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if record == nil { return } if record.FailType == mtype.FissionRewardRecordFailTypeCli && record.FailMsg == mtype.FissionRewardRecordFailTypeCliLackMsg { res.Lack = true } res.WillDie = false res.IsDie = false res.MaxLv = true res.RewardTitle = record.Title res.RewardUrl = record.ImgURL res.RewardId = record.RewardID return } // GetGrow 领养生命体 func (s *WCampaignUser) GetGrow(req *pb.GetGrowReq, res *pb.GetGrowRes) (err error) { defer s.checkErr() playerM := s.GetDao().FissionGrow player, err := playerM.WithContext(s.ctx).Where(playerM.UserID.Eq(req.GetUserId())).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if player == nil { err = workerr.NotFound("not found player") return } lifeM := s.GetDao().FissionGrowLife growing, err := lifeM.WithContext(s.ctx).Where(lifeM.UserID.Eq(player.UserID), lifeM.IsGrow.Eq(mtype.Yes)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } // 没有死亡,没有到最高等级,不重新领取 if growing != nil && growing.IsDie == mtype.No && growing.RecordID == 0 { return } confM := s.GetDao().FissionCampaignGrow conf, err := confM.WithContext(s.ctx).Where(confM.CampaignID.Eq(player.CampaignID)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if conf == nil { err = workerr.NotFound("not found grow conf") return } rewardM := s.GetDao().FissionCampaignReward reward, err := rewardM.WithContext(s.ctx).Where( rewardM.CampaignID.Eq(player.CampaignID), rewardM.RewardType.Eq(mtype.FissionCampaignRewardTypeApp), rewardM.IsDel.Eq(mtype.No), ).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if reward == nil { return } defer func() { if err != nil { return } cpn, _ := cache.NewCampaign(s.ctx).FindById(player.CampaignID) if cpn != nil && cpn.ReportType == mtype.FissionCampaignReportTypeNew { user, _ := cache.NewFissionUser(s.ctx, cpn.ID).FindById(player.UserID) fissionaction.NewMarkPoint(s.ctx).InApp(user).Grow(time.Now().Unix(), reward.ID) } }() lc := app.NewRedisLock(s.ctx, ckey.FissionGrowGetOnce(req.GetUserId())) defer lc.Release() if !lc.SoftLock() { return } tx := s.GetDao().Begin() defer func() { if err != nil { _ = tx.Rollback() return } _ = tx.Commit() }() lifeTx := tx.FissionGrowLife _, err = lifeTx.WithContext(s.ctx).Where(lifeTx.UserID.Eq(player.UserID), lifeTx.IsGrow.Eq(mtype.Yes)).UpdateSimple(lifeTx.IsGrow.Value(mtype.No)) if err != nil { err = s.BE().MysqlError(err) return } err = lifeTx.WithContext(s.ctx).Create(withdefault.FissionGrowLife(&model.FissionGrowLife{ UserID: player.UserID, CampaignID: player.CampaignID, Title: req.GetTitle(), Num: 0, Step: 0, DieTime: carbon.Now().AddHours(int(conf.DieHour)).Timestamp(), IsGrow: mtype.Yes, RewardID: reward.ID, })) if err != nil { err = s.BE().MysqlError(err) return } recordM := tx.FissionGrowRecord err = recordM.WithContext(s.ctx).Create(withdefault.FissionGrowRecord(&model.FissionGrowRecord{ UserID: player.UserID, CampaignID: player.CampaignID, Mark: mtype.FissionGrowRecordGetGrow, VarData: "", })) if err != nil { err = s.BE().MysqlError(err) return } statTx := tx.FissionUserStat _, err = statTx.WithContext(s.ctx).Where(statTx.UserID.Eq(player.UserID)).UpdateSimple(statTx.GrowNum.Add(1)) if err != nil { err = s.BE().MysqlError(err) return } *res = pb.GetGrowRes{} return } // Feed 饲养生命体 func (s *WCampaignUser) Feed(req *pb.FeedReq, res *pb.FeedRes) (err error) { defer s.checkErr() *res = pb.FeedRes{} container := new(containers.Feed) { container.Init(s.ctx, logic.WithOnce(ckey.FissionGrowFeedOnce(req.GetUserId())), logic.WithTran()) container.Req = req container.Res = res } return container.Run() } // GetFeed 领取饲养道具 func (s *WCampaignUser) GetFeed(req *pb.GetFeedReq, res *pb.GetFeedRes) (err error) { defer s.checkErr() *res = pb.GetFeedRes{} lc := app.NewRedisLock(s.ctx, ckey.FissionGrowGetFeedOnce(req.GetUserId(), req.GetMark())) defer lc.Release() if !lc.SoftLock() { return } playerM := s.GetDao().FissionGrow player, err := playerM.WithContext(s.ctx).Where(playerM.UserID.Eq(req.GetUserId())).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if player == nil { err = workerr.NotFound("not found player") return } confM := s.GetDao().FissionCampaignGrow conf, err := confM.WithContext(s.ctx).Where(confM.CampaignID.Eq(player.CampaignID)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if conf == nil { err = workerr.NotFound("not found grow conf") return } if req.GetMark() != "auto" { return } now := carbon.Now() next := carbon.CreateFromTimestamp(player.PropsTime) if next.Gt(now) { return } _, err = playerM.WithContext(s.ctx).Where(playerM.ID.Eq(player.ID)).UpdateSimple( playerM.GrowNum.Add(conf.AutoNum), playerM.AutoNum.Add(conf.AutoNum), playerM.PropsTime.Value(now.AddHours(int(conf.AutoHour)).Timestamp()), ) if err != nil { err = s.BE().MysqlError(err) return } return } // GrowRecord 成长记录 func (s *WCampaignUser) GrowRecord(req *pb.GrowRecordReq, res *pb.GrowRecordRes) (err error) { defer s.checkErr() cpn, err := cache.NewCampaign(s.ctx).FindById(req.GetCampaignId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.FissionID != consts.IdGrow { return } user, err := finder.FissionUser(s.ctx, cpn.ID, req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { return } tz := provider.NewCampaignTZ(s.ctx, cpn, user.LangMark) var date = carbon.Now().Timestamp() if req.GetDate() != "" { date = timez.GMTCarbon(tz.GetTz()).Parse(req.GetDate()).StartOfDay().Timestamp() } recordM := s.GetDao().FissionGrowRecord records, err := recordM.WithContext(s.ctx).Where( recordM.UserID.Eq(req.GetUserId()), recordM.CreatedAt.Lt(date), ).Limit(20).Order(recordM.CreatedAt.Desc(), recordM.ID.Desc()).Find() if err != nil { err = s.BE().MysqlError(err) return } l := len(records) if l == 0 { return } type DateGroup struct { idx int data []*pb.GrowRecordRes_Record } var lastRecord *model.FissionGrowRecord var idx int var dateMap = make(map[string]*DateGroup) for i, v := range records { ct := timez.GMTCarbon(tz.GetTz()).CreateFromTimestamp(v.CreatedAt) sd := ct.Format(consts.Ymd_) d := &pb.GrowRecordRes_Record{ Mark: v.Mark, His: ct.Format(consts.His_), VarData: nil, } for _, kv := range v.GetVarData() { d.VarData = append(d.VarData, &pb.GrowRecordRes_KV{ Key: kv.Key, Value: kv.Value, IdMark: kv.IdMark, }) } _, ok := dateMap[sd] if !ok { dateMap[sd] = &DateGroup{ idx: idx, data: []*pb.GrowRecordRes_Record{d}, } idx++ } else { dateMap[sd].data = append(dateMap[sd].data, d) } if i == l-1 { lastRecord = v } } if lastRecord == nil { return } var ld = timez.GMTCarbon(tz.GetTz()).CreateFromTimestamp(lastRecord.CreatedAt) sd := ld.Format(consts.Ymd_) var list []*model.FissionGrowRecord list, err = recordM.WithContext(s.ctx).Where( recordM.UserID.Eq(req.GetUserId()), recordM.ID.Lt(lastRecord.ID), recordM.CreatedAt.Lte(ld.EndOfDay().Timestamp()), ).Order(recordM.CreatedAt.Desc()).Find() if err != nil { err = s.BE().MysqlError(err) return } for _, v := range list { ct := timez.GMTCarbon(tz.GetTz()).CreateFromTimestamp(v.CreatedAt) d := &pb.GrowRecordRes_Record{ Mark: v.Mark, His: ct.Format(consts.His_), VarData: nil, } for _, kv := range v.GetVarData() { d.VarData = append(d.VarData, &pb.GrowRecordRes_KV{ Key: kv.Key, Value: kv.Value, IdMark: kv.IdMark, }) } dateMap[sd].data = append(dateMap[sd].data, d) } *res = pb.GrowRecordRes{ List: make([]*pb.GrowRecordRes_One, len(dateMap)), } for d, v := range dateMap { res.List[v.idx] = &pb.GrowRecordRes_One{ Date: d, Records: v.data, } } return } // ContentLink 内容链接 func (s *WCampaignUser) ContentLink(req *pb.ContentLinkReq, res *pb.ContentLinkRes) (err error) { defer s.checkErr() cpn, err := cache.NewCampaign(s.ctx).FindById(req.GetCampaignId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.IsDel == mtype.Yes { err = workerr.NotFound("not found cpn") return } user, err := finder.FissionUser(s.ctx, cpn.ID, req.GetUserId()) if err != nil { err = s.be.CacheError(err) return } ct, err := cmm.NewCMM(s.ctx, s.dao).CreateContentLink(user, req.GetMarkId(), req.GetMark()) if err != nil { return } if ct.LinkURL != "" && user.ShareLink != ct.LinkURL { userM := s.dao.FissionUser _, err = userM.WithContext(s.ctx).Where(userM.ID.Eq(user.ID)).UpdateSimple(userM.ShareLink.Value(ct.LinkURL)) if err != nil { err = s.be.MysqlError(err) return } userMs := s.dao.FissionUser.SubTable(user.CampaignID) _, err = userMs.WithContext(s.ctx).Where(userMs.ID.Eq(user.ID)).UpdateSimple(userMs.ShareLink.Value(ct.LinkURL)) if err != nil { err = s.be.MysqlError(err) return } _ = cache.NewFissionUser(s.ctx, user.CampaignID).Clear(user) } *res = pb.ContentLinkRes{ LinkUrl: ct.LinkURL, } return } // LinkContent 链接内容 func (s *WCampaignUser) LinkContent(req *pb.LinkContentReq, res *pb.LinkContentRes) (err error) { defer s.checkErr() m := s.GetDao().FissionUserCtlink ct, err := m.WithContext(s.ctx).Where(m.HashID.Eq(req.GetCtId())).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if ct == nil { return } user, err := finder.FissionUser(s.ctx, ct.CampaignID, ct.UserID) if err != nil { err = s.be.CacheError(err) return } cpn, err := cache.NewCampaign(s.ctx).FindById(ct.CampaignID) if err != nil { err = s.be.CacheError(err) return } *res = pb.LinkContentRes{ Mark: ct.Mark, } switch ct.Mark { case mtype.FissionUserCtLinkMarkQa: qam := s.GetDao().LibraryQa var qa *model.LibraryQa qa, err = qam.WithContext(s.ctx).Where(qam.ID.Eq(ct.MarkID)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if qa == nil { res.Qa = &pb.LinkContentRes_Qa{HomeShare: true} return } optionM := s.GetDao().LibraryQaOption var options []*model.LibraryQaOption options, err = optionM.WithContext(s.ctx).Where(optionM.QaID.Eq(qa.ID), optionM.IsDel.Eq(mtype.No)).Find() if err != nil { err = s.BE().MysqlError(err) return } res.Qa = &pb.LinkContentRes_Qa{ Id: qa.ID, HashId: qa.HashID, Mark: qa.Mark, Title: qa.Title, CoverUrl: qa.CoverURL, LinkUrl: qa.LinkURL, Options: make([]*pb.LinkContentRes_Option, 0, len(options)), AnswerMark: qa.AnswerMark, } for _, v := range options { res.Qa.Options = append(res.Qa.Options, &pb.LinkContentRes_Option{ Id: v.ID, Title: v.Title, ImgUrl: v.ImgURL, }) } return case mtype.FissionUserCtLinkMarkBallot: rewardM := s.GetDao().FissionCampaignReward var reward *model.FissionCampaignReward reward, err = rewardM.WithContext(s.ctx).Where(rewardM.ID.Eq(ct.MarkID)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if reward == nil { return } preward, _ := provider.NewRewards(s.ctx, cpn.ProjectID, reward.RewardID) info := preward.AutoLang(reward.RewardID, user.LangMark) res.Ballot = &pb.LinkContentRes_Ballot{ Id: reward.ID, Title: info.Title, ImgUrl: info.ImgUrl, } return case mtype.FissionUserCtLinkMarkChop: rewardM := s.GetDao().FissionCampaignReward var rewards []*model.FissionCampaignReward rewards, err = rewardM.WithContext(s.ctx).Where(rewardM.CampaignID.Eq(ct.CampaignID), rewardM.IsDel.Eq(mtype.No)).Find() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } res.Chop = &pb.LinkContentRes_Chop{ Rewards: make([]*pb.LinkContentRes_ChopReward, 0, len(rewards)), } var bids []int64 for _, v := range rewards { bids = append(bids, v.RewardID) } preward, _ := provider.NewRewards(s.ctx, cpn.ProjectID, bids...) for _, v := range rewards { info := preward.AutoLang(v.RewardID, user.LangMark) res.Chop.Rewards = append(res.Chop.Rewards, &pb.LinkContentRes_ChopReward{ Title: info.Title, ImgUrl: info.ImgUrl, Selected: v.ID == ct.MarkID, Id: v.ID, }) } return } return } // ChopSelect 选择砍一刀奖品 func (s *WCampaignUser) ChopSelect(req *pb.ChopSelectReq, res *pb.ChopSelectRes) (err error) { defer s.checkErr() user, err := finder.FissionUser(s.ctx, req.GetCampaignId(), req.GetUserId()) if err != nil { err = s.be.CacheError(err) return } chop, err := players.NewChop(s.ctx, user) if err != nil { return } err = chop.SelectReward(req.GetRewardId()) if err != nil { return } *res = pb.ChopSelectRes{} return } // ChopReselect 重选砍一刀奖品 func (s *WCampaignUser) ChopReselect(req *pb.ChopReselectReq, res *pb.ChopReselectRes) (err error) { defer s.checkErr() user, err := finder.FissionUser(s.ctx, req.GetCampaignId(), req.GetUserId()) if err != nil { err = s.be.CacheError(err) return } chop, err := players.NewChop(s.ctx, user) if err != nil { return } err = chop.Reselect() if err != nil { return } canSelect, err := chop.ExistSelectReward() if err != nil { return } *res = pb.ChopReselectRes{ RewardNone: !canSelect, } return } // ChopHelp 砍一刀助力记录 func (s *WCampaignUser) ChopHelp(req *pb.ChopHelpReq, res *pb.ChopHelpRes) (err error) { defer s.checkErr() playerM := s.GetDao().FissionChop player, err := playerM.WithContext(s.ctx).Where(playerM.UserID.Eq(req.GetUserId())).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if player == nil { err = workerr.NotFound("not found player") return } if player.ChopRewardID == 0 { return } m := s.GetDao().FissionChopHelp var cond = []gen.Condition{ m.UserID.Eq(player.UserID), m.ChopRewardID.Eq(player.ChopRewardID), } offset, limit := utils.PpDbLo(req.GetPage(), req.GetPerPage()) list, total, err := m.WithContext(s.ctx).Where(cond...).Order(m.ID.Desc()).FindByPage(offset, limit) if err != nil { return s.BE().MysqlError(err) } *res = pb.ChopHelpRes{ List: make([]*pb.ChopHelpRes_One, 0, len(list)), Total: total, } if total == 0 { return } for _, v := range list { res.List = append(res.List, &pb.ChopHelpRes_One{ Id: v.ID, Mark: v.Mark, Percent: v.Percent, CreatedTime: v.CreatedAt, }) } return } // LevelList 用户等级列表 func (s *WCampaignUser) LevelList(req *pb.LevelListReq, res *pb.LevelListRes) (err error) { defer s.checkErr() project, err := finder.Project(s.ctx, req.GetProjectHashId()) if err != nil { err = s.BE().CacheError(err) return } if project == nil { return } m := s.GetDao().FissionUserLevel list, err := m.WithContext(s.ctx).Where(m.ProjectID.Eq(project.ID), m.DeletedAt.Eq(0)).Order(m.ID).Find() if err != nil { err = s.BE().MysqlError(err) return } *res = pb.LevelListRes{ List: make([]*pb.LevelListRes_One, 0, len(list)), } var ids []int64 for _, v := range list { ids = append(ids, v.ID) } type Num struct { LevelId int64 Num int64 } var num []*Num relateM := s.GetDao().FissionUserLevelRelated err = relateM.WithContext(s.ctx). Select(relateM.LevelID, relateM.ID.Count().As("num")). Where(relateM.LevelID.In(ids...), relateM.CancelTime.Eq(0)). Group(relateM.LevelID). Scan(&num) if err != nil { err = s.BE().MysqlError(err) return } var numMap = map[int64]int64{} for _, v := range num { numMap[v.LevelId] = v.Num } for _, v := range list { res.List = append(res.List, &pb.LevelListRes_One{ Id: v.ID, Title: v.Title, Mark: v.Mark, CreatedAt: v.CreatedAt, Num: numMap[v.ID], }) } return } // LevelStore 创建用户等级 func (s *WCampaignUser) LevelStore(req *pb.LevelStoreReq, res *pb.LevelStoreRes) (err error) { defer s.checkErr() project, err := finder.Project(s.ctx, req.GetProjectHashId()) if err != nil { err = s.BE().CacheError(err) return } if project == nil { err = workerr.NotFound("not found project") return } lc := app.NewRedisLock(s.ctx, ckey.FissionUserLevelOperateOnce(project.ID, req.GetMark())).Lock() defer lc.Release() if lc.Error() != nil { err = workerr.BusyError return } m := s.GetDao().FissionUserLevel exist, err := m.WithContext(s.ctx).Where(m.ProjectID.Eq(project.ID), m.Mark.Eq(req.GetMark()), m.DeletedAt.Eq(0)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if exist != nil { err = s.BE().VerifyError("level exist") return } err = m.WithContext(s.ctx).Create(withdefault.FissionUserLevel(&model.FissionUserLevel{ ProjectID: project.ID, Mark: req.GetMark(), Title: req.GetTitle(), })) if err != nil { err = s.BE().MysqlError(err) return } *res = pb.LevelStoreRes{} return } // LevelEdit 更新用户等级 func (s *WCampaignUser) LevelEdit(req *pb.LevelEditReq, res *pb.LevelEditRes) (err error) { defer s.checkErr() m := s.GetDao().FissionUserLevel c := cache.NewFissionUserLevel(s.ctx) lv, err := c.FindById(req.GetId()) if err != nil { err = s.BE().CacheError(err) return } if lv == nil || lv.DeletedAt > 0 { err = workerr.NotFound("not found user level") return } lc := app.NewRedisLock(s.ctx, ckey.FissionUserLevelOperateOnce(lv.ProjectID, req.GetMark())).Lock() defer lc.Release() if lc.Error() != nil { err = workerr.BusyError return } exist, err := m.WithContext(s.ctx).Where(m.ProjectID.Eq(lv.ProjectID), m.Mark.Eq(req.GetMark()), m.DeletedAt.Eq(0), m.ID.Neq(lv.ID)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if exist != nil { err = s.BE().VerifyError("level exist") return } _, err = m.WithContext(s.ctx).Where(m.ID.Eq(lv.ID)).UpdateSimple(m.Title.Value(req.GetTitle()), m.Mark.Value(req.GetMark())) if err != nil { err = s.BE().MysqlError(err) return } _ = c.Clear(lv) *res = pb.LevelEditRes{} return } // LevelDestroy 删除用户等级 func (s *WCampaignUser) LevelDestroy(req *pb.LevelDestroyReq, res *pb.LevelDestroyRes) (err error) { defer s.checkErr() m := s.GetDao().FissionUserLevel c := cache.NewFissionUserLevel(s.ctx) lv, err := c.FindById(req.GetId()) if err != nil { err = s.BE().CacheError(err) return } if lv == nil || lv.DeletedAt > 0 { return } _, err = m.WithContext(s.ctx).Where(m.ID.Eq(lv.ID)).UpdateSimple(m.DeletedAt.Value(time.Now().Unix())) if err != nil { err = s.BE().MysqlError(err) return } _ = c.Clear(lv) *res = pb.LevelDestroyRes{} return } // ProjectList 项目参与用户列表 func (s *WCampaignUser) ProjectList(req *pb.ProjectListReq, res *pb.ProjectListRes) (err error) { defer s.checkErr() project, err := finder.Project(s.ctx, req.GetProjectHashId()) if err != nil { err = s.BE().CacheError(err) return } if project == nil || project.IsDel == mtype.Yes { return } m := s.GetDao().FissionCampaign list, err := m.WithContext(s.ctx).Where(m.ProjectID.Eq(project.ID), m.IsDel.Eq(mtype.No)).Find() if err != nil { err = s.BE().MysqlError(err) return } if len(list) == 0 { return } var cpnMap = make(map[int64]*model.FissionCampaign) var ids []int64 for _, v := range list { cpnMap[v.ID] = v ids = append(ids, v.ID) } userM := s.GetDao().FissionUser var cond = []gen.Condition{ userM.IsDel.Eq(mtype.No), userM.IsView.Eq(mtype.No), userM.CampaignID.In(ids...), userM.SubUserID.Neq(""), } if req.GetStart() > 0 { cond = append(cond, userM.CreatedAt.Gte(req.GetStart())) } if req.GetEnd() > 0 { cond = append(cond, userM.CreatedAt.Lte(req.GetEnd())) } offset, limit := utils.PpDbLo(req.GetPage(), req.GetPerPage()) userList, total, err := userM.WithContext(s.ctx).Where(cond...).Order(userM.ID).FindByPage(offset, limit) if err != nil { return s.BE().MysqlError(err) } if total == 0 { return } *res = pb.ProjectListRes{ List: make([]*pb.ProjectListRes_One, 0, len(userList)), Total: total, } var shareCond = make(map[int64][]string) var userIds = make([]int64, 0, len(list)) for _, v := range userList { userIds = append(userIds, v.ID) shareCond[v.CampaignID] = append(shareCond[v.CampaignID], fmt.Sprint(v.ID)) } statM := s.GetDao().FissionUserStat stats, err := statM.WithContext(s.ctx).Where(statM.UserID.In(userIds...)).Find() if err != nil { err = s.BE().MysqlError(err) return } var statMap = make(map[int64]*model.FissionUserStat, len(stats)) for _, v := range stats { statMap[v.UserID] = v } for _, v := range userList { one := &pb.ProjectListRes_One{ Id: v.ID, SubUserId: v.SubUserID, HashId: v.HashID, CampaignTitle: cpnMap[v.CampaignID].Title, CampaignHashId: cpnMap[v.CampaignID].HashID, CreatedAt: v.CreatedAt, EffectNum: 0, IsNew: int32(v.IsNew), HelpStatus: 0, } if v.ParentID > 0 { one.HelpStatus = utils.Ternary[int32](v.IsHelp == mtype.Yes, 1, 2) } if stat, ok := statMap[v.ID]; ok { one.EffectNum = stat.EffectiveNum } res.List = append(res.List, one) } return } // FinishStep 完成现金抽奖阶段 func (s *WCampaignUser) FinishStep(req *pb.FinishStepReq, res *pb.FinishStepRes) (err error) { defer s.checkErr() lc := app.NewRedisLock(s.ctx, ckey.FissionUserFinishStepOnce(req.GetUserId())) defer lc.Release() if !lc.SoftLock() { err = workerr.BusyError return } cpn, err := cache.NewCampaign(s.ctx).FindById(req.GetCampaignId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.IsDel == mtype.Yes { err = workerr.NotFound("not found cpn") return } user, err := cache.NewFissionUser(s.ctx, cpn.ID).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { err = workerr.NotFound("not found user") return } cash, err := players.NewCash(s.ctx, user) if err != nil { return } *res = pb.FinishStepRes{} switch req.GetStep() { case mtype.FissionCashNextStepOpenGift: res.OpenBox, res.LeftBox, res.RightBox, err = cash.OpenGift() return case mtype.FissionCashNextStepTriggerShare: return cash.TriggerShare() case mtype.FissionCashNextStepShowReward: return cash.ShowReward() case mtype.FissionCashNextStepLastSpin: return cash.LastSpin() default: return } } // Spin 现金转盘抽奖 func (s *WCampaignUser) Spin(req *pb.SpinReq, res *pb.SpinRes) (err error) { defer s.checkErr() lc := app.NewRedisLock(s.ctx, ckey.FissionUserSpinOnce(req.GetUserId())) defer lc.Release() if !lc.SoftLock() { err = workerr.BusyError return } cpn, err := cache.NewCampaign(s.ctx).FindById(req.GetCampaignId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.IsDel == mtype.Yes { err = workerr.NotFound("not found cpn") return } user, err := cache.NewFissionUser(s.ctx, cpn.ID).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { err = workerr.NotFound("not found user") return } var id int64 var failType int32 switch cpn.FissionID { case consts.IdGold: var gold *players.Gold gold, err = players.NewGold(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } id, failType, err = gold.Spin() if err != nil { return } default: var cash *players.Cash cash, err = players.NewCash(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } id, failType, err = cash.Spin() if err != nil { return } } *res = pb.SpinRes{ Id: id, FailType: failType, } return } // CashRecords 现金转盘记录 func (s *WCampaignUser) CashRecords(req *pb.CashRecordsReq, res *pb.CashRecordsRes) (err error) { defer s.checkErr() cpn, err := cache.NewCampaign(s.ctx).FindById(req.GetCampaignId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.IsDel == mtype.Yes { err = workerr.NotFound("not found cpn") return } user, err := cache.NewFissionUser(s.ctx, cpn.ID).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { err = workerr.NotFound("not found user") return } cash, err := players.NewCash(s.ctx, user) if err != nil { return } player := cash.GetPlayer() if !verify.InArray(req.GetType(), mtype.FissionCashRecordTypeInvite, mtype.FissionCashRecordTypeEnergy, mtype.FissionCashRecordTypeCash) { return } offset, limit := utils.PpDbLo(req.GetPage(), req.GetPerPage()) recordM := s.GetDao().FissionCashRecord list, total, err := recordM.WithContext(s.ctx). Where(recordM.CashID.Eq(player.ID), recordM.Type.Eq(int8(req.GetType()))). Order(recordM.CreatedAt.Desc(), recordM.ID.Desc()). FindByPage(offset, limit) if err != nil { err = s.BE().MysqlError(err) return } if len(list) == 0 { return } *res = pb.CashRecordsRes{ List: make([]*pb.CashRecordsRes_One, 0, len(list)), Total: total, } switch req.GetType() { case mtype.FissionCashRecordTypeInvite: var inviteIds []int64 for _, v := range list { inviteIds = append(inviteIds, v.GetDataInvite().UserId) } var users []*model.FissionUser userM := s.GetDao().FissionUser.SubTable(cpn.ID) users, err = userM.WithContext(s.ctx).Where(userM.ID.In(inviteIds...)).Find() if err != nil { err = s.BE().MysqlError(err) return } var userMap = make(map[int64]string) for _, v := range users { userMap[v.ID] = v.UserMark } for _, v := range list { invite := v.GetDataInvite() res.List = append(res.List, &pb.CashRecordsRes_One{ SubUserId: userMap[invite.UserId], CreatedAt: v.CreatedAt, IsHelp: invite.Help, }) } case mtype.FissionCashRecordTypeCash: for _, v := range list { cashData := v.GetDataCash() res.List = append(res.List, &pb.CashRecordsRes_One{ TitleMark: cashData.TitleMark, CreatedAt: v.CreatedAt, DecOrAdd: cashData.DecOrAdd, Val: cashData.Cash, }) } case mtype.FissionCashRecordTypeEnergy: for _, v := range list { data := v.GetDataEnergy() res.List = append(res.List, &pb.CashRecordsRes_One{ TitleMark: data.TitleMark, CreatedAt: v.CreatedAt, DecOrAdd: data.DecOrAdd, Val: data.Energy, }) } default: } return } // MixReward 合成奖品 func (s *WCampaignUser) MixReward(req *pb.MixRewardReq, res *pb.MixRewardRes) (err error) { defer s.checkErr() if !app.NewRedisLock(s.ctx, ckey.FissionUserMixReward(req.GetUserId())).SoftLock() { return workerr.OnceLockError } cpn, user, err := s.CpnAndUser(req.GetCampaignId(), req.GetUserId()) if err != nil { return } dice, err := players.NewDice(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } reward, err := dice.MixReward(req.GetRewardId()) if err != nil { return } *res = pb.MixRewardRes{ Lack: reward.Lack, RewardId: reward.RewardId, RewardTitle: reward.RewardTitle, ImgUrl: reward.ImgUrl, ReceiveType: reward.ReceiveType, KvData: make([]*pb.MixRewardRes_KV, 0, len(reward.KvData)), Contact: reward.Contact, RewardHashId: reward.RewardHashId, OpenToUse: reward.OpenToUse, WebUrl: reward.WebUrl, AppParam: reward.AppParam, PcParam: reward.PcParam, } return } // DiceRecord 骰子记录 func (s *WCampaignUser) DiceRecord(req *pb.DiceRecordReq, res *pb.DiceRecordRes) (err error) { defer s.checkErr() *res = pb.DiceRecordRes{} container := new(containers.DiceRecord) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // RewardForm 奖品需要填写的表单 func (s *WCampaignUser) RewardForm(req *pb.RewardFormReq, res *pb.RewardFormRes) (err error) { defer s.checkErr() cpn, err := finder.Campaign(s.ctx, req.GetCampaignId(), req.GetCampaignHashId()) if err != nil { return } if cpn == nil { err = workerr.NotFound("not found cpn") return } m := s.GetDao().FissionRewardRecord.SubTable(cpn.ID) record, err := m.WithContext(s.ctx).Where(m.HashID.Eq(req.GetRewardHashId())).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if record == nil { err = workerr.NotFound("not found record") return } user, err := finder.FissionUser(s.ctx, record.CampaignID, record.UserID) if err != nil { err = s.BE().CacheError(err) return } if user == nil { err = workerr.NotFound("not found user") return } if record.Status == mtype.FissionRewardRecordStatusSubmitForm { rfm := s.GetDao().FissionRewardRecordForm var recordForm *model.FissionRewardRecordForm recordForm, err = rfm.WithContext(s.ctx).Where(rfm.RecordID.Eq(record.ID)).Take() if err != nil { err = s.BE().MysqlError(err) return } items := recordForm.GetItems() var form *model.Form form, err = cache.NewForm(s.ctx).FindById(recordForm.FormID) if err != nil { err = s.BE().CacheError(err) return } *res = pb.RewardFormRes{ IsSubmit: true, Title: form.Title, Items: make([]*pb.RewardFormRes_Item, 0, len(items)), Id: record.ID, RewardId: record.RewardID, } for _, item := range items { res.Items = append(res.Items, &pb.RewardFormRes_Item{ Name: item.Name, Key: item.Key, Value: item.Value, }) } return } breward, err := cache.NewReward(s.ctx).FindById(record.BaseRewardID) if err != nil { err = s.BE().CacheError(err) return } if breward.ReceiveType != mtype.RewardReceiveTypeForm { return } form, err := cache.NewForm(s.ctx).FindById(breward.FormID) if err != nil { err = s.BE().CacheError(err) return } items := form.GetItems() *res = pb.RewardFormRes{ IsSubmit: false, Title: form.Title, Items: make([]*pb.RewardFormRes_Item, 0, len(items)), Id: record.ID, RewardId: record.RewardID, } for _, v := range items { res.Items = append(res.Items, &pb.RewardFormRes_Item{ Name: v.GetTranName(req.GetLangMark()), Key: v.Name, Value: "", }) } return } // SubmitForm 提交表单 func (s *WCampaignUser) SubmitForm(req *pb.SubmitFormReq, res *pb.SubmitFormRes) (err error) { defer s.checkErr() m := s.GetDao().FissionRewardRecord.SubTable(req.GetCampaignId()) record, err := m.WithContext(s.ctx).Where(m.HashID.Eq(req.GetRewardHashId())).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if record == nil { err = workerr.NotFound("not found record") return } switch record.Status { case mtype.FissionRewardRecordStatusSubmitForm: *res = pb.SubmitFormRes{ FailType: 1, } return case mtype.FissionRewardRecordStatusFail: *res = pb.SubmitFormRes{ FailType: 3, } return default: } breward, err := cache.NewReward(s.ctx).FindById(record.BaseRewardID) if err != nil { err = s.BE().CacheError(err) return } if breward.ReceiveType != mtype.RewardReceiveTypeForm { *res = pb.SubmitFormRes{ FailType: 3, } return } form, err := cache.NewForm(s.ctx).FindById(breward.FormID) if err != nil { err = s.BE().CacheError(err) return } var items = form.GetItems() var itemMap = make(map[string]struct{}) for _, item := range form.GetItems() { itemMap[item.Name] = struct{}{} } var submitItems = make([]*mtype.SubmitFormItem, 0, len(items)) for _, v := range req.GetItems() { if _, ok := itemMap[v.GetKey()]; !ok { continue } submitItems = append(submitItems, &mtype.SubmitFormItem{ Name: v.GetName(), Key: v.GetKey(), Value: v.GetValue(), }) } recordForm := withdefault.FissionRewardRecordForm(&model.FissionRewardRecordForm{ CampaignID: record.CampaignID, RecordID: record.ID, FormID: form.ID, Items: "", }) recordForm.SetItems(submitItems) err = s.GetDao().FissionRewardRecordForm.WithContext(s.ctx).Create(recordForm) if err != nil { err = s.BE().MysqlError(err) return } _, err = m.WithContext(s.ctx).Where(m.ID.Eq(record.ID)).UpdateSimple(m.Status.Value(mtype.FissionRewardRecordStatusSubmitForm)) if err != nil { err = s.BE().MysqlError(err) return } user, _ := cache.NewFissionUser(s.ctx, record.CampaignID).FindById(record.UserID) if user != nil { fissionaction.NewMarkPoint(s.ctx).InApp(user).FormSubmit(time.Now().Unix(), record.RewardID, record.ID) } return } // GetAdsUrl 广告停留回传 func (s *WCampaignUser) GetAdsUrl(req *pb.GetAdsUrlReq, res *pb.GetAdsUrlRes) (err error) { defer s.checkErr() m := s.GetDao().FissionCampaignCond cond, err := m.WithContext(s.ctx).Where(m.ID.Eq(req.GetCondId())).Take() if err != nil { err = s.BE().MysqlError(err) return } if cond == nil { err = workerr.NotFound("not found cond") return } user, err := finder.FissionUser(s.ctx, cond.CampaignID, req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { err = workerr.NotFound("not found user") return } ad, err := cache.NewProjectAd(s.ctx).FindByProjectId(cond.ProjectID) if err != nil { err = s.BE().CacheError(err) return } if ad == nil || ad.OpenAd == mtype.No { err = workerr.NotFound("not open ad") return } eventVal := fmt.Sprint(cond.WatchSec) jt := time.Now().Unix() token := app.Encode(user.HashID, cond.Event, cond.EventKey, eventVal, jt) err = app.Redis.Set(s.ctx, ckey.FissionUserAdsOnce(token), fmt.Sprint(cond.ID), consts.TimeDay) if err != nil { err = s.BE().RedisError(err) return } if cond.AdsStrategyID != "" { *res = pb.GetAdsUrlRes{ Url: blink.NewAdsJump(cond.AdsStrategyID, blink.SetAdsJumpLg(user.LangMark)).Link(), Token: token, UserHashId: user.HashID, Event: cond.Event, EventKey: cond.EventKey, EventVal: eventVal, JumpTime: jt, } return } act, host, uri := app.AdsRandOne(ad.AdStatus == mtype.ProjectAdStatusProd, ad.ProjectID) *res = pb.GetAdsUrlRes{ Url: fmt.Sprintf("%s%s", host, uri), Token: token, UserHashId: user.HashID, Event: cond.Event, EventKey: cond.EventKey, EventVal: eventVal, JumpTime: jt, AdG: &pb.GetAdsUrlRes_AdG{ Adc: act, GaShowId: ad.GaShowID, GaEmbedId: ad.GaEmbedID, GaDoubleId: ad.GaDoubleID, }, } return } // AdsStay 广告停留回传 func (s *WCampaignUser) AdsStay(req *pb.AdsStayReq, res *pb.AdsStayRes) (err error) { defer s.checkErr() if !app.TokenOk(req.GetToken(), req.GetUserHashId(), req.GetEvent(), req.GetEventKey(), req.GetEventVal(), req.GetJumpTime()) { err = s.BE().VerifyError("params error") return } key := ckey.FissionUserAdsOnce(req.GetToken()) defer func() { if err == nil { _ = app.Redis.Del(s.ctx, key) } }() nd := time.Now().Unix() - req.GetJumpTime() st := utils.StrToInt64(req.GetEventVal()) if nd < st { sl := int32(st - nd) *res = pb.AdsStayRes{ StayLave: utils.Ternary[int32](sl < 0, 0, sl), } return } condId, err := app.Redis.Cache.Get(s.ctx, key).Int64() if !errors.Is(err, grds.Nil) && err != nil { err = s.BE().CacheError(err) return } if errors.Is(err, grds.Nil) || condId == 0 { err = nil return } cond, err := cache.NewCampaignCond(s.ctx).FindById(condId) if err != nil { err = s.BE().CacheError(err) return } if cond == nil { return } user, err := finder.FissionUser(s.ctx, cond.CampaignID, req.GetUserHashId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { err = workerr.NotFound("not found user") return } cpn, err := cache.NewCampaign(s.ctx).FindById(user.CampaignID) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.IsDel == mtype.Yes || !verify.InArray(cpn.Status, mtype.FissionCampaignStatusPubPre, mtype.FissionCampaignStatusPub) { err = workerr.CEndError return } producer.NewCampaignNotice(s.ctx).ValidEvents(types.ValidEvents{ UserId: user.ID, NewUser: false, BehaviorTime: time.Now().Unix(), NoticeType: types.NoticeTypeCustom, Event: req.GetEvent(), EventData: []types.EventData{ { EventKey: req.GetEventKey(), EventVal: "1", }, }, EventType: mtype.FissionCampaignCondEventTypeAds, AdsCondId: condId, CampaignId: cpn.ID, }) *res = pb.AdsStayRes{ Done: true, } return } // ClueNotified 通知信息已经被接收 func (s *WCampaignUser) ClueNotified(req *pb.ClueNotifiedReq, res *pb.ClueNotifiedRes) (err error) { defer s.checkErr() provider.NewFissionClue(s.ctx, req.GetUserId()).Notified() *res = pb.ClueNotifiedRes{} return } // ChangeUserLevel 修改用户等级 func (s *WCampaignUser) ChangeUserLevel(req *pb.ChangeUserLevelReq, res *pb.ChangeUserLevelRes) (err error) { defer s.checkErr() m := s.GetDao().FissionCampaign list, err := m.WithContext(s.ctx). Where( m.ProjectID.Eq(req.GetProjectId()), m.Status.In(mtype.FissionCampaignStatusPub, mtype.FissionCampaignStatusPubPre), ).Find() if err != nil { err = s.BE().MysqlError(err) return } if len(list) == 0 { return } var ids []int64 var cpnMap = make(map[int64]*model.FissionCampaign, len(list)) for _, v := range list { ids = append(ids, v.ID) cpnMap[v.ID] = v } confM := s.GetDao().FissionCampaignConfig confList, err := confM.WithContext(s.ctx).Where(confM.CampaignID.In(ids...)).Find() if err != nil { err = s.BE().MysqlError(err) return } if len(confList) == 0 { return } cc1 := cache.NewFissionUserAttr(s.ctx) for _, v := range confList { cc := cache.NewFissionUser(s.ctx, v.CampaignID) var user *model.FissionUser user, err = cc.FindBySubUserId(req.GetSubUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { continue } uct, _ := cmm.NewCMM(s.ctx, s.GetDao()).UserCampaignType(cpnMap[v.CampaignID], v, "", req.GetUserLevel(), "") setLv := strings.Split(req.GetUserLevel(), ",") userM := s.GetDao().FissionUser _, err = userM.WithContext(s.ctx).Where(userM.ID.Eq(user.ID)).UpdateSimple( userM.LevelMark.Value(req.GetUserLevel()), userM.UserLevel.Value(uct.LevelId), userM.UserLevelMark.Value(uct.LevelMark), userM.FixedUserLevel.Value(mtype.Yes), ) if err != nil { err = s.BE().MysqlError(err) return } userMs := s.GetDao().FissionUser.SubTable(user.CampaignID) _, err = userMs.WithContext(s.ctx).Where(userMs.ID.Eq(user.ID)).UpdateSimple( userMs.LevelMark.Value(req.GetUserLevel()), userMs.UserLevel.Value(uct.LevelId), userMs.UserLevelMark.Value(uct.LevelMark), userMs.FixedUserLevel.Value(mtype.Yes), ) if err != nil { err = s.BE().MysqlError(err) return } _ = cc.Clear(user) attrVal := utils.Ternary[string](verify.InArray[string](uct.LevelMark, setLv...), uct.LevelMark, setLv[0]) var attr *model.FissionUserAttr attr, err = cache.NewFissionUserAttr(s.ctx).FindByUniqIdx(user.ID, mtype.FissionUserAttrMarkUserLv, cache.WithNilSet(func() ([]byte, error) { pAttr := withdefault.FissionUserAttr(&model.FissionUserAttr{ CampaignID: user.CampaignID, UserID: user.ID, Attr: mtype.FissionUserAttrMarkUserLv, Value: attrVal, Values: req.GetUserLevel(), }) err = s.GetDao().FissionUserAttr.WithContext(s.ctx).Create(pAttr) if err != nil { return nil, err } return jsonm.Marshal(pAttr) })) if err != nil { err = s.BE().CacheError(err) return } // 如果没更新,或者平台是其他,就不用处理了 if attrVal == attr.Value { continue } vals := attr.GetValues() for _, lv := range setLv { if !verify.InArray(lv, vals...) { vals = append(vals, lv) } } attrM := s.GetDao().FissionUserAttr _, err = attrM.WithContext(s.ctx).Where(attrM.ID.Eq(attr.ID)).UpdateSimple( attrM.Value.Value(attrVal), attrM.Values.Value(strings.Join(vals, ",")), ) if err != nil { err = s.BE().MysqlError(err) return } _ = cc1.Clear(attr) } *res = pb.ChangeUserLevelRes{} return } // ChopReward 砍一刀可选奖品 func (s *WCampaignUser) ChopReward(req *pb.ChopRewardReq, res *pb.ChopRewardRes) (err error) { defer s.checkErr() user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { err = workerr.NotFound("not found user") return } rewards, err := cmm.NewCMM(s.ctx, s.GetDao()).UserAppReward(user) if err != nil { return } var bRewardIds []int64 var limitIds []int64 for _, reward := range rewards { if reward.HasRule == mtype.Yes { limitIds = append(limitIds, reward.ID) } bRewardIds = append(bRewardIds, reward.RewardID) } prewards, _ := provider.NewRewards(s.ctx, 0, bRewardIds...) if len(limitIds) == 0 { *res = pb.ChopRewardRes{ Rewards: make([]*pb.ChopRewardRes_Reward, 0, len(rewards)), } for _, reward := range rewards { info, _ := prewards.InfoAutoLang(reward.RewardID, user.LangMark) res.Rewards = append(res.Rewards, &pb.ChopRewardRes_Reward{ Id: reward.ID, Title: info.Title, ImgUrl: info.ImgUrl, }) } return } ruleM := s.GetDao().FissionCampaignRewardRule rules, err := ruleM.WithContext(s.ctx).Where(ruleM.CampaignID.Eq(user.CampaignID), ruleM.RewardID.In(limitIds...)).Find() if err != nil { err = s.BE().MysqlError(err) return } var ruleMap = make(map[int64]*model.FissionCampaignRewardRule, len(rules)) for _, rule := range rules { ruleMap[rule.RewardID] = rule } type rewardGet struct { RewardId int64 `json:"reward_id"` Num int32 `json:"num"` } var gets []*rewardGet chopRewardM := s.GetDao().FissionChopReward err = chopRewardM.WithContext(s.ctx). Select(chopRewardM.ID.Count().As("num"), chopRewardM.RewardID). Where(chopRewardM.UserID.Eq(user.ID), chopRewardM.RecordID.Gt(0)). Group(chopRewardM.RewardID). Scan(&gets) if err != nil { err = s.BE().MysqlError(err) return } var filterMap = make(map[int64]struct{}) for _, v := range gets { if rule, ok := ruleMap[v.RewardId]; ok && rule.CampaignLimit <= v.Num { filterMap[v.RewardId] = struct{}{} } } *res = pb.ChopRewardRes{} for _, reward := range rewards { if _, ok := filterMap[reward.ID]; ok { continue } info, _ := prewards.InfoAutoLang(reward.RewardID, user.LangMark) res.Rewards = append(res.Rewards, &pb.ChopRewardRes_Reward{ Id: reward.ID, Title: info.Title, ImgUrl: info.ImgUrl, }) } return } // HelpPercent 助力进度 func (s *WCampaignUser) HelpPercent(req *pb.HelpPercentReq, res *pb.HelpPercentRes) (err error) { defer s.checkErr() user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } *res = pb.HelpPercentRes{} chop, err := players.NewChop(s.ctx, user) if err != nil { return } res.IsFix, res.OldPercent, res.AddPercent = chop.HelpClue() return } // InvokeCond 触发前置条件 func (s *WCampaignUser) InvokeCond(req *pb.InvokeCondReq, res *pb.InvokeCondRes) (err error) { defer s.checkErr() user, err := finder.FissionUser(s.ctx, req.GetCampaignId(), req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } m := s.GetDao().FissionUserPreCond pre, err := m.WithContext(s.ctx).Select(m.ID).Where(m.UserID.Eq(user.ID), m.PreCond.Eq(req.GetPreCond())).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } taskM := s.GetDao().FissionCampaignTask task, err := taskM.WithContext(s.ctx).Where( taskM.CampaignID.Eq(user.CampaignID), taskM.PreCond.Eq(req.GetPreCond()), taskM.IsDel.Eq(mtype.No), ).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if task == nil { return } if pre == nil && verify.InArray(task.PreCond, mtype.FissionCampaignTaskPreCondClickIcon, mtype.FissionCampaignTaskPreCondWait30s) { pre = withdefault.FissionUserPreCond(&model.FissionUserPreCond{ CampaignID: user.CampaignID, UserID: user.ID, PreCond: task.PreCond, ExpiredAt: time.Now().Add(time.Duration(task.ExpiredMin) * time.Minute).Unix(), }) err = m.WithContext(s.ctx).Create(pre) if err != nil { err = s.BE().MysqlError(err) return } } if pre == nil { return } condId := utils.FissionCampaignTaskMarkCondOneCondId(task.TaskMark) cond, err := cache.NewCampaignCond(s.ctx).FindById(condId) if err != nil { err = s.BE().CacheError(err) return } cpn, err := cache.NewCampaign(s.ctx).FindById(cond.CampaignID) if err != nil { err = s.BE().CacheError(err) return } // 用户当前语言是配置的语言 var condLangMap = make(map[int64]*mtype.LangCond) if verify.InArray(user.LangMark, cpn.GetLangMarks()...) { lang, err1 := cache.NewCampaignLang(s.ctx).FindByCampaignId(user.CampaignID, user.LangMark) if err1 != nil { err = s.BE().CacheError(err1) return } if lang != nil { for _, v := range lang.GetConds() { condLangMap[v.CondId] = v } } } var condExtra = make(map[string]*deventpb.GetCustomEventListRes_Info) eventRes, _ := app.NewDeepLinkEvent().GetCustomEventList(s.ctx, &deventpb.GetCustomEventListReq{ ProjectId: cpn.ProjectID, EventKeyList: []string{cond.Event}, LangMark: user.LangMark, }) for _, v := range eventRes.GetList() { condExtra[v.GetEventKey()] = v } *res = pb.InvokeCondRes{ Id: cond.ID, Desc: cond.Desc, IfCond: int32(cond.IfCond), Event: cond.Event, EventKey: cond.EventKey, EventVal: cond.EventVal, TaskChance: task.Chance, WebUrl: cond.WebURL, AppParam: cond.ExtraParam, EventType: int32(cond.EventType), ViewType: int32(cond.ViewType), GoShow: int32(cond.GoShow), AdsStrategyId: cond.AdsStrategyID, IsSuper: int32(cond.IsSuper), HasPre: int32(task.HasPre), Reward: nil, PropMark: task.PropMark, ExpiredSec: pre.ExpiredAt - time.Now().Unix(), PcParam: cond.PcParam, } if condLang, ok := condLangMap[cond.ID]; ok { res.Desc = condLang.Desc } if cond.OpenJump == mtype.Yes { if condLang, ok := condLangMap[cond.ID]; ok { res.WebUrl = condLang.WebURL res.AppParam = condLang.ExtraParam res.PcParam = condLang.ExtraParam } } else { if param, ok := condExtra[cond.Event]; ok { res.WebUrl = param.WebUrl res.AppParam = param.ExtraParam res.PcParam = param.PcParam } } if task.RewardID == 0 { return } rewardM := s.GetDao().FissionCampaignReward reward, err := rewardM.WithContext(s.ctx).Where(rewardM.ID.Eq(task.RewardID)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if reward == nil { return } bewards, err := provider.NewRewards(s.ctx, cpn.ProjectID, reward.RewardID) if err != nil { return } info := bewards.AutoLang(reward.RewardID, user.LangMark) res.Reward = &pb.InvokeCondRes_Reward{ Id: reward.ID, Title: info.Title, ImgUrl: info.ImgUrl, } return } // KeepReward 激励养成可选奖品 func (s *WCampaignUser) KeepReward(req *pb.KeepRewardReq, res *pb.KeepRewardRes) (err error) { defer s.checkErr() user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { err = workerr.NotFound("not found user") return } rewards, err := cmm.NewCMM(s.ctx, s.GetDao()).UserAppReward(user) if err != nil { return } var rewardIds, bRewardIds, limitIds []int64 for _, reward := range rewards { if reward.HasRule == mtype.Yes { limitIds = append(limitIds, reward.ID) } bRewardIds = append(bRewardIds, reward.RewardID) rewardIds = append(rewardIds, reward.ID) } hmap, err := cachecurd.NewHMap(s.ctx, ckey.FissionKeepRewardSelectedUser(user.CampaignID), cachecurd.SetKeepRewardSelectBuild(user.CampaignID)) if err != nil { return } selectReward, _ := hmap.Int64ToInt64() var useStock = make(map[int64]int64, len(rewardIds)) for _, id := range rewardIds { useStock[id] = selectReward[id] } prewards, _ := provider.NewRewards(s.ctx, 0, bRewardIds...) if len(limitIds) == 0 { *res = pb.KeepRewardRes{ Rewards: make([]*pb.KeepRewardRes_Reward, 0, len(rewards)), } for _, reward := range rewards { var status int32 if int64(reward.Stock) <= useStock[reward.ID] { status = 2 } info := prewards.AutoLang(reward.RewardID, user.LangMark) res.Rewards = append(res.Rewards, &pb.KeepRewardRes_Reward{ Id: reward.ID, Title: info.Title, ImgUrl: info.ImgUrl, Num: useStock[reward.ID], Status: status, }) } return } ruleM := s.GetDao().FissionCampaignRewardRule rules, err := ruleM.WithContext(s.ctx).Where(ruleM.CampaignID.Eq(user.CampaignID), ruleM.RewardID.In(limitIds...)).Find() if err != nil { err = s.BE().MysqlError(err) return } var ruleMap = make(map[int64]*model.FissionCampaignRewardRule, len(rules)) for _, rule := range rules { ruleMap[rule.RewardID] = rule } type rewardGet struct { RewardId int64 `json:"reward_id"` Num int32 `json:"num"` } var gets []*rewardGet keepM := s.GetDao().FissionKeep err = keepM.WithContext(s.ctx). Select(keepM.ID.Count().As("num"), keepM.RewardID). Where(keepM.UserID.Eq(user.ID)). Group(keepM.RewardID). Scan(&gets) if err != nil { err = s.BE().MysqlError(err) return } var filterMap = make(map[int64]struct{}) for _, v := range gets { if rule, ok := ruleMap[v.RewardId]; ok && rule.CampaignLimit <= v.Num { filterMap[v.RewardId] = struct{}{} } } *res = pb.KeepRewardRes{} for _, reward := range rewards { var status int32 if _, ok := filterMap[reward.ID]; ok { status = 3 } else if int64(reward.Stock) <= useStock[reward.ID] { status = 2 } info := prewards.AutoLang(reward.RewardID, user.LangMark) res.Rewards = append(res.Rewards, &pb.KeepRewardRes_Reward{ Id: reward.ID, Title: info.Title, ImgUrl: info.ImgUrl, Num: useStock[reward.ID], Status: status, }) } return } // KeepSelect 选择激励养成奖品 func (s *WCampaignUser) KeepSelect(req *pb.KeepSelectReq, res *pb.KeepSelectRes) (err error) { defer s.checkErr() user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } keepDog, err := players.NewKeepDog(s.ctx, user) if err != nil { return } status, err := keepDog.RewardSelect(req.GetRewardId()) if err != nil { return } *res = pb.KeepSelectRes{ Status: status, } return } // KeepCollect 激励养成收集一级道具 func (s *WCampaignUser) KeepCollect(req *pb.KeepCollectReq, res *pb.KeepCollectRes) (err error) { defer s.checkErr() user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } lc := app.NewRedisLock(s.ctx, ckey.FissionUserKeepDoingOnce(user.ID)).Lock() defer lc.Release() if lc.Error() != nil { err = lc.Error() return } keepDog, err := players.NewKeepDog(s.ctx, user) if err != nil { return } num, gets, err := keepDog.Collect() if err != nil { return } *res = pb.KeepCollectRes{ Gets: make([]*pb.KeepCollectRes_Reward, 0, len(gets)), Num: num, } for _, get := range gets { res.Gets = append(res.Gets, &pb.KeepCollectRes_Reward{ RewardType: get.RewardType, Chance: get.Chance, RewardId: get.RewardId, RewardTitle: get.RewardTitle, RewardImg: get.RewardImg, Lack: get.Lack, LastReward: get.LastReward, ReceiveType: get.ReceiveType, }) } return } // KeepFeed 激励养成收集一级道具 func (s *WCampaignUser) KeepFeed(req *pb.KeepFeedReq, res *pb.KeepFeedRes) (err error) { defer s.checkErr() user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } lc := app.NewRedisLock(s.ctx, ckey.FissionUserKeepDoingOnce(user.ID)).Lock() defer lc.Release() if lc.Error() != nil { err = lc.Error() return } keepDog, err := players.NewKeepDog(s.ctx, user) if err != nil { return } status, addPercent, err := keepDog.Feed() if err != nil { return } *res = pb.KeepFeedRes{ Status: status, AddPercent: addPercent, } return } // MachineSave 激励养成保存机器道具 func (s *WCampaignUser) MachineSave(req *pb.MachineSaveReq, res *pb.MachineSaveRes) (err error) { defer s.checkErr() user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } keepDog, err := players.NewKeepDog(s.ctx, user) if err != nil { return } err = keepDog.MachineSave(req.GetNum()) if err != nil { return } *res = pb.MachineSaveRes{} return } // MachineRecycle 激励养成保存机器道具 func (s *WCampaignUser) MachineRecycle(req *pb.MachineRecycleReq, res *pb.MachineRecycleRes) (err error) { defer s.checkErr() user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } keepDog, err := players.NewKeepDog(s.ctx, user) if err != nil { return } limit, getNum, err := keepDog.MachineRecycle(req.GetNum()) if err != nil { return } conf := keepDog.GetConf() *res = pb.MachineRecycleRes{ MachineLimit: limit, NextFull: time.Now().Add(time.Duration(conf.OfflineMin)*time.Minute).Unix() - time.Now().Unix(), GetNum: getNum, } return } // GetPropFeed 收喂养次数的道具 func (s *WCampaignUser) GetPropFeed(req *pb.GetPropFeedReq, res *pb.GetPropFeedRes) (err error) { defer s.checkErr() user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } keepDog, err := players.NewKeepDog(s.ctx, user) if err != nil { return } num, err := keepDog.GetPropFeed() if err != nil { return } *res = pb.GetPropFeedRes{ Num: num, } return } // KeepLog 激励养成记录 func (s *WCampaignUser) KeepLog(req *pb.KeepLogReq, res *pb.KeepLogRes) (err error) { defer s.checkErr() user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } keepDog, err := players.NewKeepDog(s.ctx, user) if err != nil { return } player := keepDog.GetPlayer() m := s.GetDao().FissionKeepLog var cond = []gen.Condition{ m.KeepID.Eq(player.ID), } if len(req.GetType()) > 0 { var ts = make([]int8, 0, len(req.GetType())) for _, v := range req.GetType() { ts = append(ts, int8(v)) } cond = append(cond, m.Type.In(ts...)) } offset, limit := utils.PpDbLo(req.GetPage(), req.GetPerPage()) list, total, err := m.WithContext(s.ctx).Where(cond...).Order(m.CreatedAt.Desc()).FindByPage(offset, limit) if err != nil { err = s.BE().MysqlError(err) return } *res = pb.KeepLogRes{ List: make([]*pb.KeepLogRes_One, 0, len(list)), Total: total, } for _, v := range list { res.List = append(res.List, &pb.KeepLogRes_One{ Type: int32(v.Type), Source: v.Source, Val: v.Val, CreatedAt: v.CreatedAt, }) } return } // KeepReselect 激励养成重新选择 func (s *WCampaignUser) KeepReselect(req *pb.KeepReselectReq, res *pb.KeepReselectRes) (err error) { defer s.checkErr() user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } keepDog, err := players.NewKeepDog(s.ctx, user) if err != nil { return } status, err := keepDog.Reselect() if err != nil { return } *res = pb.KeepReselectRes{ Status: status, } return } // KeepGuide 激励养成指引 func (s *WCampaignUser) KeepGuide(req *pb.KeepGuideReq, res *pb.KeepGuideRes) (err error) { defer s.checkErr() user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } keepDog, err := players.NewKeepDog(s.ctx, user) if err != nil { return } reward, err := keepDog.Guided() if err != nil { return } *res = pb.KeepGuideRes{ RewardType: reward.RewardType, Chance: reward.Chance, RewardId: reward.RewardId, RewardTitle: reward.RewardTitle, RewardImg: reward.RewardImg, Lack: reward.Lack, ReceiveType: reward.ReceiveType, } return } // KeepFirstInvite 激励养成首邀状态 func (s *WCampaignUser) KeepFirstInvite(req *pb.KeepFirstInviteReq, res *pb.KeepFirstInviteRes) (err error) { defer s.checkErr() user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } cpn, err := cache.NewCampaign(s.ctx).FindById(user.CampaignID) if err != nil { err = s.BE().CacheError(err) return } tz := provider.NewCampaignTZ(s.ctx, cpn, user.LangMark) start, _ := timez.GMTTimeStart(tz.GetTz()) keepDog, err := players.NewKeepDog(s.ctx, user) if err != nil { return } status, err := keepDog.GetStatus() if err != nil { return } conf := keepDog.GetConf() *res = pb.KeepFirstInviteRes{ OpenInvite: int32(conf.OpenInvite), DayFirstInvite: status.DayFirstInvite, DayFirstFeed: status.DayFirstFeed, ExpiredSec: start.Unix() - time.Now().Unix() + 86400, } return } // Child 子活动信息 func (s *WCampaignUser) Child(req *pb.ChildReq, res *pb.ChildRes) (err error) { defer s.checkErr() *res = pb.ChildRes{} container := new(containers.Child) { container.Init(s.ctx, logic.WithErrData(req)) container.Req = req container.Res = res } return container.Run() } // ChildActive 参与子活动 func (s *WCampaignUser) ChildActive(req *pb.ChildActiveReq, res *pb.ChildActiveRes) (err error) { defer s.checkErr() *res = pb.ChildActiveRes{} container := new(containers.ChildActive) { container.Init(s.ctx, logic.WithErrData(req)) container.Req = req container.Res = res } return container.Run() } // GoldFinishStep 完成金币任务阶段 func (s *WCampaignUser) GoldFinishStep(req *pb.GoldFinishStepReq, res *pb.GoldFinishStepRes) (err error) { defer s.checkErr() lc := app.NewRedisLock(s.ctx, ckey.FissionUserFinishStepOnce(req.GetUserId())) defer lc.Release() if !lc.SoftLock() { err = workerr.BusyError return } cpn, err := cache.NewCampaign(s.ctx).FindById(req.GetCampaignId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.IsDel == mtype.Yes { err = workerr.NotFound("not found cpn") return } user, err := cache.NewFissionUser(s.ctx, cpn.ID).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { err = workerr.NotFound("not found user") return } *res = pb.GoldFinishStepRes{} gold, err := players.NewGold(s.ctx, user) if err != nil { return } switch req.GetStep() { case mtype.FissionGoldNextStepOpenGift: res.OpenBox, res.LeftBox, res.RightBox, err = gold.OpenGift() return case mtype.FissionGoldNextStepTriggerShare: return gold.TriggerShare() case mtype.FissionGoldNextStepShowReward: return gold.ShowReward() case mtype.FissionGoldNextStepLastSpin: return gold.LastSpin() case mtype.FissionGoldNextStepGoldRain: return gold.GoldRain() default: return } } // GoldNotify 金币获取通知 func (s *WCampaignUser) GoldNotify(req *pb.GoldNotifyReq, res *pb.GoldNotifyRes) (err error) { defer s.checkErr() user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } *res = pb.GoldNotifyRes{} gold, err := players.NewGold(s.ctx, user) if err != nil { return } res.OldGold, res.AddGold = gold.Clue() return } // GoldRecord 金币获取记录 func (s *WCampaignUser) GoldRecord(req *pb.GoldRecordReq, res *pb.GoldRecordRes) (err error) { defer s.checkErr() cpn, user, err := s.CpnAndUser(req.GetCampaignId(), req.GetUserId()) if err != nil { return } gold, err := players.NewGold(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } player := gold.GetPlayer() m := s.GetDao().FissionGoldLog offset, limit := utils.PpDbLo(req.GetPage(), req.GetPerPage()) list, count, err := m.WithContext(s.ctx). Where(m.CampaignID.Eq(cpn.ID), m.GoldID.Eq(player.ID), m.Type.Eq(mtype.FissionGoldLogTypeDoTask)). Order(m.CreatedAt.Desc()). FindByPage(offset, limit) if err != nil { err = s.BE().MysqlError(err) return } *res = pb.GoldRecordRes{ List: make([]*pb.GoldRecordRes_One, 0, len(list)), Total: count, } var condIds []int64 var condMap = make(map[int64]string) for _, v := range list { val := v.GetVal() if _, ok := condMap[val.CondId]; !ok { condIds = append(condIds, val.CondId) condMap[val.CondId] = "" } } langTitle, err := provider.NewLangTitle(s.ctx, cpn, user.LangMark) if err != nil { return } condMap, err = langTitle.GetCondTitle(condIds...) if err != nil { return } for _, v := range list { val := v.GetVal() title, ok := condMap[val.CondId] one := &pb.GoldRecordRes_One{ Title: title, GoldNum: val.Chance, CreatedAt: v.CreatedAt, Mark: utils.Ternary[string](ok, "record:completed_task", "record:completed_task_none"), } if verify.InArray[string](v.Source, mtype.FissionLogSourceInstall, mtype.FissionLogSourceRegister) { one.Mark = "record:completed_invite_task" } res.List = append(res.List, one) } return } // Deduct 扣除积分 func (s *WCampaignUser) Deduct(req *pb.DeductReq, res *pb.DeductRes) (err error) { defer s.checkErr() lc := app.NewRedisLock(s.ctx, ckey.FissionCoinChangeLock(req.GetUserId())) defer lc.Release() if !lc.SoftLock() { err = workerr.OnceLockError return } user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } player, err := players.NewCoin(s.ctx, user) if err != nil { return } useNum, status, err := player.Deduct() if err != nil { return } playerStatus, err := player.GetStatus() if err != nil { return } *res = pb.DeductRes{ Status: status, Total: playerStatus.AllCoin, UseNum: useNum, GetCoin: playerStatus.GetCoin, OpenSec: playerStatus.OpenSec, } return } // Gain 领取积分 func (s *WCampaignUser) Gain(req *pb.GainReq, res *pb.GainRes) (err error) { defer s.checkErr() lc := app.NewRedisLock(s.ctx, ckey.FissionCoinChangeLock(req.GetUserId())) defer lc.Release() if !lc.SoftLock() { err = workerr.OnceLockError return } user, err := cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } player, err := players.NewCoin(s.ctx, user) if err != nil { return } getCoin, status, err := player.Gain() if err != nil { return } *res = pb.GainRes{ Status: status, GetCoin: getCoin, } return } // CoinRecord 金币池记录 func (s *WCampaignUser) CoinRecord(req *pb.CoinRecordReq, res *pb.CoinRecordRes) (err error) { defer s.checkErr() cpn, err := finder.Campaign(s.ctx, req.GetCampaignId(), req.GetCampaignHashId()) if err != nil { err = s.BE().CacheError(err) return } m := s.GetDao().FissionCoinLog var cond = []gen.Condition{ m.CampaignID.Eq(cpn.ID), } var userMap = make(map[int64]string) if req.GetUserId() > 0 { var user *model.FissionUser user, err = cache.NewFissionUser(s.ctx, cpn.ID).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { return } cond = append(cond, m.UserID.Eq(user.ID)) userMap[user.ID] = user.SubUserID } if req.GetSubUserId() != "" { var user *model.FissionUser user, err = cache.NewFissionUser(s.ctx, cpn.ID).FindBySubUserId(req.GetSubUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { return } cond = append(cond, m.UserID.Eq(user.ID)) userMap[user.ID] = user.SubUserID } if len(req.GetType()) > 0 { var status = make([]int8, 0, len(req.GetType())) for _, v := range req.GetType() { status = append(status, int8(v)) } cond = append(cond, m.Type.In(status...)) } if req.GetSceneId() > 0 { cond = append(cond, m.SceneID.Eq(req.GetSceneId())) } if req.GetSource() != "" { cond = append(cond, m.Source.Eq(req.GetSource())) } tz := utils.STernary[int32](req.GetTOffset(), consts.DefaultTz, cpn.TOffset) if req.GetStart() > 0 { cond = append(cond, m.CreatedAt.Gte(timez.GMT(req.GetStart(), tz))) } if req.GetEnd() > 0 { cond = append(cond, m.CreatedAt.Lte(timez.GMT(req.GetEnd(), tz))) } offset, limit := utils.PpDbLo(req.GetPage(), req.GetPerPage()) list, count, err := m.WithContext(s.ctx). Where(cond...). Order(m.CreatedAt.Desc()). FindByPage(offset, limit) if err != nil { err = s.BE().MysqlError(err) return } sceneM := s.GetDao().FissionCoinScene scenes, err := sceneM.WithContext(s.ctx).Where(sceneM.CampaignID.Eq(cpn.ID)).Find() if err != nil { err = s.BE().MysqlError(err) return } gmt := utils.Ternary[string](cpn.TOffset < 0, fmt.Sprint(cpn.TOffset), fmt.Sprintf("+%d", cpn.TOffset)) var titleMap = make(map[int64]string, len(scenes)) for _, v := range scenes { day, _, _ := timez.GMTStartAndEndTs(cpn.TOffset, v.OpenTime) titleMap[v.ID] = fmt.Sprintf("%s(GMT%s)", day, gmt) } if req.GetUserId() == 0 && req.GetSubUserId() == "" { var userId []int64 for _, v := range list { if _, ok := userMap[v.UserID]; !ok { userId = append(userId, v.UserID) } } userM := s.GetDao().FissionUser.SubTable(cpn.ID) var users []*model.FissionUser users, err = userM.WithContext(s.ctx).Where(userM.ID.In(userId...)).Find() if err != nil { err = s.BE().MysqlError(err) return } for _, v := range users { userMap[v.ID] = v.SubUserID } } *res = pb.CoinRecordRes{ List: make([]*pb.CoinRecordRes_One, 0, len(list)), Total: count, } for _, v := range list { val := v.GetVal() res.List = append(res.List, &pb.CoinRecordRes_One{ Id: v.ID, Type: int32(v.Type), CreatedAt: v.CreatedAt, Source: v.Source, Num: val.CoinNum, SubUserId: userMap[v.UserID], Title: titleMap[v.SceneID], }) } return } // ChildList 子活动用户列表 func (s *WCampaignUser) ChildList(req *pb.ChildListReq, res *pb.ChildListRes) (err error) { defer s.checkErr() *res = pb.ChildListRes{} container := new(containers.ChildList) { container.Init(s.ctx, logic.WithErrData(req)) container.Req = req container.Res = res } return container.Run() } // ReceiveReward 领取奖励 func (s *WCampaignUser) ReceiveReward(req *pb.ReceiveRewardReq, res *pb.ReceiveRewardRes) (err error) { defer s.checkErr() lc := app.NewRedisLock(s.ctx, ckey.FissionReceiveRewardLock(req.GetUserId(), req.GetTaskId())) defer lc.Release() if !lc.SoftLock() { err = workerr.OnceLockError return } m := s.GetDao().FissionUserTaskReward list, err := m.WithContext(s.ctx).Where( m.UserID.Eq(req.GetUserId()), m.TaskID.Eq(req.GetTaskId()), m.ReceiveTime.Eq(0), ).Find() if err != nil { err = s.BE().MysqlError(err) return } if len(list) == 0 { return } cpn, user, err := s.CpnAndUser(req.GetCampaignId(), req.GetUserId()) if err != nil { return } var reward *award.RewardRes var chance int32 switch cpn.FissionID { case consts.IdPrizeWheel: var player *players.Wheel player, err = players.NewWheel(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } chance, reward, err = player.ReceiveReward(list...) if err != nil { return } case consts.IdBlindBox: var player *players.Blind player, err = players.NewBlind(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } chance, reward, err = player.ReceiveReward(list...) if err != nil { return } case consts.IdLuckyGrid: var player *players.Grid player, err = players.NewGrid(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } chance, reward, err = player.ReceiveReward(list...) if err != nil { return } case consts.IdFlip: var player *players.Flip player, err = players.NewFlip(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } chance, reward, err = player.ReceiveReward(list...) if err != nil { return } case consts.IdSlotMachine: var player *players.Slot player, err = players.NewSlot(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } chance, reward, err = player.ReceiveReward(list...) if err != nil { return } case consts.IdKeep: var player *players.KeepDog player, err = players.NewKeepDog(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } chance, reward, err = player.ReceiveReward(list...) if err != nil { return } case consts.IdVs: var player *players.Vs player, err = players.NewVs(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } chance, reward, err = player.ReceiveReward(list...) if err != nil { return } case consts.IdGashapon: var player *players.Gashapon player, err = players.NewGashapon(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } chance, reward, err = player.ReceiveReward(list...) case consts.IdPrizeAnswer, consts.IdQa, consts.IdQaAudio, consts.IdQaVideo: var player *players.Qa player, err = players.NewQa(s.ctx, user, cpn.FissionID, players.SetCpn(cpn)) if err != nil { return } chance, reward, err = player.ReceiveReward(list...) if err != nil { return } default: return s.BE().VerifyError("Not supported") } *res = pb.ReceiveRewardRes{ PropMark: mtype.FissionCampaignRewardPropMarkChance, Chance: chance, Reward: nil, } if reward != nil { res.PropMark = reward.Reward.PropMark res.Reward = &pb.ReceiveRewardRes_Reward{ HashId: reward.Record.HashID, Title: reward.Info.Title, Img: reward.Info.ImgUrl, JumpUrl: "", KvData: nil, ReceiveType: reward.Info.ReceiveType, Contact: reward.Info.Contact, CreatedAt: reward.Record.CreatedAt, OpenToUse: reward.Info.OpenToUse, WebUrl: reward.Info.WebUrl, AppParam: reward.Info.AppParam, PcParam: reward.Info.PcParam, Lack: utils.Ternary[int32](reward.Record.FailMsg == mtype.FissionRewardRecordFailTypeCliLackMsg, 1, 0), RewardNum: reward.Record.RewardNum, } for _, v := range reward.Info.KvData { res.Reward.KvData = append(res.Reward.KvData, &pb.ReceiveRewardRes_KV{ Key: v.Key, Value: v.Value, IsShow: v.IsShow, }) } } return } // LotteryLog 抽奖玩法日志 func (s *WCampaignUser) LotteryLog(req *pb.LotteryLogReq, res *pb.LotteryLogRes) (err error) { defer s.checkErr() *res = pb.LotteryLogRes{} container := new(containers.LotteryLog) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // UserList 活动用户数据 func (s *WCampaignUser) UserList(req *pb.UserListReq, res *pb.UserListRes) (err error) { defer s.checkErr() m := s.GetDao().FissionUser.SubTable(req.GetCampaignId()) var idsGroup = utils.Groups[int64](req.GetIds(), 200) var list []*model.FissionUser for _, ids := range idsGroup { var parts []*model.FissionUser parts, err = m.WithContext(s.ctx).Where(m.ID.In(ids...)).Find() if err != nil { return } list = append(list, parts...) } *res = pb.UserListRes{ List: make([]*pb.UserListRes_One, 0, len(list)), } for _, v := range list { res.List = append(res.List, &pb.UserListRes_One{ Id: v.ID, HashId: v.HashID, SubUserId: v.SubUserID, DeviceId: v.DeviceID, }) } return } // CashAgain 现金大抽奖再玩一次 func (s *WCampaignUser) CashAgain(req *pb.CashAgainReq, res *pb.CashAgainRes) (err error) { defer s.checkErr() user, err := finder.FissionUser(s.ctx, req.GetCampaignId(), req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { err = s.BE().VerifyError("not found user") return } cash, err := players.NewCash(s.ctx, user) if err != nil { return } err = cash.Again() if err != nil { return } *res = pb.CashAgainRes{} return } // MarkLevel 用户等级标识列表 func (s *WCampaignUser) MarkLevel(req *pb.MarkLevelReq, res *pb.MarkLevelRes) (err error) { defer s.checkErr() project, err := finder.Project(s.ctx, req.GetProjectId()) if err != nil { err = s.BE().CacheError(err) return } if project == nil { return } m := s.GetDao().FissionUserLevel list, err := m.WithContext(s.ctx).Where( m.ProjectID.Eq(project.ID), m.Mark.In(req.GetMarks()...), m.DeletedAt.Eq(0), ).Find() if err != nil { err = s.BE().MysqlError(err) return } *res = pb.MarkLevelRes{ List: make([]*pb.MarkLevelRes_One, 0, len(list)), } for _, v := range list { res.List = append(res.List, &pb.MarkLevelRes_One{ Id: v.ID, Title: v.Title, Mark: v.Mark, }) } return } // DiceCollect 用户手机碎片 func (s *WCampaignUser) DiceCollect(req *pb.DiceCollectReq, res *pb.DiceCollectRes) (err error) { defer s.checkErr() cpn, err := finder.Campaign(s.ctx, req.GetCampaignHashId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil { return } user, err := finder.FissionUser(s.ctx, cpn.ID, req.GetHashId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil { return } collectM := s.GetDao().FissionDiceCollect collects, err := collectM.WithContext(s.ctx).Where(collectM.UserID.Eq(user.ID)).Find() if err != nil { err = s.BE().MysqlError(err) return } var collectMap = make(map[int64]*model.FissionDiceCollect) for _, v := range collects { collectMap[v.RewardID] = v } rewards, err := cmm.NewCMM(s.ctx, s.GetDao()).UserAppReward(user) if err != nil { return } var brIds []int64 for _, v := range rewards { brIds = append(brIds, v.RewardID) } rewardM := s.GetDao().Reward rewardList, err := rewardM.WithContext(s.ctx).Where(rewardM.ID.In(brIds...)).Find() if err != nil { err = s.BE().MysqlError(err) return } var rewardTitle = make(map[int64]string, len(rewardList)) for _, v := range rewardList { rewardTitle[v.ID] = v.RewardTitle } for _, reward := range rewards { one := &pb.DiceCollectRes_One{ RewardId: reward.ID, Num: 0, CollectNum: reward.CollectNum, Title: rewardTitle[reward.RewardID], MixNum: 0, MaxNum: reward.CollectNum, } rule := reward.GetCollectRule() if rule.Open == mtype.Yes { one.MaxNum = rule.InitCollect } if collect, ok := collectMap[reward.ID]; ok { one.Num = collect.Num one.MixNum = collect.IntactNum if rule.Open == mtype.Yes { one.MaxNum = rule.InitCollect * collect.SignNum } } res.List = append(res.List, one) } return } // ClientReward 用户手机碎片 func (s *WCampaignUser) ClientReward(req *pb.ClientRewardReq, res *pb.ClientRewardRes) (err error) { defer s.checkErr() var userId = req.GetUserId() var projectId, cpnId int64 if req.GetPorjectHashId() != "" { var project *model.Project project, err = finder.Project(s.ctx, req.GetPorjectHashId()) if err != nil { err = s.BE().CacheError(err) return } if project != nil { projectId = project.ID } } if req.GetCampaignUserId() != 0 { var user *model.FissionUser user, err = cache.NewFissionUser(s.ctx, req.GetCampaignId()).FindById(req.GetCampaignUserId()) if err != nil { err = s.BE().CacheError(err) return } if user != nil { userId = user.SubUserID var cpn *model.FissionCampaign cpn, err = finder.Campaign(s.ctx, user.CampaignID) if err != nil { err = s.BE().CacheError(err) return } if cpn != nil { projectId = cpn.ProjectID cpnId = cpn.ID } } } m := s.GetDao().FissionClientReward var cond = []gen.Condition{ m.UserID.Eq(userId), m.ReceiveAt.Eq(0), } if projectId > 0 { cond = append(cond, m.ProjectID.Eq(projectId)) } if cpnId > 0 { cond = append(cond, m.CampaignID.Eq(cpnId)) } *res = pb.ClientRewardRes{ Rewards: make([]*pb.ClientRewardRes_Reward, 0, 20), } var rewardMap = make(map[int64]*model.Reward) var list []*model.FissionClientReward err = m.WithContext(s.ctx).Where(cond...).FindInBatches(&list, 200, func(tx gen.Dao, batch int) error { var ids []int64 var recordIds []int64 for _, v := range list { ids = append(ids, v.ID) recordIds = append(recordIds, v.RecordID) } recordM := s.GetDao().FissionRewardRecord records, err1 := recordM.WithContext(s.ctx).Where(recordM.ID.In(recordIds...)).Find() if err1 != nil { return s.BE().MysqlError(err) } var rewardIds []int64 for _, record := range records { if _, ok := rewardMap[record.BaseRewardID]; !ok { rewardMap[record.BaseRewardID] = nil rewardIds = append(rewardIds, record.BaseRewardID) } } if len(rewardIds) > 0 { rewardM := s.GetDao().Reward var rewards []*model.Reward rewards, err = rewardM.WithContext(s.ctx).Where(rewardM.ID.In(rewardIds...)).Find() if err != nil { return s.BE().MysqlError(err) } for _, reward := range rewards { rewardMap[reward.ID] = reward } } for _, record := range records { one := &pb.ClientRewardRes_Reward{ HashId: record.HashID, CreatedAt: record.CreatedAt, KvData: make([]*pb.ClientRewardRes_KV, 0), } if reward, ok := rewardMap[record.BaseRewardID]; ok { for _, kv := range reward.GetKvData() { one.KvData = append(one.KvData, &pb.ClientRewardRes_KV{ Key: kv.Key, Value: kv.Value, }) } } res.Rewards = append(res.Rewards, one) } _, err = recordM.WithContext(s.ctx).Where(recordM.ID.In(recordIds...)).UpdateSimple(recordM.Status.Value(mtype.FissionRewardRecordStatusSuccess)) if err != nil { return s.BE().MysqlError(err) } subM := s.GetDao().FissionRewardRecord.SubTable(cpnId) _, err = subM.WithContext(s.ctx).Where(subM.ID.In(recordIds...)).UpdateSimple(subM.Status.Value(mtype.FissionRewardRecordStatusSuccess)) if err != nil { return s.BE().MysqlError(err) } _, err = m.WithContext(s.ctx).Where(m.ID.In(ids...)).UpdateSimple(m.ReceiveAt.Value(time.Now().Unix())) if err != nil { return s.BE().MysqlError(err) } return nil }) if err != nil { err = s.BE().MysqlError(err) return } return } // PointsUse 积分兑换 func (s *WCampaignUser) PointsUse(req *pb.PointsUseReq, res *pb.PointsUseRes) (err error) { defer s.checkErr() cpn, user, err := s.CpnAndUser(req.GetCampaignId(), req.GetUserId()) if err != nil { return } var status int32 switch cpn.FissionID { case consts.IdPrizeWheel: var player *players.Wheel player, err = players.NewWheel(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } status, err = player.PointsUse() case consts.IdDice: var player *players.Dice player, err = players.NewDice(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } status, err = player.PointsUse() case consts.IdGashapon: var player *players.Gashapon player, err = players.NewGashapon(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } status, err = player.PointsUse() default: return s.BE().VerifyError("Not supported") } *res = pb.PointsUseRes{ Status: status, } return } // Chat Ai聊天 func (s *WCampaignUser) Chat(req *pb.ChatReq, res *pb.ChatRes) (err error) { defer s.checkErr() *res = pb.ChatRes{} container := new(containers.Chat) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // ChatList Ai聊天 func (s *WCampaignUser) ChatList(req *pb.ChatListReq, res *pb.ChatListRes) (err error) { defer s.checkErr() *res = pb.ChatListRes{} container := new(containers.ChatList) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // ScheduleList 赛程信息 func (s *WCampaignUser) ScheduleList(req *pb.ScheduleListReq, res *pb.ScheduleListRes) (err error) { defer s.checkErr() cpn, user, err := s.CpnAndUser(req.GetCampaignId(), req.GetUserId()) if err != nil { return } player, err := players.NewVs(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } schedules, err := player.Schedules(req.GetTabType()) if err != nil { return } var list = make([]*pb.ScheduleListRes_One, 0, len(schedules)) for _, schedule := range schedules { one := &pb.ScheduleListRes_One{ Id: schedule.Id, Desc: schedule.Desc, VsImg: schedule.VsImg, VsDate: schedule.VsDate, VsTz: schedule.VsTz, VoteCountdown: schedule.VoteCountdown, Status: schedule.Status, WinType: schedule.WinType, WinTeamId: schedule.WinTeamId, Teams: make([]*pb.ScheduleListRes_Team, 0, len(schedule.Teams)), UserVote: nil, Reward: nil, Votes: make([]*pb.ScheduleListRes_Vote, 0, len(schedule.Votes)), OtherVote: schedule.OtherVote, Scores: make([]*pb.ScheduleListRes_Score, 0, len(schedule.Scores)), OpenOdds: schedule.OpenOdds, OddsLeft: schedule.OddsLeft, OddsRight: schedule.OddsRight, OddsDraw: schedule.OddsDraw, } if schedule.UserVote != nil { one.UserVote = &pb.ScheduleListRes_UserVote{ UserWinType: schedule.UserVote.UserWinType, UserWinTeamId: schedule.UserVote.UserWinTeamId, IsWin: schedule.UserVote.IsWin, VoteNum: schedule.UserVote.VoteNum, } } for _, team := range schedule.Teams { one.Teams = append(one.Teams, &pb.ScheduleListRes_Team{ Id: team.Id, Name: team.Name, LogoImg: team.LogoImg, Score: team.Score, }) } for _, vote := range schedule.Votes { one.Votes = append(one.Votes, &pb.ScheduleListRes_Vote{ WinType: vote.WinType, WinTeamId: vote.WinTeamId, Num: vote.Num, }) } for _, score := range schedule.Scores { one.Scores = append(one.Scores, &pb.ScheduleListRes_Score{ TeamId: score.TeamId, Score: score.Score, }) } if reward := schedule.Reward; reward != nil { one.Reward = &pb.ScheduleListRes_Reward{ RewardId: reward.Id, PropMark: reward.PropMark, Title: reward.Title, Img: reward.Img, KvData: make([]*pb.ScheduleListRes_KV, 0, len(reward.KvData)), ReceiveType: reward.ReceiveType, Contact: reward.Contact, OpenToUse: reward.OpenToUse, WebUrl: reward.WebUrl, AppParam: reward.AppParam, PcParam: reward.PcParam, PropNum: reward.PropNum, } for _, kv := range reward.KvData { one.Reward.KvData = append(one.Reward.KvData, &pb.ScheduleListRes_KV{ Key: kv.Key, Value: kv.Value, IsShow: kv.IsShow, }) } } list = append(list, one) } *res = pb.ScheduleListRes{ List: list, } return } // MallList 用户商城奖品列表 func (s *WCampaignUser) MallList(req *pb.MallListReq, res *pb.MallListRes) (err error) { defer s.checkErr() *res = pb.MallListRes{} container := new(containers.MallList) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // Exchange 商城奖品兑换 func (s *WCampaignUser) Exchange(req *pb.ExchangeReq, res *pb.ExchangeRes) (err error) { defer s.checkErr() *res = pb.ExchangeRes{} container := new(containers.Exchange) { container.Init(s.ctx, logic.WithTran()) container.Req = req container.Res = res } return container.Run() } // VoteList 投票列表 func (s *WCampaignUser) VoteList(req *pb.VoteListReq, res *pb.VoteListRes) (err error) { defer s.checkErr() cpn, user, err := s.CpnAndUserStr(req.GetCampaignHashId(), req.GetUserHashId()) if err != nil { return } m := s.GetDao().FissionVsVote votes, err := m.WithContext(s.ctx).Where( m.CampaignID.Eq(cpn.ID), m.UserID.Eq(user.ID), ).Order(m.ID.Desc()).Find() if err != nil { err = s.BE().MysqlError(err) return } teamM := s.GetDao().FissionCampaignVsTeam teams, err := teamM.WithContext(s.ctx).Where( teamM.CampaignID.Eq(cpn.ID), ).Find() if err != nil { err = s.BE().MysqlError(err) return } var teamMap = make(map[int64]*pb.VoteListRes_Team, len(teams)) for _, team := range teams { teamMap[team.ID] = &pb.VoteListRes_Team{ Id: team.ID, Name: team.Name, LogoImg: team.LogoImg, } } var scheduleIds []int64 for _, vote := range votes { scheduleIds = append(scheduleIds, vote.ScheduleID) } scheduleM := s.GetDao().FissionCampaignVsSchedule schedules, err := scheduleM.WithContext(s.ctx).Where( scheduleM.ID.In(scheduleIds...), ).Find() if err != nil { err = s.BE().MysqlError(err) return } var scheduleTeamMap = make(map[int64][]*pb.VoteListRes_Team, len(schedules)) for _, schedule := range schedules { for _, id := range schedule.GetVsTeamIds() { scheduleTeamMap[schedule.ID] = append(scheduleTeamMap[schedule.ID], teamMap[id]) } } *res = pb.VoteListRes{ List: make([]*pb.VoteListRes_One, 0, len(votes)), } for _, vote := range votes { res.List = append(res.List, &pb.VoteListRes_One{ Id: vote.ID, Teams: scheduleTeamMap[vote.ScheduleID], WinType: int32(vote.WinType), WinTeamId: vote.WinTeamID, FreeVote: vote.FreeVote, PointVote: vote.PointVote, }) } return } // VsTipReward 接收投票结果 func (s *WCampaignUser) VsTipReward(req *pb.VsTipRewardReq, res *pb.VsTipRewardRes) (err error) { defer s.checkErr() cpn, user, err := s.CpnAndUser(req.GetCampaignId(), req.GetUserId()) if err != nil { return } player, err := players.NewVs(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } err = player.TipReward() if err != nil { return } *res = pb.VsTipRewardRes{} return } // UnoRandCard uno随机牌 func (s *WCampaignUser) UnoRandCard(req *pb.UnoRandCardReq, res *pb.UnoRandCardRes) (err error) { defer s.checkErr() *res = pb.UnoRandCardRes{} container := new(containers.UnoRandCard) { container.Init(s.ctx, logic.WithTran(), logic.WithOnce(ckey.FissionUserUnoRandCardOnce(req.GetUserId()))) container.Req = req container.Res = res } return container.Run() } // UnoClaim uno领取牌奖励 func (s *WCampaignUser) UnoClaim(req *pb.UnoClaimReq, res *pb.UnoClaimRes) (err error) { defer s.checkErr() cpn, user, err := s.CpnAndUser(req.GetCampaignId(), req.GetUserId()) if err != nil { return } player, err := players.NewUno(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } status, info, record, err := player.Claim(req.GetColorMark()) if err != nil { return } *res = pb.UnoClaimRes{ Status: status, } if record != nil { res.Id = record.ID res.HashId = record.HashID res.RewardId = record.RewardID res.Title = info.Title res.ImgUrl = info.ImgUrl res.KvData = make([]*pb.UnoClaimRes_KV, 0, len(info.KvData)) res.ReceiveType = info.ReceiveType res.Contact = info.Contact res.OpenToUse = info.OpenToUse res.CustomRewardVal = record.CustomRewardVal res.WebUrl = info.WebUrl res.AppParam = info.AppParam res.PcParam = info.PcParam for _, kv := range info.KvData { res.KvData = append(res.KvData, &pb.UnoClaimRes_KV{ Key: kv.Key, Value: kv.Value, IsShow: kv.IsShow, }) } } return } // UnoCard uno卡牌 func (s *WCampaignUser) UnoCard(req *pb.UnoCardReq, res *pb.UnoCardRes) (err error) { defer s.checkErr() cpn, user, err := s.CpnAndUserStr(req.GetCampaignHashId(), req.GetUserHashId()) if err != nil { return } m := s.GetDao().FissionUnoCollect list, err := m.WithContext(s.ctx).Where(m.UserID.Eq(user.ID)).Find() if err != nil { err = s.BE().MysqlError(err) return } var collectMap = make(map[string]*model.FissionUnoCollect, len(list)) for _, v := range list { collectMap[v.Mark] = v } groupM := s.GetDao().FissionCampaignUnoGroup groups, err := groupM.WithContext(s.ctx).Where(groupM.CampaignID.Eq(cpn.ID)).Find() if err != nil { err = s.BE().MysqlError(err) return } *res = pb.UnoCardRes{ List: make([]*pb.UnoCardRes_One, 0, len(list)), } for _, v := range groups { one := &pb.UnoCardRes_One{ Id: v.ID, Mark: v.Mark, LimitNum: 9, } if collect, ok := collectMap[v.Mark]; ok { one.PreIntactNum = collect.PreIntactNum one.IntactNum = collect.IntactNum one.CardInfo = collect.GetCardInfo() if v.OpenRule == mtype.Yes { rule := v.GetLimitRule() one.LimitNum = rule.InitNum + rule.AddNum*(collect.SignNum/rule.SignDay) if one.LimitNum > 9 { one.LimitNum = 9 } } } res.List = append(res.List, one) } return } // Show 用户详情 func (s *WCampaignUser) Show(req *pb.ShowReq, res *pb.ShowRes) (err error) { defer s.checkErr() cpn, user, err := s.CpnAndUserStr(req.GetCampaignHashId(), req.GetUserHashId()) if err != nil { return } attr := provider.NewFissionUserAttr(s.ctx, user) platform, err := attr.GetAttr(mtype.FissionUserAttrMarkPlatform) if err != nil { return } var oss string var os string if platform != nil { os = platform.Value oss = platform.Values } lang, _ := attr.GetAttr(mtype.FissionUserAttrMarkLang) var langMarks []string if lang != nil { langMarks = lang.GetValues() } lv, _ := attr.GetAttr(mtype.FissionUserAttrMarkUserLv) var lvMarks string if lv != nil { lvMarks = lv.Values } lastView, err := app.NewFissionBiFissionAction().FindLast(s.ctx, &bi_fission_actionpb.FindLastReq{ CampaignId: cpn.ID, Type: mtype.FissionActionTypeView, UserMark: fmt.Sprint(user.ID), }) if err != nil { return } *res = pb.ShowRes{ Id: user.ID, HashId: user.HashID, UserId: user.SubUserID, DeviceId: user.DeviceID, CreatedAt: user.CreatedAt, Source: int32(user.Source), LangMark: user.LangMark, LangMarks: langMarks, LvMark: user.LevelMark, LvMarks: lvMarks, Os: os, Oss: oss, JoinAt: user.JoinAt, JoinAtLast: lastView.GetActionTime(), Tz: cpn.TOffset, } return } // EventFirstVisit 首次访问活动 func (s *WCampaignUser) EventFirstVisit(req *pb.EventFirstVisitReq, res *pb.EventFirstVisitRes) (err error) { defer s.checkErr() cpn, user, err := s.CpnAndUser(req.GetCampaignId(), req.GetUserId()) if err != nil { return } var rewards []*players.EventReward switch cpn.FissionID { case consts.IdVs: var player *players.Vs player, err = players.NewVs(s.ctx, user, players.SetCpn(cpn)) if err != nil { return } rewards, err = player.FirstVisit() if err != nil { return } } *res = pb.EventFirstVisitRes{ Rewards: make([]*pb.EventFirstVisitRes_EventReward, 0, len(rewards)), } for _, v := range rewards { var reward *pb.EventFirstVisitRes_Reward if verify.InArray[string](v.PropMark, mtype.FissionCampaignRewardPropMarkPoint, mtype.FissionCampaignRewardPropMarkReward) { record, info := v.Reward.Record, v.Reward.Info reward = &pb.EventFirstVisitRes_Reward{ Id: record.ID, HashId: record.HashID, RewardId: record.RewardID, RewardNum: record.RewardNum, Title: record.Title, ImgUrl: record.ImgURL, KvData: make([]*pb.EventFirstVisitRes_KV, 0, len(info.KvData)), ReceiveType: info.ReceiveType, Contact: info.Contact, CustomRewardVal: record.CustomRewardVal, WebUrl: info.WebUrl, AppParam: info.AppParam, PcParam: info.PcParam, } for _, kv := range info.KvData { reward.KvData = append(reward.KvData, &pb.EventFirstVisitRes_KV{ Key: kv.Key, Value: kv.Value, IsShow: kv.IsShow, }) } } res.Rewards = append(res.Rewards, &pb.EventFirstVisitRes_EventReward{ PropMark: v.PropMark, Reward: reward, Chance: v.Chance, }) } return } // FindByUniq 通过唯一键找用户id func (s *WCampaignUser) FindByUniq(req *pb.FindByUniqReq, res *pb.FindByUniqRes) (err error) { defer s.checkErr() c := cache.NewFissionUser(s.ctx, req.GetCampaignId()) var user *model.FissionUser if req.GetSubUserId() != "" { user, err = c.FindBySubUserId(req.GetSubUserId()) if err != nil { err = s.BE().CacheError(err) return } } if req.GetDeviceId() != "" { user, err = c.FindBySubUserId(req.GetDeviceId()) if err != nil { err = s.BE().CacheError(err) return } } var id int64 if user != nil { id = user.ID } *res = pb.FindByUniqRes{ Id: id, } return } // TaskTip 任务提示 func (s *WCampaignUser) TaskTip(req *pb.TaskTipReq, res *pb.TaskTipRes) (err error) { defer s.checkErr() cpn, user, err := s.CpnAndUser(req.GetCampaignId(), req.GetUserId()) if err != nil || cpn == nil || user == nil { return } list, err := players.GetTaskTip(s.ctx, user.ID) if err != nil { return } *res = pb.TaskTipRes{ Rewards: make([]*pb.TaskTipRes_EventReward, 0), L: int32(len(list)), } var hasCoin bool var recordIds []int64 for _, v := range list { if v.PropMark == mtype.FissionCampaignRewardPropMarkPoint { hasCoin = true } if v.RecordId > 0 { recordIds = append(recordIds, v.RecordId) } } var recordMap = make(map[int64]*model.FissionRewardRecord) var preward *provider.Rewards if len(recordIds) > 0 { m := s.GetDao().FissionRewardRecord.SubTable(req.GetCampaignId()) var records []*model.FissionRewardRecord records, err = m.WithContext(s.ctx).Where(m.ID.In(recordIds...)).Find() if err != nil { return } var bIds []int64 var bMap = make(map[int64]struct{}) for _, v := range records { recordMap[v.ID] = v if _, ok := bMap[v.BaseRewardID]; !ok && v.BaseRewardID > 0 { bIds = append(bIds, v.BaseRewardID) bMap[v.BaseRewardID] = struct{}{} } } if len(bIds) > 0 { preward, err = provider.NewRewards(s.ctx, cpn.ProjectID, bIds...) if err != nil { return } } } var title, imgUrl string if hasCoin { title, imgUrl, _, err = cmm.NewCMM(s.ctx, s.GetDao()).GetCoinInfo(cpn.ProjectID, user.LangMark) if err != nil { return } } for _, v := range list { switch v.PropMark { case mtype.FissionCampaignRewardPropMarkChance: res.Rewards = append(res.Rewards, &pb.TaskTipRes_EventReward{ PropMark: v.PropMark, Reward: nil, Chance: v.Chance, }) case mtype.FissionCampaignRewardPropMarkReward: r := recordMap[v.RecordId] info, _ := preward.InfoAutoLang(r.BaseRewardID, user.LangMark) var kv = make([]*pb.TaskTipRes_KV, 0, len(info.KvData)) for _, d := range info.KvData { kv = append(kv, &pb.TaskTipRes_KV{ Key: d.Key, Value: d.Value, IsShow: d.IsShow, }) } res.Rewards = append(res.Rewards, &pb.TaskTipRes_EventReward{ PropMark: v.PropMark, Reward: &pb.TaskTipRes_Reward{ Id: r.ID, HashId: r.HashID, RewardId: r.RewardID, RewardNum: r.RewardNum, Title: info.Title, ImgUrl: info.ImgUrl, KvData: kv, ReceiveType: info.ReceiveType, Contact: info.Contact, CustomRewardVal: r.CustomRewardVal, WebUrl: info.WebUrl, AppParam: info.AppParam, PcParam: info.PcParam, }, Chance: v.Chance, }) case mtype.FissionCampaignRewardPropMarkPoint: r := recordMap[v.RecordId] res.Rewards = append(res.Rewards, &pb.TaskTipRes_EventReward{ PropMark: v.PropMark, Reward: &pb.TaskTipRes_Reward{ Id: r.ID, HashId: r.HashID, RewardId: r.RewardID, RewardNum: r.RewardNum, Title: title, ImgUrl: imgUrl, }, Chance: r.RewardNum, }) } } return } // TaskTipOk 任务提示完成 func (s *WCampaignUser) TaskTipOk(req *pb.TaskTipOkReq, res *pb.TaskTipOkRes) (err error) { defer s.checkErr() cpn, user, err := s.CpnAndUser(req.GetCampaignId(), req.GetUserId()) if err != nil || cpn == nil || user == nil { return } players.DelTaskTip(s.ctx, user.ID, req.GetL()) *res = pb.TaskTipOkRes{} return } // CoinLog 金币日志 func (s *WCampaignUser) CoinLog(req *pb.CoinLogReq, res *pb.CoinLogRes) (err error) { defer s.checkErr() cpn, user, err := s.CpnAndUser(req.GetCampaignId(), req.GetUserId()) if err != nil || cpn == nil || user == nil { return } if user.SubUserID == "" { return } pu, err := projectuser.NewProjectUser(s.ctx, projectuser.WithInit(cpn.ProjectID, user.SubUserID)) if err != nil { return } m := s.GetDao().ProjectUserCoinRecord var cond = []gen.Condition{ m.UserID.Eq(pu.GetProjectUser().ID), m.Source.Eq(mtype.ProjectUserCoinSourceCampaign), m.SourceID.Eq(cpn.ID), m.CreatedAt.Gt(cpn.StartTime), } if req.GetType() > 0 { cond = append(cond, m.Type.Eq(int8(req.GetType()))) } o, l := utils.PpDbLo(req.GetPage(), req.GetPerPage()) list, total, err := m.WithContext(s.ctx).Where(cond...).Order(m.ID.Desc()).FindByPage(o, l) if err != nil { err = s.BE().MysqlError(err) return } if total == 0 { return } *res = pb.CoinLogRes{ List: make([]*pb.CoinLogRes_One, 0, len(list)), Total: total, } for _, v := range list { res.List = append(res.List, &pb.CoinLogRes_One{ CreatedAt: v.CreatedAt, Mark: fmt.Sprintf("coin_log:%s", v.Mark), Num: v.Num, Type: int32(v.Type), }) } return } // AnswerHistory 答题历史 func (s *WCampaignUser) AnswerHistory(req *pb.AnswerHistoryReq, res *pb.AnswerHistoryRes) (err error) { defer s.checkErr() cpn, err := cache.NewCampaign(s.ctx).FindById(req.GetCampaignId()) if err != nil || cpn == nil { return } rewardM := s.GetDao().FissionRewardRecord.SubTable(cpn.ID) reward, err := rewardM.WithContext(s.ctx).Where(rewardM.CampaignID.Eq(cpn.ID), rewardM.HashID.Eq(req.GetRewardHashId())).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } answers := reward.GetAnswer() var qid []int64 var selectMap = make(map[int64]map[int64]struct{}) for _, v := range answers { qid = append(qid, v.QID) if _, ok := selectMap[v.QID]; !ok { selectMap[v.QID] = make(map[int64]struct{}) } for _, a := range v.AID { selectMap[v.QID][a] = struct{}{} } } m := s.GetDao().LibraryQa qa, err := m.WithContext(s.ctx).Where(m.ID.In(qid...)).Find() if err != nil { err = s.BE().MysqlError(err) return } var qMap = make(map[int64]*model.LibraryQa) for _, v := range qa { qMap[v.ID] = v } optionM := s.GetDao().LibraryQaOption options, err := optionM.WithContext(s.ctx).Where(optionM.QaID.In(qid...), optionM.IsDel.Eq(mtype.No)).Find() if err != nil { err = s.BE().MysqlError(err) return } var qaMap = make(map[int64][]*model.LibraryQaOption) for _, option := range options { qaMap[option.QaID] = append(qaMap[option.QaID], option) } *res = pb.AnswerHistoryRes{ List: make([]*pb.AnswerHistoryRes_One, 0, len(qid)), } for _, v := range answers { q, ok := qMap[v.QID] if !ok { continue } one := &pb.AnswerHistoryRes_One{ Id: q.ID, HashId: q.HashID, Mark: q.Mark, Title: q.Title, CoverUrl: q.CoverURL, LinkUrl: q.LinkURL, ExplainText: q.ExplainText, ExplainImg: q.ExplainImg, Options: make([]*pb.AnswerHistoryRes_Option, 0, len(qaMap[v.QID])), AnswerMark: q.AnswerMark, SelectOptionId: v.AID, } for _, opt := range qaMap[v.QID] { one.Options = append(one.Options, &pb.AnswerHistoryRes_Option{ Id: opt.ID, Title: opt.Title, ImgUrl: opt.ImgURL, IsRight: int32(opt.IsRight), }) } res.List = append(res.List, one) } return }