package taskser import ( "91porn-server/app/appg" "91porn-server/common/db" "91porn-server/common/log" "91porn-server/common/stderr" "91porn-server/common/timeutil" "91porn-server/models/v/prizemod" "91porn-server/models/v/signtaskmod" "91porn-server/models/v/taskrecordmod" "91porn-server/models/v/txnmod" "91porn-server/models/v/usermod" "encoding/json" "sort" "strconv" "time" "go.mongodb.org/mongo-driver/bson/primitive" ) // 签到 func Sign(uid uint64, configID string) (code stderr.Code) { now := time.Now() id, err := primitive.ObjectIDFromHex(configID) if err != nil { return stderr.ErrParamError } // 获取用户信息 u, err := usermod.FindUserByUID(uid) if err != nil || u == nil { code = stderr.UserIsNotExists return } // 获取配置列表 signConfig, err := signtaskmod.GetConfigList() if err != nil { return stderr.ErrDbQueryError } // 查询当前签到配置 configInfo, err := signtaskmod.GetConfigByID(id) if err != nil { return stderr.ErrDbQueryError } // 异常判定 未配置签到福利/签到福利类型不正确 if configInfo == nil || signConfig == nil || len(signConfig) == 0 { log.Info("未配置签到福利") return stderr.ErrInvalidRequest } // 查询签到信息 signRecordMap := make(map[string]bool, 0) taskInfo, err := taskrecordmod.GetSignRecord(uid) if err != nil { return stderr.ErrDbQueryError } if taskInfo == nil { log.Info("未查询到签到任务") return stderr.ErrDbQueryError } for _, taskId := range taskInfo.SignRecord { signRecordMap[taskId.Hex()] = true } // 判断是否重复签到 if _, ok := signRecordMap[configID]; ok { log.Info("已签到") return stderr.HasSigned } // 计算相差多少天 duration := timeutil.BeginningOfDay(now).Sub(taskInfo.SignTime) diffDays := int64(duration.Hours() / 24) // 判断此签到是否是当天签到 if configInfo.FinishCondition-1 != diffDays { log.Info("条件不匹配") return stderr.ErrInvalidRequest } // 获取奖品列表 prizes, err := prizemod.GetPrizeListByIDs(configInfo.Prizes) if err != nil { return stderr.ErrDbQueryError } // 获取额外奖品列表 signCount := len(signRecordMap) for _, item := range signConfig { if item.FinishCondition == int64(signCount)+1 { extraPrizeIds, e := prizemod.GetPrizeListByIDs(item.ExtraPrizes) if e != nil { continue } prizes = append(prizes, extraPrizeIds...) } } // 更新签到记录(事务) if err = appg.VideoDB.Trans(func(t *db.MongoTool) error { if err = taskrecordmod.TaskSignUpdate(t, uid, id); err != nil { return err } return nil }); err != nil { return stderr.ErrDbTransError } // 发放奖励 for _, v := range prizes { for i := 0; i < int(v.Count); i++ { handler, err := prizemod.Run(uid, *v, txnmod.SignBoon) if err != nil { log.Error("签到发放奖励handler失败:", log.Any("err", err)) continue } err = appg.VideoDB.Trans(func(t *db.MongoTool) error { err = handler.Run(t) if err != nil { return err } err = txnmod.InsertManyTransactionLog(t, handler.GetTransactionLog()) if err != nil { return err } return nil }) if err != nil { log.Error("签到发放奖励事务失败:", log.Any("err", err)) continue } } } return stderr.Success } // 补签 func ReSign(uid uint64, configID string) (code stderr.Code) { now := time.Now() redisKey := "task::resign::" + strconv.FormatUint(uid, 10) if appg.Redis.Exists(redisKey) { return stderr.ExceededTimes } id, err := primitive.ObjectIDFromHex(configID) if err != nil { return stderr.ErrParamError } // 获取用户信息 u, err := usermod.FindUserByUID(uid) if err != nil || u == nil { code = stderr.UserIsNotExists return } // 获取配置列表 signConfig, err := signtaskmod.GetConfigList() if err != nil { return stderr.ErrDbQueryError } // 查询当前签到配置 configInfo, err := signtaskmod.GetConfigByID(id) if err != nil { return stderr.ErrDbQueryError } // 异常判定 未配置签到福利/签到福利类型不正确 if configInfo == nil || signConfig == nil || len(signConfig) == 0 { log.Info("未配置签到福利") return stderr.ErrInvalidRequest } //查询签到信息 signRecordMap := make(map[string]bool, 0) taskInfo, err := taskrecordmod.GetSignRecord(uid) if err != nil { return stderr.ErrDbQueryError } if taskInfo == nil { log.Info("未查询到签到任务") return stderr.ErrDbQueryError } for _, taskId := range taskInfo.SignRecord { signRecordMap[taskId.Hex()] = true } // 判断是否重复签到 if _, ok := signRecordMap[configID]; ok { log.Info("已签到") return stderr.HasSigned } // 计算相差多少天 duration := timeutil.BeginningOfDay(now).Sub(taskInfo.SignTime) diffDays := int64(duration.Hours() / 24) // 判断是否在补签范围 if configInfo.FinishCondition > diffDays { log.Info("条件不匹配") return stderr.ErrInvalidRequest } // redis作为倒计时(一天只能补签一次) seconds := int64(timeutil.BeginningOfTomorrow(now).Sub(now).Seconds()) err = appg.Redis.Set(redisKey, configID, time.Duration(seconds)*time.Second) if err != nil { log.Error(err.Error()) } return stderr.Success } // 补签回调 func ReSignCallBack(uid uint64) (code stderr.Code) { now := time.Now() redisKey := "task::resign::" + strconv.FormatUint(uid, 10) if !appg.Redis.Exists(redisKey) { return stderr.ErrParamError } configID, err := appg.Redis.Get(redisKey) if err != nil { log.Error("redis缓存不存在!") return stderr.ErrParamError } if configID == nil { log.Error("签到配置不存在!") return stderr.ErrParamError } id, err := primitive.ObjectIDFromHex(*configID) if err != nil { return stderr.ErrParamError } // 获取用户信息 u, err := usermod.FindUserByUID(uid) if err != nil || u == nil { code = stderr.UserIsNotExists return } // 获取配置列表 signConfig, err := signtaskmod.GetConfigList() if err != nil { return stderr.ErrDbQueryError } // 查询当前签到配置 configInfo, err := signtaskmod.GetConfigByID(id) if err != nil { return stderr.ErrDbQueryError } // 异常判定 未配置签到福利/签到福利类型不正确 if configInfo == nil || signConfig == nil || len(signConfig) == 0 { log.Info("未配置签到福利") return stderr.ErrInvalidRequest } //查询签到信息 signRecordMap := make(map[string]bool, 0) taskInfo, err := taskrecordmod.GetSignRecord(uid) if err != nil { return stderr.ErrDbQueryError } if taskInfo == nil { log.Info("未查询到签到任务") return stderr.ErrDbQueryError } for _, taskId := range taskInfo.SignRecord { signRecordMap[taskId.Hex()] = true } // 判断是否重复签到 if _, ok := signRecordMap[*configID]; ok { log.Info("已签到") return stderr.HasSigned } // 计算相差多少天 duration := timeutil.BeginningOfDay(now).Sub(taskInfo.SignTime) diffDays := int64(duration.Hours() / 24) // 判断是否在补签范围 if configInfo.FinishCondition > diffDays { log.Info("条件不匹配") return stderr.ErrInvalidRequest } // 获取奖品列表 prizes, err := prizemod.GetPrizeListByIDs(configInfo.Prizes) if err != nil { return stderr.ErrDbQueryError } // 获取额外奖品列表 signCount := len(signRecordMap) for _, item := range signConfig { if item.FinishCondition == int64(signCount) { extraPrizeIds, e := prizemod.GetPrizeListByIDs(item.ExtraPrizes) if e != nil { continue } prizes = append(prizes, extraPrizeIds...) } } // 更新签到记录(事务) if err = appg.VideoDB.Trans(func(t *db.MongoTool) error { if err = taskrecordmod.TaskSignUpdate(t, uid, id); err != nil { return err } return nil }); err != nil { return stderr.ErrDbTransError } // 发放奖励 for _, v := range prizes { for i := 0; i < int(v.Count); i++ { handler, err := prizemod.Run(uid, *v, txnmod.SignBoon) if err != nil { log.Error("签到发放奖励handler失败:", log.Any("err", err)) continue } err = appg.VideoDB.Trans(func(t *db.MongoTool) error { err = handler.Run(t) if err != nil { return err } err = txnmod.InsertManyTransactionLog(t, handler.GetTransactionLog()) if err != nil { return err } return nil }) if err != nil { log.Error("签到发放奖励事务失败:", log.Any("err", err)) continue } } } return stderr.Success } // 获取签到额外奖励 func SignExtraPrizes(uid uint64) (out []map[string]interface{}, code stderr.Code) { out = make([]map[string]interface{}, 0) taskInfo, err := taskrecordmod.GetSignRecord(uid) if err != nil { return out, stderr.ErrDbQueryError } signRecords := make([]primitive.ObjectID, 0) if taskInfo != nil { signRecords = taskInfo.SignRecord } signConfig, err := signtaskmod.GetConfigList() if err != nil { return out, stderr.ErrDbQueryError } // 获取奖品列表 prizes, err := prizemod.GetPrizeList() for _, item := range signConfig { if len(item.ExtraPrizes) == 0 { continue } extraPrizes := getPrizeList(item.ExtraPrizes, prizes) for _, prize := range extraPrizes { b, _ := json.Marshal(&prize) var extraPrizeMap map[string]interface{} _ = json.Unmarshal(b, &extraPrizeMap) days := item.FinishCondition - int64(len(signRecords)) if days < 0 { days = 0 } extraPrizeMap["finishCondition"] = days // 设置额外奖励领取状态 if len(signRecords) >= int(item.FinishCondition) { extraPrizeMap["extraPrizeStatus"] = true } else { extraPrizeMap["extraPrizeStatus"] = false } out = append(out, extraPrizeMap) } } sort.Slice(out, func(i, j int) bool { valI := out[i]["extraPrizeStatus"].(bool) valJ := out[j]["extraPrizeStatus"].(bool) return !valI && valJ }) return out, stderr.Success } // 获取签到详情 func GetSignDetails(uid uint64) (out SignDetailsResponse, code stderr.Code) { now := time.Now() // 获取配置列表 signConfig, err := signtaskmod.GetConfigList() if err != nil { return out, stderr.ErrDbQueryError } // 查询用户签到信息 signRecordMap := make(map[string]bool, 0) taskInfo, err := taskrecordmod.GetSignRecord(uid) if err != nil { return out, stderr.ErrDbQueryError } // 新增用户任务记录 if taskInfo == nil { taskInfo, err = taskrecordmod.TaskSignInit(uid) if err != nil { return out, stderr.ErrDbQueryError } } // 计算相差多少天 diffDays := int(timeutil.BeginningOfDay(now).Sub(taskInfo.SignTime).Hours() / 24) // 判断是否重置数据 if diffDays >= len(signConfig) { taskInfo, err = taskrecordmod.TaskSignReset(uid) if err != nil { return out, stderr.ErrDbQueryError } } // 构建签到记录map for _, item := range taskInfo.SignRecord { signRecordMap[item.String()] = true } // 获取奖品列表 prizes, err := prizemod.GetPrizeList() if err != nil { return out, stderr.ErrDbQueryError } out.Value = int64(len(taskInfo.SignRecord)) out.List = make([]Config, len(signConfig)) for i, v := range signConfig { taskConfig := Config{ ID: v.ID, Prizes: getPrizeList(v.Prizes, prizes), FinishCondition: v.FinishCondition, Title: v.Title, Desc: v.Desc, Status: UnDone, } // 存在表示已经签到,不存在则需要判断是否是补签 if _, ok := signRecordMap[v.ID.String()]; ok { // 如果存在,标记为已完成 taskConfig.Status = Finish } else { diffDays = int(timeutil.BeginningOfDay(now).Sub(taskInfo.SignTime).Hours() / 24) if i < diffDays { taskConfig.Status = ReDo } } out.List[i] = taskConfig } // 当日任务标识 if diffDays >= 0 && diffDays < len(out.List) { out.List[diffDays].IsToday = true } return out, stderr.Success }