package taskser import ( "91porn-server/models/v/taskrecordmod" "91porn-server/web/webg" "errors" "fmt" "strconv" "time" "go.mongodb.org/mongo-driver/bson" "91porn-server/app/appg" "91porn-server/common/constant/redisconst" "91porn-server/common/db" "91porn-server/common/log" "91porn-server/common/stderr" "91porn-server/common/timeutil" "91porn-server/models/l/adsclicklogmod" "91porn-server/models/l/userdailytasklogmod" "91porn-server/models/v/dailytaskmod" "91porn-server/models/v/oncetaskmod" "91porn-server/models/v/prizemod" "91porn-server/models/v/proxymod" "91porn-server/models/v/taskmod" "91porn-server/models/v/txnmod" "91porn-server/models/v/usermod" "go.mongodb.org/mongo-driver/bson/primitive" ) /* // 获取任务 func GetTaskList(uid uint64) (out TaskResponse, code stderr.Code) { var ( louFengIsReceive bool now time.Time = time.Now() consumerFeedbackTask Config = Config{ BoonType: taskmod.ConsumerFeedback, Status: UnDone, } ) out.JewelBoxDetails.List = make([]Config, 0) out.TaskList = make([]Config, 0) // 获取用户签到信息 signInfo, err := taskrecordmod.GetByUID(uid) if err != nil { code = stderr.ErrDbQueryError return } // 异常判定 if signInfo == nil { code = stderr.ErrInvalidRequest return } // 获取奖品列表 prizes, err := prizemod.GetPrizeList() if err != nil { code = stderr.ErrDbQueryError return } // 获取任务配置 list, err := taskmod.ConfigList() if err != nil { code = stderr.ErrDbQueryError return } for _, v := range list { switch v.Type { case taskmod.JewelBox: taskConfig := Config{ ID: v.ID, Prizes: getPrizeList(v.Prizes, prizes), FinishCondition: v.FinishCondition, Title: v.Title, Desc: v.Desc, Status: UnDone, BoonType: v.Type, } // 达到领取条件 if signInfo.CurrentValue >= v.FinishCondition { // 已领取 taskConfig.Status = Finish if signInfo.HasReceived(v.ID, taskrecordmod.JewelBox) { taskConfig.Status = Receive } taskConfig.FinishValue = v.FinishCondition } else { taskConfig.FinishValue = signInfo.CurrentValue if out.JewelBoxDetails.TotalValue < taskConfig.FinishCondition { out.JewelBoxDetails.TotalValue = taskConfig.FinishCondition } } out.JewelBoxDetails.List = append(out.JewelBoxDetails.List, taskConfig) case taskmod.ConsumerFeedback: consumerFeedbackTask.ID = v.ID consumerFeedbackTask.Prizes = getPrizeList(v.Prizes, prizes) consumerFeedbackTask.FinishCondition = v.FinishCondition consumerFeedbackTask.Title = v.Title consumerFeedbackTask.Desc = v.Desc if !louFengIsReceive { louFengIsReceive = true // 统计今日楼凤消费 totalAmount, _, err := txnmod.GetIncomeByType(uid, txnmod.LouFeng, timeutil.BeginningOfDay(now), timeutil.BeginningOfDay(now.AddDate(0, 0, 1))) if err != nil { code = stderr.ErrDbQueryError return } consumerFeedbackTask.FinishValue = -int64(totalAmount) } // 任务记录刷新 if !signInfo.ConsumerFeedbackReceiveTime.After(timeutil.BeginningOfDay(now)) { signInfo, err = taskrecordmod.ConsumerFeedbackReset(uid) if err != nil { code = stderr.ErrDbQueryError return } } if consumerFeedbackTask.FinishValue >= v.FinishCondition && !signInfo.HasReceived(v.ID, taskrecordmod.ConsumerFeedback) { consumerFeedbackTask.Status = Finish } } } if len(out.JewelBoxDetails.List) > 0 && signInfo != nil { out.JewelBoxDetails.Value = signInfo.CurrentValue } if !consumerFeedbackTask.ID.IsZero() { out.TaskList = append(out.TaskList, consumerFeedbackTask) } code = stderr.Success return } */ /* func GetTaskDetails(uid uint64, boonType int) (out TaskDetailsResponse, code stderr.Code) { now := time.Now() // 获取配置列表 taskDetail, err := taskmod.GetConfigListByType(taskmod.ConfigType(boonType)) if err != nil { return out, stderr.ErrDbQueryError } // 获取奖品列表 prizes, err := prizemod.GetPrizeList() if err != nil { return out, stderr.ErrDbQueryError } //查询用户签到信息 taskInfo, err := taskrecordmod.GetByUID(uid) if err != nil { return out, stderr.ErrDbQueryError } // 新增用户任务记录 if taskInfo == nil { taskInfo, err = taskrecordmod.AddTaskRecord(uid) if err != nil { return out, stderr.ErrDbQueryError } } switch taskmod.ConfigType(boonType) { case taskmod.ConsumerFeedback: // 统计今日楼凤消费 totalAmount, _, err := txnmod.GetIncomeByType(uid, txnmod.LouFeng, timeutil.BeginningOfDay(now), timeutil.BeginningOfDay(now.AddDate(0, 0, 1))) if err != nil { code = stderr.ErrDbQueryError return } out.Value = -int64(totalAmount) default: code = stderr.ErrInvalidRequest return } sort.Slice(taskDetail, func(i, j int) bool { // 按照赠送门槛逆序,保证游戏用户能领取游戏充值的游戏币最多的礼物 return taskDetail[i].FinishCondition > taskDetail[j].FinishCondition }) out.TaskList = make([]Config, len(taskDetail)) for i, v := range taskDetail { taskConfig := Config{ ID: v.ID, Prizes: getPrizeList(v.Prizes, prizes), FinishCondition: v.FinishCondition, Title: v.Title, Desc: v.Desc, Status: UnDone, BoonType: v.Type, } if out.Value > taskConfig.FinishCondition { // 充值/消费金额满足礼物要求 switch v.Type { case taskmod.ConsumerFeedback: // 楼凤消费礼物可以同时领取多个 taskConfig.Status = Finish if taskInfo.HasReceived(v.ID, taskrecordmod.ConfigType(v.Type)) { taskConfig.Status = Receive } } } out.TaskList[i] = taskConfig } return out, stderr.Success } */ /* // 领取福利 func GetBoon(ctx context.Context, uid uint64, configID string, boonType int) stderr.Code { var ( now time.Time = time.Now() transType txnmod.TransType ) id, err := primitive.ObjectIDFromHex(configID) if err != nil { return stderr.ErrParamError } // 获取任务配置 configInfo, err := taskmod.GetConfigByID(id) if err != nil { return stderr.ErrDbQueryError } // 异常判定 配置关闭后请求/配置ID不正确 if configInfo == nil || configInfo.Type != taskmod.ConfigType(boonType) { log.InfoX(ctx, "配置关闭后请求/配置ID不正确") return stderr.ErrInvalidRequest } // 获取任务记录 taskInfo, err := taskrecordmod.GetByUID(uid) if err != nil { return stderr.ErrDbQueryError } // 异常判定 不满足领取条件用户不会请求该接口 if taskInfo == nil { log.InfoX(ctx, "不满足领取条件用户不会请求该接口") return stderr.ErrInvalidRequest } switch taskmod.ConfigType(boonType) { case taskmod.JewelBox: // 领取条件判定 if taskInfo.CurrentValue < configInfo.FinishCondition { log.InfoX(ctx, "领取条件判定") return stderr.ErrInvalidRequest } transType = txnmod.JewelBoxBoon case taskmod.ConsumerFeedback: // 统计今日楼凤消费 totalAmount, _, err := txnmod.GetIncomeByType(uid, txnmod.LouFeng, timeutil.BeginningOfDay(now), timeutil.BeginningOfDay(now.AddDate(0, 0, 1))) if err != nil { return stderr.ErrDbQueryError } if -totalAmount < float64(configInfo.FinishCondition) { log.InfoX(ctx, "消费回馈(站群)领取条件不足") return stderr.ErrInvalidRequest } transType = txnmod.LouFengConsumerRebate default: return stderr.ErrParamError } // 异常判定 重复领取 for _, v := range taskInfo.JewelBoxRecord { if v == id { return stderr.ErrDbQueryError } } // 获取奖品列表 prizes, err := prizemod.GetPrizeListByIDs(configInfo.Prizes) if err != nil { return stderr.ErrDbQueryError } // 奖励发放 hanlders := make([]prizemod.PrizeHanlder, 0, len(prizes)) var transactionLogs []txnmod.TransactionLog var gameHanlder, addGoldHanlder prizemod.PrizeHanlder for _, v := range prizes { hanlder, err := prizemod.Run(uid, *v, transType) if err != nil { return stderr.ErrDbQueryError } switch v.Type { case prizemod.Gold: addGoldHanlder = hanlder hanlders = append(hanlders, hanlder) default: hanlders = append(hanlders, hanlder) transactionLogs = append(transactionLogs, hanlder.GetTransactionLog()...) } } if err = appg.VideoDB.Trans(func(t *db.MongoTool) error { if err = taskrecordmod.BoonRecordUpdate(t, uid, id, taskrecordmod.ConfigType(boonType)); err != nil { return err } for _, v := range hanlders { if err = v.Run(t); err != nil { return err } } if addGoldHanlder != nil { transactionLogs = append(transactionLogs, addGoldHanlder.GetTransactionLog()...) } if len(transactionLogs) > 0 { if err = txnmod.InsertManyTransactionLog(t, transactionLogs); err != nil { return err } } // 特殊处理棋牌金币增加 if gameHanlder != nil { if err = gameHanlder.Run(t); err != nil { return err } } return nil }); err != nil { return stderr.ErrDbTransError } return stderr.Success } */ func GetDailyTask(uid uint64) ([]DailyTaskResponse, stderr.Code, string) { tasks, err := dailytaskmod.GetUserDailyTasks(nil) if err != nil { return nil, stderr.ErrDbQueryError, "" } tasksLen := len(tasks) if tasksLen == 0 { return nil, stderr.Success, "" } dtrs := make([]DailyTaskResponse, tasksLen) for i, task := range tasks { dtrs[i] = DailyTaskResponse{ ID: task.ID, Title: task.Title, Img: task.Img, Type: task.Type, Desc: task.Desc, Link: task.Link, Status: 0, } today := timeutil.BeginningOfDay(time.Now()) item, err := taskrecordmod.GetUserRecordByTime(uid, task.ID, today) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;查询用户领取金币任务信息异常:%v", uid, err)) return nil, stderr.ErrDbQueryError, "" } if item != nil && !item.ID.IsZero() { dtrs[i].Status = item.Status } //if task.Type == dailytaskmod.DailyUserLogin || task.Type == dailytaskmod.DailyComment || task.Type == dailytaskmod.DailyPublish || // task.Type == dailytaskmod.DailyTaskTypeAdsClick || task.Type == dailytaskmod.DailyTaskTypeUserInvite { // today := timeutil.BeginningOfDay(time.Now()) // item, err := taskrecordmod.GetUserRecordByTime(uid, task.ID, today) // if err != nil { // log.Error(fmt.Sprintf("用户ID:%d;查询用户领取金币任务信息异常:%v", uid, err)) // return nil, stderr.ErrDbQueryError, "" // } // if item != nil && !item.ID.IsZero() { // dtrs[i].Status = item.Status // } //} } return dtrs, stderr.Success, "" } func mergePidsAndTrimRepeat(ids1, ids2 []primitive.ObjectID) []primitive.ObjectID { ids1Len := len(ids1) ids2Len := len(ids2) if ids1Len == 0 { return ids2 } if ids2Len == 0 { return ids1 } newIds := make([]primitive.ObjectID, 0, ids1Len+ids2Len) for _, v := range append(ids1, ids2...) { found := false for _, vv := range newIds { if v == vv { found = true break } } if found { continue } newIds = append(newIds, v) } return newIds } func CompleteDailyTask(t *db.MongoTool, uid uint64, taskType dailytaskmod.DailyTaskTypeEnum) error { today := timeutil.BeginOfToday() cacheKey := redisconst.DailyTaskCacheKey(uid, taskType, today) redisCli := appg.Redis if redisCli == nil { redisCli = webg.Redis } if redisCli.Exists(cacheKey) { return nil // 今日已完成 } // 获取每日任务 task, err := dailytaskmod.GetUserDailyTaskByType(nil, taskType) if err != nil { return stderr.ErrDbQueryError } if task == nil || task.ID.IsZero() { return errors.New("daily task is null") } // 判断今日是否已完成 item, err := taskrecordmod.GetUserRecordByTime(uid, task.ID, today) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;获取今日任务完成记录异常:%v", uid, err)) return stderr.ErrDbQueryError } if item == nil || item.ID.IsZero() { var tType taskrecordmod.TaskType switch taskType { case dailytaskmod.DailyTaskTypeAdsClick: tType = taskrecordmod.DailyTaskTypeAdsClick case dailytaskmod.DailyTaskTypeUserInvite: tType = taskrecordmod.DailyTaskTypeUserInvite case dailytaskmod.DailyUserLogin: tType = taskrecordmod.DailyUserLogin case dailytaskmod.CommentSetGod: tType = taskrecordmod.DailyTaskCommentSetGod case dailytaskmod.DailyDoCollect: tType = taskrecordmod.DailyDoCollect case dailytaskmod.DailyPublish: tType = taskrecordmod.DailyPublish case dailytaskmod.DailyUnlockByGold: tType = taskrecordmod.DailyUnlockByGold case dailytaskmod.DailyComment: tType = taskrecordmod.DailyComment default: return errors.New("不支持的任务类型") } // 更新今日任务记录 now := time.Now() filter := bson.M{"uid": uid, "recordTime": today, "taskId": task.ID} cond := bson.M{ "uid": uid, "recordTime": today, "taskId": task.ID, "type": taskrecordmod.DailyTask, "taskType": tType, "status": taskrecordmod.UnReceived, "updateTime": now, "createTime": now, } if err := taskrecordmod.InsertTask(nil, filter, cond); err != nil { return err } } // 缓存标识,以免重复查询 _ = redisCli.Set(cacheKey, 1, time.Hour*24) return nil } func GetDailyTaskBoon(uid uint64, taskId primitive.ObjectID) error { redisKey := redisconst.GetUserDailyTaskRewardLockKey(uid, taskId.String()) success, err := appg.Redis.Setnx_NewOK(redisKey, "1", redisconst.GetUserDailyTaskRewardLockExpired()) if err != nil { return err } if !success { return errors.New("请求过于频繁, 请稍后再试") } defer func() { _, _ = appg.Redis.Del(redisKey) }() task, err := dailytaskmod.GetUserDailyTaskByID(nil, taskId) if err != nil { return err } var transType txnmod.TransType switch task.Type { case dailytaskmod.DailyTaskTypeAdsClick: transType = txnmod.DailyTaskAdsClick case dailytaskmod.DailyTaskTypeUserInvite: transType = txnmod.DailyTaskUserInvite } return appg.VideoDB.Trans(func(t *db.MongoTool) error { prizeIDs, err := getDailyRewards(t, uid, task) if err != nil { return err } if len(prizeIDs) == 0 { return nil } // 获取奖品 return getPrizes(t, uid, prizeIDs, transType) }) } func getDailyRewards(t *db.MongoTool, uid uint64, task *dailytaskmod.DailyTask) ([]primitive.ObjectID, error) { if task == nil { return nil, nil } taskDetailLen := len(task.Detail) if taskDetailLen == 0 { return nil, nil } count, err := getUserDailyCountByMongo(uid, task.Type) // 每日已完成数量(已点击次数, 已邀请人数等) if err != nil { return nil, err } finishCount, err := getUserDailyFinish(t, uid, task.Type) // 每日已领取奖励次数 if err != nil { return nil, err } if finishCount >= uint64(len(task.Detail)) { return nil, nil } var rewards []primitive.ObjectID var completeTime uint64 for i, detail := range task.Detail { if uint64(i) < finishCount { // 已完成过的不要重复领奖 count -= detail.FinishCondition continue } if count < detail.FinishCondition { break } count -= detail.FinishCondition completeTime++ rewards = append(rewards, detail.Prizes...) } if err := userdailytasklogmod.CompleteDailyTask(uid, int64(task.Type), completeTime); err != nil { return nil, err } go func() { redisKey := redisconst.GetUserDailyTaskRewardTimeKey(uid, int64(task.Type)) _ = appg.Redis.Set(redisKey, finishCount+completeTime, redisconst.GetUserDailyTaskExpired()) }() return rewards, nil } // 获取用户每日数量(广告点击数, 用户邀请数等) func getUserDailyCount(uid uint64, taskType dailytaskmod.DailyTaskTypeEnum) (uint64, stderr.Code, string) { count, err := getUserDailyCountByRedis(uid, taskType) if err == nil { return count, stderr.Success, "" } count, err = getUserDailyCountByMongo(uid, taskType) if err != nil { return 0, stderr.ErrDbQueryError, "" } return count, stderr.Success, "" } func getUserDailyCountByRedis(uid uint64, taskType dailytaskmod.DailyTaskTypeEnum) (uint64, error) { redisKey := redisconst.GetUserDailyTaskCountKey(uid, int64(taskType)) ct, err := appg.Redis.Get(redisKey) if err != nil { return 0, err } if ct == nil || *ct == "" { return 0, errors.New("daily task count not found in redis") } return strconv.ParseUint(*ct, 10, 0) } func getUserDailyCountByMongo(uid uint64, taskType dailytaskmod.DailyTaskTypeEnum) (uint64, error) { redisKey := redisconst.GetUserDailyTaskCountKey(uid, int64(taskType)) switch taskType { case dailytaskmod.DailyTaskTypeAdsClick: // 每日广告点击 count, err := adsclicklogmod.GetDailyClickCount(uid) if err != nil { return 0, err } go func() { _ = appg.Redis.Set(redisKey, count, redisconst.GetUserDailyTaskExpired()) }() return count, nil case dailytaskmod.DailyTaskTypeUserInvite: // 每日邀请 now := time.Now() count, err := proxymod.CountByUIDAndTime(uid, time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)) if err != nil { return 0, err } go func() { _ = appg.Redis.Set(redisKey, count, redisconst.GetUserDailyTaskExpired()) }() return uint64(count), nil default: return 0, nil } } // 获取用户每日完成任务次数 func getUserDailyFinish(t *db.MongoTool, uid uint64, taskType dailytaskmod.DailyTaskTypeEnum) (uint64, error) { redisKey := redisconst.GetUserDailyTaskRewardTimeKey(uid, int64(taskType)) ct, redisErr := appg.Redis.Get(redisKey) if redisErr == nil && ct != nil && *ct != "" { if count, err := strconv.ParseUint(*ct, 10, 0); err == nil { return count, nil } } switch taskType { case dailytaskmod.DailyTaskTypeAdsClick, dailytaskmod.DailyTaskTypeUserInvite: // 每日广告点击或每日邀请 finishCount, err := userdailytasklogmod.GetUserFinishCount(uid, taskType) if err != nil { return 0, err } go func() { _ = appg.Redis.Set(redisKey, finishCount, redisconst.GetUserDailyTaskExpired()) }() return finishCount, nil default: return 0, nil } } func GetOnceTask(uid uint64) ([]OnceTaskResponse, stderr.Code, string) { tasks, err := oncetaskmod.GetOnceTaskValid(nil) if err != nil { return nil, stderr.ErrDbQueryError, "" } tasksLen := len(tasks) if tasksLen == 0 { return nil, stderr.Success, "" } dtrs := make([]OnceTaskResponse, tasksLen) for i, task := range tasks { dtrs[i] = OnceTaskResponse{ ID: task.ID, Title: task.Title, Img: task.Img, Type: task.Type, Status: 0, Desc: task.Desc, Link: task.Link, } if task.Type == oncetaskmod.Download { dtrs[i].Status, _ = taskrecordmod.IsDownloadTaskComplete(nil, uid, task.ID) } else { hasComplete, _ := taskrecordmod.IsOnceTaskComplete(nil, uid, task.ID) if hasComplete { dtrs[i].Status = taskrecordmod.Received } } //taskRecord, err := taskrecordmod.GetUserTaskRecordByUid(uid, taskrecordmod.OnceTask, task.ID) //if err != nil { // continue //} //if taskRecord == nil || taskRecord.ID.IsZero() { // continue //} //dtrs[i].Status = taskRecord.Status } return dtrs, stderr.Success, "" } // GetGrowthTask 获取成长任务 func GetGrowthTask(uid uint64) ([]*GrowthTaskResponse, stderr.Code, string) { list, err := taskmod.ConfigList() if err != nil { return nil, stderr.ErrDbQueryError, "" } res := []*GrowthTaskResponse{} for _, v := range list { item := &GrowthTaskResponse{ ID: v.ID, Type: int(v.Type), Title: v.Title, Img: v.Img, SubTitle: v.Desc, } res = append(res, item) if len(v.Detail) == 0 { continue } // 获取任务完成记录 taskRecord, err := taskrecordmod.GetUserTask(uid, v.ID) if err != nil { continue } if taskRecord.Stage < len(v.Detail) { item.SubTitle = v.Detail[taskRecord.Stage].SubTitle item.Status = taskRecord.Status } else { item.Status = taskrecordmod.Received // 已经超过最后一个阶段,直接展示已领取 } } return res, stderr.Success, "" } func hasFinishOneceTaskByRedis(uid uint64, taskType oncetaskmod.OnceTaskTypeEnum) (bool, error) { redisKey := redisconst.GetUserOnceTaskCompleteKey(uid, int64(taskType)) ct, err := appg.Redis.Get(redisKey) if err != nil { return false, err } if ct == nil || *ct == "" { return false, errors.New("not found in redis") } return *ct == "1", nil } func hasFinishOnceTaskByMongo(uid uint64, taskId primitive.ObjectID) (bool, error) { u, err := taskrecordmod.GetByUID(uid) if err != nil { return false, err } if u == nil { return false, nil } for _, v := range u.OnceTask { if v == taskId { return true, nil } } return false, nil } func CompleteGrowthTask(uid uint64, configType taskmod.ConfigType, progress int64) { // 获取该任务 taskList, err := taskmod.GetConfigListByType(configType) if err != nil { log.Error("CompleteGrowthTask taskmod.GetConfigListByType", log.E(err)) return } if len(taskList) == 0 { return } task := taskList[0] if len(task.Detail) == 0 { return } // 获取该任务的完成进度 taskRecord, err := taskrecordmod.GetUserTask(uid, task.ID) if err != nil { log.Error("CompleteGrowthTask taskrecordmod.GetUserTaskRecordByUid", log.E(err)) return } // 如果是待领取或者是已领取的情况,则直接返回 if taskRecord.Status > 0 { return } // 已经没有下一阶段 if taskRecord.Stage >= len(task.Detail) { return } if progress < int64(task.Detail[taskRecord.Stage].FinishCondition) { return } taskRecord.Status = taskrecordmod.UnReceived // 修改为待领取状态 filter := bson.M{ "uid": uid, "taskId": task.ID, } updateData := bson.M{ "$set": bson.M{ "status": taskRecord.Status, "updateTime": time.Now(), }, "$setOnInsert": bson.M{ "uid": uid, "taskId": task.ID, "createTime": time.Now(), }, } err = taskrecordmod.UpsertOne(filter, updateData) if err != nil { log.Error("CompleteGrowthTask taskrecordmod.UpsertOne", log.E(err)) return } return } func CompleteOnceTask(t *db.MongoTool, uid uint64, onceTaskType oncetaskmod.OnceTaskTypeEnum) error { hasComplete, err := hasFinishOneceTaskByRedis(uid, onceTaskType) if err == nil && hasComplete { return nil } ot, err := oncetaskmod.GetOnceTaskValidByType(t, onceTaskType) if err != nil { if err.Error() == "not found" { return nil } return err } if ot == nil { return nil } hasComplete, err = hasFinishOnceTaskByMongo(uid, ot.ID) if err != nil { return err } if hasComplete { return nil } var transType txnmod.TransType switch ot.Type { case oncetaskmod.OnceTaskTypeUserBuyVip: transType = txnmod.OnceTaskBuyVIP case oncetaskmod.OnceTaskTypeUserBuyCoin: transType = txnmod.OnceTaskTypeUserBuyCoin case oncetaskmod.OnceTaskTypeBindMobile: transType = txnmod.OnceTaskBindMobile default: } user, err := usermod.FindUserByUIDTrans(t, uid) if err != nil { return err } if user.ID.IsZero() { return errors.New("user not found") } redisKey := redisconst.GetUserOnceTaskCompleteKey(uid, int64(onceTaskType)) switch ot.Type { case oncetaskmod.OnceTaskTypeUserBuyVip: // 购买viP if !user.IsVIP(time.Now()) { _ = appg.Redis.Set(redisKey, 0, redisconst.GetUserOnceTaskCompleteExpired()) return nil } if err = taskrecordmod.CompleteOnceTask(t, uid, ot.ID); err != nil { return err } if err = getPrizes(t, uid, ot.Prizes, transType); err != nil { return err } _ = appg.Redis.Set(redisKey, 1, redisconst.GetUserOnceTaskCompleteExpired()) return nil case oncetaskmod.OnceTaskTypeBindMobile: // 绑定手机 if user.Mobile == "" { _ = appg.Redis.Set(redisKey, 0, redisconst.GetUserOnceTaskCompleteExpired()) return nil } if err = taskrecordmod.CompleteOnceTask(t, uid, ot.ID); err != nil { return err } if err = getPrizes(t, uid, ot.Prizes, transType); err != nil { return err } _ = appg.Redis.Set(redisKey, 1, redisconst.GetUserOnceTaskCompleteExpired()) return nil case oncetaskmod.OnceTaskTypeUserBuyCoin: // 购买金币 if err = taskrecordmod.CompleteOnceTask(t, uid, ot.ID); err != nil { return err } if err = getPrizes(t, uid, ot.Prizes, transType); err != nil { return err } _ = appg.Redis.Set(redisKey, 1, redisconst.GetUserOnceTaskCompleteExpired()) return nil default: return errors.New("unknown type") } } // 发放奖励 func getPrizes(t *db.MongoTool, uid uint64, prizeIDs []primitive.ObjectID, transType txnmod.TransType) error { if len(prizeIDs) == 0 { return nil } // 获取奖品列表 prizes, err := prizemod.GetPrizeListByIDs(prizeIDs) if err != nil { return err } if len(prizes) == 0 { return nil } // 奖励发放 hanlders := make([]prizemod.PrizeHanlder, 0, len(prizes)) var transactionLogs []txnmod.TransactionLog var addGoldHanlder prizemod.PrizeHanlder for _, v := range prizes { hanlder, err := prizemod.Run(uid, *v, transType) if err != nil { return err } switch v.Type { case prizemod.Gold: addGoldHanlder = hanlder hanlders = append(hanlders, hanlder) default: hanlders = append(hanlders, hanlder) transactionLogs = append(transactionLogs, hanlder.GetTransactionLog()...) } } for _, v := range hanlders { if err = v.Run(t); err != nil { return err } } if addGoldHanlder != nil { transactionLogs = append(transactionLogs, addGoldHanlder.GetTransactionLog()...) } if len(transactionLogs) > 0 { if err = txnmod.InsertManyTransactionLog(t, transactionLogs); err != nil { return err } } return nil } func ReceiveTask(uid uint64, in *taskmod.ReceiveTaskReq) (code stderr.Code) { var ( transactionLogs []txnmod.TransactionLog handlers []prizemod.PrizeHanlder pIds []primitive.ObjectID rId primitive.ObjectID ) user, err := usermod.FindUserByUID(uid) if err != nil { return stderr.ErrParamError } if user.ID.IsZero() { return stderr.UserIsNotExists } configID := in.TaskID id, err := primitive.ObjectIDFromHex(configID) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;领取任务ID:%v;转化ObjectID异常:%v", uid, configID, err)) return stderr.ErrParamError } if in.Type == 1 { // 每日任务 dailyTask, err := dailytaskmod.GetUserDailyTaskByID(nil, id) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;领取任务ID:%v;查询领取任务配置信息异常:%v", uid, configID, err)) return stderr.ErrDbQueryError } if dailyTask == nil || dailyTask.ID.IsZero() { log.Warn(fmt.Sprintf("用户ID:%d;领取任务ID:%v;未配置领取福利/领取福利类型不正确", uid, configID)) return stderr.ErrInvalidRequest } // 判断今日是否领取金币 today := timeutil.BeginningOfDay(time.Now()) item, err := taskrecordmod.GetUserRecordByTime(uid, dailyTask.ID, today) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;领取任务ID:%v;查询用户领取任务信息异常:%v", uid, configID, err)) return stderr.ErrDbQueryError } // 异常判定 if item == nil || item.ID.IsZero() { log.Warn(fmt.Sprintf("用户ID:%d;领取任务ID:%v;今日已领取", uid, configID)) return stderr.ErrInvalidRequest } if item.Status == taskrecordmod.Received { return stderr.UserHasReceivedIntegral } for _, p := range dailyTask.Detail { pIds = append(pIds, p.Prizes...) } rId = item.ID } if in.Type == 2 { // 一次性任务 onceTask, err := oncetaskmod.GetTaskByID(nil, id) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;领取任务ID:%v;查询领取任务配置信息异常:%v", uid, configID, err)) return stderr.ErrDbQueryError } if onceTask == nil || onceTask.ID.IsZero() { log.Warn(fmt.Sprintf("用户ID:%d;领取任务ID:%v;未配置领取福利/领取福利类型不正确", uid, configID)) return stderr.ErrInvalidRequest } // 校验是否领取 task, err := taskrecordmod.GetUserTaskRecordByUid(uid, taskrecordmod.OnceTask, id) if err != nil { return stderr.ErrDbQueryError } if task == nil || task.ID.IsZero() { return stderr.UserHasDoTask } if task.Status == taskrecordmod.Received { return stderr.UserHasReceivedIntegral } // 获取任务记录 pIds = onceTask.Prizes rId = task.ID } if in.Type == 3 { // 进阶任务 growthTask, err := taskmod.QueryTaskConfigByCond(bson.M{"_id": id, "status": true}) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;领取任务ID:%v;查询领取任务配置信息异常:%v", uid, configID, err)) return stderr.ErrDbQueryError } if growthTask == nil || growthTask.ID.IsZero() { log.Warn(fmt.Sprintf("用户ID:%d;领取任务ID:%v;未配置领取福利/领取福利类型不正确", uid, configID)) return stderr.ErrInvalidRequest } task, err := taskrecordmod.GetUserTask(uid, id) if err != nil { return stderr.ErrDbQueryError } if task.ID.IsZero() { return stderr.UserHasDoTask } if task.Status == taskrecordmod.Received { return stderr.UserHasReceivedIntegral } // 超过了当前阶段 if len(growthTask.Detail) <= task.Stage { return stderr.ErrInvalidRequest } // 获取任务记录 pIds = []primitive.ObjectID{growthTask.Detail[task.Stage].Prize} rId = task.ID } prizes, err := prizemod.GetPrizeListByIDs(pIds) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;领取积分任务ID:%v;查询奖品列表异常:%v", uid, configID, err)) return stderr.ErrDbQueryError } if prizes == nil || len(prizes) == 0 { log.Warn(fmt.Sprintf("用户ID:%d;领取积分任务ID:%v;奖品列表异常", uid, configID)) return stderr.ErrInvalidRequest } for _, v := range prizes { handler, err := prizemod.Run(uid, *v, txnmod.ReceiveIntegral) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;领取积分任务ID:%v;奖品派发任务初始化异常:%v", uid, configID, err)) return stderr.ErrDbQueryError } handlers = append(handlers, handler) } if err = appg.VideoDB.Trans(func(t *db.MongoTool) error { status := taskrecordmod.Received if in.Type == 3 { status = 0 } if _, err = taskrecordmod.UpdateStatusById(t, rId, status); err != nil { return err } for _, v := range handlers { if err = v.Run(t); err != nil { log.Error(fmt.Sprintf("用户ID:%d;领取积分任务ID:%v;奖品派发任务异常:%v", uid, configID, err)) return err } transactionLogs = append(transactionLogs, v.GetTransactionLog()...) } if len(transactionLogs) > 0 { err = txnmod.InsertManyTransactionLog(t, transactionLogs) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;领取积分任务ID:%v;奖品派发资金流水日志插入异常:%v", uid, configID, err)) return err } } return nil }); err != nil { return stderr.ErrDbTransError } log.Info(fmt.Sprintf("用户ID:%d;领取积分任务ID:%v;领取积分成功", uid, in.TaskID)) return stderr.Success } func DoTask(uid uint64, in *taskmod.DoTaskReq) (code stderr.Code) { user, err := usermod.FindUserByUID(uid) if err != nil { return stderr.ErrParamError } if user.ID.IsZero() { return stderr.UserIsNotExists } configID := in.TaskID id, err := primitive.ObjectIDFromHex(configID) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;领取任务ID:%v;转化ObjectID异常:%v", uid, configID, err)) return stderr.ErrParamError } var taskType taskrecordmod.ConfigType if in.Type == 1 { // 每日任务 dailyTask, err := dailytaskmod.GetUserDailyTaskByID(nil, id) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;领取任务ID:%v;查询领取任务配置信息异常:%v", uid, configID, err)) return stderr.ErrDbQueryError } if dailyTask.ID.IsZero() { log.Warn(fmt.Sprintf("用户ID:%d;领取任务ID:%v;未配置领取福利/领取福利类型不正确", uid, configID)) return stderr.ErrInvalidRequest } // 判断今日是否领取金币 today := timeutil.BeginningOfDay(time.Now()) item, err := taskrecordmod.GetUserRecordByTime(uid, dailyTask.ID, today) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;领取任务ID:%v;查询用户领取任务信息异常:%v", uid, configID, err)) return stderr.ErrDbQueryError } // 异常判定 if item != nil && !item.ID.IsZero() { log.Warn(fmt.Sprintf("用户ID:%d;领取任务ID:%v;今日已领取", uid, configID)) return stderr.ErrInvalidRequest } taskType = taskrecordmod.DailyTask } if in.Type == 2 { // 一次性任务 onceTask, err := oncetaskmod.GetTaskByID(nil, id) if err != nil { log.Error(fmt.Sprintf("用户ID:%d;领取任务ID:%v;查询领取任务配置信息异常:%v", uid, configID, err)) return stderr.ErrDbQueryError } if onceTask == nil || onceTask.ID.IsZero() { log.Warn(fmt.Sprintf("用户ID:%d;领取任务ID:%v;未配置领取福利/领取福利类型不正确", uid, configID)) return stderr.ErrInvalidRequest } // 校验是否领取 task, err := taskrecordmod.GetUserTaskRecordByUid(uid, taskrecordmod.OnceTask, id) if err != nil { return stderr.ErrDbQueryError } if task != nil && !task.ID.IsZero() { return stderr.UserHasDoTask } // 获取任务记录 taskType = taskrecordmod.OnceTask } if err = appg.VideoDB.Trans(func(t *db.MongoTool) error { now := time.Now() today := timeutil.BeginningOfDay(now) // 更新用户记录 if err = taskrecordmod.InsertOne(taskrecordmod.Task{ TaskID: id, Type: taskType, TaskType: taskrecordmod.Download, UID: uid, Status: taskrecordmod.UnReceived, RecordTime: today, Count: 1, UpdateTime: now, CreateTime: now, }); err != nil { return stderr.ErrDbInsertError } return nil }); err != nil { return stderr.ErrDbTransError } log.Info(fmt.Sprintf("用户ID:%d;任务ID:%v;做任务成功", uid, in.TaskID)) return stderr.Success }