package task import ( "context" "encoding/json" "errors" "github.com/spf13/cast" "github.com/zeromicro/go-zero/core/logx" "nova_task/internal/consts" "nova_task/internal/model" "nova_task/internal/pkg/aptos" "nova_task/internal/pkg/errs" "nova_task/internal/pkg/tribally" "nova_task/internal/svc" "nova_task/internal/types" "time" ) // VerifyTaskResultLogic 校验任务结果逻辑 type VerifyTaskResultLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewVerifyTaskResultLogic(ctx context.Context, svcCtx *svc.ServiceContext) *VerifyTaskResultLogic { return &VerifyTaskResultLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.VerifyTaskResultReq) (*types.VerifyTaskResultResp, error) { uid := cast.ToStringMapInt(l.ctx.Value("data"))["id"] task, err := l.svcCtx.TaskModel.FindOne(l.ctx, req.ID) if err != nil { if errors.Is(err, model.ErrNotFound) { return nil, errs.New(errs.ErrTaskNotFound, "task not found") } return nil, errs.New(errs.ErrDatabaseOperate, err) } var taskSeq int if task.Type == model.TASKTYPE_DAILY_PAY || task.Type == model.TASKTYPE_AMBASSADOR_TASK { taskSeq = cast.ToInt(time.Now().Format("20060102")) } tp, err := l.svcCtx.TaskProgressModel.FindOneByUidTaskIdTaskSeq(l.ctx, uid, task.Id, taskSeq) if err != nil { if !errors.Is(err, model.ErrNotFound) { l.Errorw("find task progress error", logx.Field("err", err)) return nil, errs.New(errs.ErrDatabaseOperate, err) } tp = &model.NhTaskProgress{ Uid: uid, TaskId: task.Id, TaskSeq: taskSeq, Stage: model.TASK_PROGRESS_NOT_FINISHED, } } if tp.Stage == model.TASK_PROGRESS_REWARDED { return nil, errs.New(errs.ErrTaskAlreadyReward, "task already reward") } // todo: 校验用户是否完成该任务 switch task.Type { case model.TASKTYPE_BIND_TWITTER: if !l.svcCtx.HasBindTwitter(l.ctx, uint(uid)) { return &types.VerifyTaskResultResp{Finish: false}, nil } case model.TASKTYPE_INVITE_USER: count, err := l.svcCtx.PromoteBindModel.UserInviteCount(l.ctx, uint(uid)) if err != nil { l.Errorw("get user invite count failed", logx.Field("err", err), logx.Field("uid", uid)) return nil, errs.New(errs.ErrDatabaseOperate, err) } if count < cast.ToInt64(task.Param) { return &types.VerifyTaskResultResp{Finish: false}, nil } case model.TASKTYPE_BIND_DISCORD: case model.TASKTYPE_DAILY_PAY, model.TASKTYPE_TRUMP_HEAD: if req.Params == "" { return &types.VerifyTaskResultResp{Finish: false}, nil } else { if !l.checkoutTranscation(uid, req.Params) { return &types.VerifyTaskResultResp{Finish: false}, nil } } case model.TASKTYPE_AMBASSADOR_TASK: if !l.svcCtx.IsAmbassador(l.ctx, uint(uid), 0) { return &types.VerifyTaskResultResp{Finish: false}, nil } case model.TASKTYPE_BIND_TRIBALLY: if req.Params == "" { return &types.VerifyTaskResultResp{Finish: false}, nil } else { if err := tribally.VerifyTribally(req.Params); err != nil { l.Errorw("verify tribally error", logx.Field("err", err), logx.Field("params", req.Params), logx.Field("uid", uid)) return &types.VerifyTaskResultResp{Finish: false}, nil } } default: } tp.Stage = model.TASK_PROGRESS_WAIT_REWARD if tp.Id > 0 { err = l.svcCtx.TaskProgressModel.Update(l.ctx, tp) } else { _, err = l.svcCtx.TaskProgressModel.Insert(l.ctx, tp) } if err != nil { l.Errorw("update task progress error", logx.Field("err", err)) return nil, errs.New(errs.ErrDatabaseOperate, err) } return &types.VerifyTaskResultResp{Finish: true}, nil } func (l *VerifyTaskResultLogic) checkoutTranscation(uid int, txHash string) bool { conf := struct { Contract string `json:"contract"` Network string `json:"network"` }{} cf, err := l.svcCtx.ConfigModel.FindOneByName(l.ctx, consts.DailyPayConf) if err != nil { if !errors.Is(err, model.ErrNotFound) { l.Errorw("find daily pay conf error", logx.Field("err", err)) } return false } err = json.Unmarshal([]byte(cf.Value), &conf) if err != nil { l.Errorw("unmarshal daily pay conf error", logx.Field("err", err), logx.Field("value", cf.Value)) return false } address, err := aptos.GetTransactionOwnerAddress(conf.Contract, txHash, conf.Network) if err != nil { l.Errorw("get transaction owner address error", logx.Field("err", err)) return false } targetUid, err := l.svcCtx.WalletModel.FindUidByAddress(l.ctx, address) if err != nil { l.Errorw("find wallet by address error", logx.Field("err", err), logx.Field("address", address), logx.Field("target_uid", targetUid)) return false } return targetUid == uint(uid) }