增加社区列表接口,任务相关接口修改

This commit is contained in:
lianghuanjie
2024-12-19 21:14:14 +08:00
parent 391a9d3481
commit a3c4adfa25
32 changed files with 1163 additions and 197 deletions

View File

@@ -37,8 +37,7 @@ build:
.PHONY: img .PHONY: img
# 构建Docker镜像 # 构建Docker镜像
img: img:
docker build --platform=amd64 -t nova-task:latest . docker build --platform=amd64 -t harbor.phantom-u3d002.com/nova/nova-task:latest .
docker tag `docker images -aq -f "reference=nova-task:latest"` harbor.phantom-u3d002.com/nova/nova-task:latest
.PHONY: push .PHONY: push
push: push:

View File

@@ -8,6 +8,10 @@ service novatask {
@doc "获取任务列表" @doc "获取任务列表"
@handler GetTaskList @handler GetTaskList
get /tasks (GetTaskListReq) returns (GetTaskListResp) get /tasks (GetTaskListReq) returns (GetTaskListResp)
@doc "获取社区列表"
@handler GetCommunityList
get /community returns (GetCommunityListResp)
} }
@server ( @server (
@@ -18,7 +22,7 @@ service novatask {
service novatask { service novatask {
@doc "校验任务结果" @doc "校验任务结果"
@handler VerifyTaskResult @handler VerifyTaskResult
get /task/:id (TaskIdPath) returns (VerifyTaskResultResp) get /task (VerifyTaskResultReq) returns (VerifyTaskResultResp)
@doc "领取任务奖励" @doc "领取任务奖励"
@handler GetTaskReward @handler GetTaskReward
@@ -37,11 +41,14 @@ type Task {
Description string `json:"description"` // 任务描述 Description string `json:"description"` // 任务描述
Points int `json:"points"` // 任务积分 Points int `json:"points"` // 任务积分
ButtonText string `json:"button_text"` // 按钮文字 ButtonText string `json:"button_text"` // 按钮文字
Type int8 `json:"type"` // 任务类型: 0=follow_twitter,1=bind_twitter,2=cast_twitter,3=publish_twitter,4=repost_twitter,5=watch_youtube,6=follow_youtube,7=bind_discord,8=join_telegram,9=daily_pay Params string `json:"params"` // 参数
Type int8 `json:"type"` // 任务类型: 0=follow_twitter,1=bind_twitter,2=cast_twitter,3=publish_twitter,4=repost_twitter,5=watch_youtube,6=follow_youtube,7=bind_discord,8=join_telegram,9=daily_pay,10=invite_user
Url string `json:"url"` // 跳转链接 Url string `json:"url"` // 跳转链接
Status int8 `json:"status"` // 任务状态: 0=不启用1=启用 Sort int `json:"sort"` // 排序
StartAt string `json:"start_at"` // 开始时间 StartAt string `json:"start_at"` // 开始时间
EndAt string `json:"end_at"` // 结束时间 EndAt string `json:"end_at"` // 结束时间
HasFinishCount int `json:"has_finish_count"` // 当前完成进度
TotalCount int `json:"total_count"` // 总进度
FinishState int8 `json:"finish_state"` // 0:未完成 1:待校验 2:已完成未领取 3:已领取 FinishState int8 `json:"finish_state"` // 0:未完成 1:待校验 2:已完成未领取 3:已领取
} }
@@ -49,6 +56,11 @@ type GetTaskListResp {
Tasks []Task `json:"tasks"` Tasks []Task `json:"tasks"`
} }
type VerifyTaskResultReq {
ID uint `form:"id"` // 任务ID
Params string `form:"params,optional"` // 额外的参数
}
type TaskIdPath { type TaskIdPath {
ID uint `path:"id"` // 任务ID ID uint `path:"id"` // 任务ID
} }
@@ -61,3 +73,16 @@ type GetTaskRewardResp {
Points int `json:"points"` // 积分 Points int `json:"points"` // 积分
} }
type Community {
Id uint `json:"id"` // 社区ID
Title string `json:"title"` // 社区标题
Logo string `json:"logo"` // 社区图标
Description string `json:"description"` // 社区描述
StartAt int64 `json:"start_at"` // 开始时间
EndAt int64 `json:"end_at"` // 结束时间
}
type GetCommunityListResp {
CommunityList []Community `json:"community_list"` // 社区列表
}

View File

@@ -15,6 +15,23 @@
"application/json" "application/json"
], ],
"paths": { "paths": {
"/gapi/task/v1/community": {
"get": {
"summary": "获取社区列表",
"operationId": "GetCommunityList",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/GetCommunityListResp"
}
}
},
"tags": [
"task"
]
}
},
"/gapi/task/v1/reward/{id}": { "/gapi/task/v1/reward/{id}": {
"get": { "get": {
"summary": "领取任务奖励", "summary": "领取任务奖励",
@@ -45,7 +62,7 @@
] ]
} }
}, },
"/gapi/task/v1/task/{id}": { "/gapi/task/v1/task": {
"get": { "get": {
"summary": "校验任务结果", "summary": "校验任务结果",
"operationId": "VerifyTaskResult", "operationId": "VerifyTaskResult",
@@ -60,14 +77,26 @@
"parameters": [ "parameters": [
{ {
"name": "id", "name": "id",
"in": "path", "description": " 任务ID",
"in": "query",
"required": true, "required": true,
"type": "integer",
"format": "uint32"
},
{
"name": "params",
"description": " 额外的参数",
"in": "query",
"required": false,
"type": "string" "type": "string"
} }
], ],
"tags": [ "tags": [
"task" "task"
], ],
"consumes": [
"multipart/form-data"
],
"security": [ "security": [
{ {
"apiKey": [] "apiKey": []
@@ -107,6 +136,63 @@
} }
}, },
"definitions": { "definitions": {
"Community": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "uint32",
"description": " 社区ID"
},
"title": {
"type": "string",
"description": " 社区标题"
},
"logo": {
"type": "string",
"description": " 社区图标"
},
"description": {
"type": "string",
"description": " 社区描述"
},
"start_at": {
"type": "integer",
"format": "int64",
"description": " 开始时间"
},
"end_at": {
"type": "integer",
"format": "int64",
"description": " 结束时间"
}
},
"title": "Community",
"required": [
"id",
"title",
"logo",
"description",
"start_at",
"end_at"
]
},
"GetCommunityListResp": {
"type": "object",
"properties": {
"community_list": {
"type": "array",
"items": {
"$ref": "#/definitions/Community"
},
"description": " 社区列表"
}
},
"title": "GetCommunityListResp",
"required": [
"community_list"
]
},
"GetTaskListReq": { "GetTaskListReq": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -181,19 +267,23 @@
"type": "string", "type": "string",
"description": " 按钮文字" "description": " 按钮文字"
}, },
"params": {
"type": "string",
"description": " 参数"
},
"type": { "type": {
"type": "integer", "type": "integer",
"format": "int8", "format": "int8",
"description": " 任务类型: 0=follow_twitter,1=bind_twitter,2=cast_twitter,3=publish_twitter,4=repost_twitter,5=watch_youtube,6=follow_youtube,7=bind_discord,8=join_telegram,9=daily_pay" "description": " 任务类型: 0=follow_twitter,1=bind_twitter,2=cast_twitter,3=publish_twitter,4=repost_twitter,5=watch_youtube,6=follow_youtube,7=bind_discord,8=join_telegram,9=daily_pay,10=invite_user"
}, },
"url": { "url": {
"type": "string", "type": "string",
"description": " 跳转链接" "description": " 跳转链接"
}, },
"status": { "sort": {
"type": "integer", "type": "integer",
"format": "int8", "format": "int32",
"description": " 任务状态: 0=不启用1=启用" "description": " 排序"
}, },
"start_at": { "start_at": {
"type": "string", "type": "string",
@@ -203,6 +293,16 @@
"type": "string", "type": "string",
"description": " 结束时间" "description": " 结束时间"
}, },
"has_finish_count": {
"type": "integer",
"format": "int32",
"description": " 当前完成进度"
},
"total_count": {
"type": "integer",
"format": "int32",
"description": " 总进度"
},
"finish_state": { "finish_state": {
"type": "integer", "type": "integer",
"format": "int8", "format": "int8",
@@ -218,11 +318,14 @@
"description", "description",
"points", "points",
"button_text", "button_text",
"params",
"type", "type",
"url", "url",
"status", "sort",
"start_at", "start_at",
"end_at", "end_at",
"has_finish_count",
"total_count",
"finish_state" "finish_state"
] ]
}, },
@@ -230,6 +333,24 @@
"type": "object", "type": "object",
"title": "TaskIdPath" "title": "TaskIdPath"
}, },
"VerifyTaskResultReq": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "uint32",
"description": " 任务ID"
},
"params": {
"type": "string",
"description": " 额外的参数"
}
},
"title": "VerifyTaskResultReq",
"required": [
"id"
]
},
"VerifyTaskResultResp": { "VerifyTaskResultResp": {
"type": "object", "type": "object",
"properties": { "properties": {

2
go.mod
View File

@@ -30,12 +30,14 @@ require (
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.3 // indirect github.com/openzipkin/zipkin-go v0.4.3 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect

4
go.sum
View File

@@ -57,6 +57,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg= github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg=
github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c= github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -71,6 +73,8 @@ github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=

View File

@@ -15,6 +15,12 @@ import (
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes( server.AddRoutes(
[]rest.Route{ []rest.Route{
{
// 获取社区列表
Method: http.MethodGet,
Path: "/community",
Handler: task.GetCommunityListHandler(serverCtx),
},
{ {
// 获取任务列表 // 获取任务列表
Method: http.MethodGet, Method: http.MethodGet,
@@ -36,7 +42,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
{ {
// 校验任务结果 // 校验任务结果
Method: http.MethodGet, Method: http.MethodGet,
Path: "/task/:id", Path: "/task",
Handler: task.VerifyTaskResultHandler(serverCtx), Handler: task.VerifyTaskResultHandler(serverCtx),
}, },
}, },

View File

@@ -0,0 +1,22 @@
package task
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"nova_task/internal/logic/task"
"nova_task/internal/svc"
)
// 获取社区列表
func GetCommunityListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := task.NewGetCommunityListLogic(r.Context(), svcCtx)
resp, err := l.GetCommunityList()
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}

View File

@@ -12,7 +12,7 @@ import (
// 校验任务结果 // 校验任务结果
func VerifyTaskResultHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { func VerifyTaskResultHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
var req types.TaskIdPath var req types.VerifyTaskResultReq
if err := httpx.Parse(r, &req); err != nil { if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err) httpx.ErrorCtx(r.Context(), w, err)
return return

61
internal/job/earn/earn.go Normal file
View File

@@ -0,0 +1,61 @@
package earn
import (
"context"
ea "github.com/earn-alliance/earnalliance-go"
"github.com/spf13/cast"
"github.com/zeromicro/go-zero/core/logx"
"nova_task/internal/svc"
)
// Earn 用户数据上报earn平台定时任务
type Earn struct {
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewEarn(ctx context.Context, svcCtx *svc.ServiceContext) *Earn {
e := &Earn{ctx: ctx, svcCtx: svcCtx}
e.Run()
return e
}
func (e *Earn) Spec() string {
return "@every 5m"
}
func (e *Earn) Run() {
e.pushUserInfo(666)
e.pushUserBind()
}
func (e *Earn) pushUserInfo(shareId uint) {
us, err := e.svcCtx.PromoteBindModel.FindRequirePushUser(e.ctx, shareId)
if err != nil {
logx.Errorw("find require push user failed", logx.Field("err", err), logx.Field("share_id", shareId))
return
}
for _, u := range us {
ui, err := e.svcCtx.UserModel.FindOne(e.ctx, u.InvitedUid)
if err != nil {
logx.Errorw("find user failed", logx.Field("err", err), logx.Field("uid", u.InvitedUid))
continue
}
var twitterId string
ut, err := e.svcCtx.TwitterModel.FindOne(e.ctx, u.InvitedUid)
if err == nil {
twitterId = ut.TwitterId
}
e.svcCtx.Earn.SetIdentifiers(cast.ToString(ui.Id), &ea.Identifiers{
Email: ea.IdentifierFrom(ui.Email),
TwitterId: ea.IdentifierFrom(twitterId),
})
err = e.svcCtx.PromoteBindModel.UpdatePushUser(e.ctx, u.Id)
if err != nil {
logx.Errorw("update push user failed", logx.Field("err", err), logx.Field("uid", u.InvitedUid))
}
}
}
func (e *Earn) pushUserBind() {}

63
internal/job/job.go Normal file
View File

@@ -0,0 +1,63 @@
package job
import (
"context"
"errors"
"github.com/robfig/cron/v3"
"github.com/zeromicro/go-zero/core/logx"
"nova_task/internal/job/earn"
"nova_task/internal/job/pledge"
"nova_task/internal/svc"
)
type Job struct {
ctx context.Context
cancel context.CancelFunc
svcCtx *svc.ServiceContext
c *cron.Cron
}
type Spec interface {
Spec() string
}
func NewJob(svcCtx *svc.ServiceContext) *Job {
ctx, cancel := context.WithCancel(context.Background())
var cronList = []cron.Job{
earn.NewEarn(ctx, svcCtx),
pledge.NewPledge(ctx, svcCtx),
}
var err error
c := cron.New()
for _, cr := range cronList {
if cs, ok := cr.(Spec); ok {
_, err = c.AddJob(cs.Spec(), cr)
logx.Must(err)
continue
}
if cs, ok := cr.(cron.Schedule); ok {
c.Schedule(cs, cr)
continue
}
logx.Must(errors.New("cron job must implement either Spec or Schedule interface"))
}
return &Job{
ctx: ctx,
cancel: cancel,
svcCtx: svcCtx,
c: c,
}
}
func (j *Job) Start() {
logx.Info("start cron job")
j.c.Start()
}
func (j *Job) Stop() {
logx.Info("stop cron job")
<-j.c.Stop().Done()
logx.Info("cron job stopped")
j.cancel()
}

View File

@@ -0,0 +1,26 @@
package pledge
import (
"context"
"nova_task/internal/svc"
)
type Pledge struct {
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewPledge(ctx context.Context, svcCtx *svc.ServiceContext) *Pledge {
return &Pledge{
ctx: ctx,
svcCtx: svcCtx,
}
}
func (p *Pledge) Spec() string {
return "@every 30m"
}
func (p *Pledge) Run() {
}

View File

@@ -0,0 +1,48 @@
package task
import (
"context"
"nova_task/internal/pkg/errs"
"nova_task/internal/svc"
"nova_task/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetCommunityListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 获取社区列表
func NewGetCommunityListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCommunityListLogic {
return &GetCommunityListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetCommunityListLogic) GetCommunityList() (*types.GetCommunityListResp, error) {
cs, err := l.svcCtx.CommunityModel.All(l.ctx)
if err != nil {
l.Errorw("get community list error", logx.Field("err", err))
return nil, errs.New(errs.ErrDatabaseOperate, err)
}
var communityList []types.Community
for _, c := range cs {
communityList = append(communityList, types.Community{
Id: c.Id,
Title: c.Title,
Logo: c.Logo,
Description: c.Description,
StartAt: c.StartAt.Time.Unix(),
EndAt: c.EndAt.Time.Unix(),
})
}
return &types.GetCommunityListResp{CommunityList: communityList}, nil
}

View File

@@ -33,7 +33,12 @@ func (l *GetTaskListLogic) GetTaskList(uid int, req *types.GetTaskListReq) (*typ
tasks, err := l.svcCtx.TaskModel.FindTasksByCommunity(l.ctx, req.CommunityId) tasks, err := l.svcCtx.TaskModel.FindTasksByCommunity(l.ctx, req.CommunityId)
if err != nil { if err != nil {
l.Errorw("get task list failed", logx.Field("err", err), logx.Field("communityId", req.CommunityId)) l.Errorw("get task list failed", logx.Field("err", err), logx.Field("communityId", req.CommunityId))
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
}
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))
} }
resp := &types.GetTaskListResp{} resp := &types.GetTaskListResp{}
@@ -44,12 +49,30 @@ func (l *GetTaskListLogic) GetTaskList(uid int, req *types.GetTaskListReq) (*typ
} }
var finishState int8 var finishState int8
if uid > 0 { if uid > 0 {
tp, err := l.svcCtx.TaskProgressModel.FindOneByUidTaskIdTaskSeq(l.ctx, uid, t.CommunityId, taskSeq) tp, err := l.svcCtx.TaskProgressModel.FindOneByUidTaskIdTaskSeq(l.ctx, uid, t.Id, taskSeq)
if err == nil { if err == nil {
finishState = tp.Stage finishState = tp.Stage
} }
} }
hasFinishCount := 0
totalCount := 1
if t.Type == model.TASKTYPE_INVITE_USER {
totalCount = cast.ToInt(t.Param)
hasFinishCount = cast.ToInt(count)
}
if finishState >= model.TASK_PROGRESS_WAIT_REWARD {
hasFinishCount = totalCount
}
if hasFinishCount > totalCount {
hasFinishCount = totalCount
}
if hasFinishCount >= totalCount && finishState == model.TASK_PROGRESS_NOT_FINISHED {
finishState = model.TASK_PROGRESS_WAIT_VERIFY
}
resp.Tasks = append(resp.Tasks, types.Task{ resp.Tasks = append(resp.Tasks, types.Task{
Id: t.Id, Id: t.Id,
Title: t.Title, Title: t.Title,
@@ -57,11 +80,14 @@ func (l *GetTaskListLogic) GetTaskList(uid int, req *types.GetTaskListReq) (*typ
Description: t.Description, Description: t.Description,
Points: t.Points, Points: t.Points,
ButtonText: t.ButtonText, ButtonText: t.ButtonText,
Params: t.Param,
Type: t.Type, Type: t.Type,
Url: t.Url, Url: t.Url,
StartAt: t.StartAt.Time.Format(time.DateTime), StartAt: t.StartAt.Time.Format(time.DateTime),
EndAt: t.EndAt.Time.Format(time.DateTime), EndAt: t.EndAt.Time.Format(time.DateTime),
Status: t.Status, Sort: t.Sort,
HasFinishCount: hasFinishCount,
TotalCount: totalCount,
FinishState: finishState, FinishState: finishState,
}) })
} }

View File

@@ -35,9 +35,9 @@ func (l *GetTaskRewardLogic) GetTaskReward(req *types.TaskIdPath) (*types.GetTas
task, err := l.svcCtx.TaskModel.FindOne(l.ctx, req.ID) task, err := l.svcCtx.TaskModel.FindOne(l.ctx, req.ID)
if err != nil { if err != nil {
if errors.Is(err, model.ErrNotFound) { if errors.Is(err, model.ErrNotFound) {
return nil, errs.BadRequest(errs.ErrTaskNotFound, "task not found") return nil, errs.New(errs.ErrTaskNotFound, "task not found")
} }
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
} }
var taskSeq int var taskSeq int
if task.Type == model.TASKTYPE_DAILY_PAY { if task.Type == model.TASKTYPE_DAILY_PAY {
@@ -47,15 +47,15 @@ func (l *GetTaskRewardLogic) GetTaskReward(req *types.TaskIdPath) (*types.GetTas
if err != nil { if err != nil {
if !errors.Is(err, model.ErrNotFound) { if !errors.Is(err, model.ErrNotFound) {
l.Errorw("find task progress error", logx.Field("err", err)) l.Errorw("find task progress error", logx.Field("err", err))
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
} }
return nil, errs.BadRequest(errs.ErrTaskNotFinished, "task not finished") return nil, errs.New(errs.ErrTaskNotFinished, "task not finished")
} }
switch { switch {
case tp.Stage < model.TASK_PROGRESS_WAIT_REWARD: case tp.Stage < model.TASK_PROGRESS_WAIT_REWARD:
return nil, errs.BadRequest(errs.ErrTaskNotFinished, "task not finished") return nil, errs.New(errs.ErrTaskNotFinished, "task not finished")
case tp.Stage > model.TASK_PROGRESS_WAIT_REWARD: case tp.Stage > model.TASK_PROGRESS_WAIT_REWARD:
return nil, errs.BadRequest(errs.ErrTaskAlreadyReward, "task already reward") return nil, errs.New(errs.ErrTaskAlreadyReward, "task already reward")
} }
// 修改状态,增加积分和记录都在事物中执行 // 修改状态,增加积分和记录都在事物中执行
@@ -85,7 +85,7 @@ func (l *GetTaskRewardLogic) GetTaskReward(req *types.TaskIdPath) (*types.GetTas
if err != nil { if err != nil {
l.Errorw("给予用户奖励实物执行失败", logx.Field("err", err), logx.Field("task", task.Id), logx.Field("uid", uid)) l.Errorw("给予用户奖励实物执行失败", logx.Field("err", err), logx.Field("task", task.Id), logx.Field("uid", uid))
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
} }
return &types.GetTaskRewardResp{Points: task.Points}, nil return &types.GetTaskRewardResp{Points: task.Points}, nil

View File

@@ -27,14 +27,14 @@ func NewVerifyTaskResultLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
} }
} }
func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types.VerifyTaskResultResp, error) { func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.VerifyTaskResultReq) (*types.VerifyTaskResultResp, error) {
uid := cast.ToStringMapInt(l.ctx.Value("data"))["id"] uid := cast.ToStringMapInt(l.ctx.Value("data"))["id"]
task, err := l.svcCtx.TaskModel.FindOne(l.ctx, req.ID) task, err := l.svcCtx.TaskModel.FindOne(l.ctx, req.ID)
if err != nil { if err != nil {
if errors.Is(err, model.ErrNotFound) { if errors.Is(err, model.ErrNotFound) {
return nil, errs.BadRequest(errs.ErrTaskNotFound, "task not found") return nil, errs.New(errs.ErrTaskNotFound, "task not found")
} }
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
} }
var taskSeq int var taskSeq int
if task.Type == model.TASKTYPE_DAILY_PAY { if task.Type == model.TASKTYPE_DAILY_PAY {
@@ -44,7 +44,7 @@ func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types.
if err != nil { if err != nil {
if !errors.Is(err, model.ErrNotFound) { if !errors.Is(err, model.ErrNotFound) {
l.Errorw("find task progress error", logx.Field("err", err)) l.Errorw("find task progress error", logx.Field("err", err))
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
} }
tp = &model.NhTaskProgress{ tp = &model.NhTaskProgress{
Uid: uid, Uid: uid,
@@ -54,7 +54,7 @@ func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types.
} }
} }
if tp.Stage == model.TASK_PROGRESS_REWARDED { if tp.Stage == model.TASK_PROGRESS_REWARDED {
return nil, errs.BadRequest(errs.ErrTaskAlreadyReward, "task already reward") return nil, errs.New(errs.ErrTaskAlreadyReward, "task already reward")
} }
// todo: 校验用户是否完成该任务 // todo: 校验用户是否完成该任务
switch task.Type { switch task.Type {
@@ -62,7 +62,7 @@ func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types.
tw, err := l.svcCtx.TwitterModel.FindOneByUid(l.ctx, uint(uid)) tw, err := l.svcCtx.TwitterModel.FindOneByUid(l.ctx, uint(uid))
if err != nil { if err != nil {
if !errors.Is(err, model.ErrNotFound) { if !errors.Is(err, model.ErrNotFound) {
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
} }
return &types.VerifyTaskResultResp{Finish: false}, nil return &types.VerifyTaskResultResp{Finish: false}, nil
} }
@@ -72,6 +72,9 @@ func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types.
case model.TASKTYPE_BIND_DISCORD: case model.TASKTYPE_BIND_DISCORD:
case model.TASKTYPE_DAILY_PAY: case model.TASKTYPE_DAILY_PAY:
if req.Params == "" {
return &types.VerifyTaskResultResp{Finish: false}, nil
}
default: default:
} }
@@ -84,7 +87,7 @@ func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types.
if err != nil { if err != nil {
l.Errorw("update task progress error", logx.Field("err", err)) l.Errorw("update task progress error", logx.Field("err", err))
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
} }
return &types.VerifyTaskResultResp{Finish: true}, nil return &types.VerifyTaskResultResp{Finish: true}, nil

View File

@@ -0,0 +1,81 @@
package model
import (
"context"
"errors"
"fmt"
"github.com/patrickmn/go-cache"
"github.com/spf13/cast"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"time"
)
var _ NhPromoteBindModel = (*customNhPromoteBindModel)(nil)
type (
// NhPromoteBindModel is an interface to be customized, add more methods here,
// and implement the added methods in customNhPromoteBindModel.
NhPromoteBindModel interface {
nhPromoteBindModel
withSession(session sqlx.Session) NhPromoteBindModel
FindRequirePushUser(ctx context.Context, shareUid uint) ([]NhPromoteBind, error)
UpdatePushUser(ctx context.Context, id uint) error
UpdatePushRole(ctx context.Context, id uint) error
UserInviteCount(ctx context.Context, uid uint) (int64, error)
}
customNhPromoteBindModel struct {
*defaultNhPromoteBindModel
userInviteCountCache *cache.Cache
}
)
// NewNhPromoteBindModel returns a model for the database table.
func NewNhPromoteBindModel(conn sqlx.SqlConn) NhPromoteBindModel {
return &customNhPromoteBindModel{
defaultNhPromoteBindModel: newNhPromoteBindModel(conn),
userInviteCountCache: cache.New(time.Minute, time.Second*65),
}
}
func (m *customNhPromoteBindModel) withSession(session sqlx.Session) NhPromoteBindModel {
return NewNhPromoteBindModel(sqlx.NewSqlConnFromSession(session))
}
func (m *customNhPromoteBindModel) FindRequirePushUser(ctx context.Context, shareUid uint) ([]NhPromoteBind, error) {
query := fmt.Sprintf("select %s from %s where `share_uid` = ? and `is_push_user` = 0 limit 100", nhPromoteBindRows, m.table)
var resp []NhPromoteBind
err := m.conn.QueryRowsCtx(ctx, &resp, query, shareUid)
if err != nil && !errors.Is(err, sqlx.ErrNotFound) {
return nil, err
}
return resp, nil
}
func (m *customNhPromoteBindModel) UpdatePushUser(ctx context.Context, id uint) error {
update := fmt.Sprintf("update %s set `is_push_user` = 1 where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, update, id)
return err
}
func (m *customNhPromoteBindModel) UpdatePushRole(ctx context.Context, id uint) error {
update := fmt.Sprintf("update %s set `is_push_role` = 1 where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, update, id)
return err
}
func (m *customNhPromoteBindModel) UserInviteCount(ctx context.Context, uid uint) (int64, error) {
key := cast.ToString(uid)
v, ok := m.userInviteCountCache.Get(key)
if ok {
return v.(int64), nil
}
query := fmt.Sprintf("select count(*) as `count` from %s where `share_uid` = ?", m.table)
var count int64
err := m.conn.QueryRowCtx(ctx, &count, query, uid)
if err != nil && !errors.Is(err, sqlx.ErrNotFound) {
return 0, err
}
m.userInviteCountCache.SetDefault(key, count)
return count, nil
}

View File

@@ -0,0 +1,104 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.3
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
nhPromoteBindFieldNames = builder.RawFieldNames(&NhPromoteBind{})
nhPromoteBindRows = strings.Join(nhPromoteBindFieldNames, ",")
nhPromoteBindRowsExpectAutoSet = strings.Join(stringx.Remove(nhPromoteBindFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
nhPromoteBindRowsWithPlaceHolder = strings.Join(stringx.Remove(nhPromoteBindFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
nhPromoteBindModel interface {
Insert(ctx context.Context, data *NhPromoteBind) (sql.Result, error)
FindOne(ctx context.Context, id uint) (*NhPromoteBind, error)
FindOneByInvitedUid(ctx context.Context, invitedUid uint) (*NhPromoteBind, error)
Update(ctx context.Context, data *NhPromoteBind) error
Delete(ctx context.Context, id uint) error
}
defaultNhPromoteBindModel struct {
conn sqlx.SqlConn
table string
}
NhPromoteBind struct {
Id uint `db:"id"`
ShareUid uint `db:"share_uid"` // 分享者uid
InvitedUid uint `db:"invited_uid"` // 受邀者uid
CreateTime uint `db:"create_time"` // 创建时间
IsPushUser int8 `db:"is_push_user"` // 是否已推送用户信息
IsPushRole int8 `db:"is_push_role"` // 是否已推送绑定游戏账号
}
)
func newNhPromoteBindModel(conn sqlx.SqlConn) *defaultNhPromoteBindModel {
return &defaultNhPromoteBindModel{
conn: conn,
table: "`nh_promote_bind`",
}
}
func (m *defaultNhPromoteBindModel) Delete(ctx context.Context, id uint) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultNhPromoteBindModel) FindOne(ctx context.Context, id uint) (*NhPromoteBind, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhPromoteBindRows, m.table)
var resp NhPromoteBind
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhPromoteBindModel) FindOneByInvitedUid(ctx context.Context, invitedUid uint) (*NhPromoteBind, error) {
var resp NhPromoteBind
query := fmt.Sprintf("select %s from %s where `invited_uid` = ? limit 1", nhPromoteBindRows, m.table)
err := m.conn.QueryRowCtx(ctx, &resp, query, invitedUid)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhPromoteBindModel) Insert(ctx context.Context, data *NhPromoteBind) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?)", m.table, nhPromoteBindRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.ShareUid, data.InvitedUid, data.IsPushUser, data.IsPushRole)
return ret, err
}
func (m *defaultNhPromoteBindModel) Update(ctx context.Context, newData *NhPromoteBind) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhPromoteBindRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, newData.ShareUid, newData.InvitedUid, newData.IsPushUser, newData.IsPushRole, newData.Id)
return err
}
func (m *defaultNhPromoteBindModel) tableName() string {
return m.table
}

View File

@@ -0,0 +1,45 @@
package model
import (
"context"
"errors"
"fmt"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
var _ NhTaskCommunityModel = (*customNhTaskCommunityModel)(nil)
type (
// NhTaskCommunityModel is an interface to be customized, add more methods here,
// and implement the added methods in customNhTaskCommunityModel.
NhTaskCommunityModel interface {
nhTaskCommunityModel
withSession(session sqlx.Session) NhTaskCommunityModel
All(ctx context.Context) ([]NhTaskCommunity, error)
}
customNhTaskCommunityModel struct {
*defaultNhTaskCommunityModel
}
)
func (m *customNhTaskCommunityModel) All(ctx context.Context) ([]NhTaskCommunity, error) {
query := fmt.Sprintf("select %s from %s where `status` = 1", nhTaskCommunityRows, m.table)
var resp []NhTaskCommunity
err := m.conn.QueryRowsCtx(ctx, &resp, query)
if err != nil && !errors.Is(err, sqlx.ErrNotFound) {
return nil, err
}
return resp, nil
}
// NewNhTaskCommunityModel returns a model for the database table.
func NewNhTaskCommunityModel(conn sqlx.SqlConn) NhTaskCommunityModel {
return &customNhTaskCommunityModel{
defaultNhTaskCommunityModel: newNhTaskCommunityModel(conn),
}
}
func (m *customNhTaskCommunityModel) withSession(session sqlx.Session) NhTaskCommunityModel {
return NewNhTaskCommunityModel(sqlx.NewSqlConnFromSession(session))
}

View File

@@ -0,0 +1,94 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.3
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"time"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
nhTaskCommunityFieldNames = builder.RawFieldNames(&NhTaskCommunity{})
nhTaskCommunityRows = strings.Join(nhTaskCommunityFieldNames, ",")
nhTaskCommunityRowsExpectAutoSet = strings.Join(stringx.Remove(nhTaskCommunityFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
nhTaskCommunityRowsWithPlaceHolder = strings.Join(stringx.Remove(nhTaskCommunityFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
nhTaskCommunityModel interface {
Insert(ctx context.Context, data *NhTaskCommunity) (sql.Result, error)
FindOne(ctx context.Context, id uint) (*NhTaskCommunity, error)
Update(ctx context.Context, data *NhTaskCommunity) error
Delete(ctx context.Context, id uint) error
}
defaultNhTaskCommunityModel struct {
conn sqlx.SqlConn
table string
}
NhTaskCommunity struct {
Id uint `db:"id"`
Title string `db:"title"` // 社区
Logo string `db:"logo"` // logo图片链接
Description string `db:"description"` // 描述
Status int8 `db:"status"` // 0=不启用1=启用
StartAt sql.NullTime `db:"start_at"` // 开始时间
EndAt sql.NullTime `db:"end_at"` // 结束时间
CreatedAt time.Time `db:"created_at"` // 创建时间
UpdatedAt time.Time `db:"updated_at"` // 修改时间
Sort int `db:"sort"` // 数字越小越靠前
}
)
func newNhTaskCommunityModel(conn sqlx.SqlConn) *defaultNhTaskCommunityModel {
return &defaultNhTaskCommunityModel{
conn: conn,
table: "`nh_task_community`",
}
}
func (m *defaultNhTaskCommunityModel) Delete(ctx context.Context, id uint) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultNhTaskCommunityModel) FindOne(ctx context.Context, id uint) (*NhTaskCommunity, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhTaskCommunityRows, m.table)
var resp NhTaskCommunity
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhTaskCommunityModel) Insert(ctx context.Context, data *NhTaskCommunity) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?)", m.table, nhTaskCommunityRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.Title, data.Logo, data.Description, data.Status, data.StartAt, data.EndAt, data.Sort)
return ret, err
}
func (m *defaultNhTaskCommunityModel) Update(ctx context.Context, data *NhTaskCommunity) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskCommunityRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.Title, data.Logo, data.Description, data.Status, data.StartAt, data.EndAt, data.Sort, data.Id)
return err
}
func (m *defaultNhTaskCommunityModel) tableName() string {
return m.table
}

View File

@@ -21,6 +21,7 @@ const (
TASKTYPE_BIND_DISCORD = 7 TASKTYPE_BIND_DISCORD = 7
TASKTYPE_JOIN_TELEGRAM = 8 TASKTYPE_JOIN_TELEGRAM = 8
TASKTYPE_DAILY_PAY = 9 TASKTYPE_DAILY_PAY = 9
TASKTYPE_INVITE_USER = 10
) )
type ( type (
@@ -38,7 +39,7 @@ type (
) )
func (m *customNhTaskModel) FindTasksByCommunity(ctx context.Context, communityId uint) ([]*NhTask, error) { func (m *customNhTaskModel) FindTasksByCommunity(ctx context.Context, communityId uint) ([]*NhTask, error) {
query := fmt.Sprintf("select %s from %s where community_id = 0 or community_id = ?", nhTaskRows, m.table) query := fmt.Sprintf("select %s from %s where `status` = 1 and community_id = ? order by `sort`", nhTaskRows, m.table)
var tasks []*NhTask var tasks []*NhTask
err := m.conn.QueryRowsCtx(ctx, &tasks, query, communityId) err := m.conn.QueryRowsCtx(ctx, &tasks, query, communityId)
if err != nil && !errors.Is(err, sqlx.ErrNotFound) { if err != nil && !errors.Is(err, sqlx.ErrNotFound) {

View File

@@ -51,6 +51,8 @@ type (
EndAt sql.NullTime `db:"end_at"` // 结束时间 EndAt sql.NullTime `db:"end_at"` // 结束时间
CreatedAt time.Time `db:"created_at"` // 创建时间 CreatedAt time.Time `db:"created_at"` // 创建时间
UpdatedAt time.Time `db:"updated_at"` // 修改时间 UpdatedAt time.Time `db:"updated_at"` // 修改时间
Param string `db:"param"` // 备用参数,如果是邀请任务,可以填邀请的人数
Sort int `db:"sort"` // 数字越小越靠前
} }
) )
@@ -82,14 +84,14 @@ func (m *defaultNhTaskModel) FindOne(ctx context.Context, id uint) (*NhTask, err
} }
func (m *defaultNhTaskModel) Insert(ctx context.Context, data *NhTask) (sql.Result, error) { func (m *defaultNhTaskModel) Insert(ctx context.Context, data *NhTask) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, nhTaskRowsExpectAutoSet) query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, nhTaskRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.CommunityId, data.Title, data.SubTitle, data.Description, data.Points, data.ButtonText, data.Type, data.Url, data.Status, data.StartAt, data.EndAt) ret, err := m.conn.ExecCtx(ctx, query, data.CommunityId, data.Title, data.SubTitle, data.Description, data.Points, data.ButtonText, data.Type, data.Url, data.Status, data.StartAt, data.EndAt, data.Param, data.Sort)
return ret, err return ret, err
} }
func (m *defaultNhTaskModel) Update(ctx context.Context, data *NhTask) error { func (m *defaultNhTaskModel) Update(ctx context.Context, data *NhTask) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskRowsWithPlaceHolder) query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.CommunityId, data.Title, data.SubTitle, data.Description, data.Points, data.ButtonText, data.Type, data.Url, data.Status, data.StartAt, data.EndAt, data.Id) _, err := m.conn.ExecCtx(ctx, query, data.CommunityId, data.Title, data.SubTitle, data.Description, data.Points, data.ButtonText, data.Type, data.Url, data.Status, data.StartAt, data.EndAt, data.Param, data.Sort, data.Id)
return err return err
} }

View File

@@ -0,0 +1,29 @@
package model
import "github.com/zeromicro/go-zero/core/stores/sqlx"
var _ NhTouristBindModel = (*customNhTouristBindModel)(nil)
type (
// NhTouristBindModel is an interface to be customized, add more methods here,
// and implement the added methods in customNhTouristBindModel.
NhTouristBindModel interface {
nhTouristBindModel
withSession(session sqlx.Session) NhTouristBindModel
}
customNhTouristBindModel struct {
*defaultNhTouristBindModel
}
)
// NewNhTouristBindModel returns a model for the database table.
func NewNhTouristBindModel(conn sqlx.SqlConn) NhTouristBindModel {
return &customNhTouristBindModel{
defaultNhTouristBindModel: newNhTouristBindModel(conn),
}
}
func (m *customNhTouristBindModel) withSession(session sqlx.Session) NhTouristBindModel {
return NewNhTouristBindModel(sqlx.NewSqlConnFromSession(session))
}

View File

@@ -0,0 +1,87 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.3
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
nhTouristBindFieldNames = builder.RawFieldNames(&NhTouristBind{})
nhTouristBindRows = strings.Join(nhTouristBindFieldNames, ",")
nhTouristBindRowsExpectAutoSet = strings.Join(stringx.Remove(nhTouristBindFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
nhTouristBindRowsWithPlaceHolder = strings.Join(stringx.Remove(nhTouristBindFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
nhTouristBindModel interface {
Insert(ctx context.Context, data *NhTouristBind) (sql.Result, error)
FindOne(ctx context.Context, id int) (*NhTouristBind, error)
Update(ctx context.Context, data *NhTouristBind) error
Delete(ctx context.Context, id int) error
}
defaultNhTouristBindModel struct {
conn sqlx.SqlConn
table string
}
NhTouristBind struct {
Id int `db:"id"`
TouristAccount string `db:"tourist_account"` // 游客账号
FormalAccount string `db:"formal_account"` // 正式账号
CreateTime int `db:"create_time"` // 创建时间
}
)
func newNhTouristBindModel(conn sqlx.SqlConn) *defaultNhTouristBindModel {
return &defaultNhTouristBindModel{
conn: conn,
table: "`nh_tourist_bind`",
}
}
func (m *defaultNhTouristBindModel) Delete(ctx context.Context, id int) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultNhTouristBindModel) FindOne(ctx context.Context, id int) (*NhTouristBind, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhTouristBindRows, m.table)
var resp NhTouristBind
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhTouristBindModel) Insert(ctx context.Context, data *NhTouristBind) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?)", m.table, nhTouristBindRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.TouristAccount, data.FormalAccount)
return ret, err
}
func (m *defaultNhTouristBindModel) Update(ctx context.Context, data *NhTouristBind) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTouristBindRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.TouristAccount, data.FormalAccount, data.Id)
return err
}
func (m *defaultNhTouristBindModel) tableName() string {
return m.table
}

29
internal/model/nh_user_model.go Executable file
View File

@@ -0,0 +1,29 @@
package model
import "github.com/zeromicro/go-zero/core/stores/sqlx"
var _ NhUserModel = (*customNhUserModel)(nil)
type (
// NhUserModel is an interface to be customized, add more methods here,
// and implement the added methods in customNhUserModel.
NhUserModel interface {
nhUserModel
withSession(session sqlx.Session) NhUserModel
}
customNhUserModel struct {
*defaultNhUserModel
}
)
// NewNhUserModel returns a model for the database table.
func NewNhUserModel(conn sqlx.SqlConn) NhUserModel {
return &customNhUserModel{
defaultNhUserModel: newNhUserModel(conn),
}
}
func (m *customNhUserModel) withSession(session sqlx.Session) NhUserModel {
return NewNhUserModel(sqlx.NewSqlConnFromSession(session))
}

View File

@@ -0,0 +1,108 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.3
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
nhUserFieldNames = builder.RawFieldNames(&NhUser{})
nhUserRows = strings.Join(nhUserFieldNames, ",")
nhUserRowsExpectAutoSet = strings.Join(stringx.Remove(nhUserFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
nhUserRowsWithPlaceHolder = strings.Join(stringx.Remove(nhUserFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
nhUserModel interface {
Insert(ctx context.Context, data *NhUser) (sql.Result, error)
FindOne(ctx context.Context, id uint) (*NhUser, error)
FindOneByEmail(ctx context.Context, email string) (*NhUser, error)
Update(ctx context.Context, data *NhUser) error
Delete(ctx context.Context, id uint) error
}
defaultNhUserModel struct {
conn sqlx.SqlConn
table string
}
NhUser struct {
Id uint `db:"id"`
Email string `db:"email"` // 邮箱
Password string `db:"password"` // 密码
CreateTime sql.NullInt64 `db:"create_time"` // 创建时间
InviteId int `db:"invite_id"` // 邀请码/测试码ID
LastLoginTime sql.NullInt64 `db:"last_login_time"` // 最后登陆时间
LastLoginIp string `db:"last_login_ip"` // 最后登录IP
Remarks sql.NullString `db:"remarks"` // 备注
Status uint8 `db:"status"` // 用户状态 1 正常 2 禁止
IsOpenSeason int8 `db:"is_open_season"` // 是否已开启赛季
}
)
func newNhUserModel(conn sqlx.SqlConn) *defaultNhUserModel {
return &defaultNhUserModel{
conn: conn,
table: "`nh_user`",
}
}
func (m *defaultNhUserModel) Delete(ctx context.Context, id uint) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultNhUserModel) FindOne(ctx context.Context, id uint) (*NhUser, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhUserRows, m.table)
var resp NhUser
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhUserModel) FindOneByEmail(ctx context.Context, email string) (*NhUser, error) {
var resp NhUser
query := fmt.Sprintf("select %s from %s where `email` = ? limit 1", nhUserRows, m.table)
err := m.conn.QueryRowCtx(ctx, &resp, query, email)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhUserModel) Insert(ctx context.Context, data *NhUser) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?)", m.table, nhUserRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.Email, data.Password, data.InviteId, data.LastLoginTime, data.LastLoginIp, data.Remarks, data.Status, data.IsOpenSeason)
return ret, err
}
func (m *defaultNhUserModel) Update(ctx context.Context, newData *NhUser) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhUserRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, newData.Email, newData.Password, newData.InviteId, newData.LastLoginTime, newData.LastLoginIp, newData.Remarks, newData.Status, newData.IsOpenSeason, newData.Id)
return err
}
func (m *defaultNhUserModel) tableName() string {
return m.table
}

View File

@@ -6,15 +6,13 @@ import (
) )
type err struct { type err struct {
code int code Reason
reason Reason
msg string msg string
} }
func New(code int, reason Reason, message any) error { func New(code Reason, message any) error {
return err{ return err{
code: code, code: code,
reason: reason,
msg: cast.ToString(message), msg: cast.ToString(message),
} }
} }
@@ -25,15 +23,10 @@ func (e err) Error() string {
} }
// Code return code // Code return code
func (e err) Code() int { func (e err) Code() Reason {
return e.code return e.code
} }
// Reason return reason
func (e err) Reason() Reason {
return e.reason
}
// Message return message // Message return message
func (e err) Message() string { func (e err) Message() string {
return e.msg return e.msg

View File

@@ -1,56 +1,5 @@
package errs package errs
import (
"net/http"
)
func Success() error { func Success() error {
return New(http.StatusOK, ErrSucceed, "success") return New(ErrSucceed, "ok")
}
func NotFound(reason Reason, v any) error {
return New(http.StatusNotFound, reason, v)
}
func BadRequest(reason Reason, v any) error {
return New(http.StatusBadRequest, reason, v)
}
func InternalServer(reason Reason, v any) error {
return New(http.StatusInternalServerError, reason, v)
}
// Unauthorized new Unauthorized error that is mapped to a 401 response.
func Unauthorized(reason Reason, v any) error {
return New(http.StatusUnauthorized, reason, v)
}
// Forbidden new Forbidden error that is mapped to a 403 response.
func Forbidden(reason Reason, v any) error {
return New(http.StatusForbidden, reason, v)
}
// Conflict new Conflict error that is mapped to a 409 response.
func Conflict(reason Reason, v any) error {
return New(http.StatusConflict, reason, v)
}
// ServiceUnavailable new ServiceUnavailable error that is mapped to an HTTP 503 response.
func ServiceUnavailable(reason Reason, v any) error {
return New(http.StatusServiceUnavailable, reason, v)
}
// GatewayTimeout new GatewayTimeout error that is mapped to an HTTP 504 response.
func GatewayTimeout(reason Reason, v any) error {
return New(http.StatusGatewayTimeout, reason, v)
}
// BadGateway new BadGateway error that is mapped to an HTTP 504 response.
func BadGateway(reason Reason, v any) error {
return New(http.StatusBadGateway, reason, v)
}
// ClientClosed new ClientClosed error that is mapped to an HTTP 499 response.
func ClientClosed(reason Reason, v any) error {
return New(499, reason, v)
} }

View File

@@ -2,24 +2,45 @@ package errs
import ( import (
"context" "context"
"encoding/json"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/rest/httpx" "github.com/zeromicro/go-zero/rest/httpx"
"net/http" "net/http"
"os"
"strings"
) )
var debug bool
func init() { func init() {
if strings.ToLower(os.Getenv("VANS_API_DEBUG")) == "on" {
debug = true
}
httpx.SetErrorHandlerCtx(ErrorHandleCtx) httpx.SetErrorHandlerCtx(ErrorHandleCtx)
httpx.SetErrorHandler(ErrorHandle) httpx.SetErrorHandler(ErrorHandle)
httpx.SetOkHandler(OkHandle)
} }
func SetDebug(d bool) { func OkHandle(ctx context.Context, v any) any {
debug = d return map[string]any{
"status": map[string]any{
"code": ErrSucceed,
"msg": "ok",
},
"data": v,
}
}
func WithUnauthorizedCallback() rest.RunOption {
return rest.WithUnauthorizedCallback(func(w http.ResponseWriter, r *http.Request, err error) {
body := map[string]any{
"status": map[string]any{
"code": ErrUnauthorized,
"msg": err.Error(),
},
}
data, _ := json.Marshal(body)
w.Header().Set(httpx.ContentType, "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK)
_, err = w.Write(data)
if err != nil {
logx.Errorw("error write response", logx.Field("type", "http"), logx.Field("error", err))
}
})
} }
func ErrorHandle(err error) (int, any) { func ErrorHandle(err error) (int, any) {
@@ -27,10 +48,9 @@ func ErrorHandle(err error) (int, any) {
} }
func ErrorHandleCtx(ctx context.Context, err error) (int, any) { func ErrorHandleCtx(ctx context.Context, err error) (int, any) {
code := http.StatusBadRequest code := ErrUnknownReason
reason := ErrInternalServer
var msg string var msg string
if ec, ok := err.(interface{ Code() int }); ok { if ec, ok := err.(interface{ Code() Reason }); ok {
code = ec.Code() code = ec.Code()
} }
if ec, ok := err.(interface{ Message() string }); ok { if ec, ok := err.(interface{ Message() string }); ok {
@@ -38,27 +58,17 @@ func ErrorHandleCtx(ctx context.Context, err error) (int, any) {
} else { } else {
msg = err.Error() msg = err.Error()
} }
if ec, ok := err.(interface{ Reason() Reason }); ok {
reason = ec.Reason()
}
var errMsg string if code < ErrUnknownReason && code >= ErrInternalServer {
if reason < ErrUnknownLogicError && reason != ErrSucceed { logx.Errorw("request system error", logx.Field("err-msg", msg))
errMsg = msg
msg = "system error" msg = "system error"
} }
body := map[string]any{ body := map[string]any{
"code": reason, "status": map[string]any{
"message": msg, "code": code,
"msg": msg,
},
} }
if errMsg != "" && debug { return http.StatusOK, body
body["err"] = errMsg
}
if ec, ok := err.(interface{ Metadata() any }); ok {
if md := ec.Metadata(); md != nil {
body["metadata"] = md
}
}
return code, body
} }

View File

@@ -3,10 +3,11 @@ package errs
type Reason int type Reason int
const ( const (
// ======= 系统错误:0~999 ======= // ======= 系统错误:10000~19999 =======
ErrUnknownReason Reason = 0 // 未知错误 ErrUnknownReason Reason = 10000 // 未知错误
ErrSucceed Reason = 200 // 成功 ErrSucceed Reason = 10200 // 成功
ErrOverload Reason = 403 // 请求超载 ErrUnauthorized Reason = 10401 // 未授权
ErrOverload Reason = 10403 // 请求超载
// ======= 服务器内部错误1000~9999 ======= // ======= 服务器内部错误1000~9999 =======
ErrInternalServer Reason = 1000 // 未知的服务器内部错误 ErrInternalServer Reason = 1000 // 未知的服务器内部错误
@@ -15,22 +16,10 @@ const (
ErrEncodePassword Reason = 1003 // 密码加密错误 ErrEncodePassword Reason = 1003 // 密码加密错误
ErrGenerateUUid Reason = 1004 // 生成uuid错误 ErrGenerateUUid Reason = 1004 // 生成uuid错误
ErrGenerateToken Reason = 1005 // 生成token错误 ErrGenerateToken Reason = 1005 // 生成token错误
ErrGetExchangeRate Reason = 1005 // 获取汇率错误
// ======= 业务层错误:10000~99999 ======= // ======= 业务层错误:20000~29999 =======
ErrUnknownLogicError Reason = 10000 // 未知的业务错误 ErrUnknownLogicError Reason = 20000 // 未知的业务错误
ErrInvalidParam Reason = 10001 // 无效参数错误 ErrTaskNotFound Reason = 20001 // 任务不存在
ErrInvalidSignature Reason = 10002 // 无效签名错误 ErrTaskAlreadyReward Reason = 20002 // 任务已领取
ErrInvalidToken Reason = 10003 // 无效的token ErrTaskNotFinished Reason = 20003 // 任务未完成
ErrInvoiceHasPaid Reason = 10004 // 订单已支付
ErrInvalidAppId Reason = 10005 // 应用id无效
ErrUserNotHasInviter Reason = 10006 // 用户没有邀请人
ErrTaskNotFound Reason = 10007 // 任务不存在
ErrTaskAlreadyReward Reason = 10008 // 任务已领取
ErrTaskNotFinished Reason = 10009 // 任务未完成
// ========= admin 业务相关错误码: 30000~39999 =========
ErrUnknownAdminError Reason = 30000 // 未知的admin错误
ErrInvalidPassword Reason = 30001 // 无效密码
ErrInvalidAccount Reason = 30002 // 无效账号
) )

View File

@@ -10,11 +10,17 @@ import (
type ServiceContext struct { type ServiceContext struct {
Config config.Config Config config.Config
TaskModel model.NhTaskModel TaskModel model.NhTaskModel
TaskAssetModel model.NhTaskAssetModel TaskAssetModel model.NhTaskAssetModel
TaskAssetRecordModel model.NhTaskAssetRecordModel TaskAssetRecordModel model.NhTaskAssetRecordModel
TaskProgressModel model.NhTaskProgressModel TaskProgressModel model.NhTaskProgressModel
TwitterModel model.NhTwitterModel TwitterModel model.NhTwitterModel
PromoteBindModel model.NhPromoteBindModel
TouristBindModel model.NhTouristBindModel
CommunityModel model.NhTaskCommunityModel
UserModel model.NhUserModel
Earn *ea.Client Earn *ea.Client
DBConn sqlx.SqlConn DBConn sqlx.SqlConn
} }
@@ -23,11 +29,16 @@ func NewServiceContext(c config.Config) *ServiceContext {
dbConn := c.MySql.Conn() dbConn := c.MySql.Conn()
return &ServiceContext{ return &ServiceContext{
Config: c, Config: c,
TaskModel: model.NewNhTaskModel(dbConn), TaskModel: model.NewNhTaskModel(dbConn),
TaskAssetModel: model.NewNhTaskAssetModel(dbConn), TaskAssetModel: model.NewNhTaskAssetModel(dbConn),
TaskAssetRecordModel: model.NewNhTaskAssetRecordModel(dbConn), TaskAssetRecordModel: model.NewNhTaskAssetRecordModel(dbConn),
TaskProgressModel: model.NewNhTaskProgressModel(dbConn), TaskProgressModel: model.NewNhTaskProgressModel(dbConn),
TwitterModel: model.NewNhTwitterModel(dbConn), TwitterModel: model.NewNhTwitterModel(dbConn),
PromoteBindModel: model.NewNhPromoteBindModel(dbConn),
CommunityModel: model.NewNhTaskCommunityModel(dbConn),
UserModel: model.NewNhUserModel(dbConn),
Earn: c.Earn.BuildEarnClient(), Earn: c.Earn.BuildEarnClient(),
DBConn: dbConn, DBConn: dbConn,
} }

View File

@@ -3,6 +3,19 @@
package types package types
type Community struct {
Id uint `json:"id"` // 社区ID
Title string `json:"title"` // 社区标题
Logo string `json:"logo"` // 社区图标
Description string `json:"description"` // 社区描述
StartAt int64 `json:"start_at"` // 开始时间
EndAt int64 `json:"end_at"` // 结束时间
}
type GetCommunityListResp struct {
CommunityList []Community `json:"community_list"` // 社区列表
}
type GetTaskListReq struct { type GetTaskListReq struct {
CommunityId uint `form:"community_id,optional"` // 所属社区ID CommunityId uint `form:"community_id,optional"` // 所属社区ID
} }
@@ -23,11 +36,14 @@ type Task struct {
Description string `json:"description"` // 任务描述 Description string `json:"description"` // 任务描述
Points int `json:"points"` // 任务积分 Points int `json:"points"` // 任务积分
ButtonText string `json:"button_text"` // 按钮文字 ButtonText string `json:"button_text"` // 按钮文字
Type int8 `json:"type"` // 任务类型: 0=follow_twitter,1=bind_twitter,2=cast_twitter,3=publish_twitter,4=repost_twitter,5=watch_youtube,6=follow_youtube,7=bind_discord,8=join_telegram,9=daily_pay Params string `json:"params"` // 参数
Type int8 `json:"type"` // 任务类型: 0=follow_twitter,1=bind_twitter,2=cast_twitter,3=publish_twitter,4=repost_twitter,5=watch_youtube,6=follow_youtube,7=bind_discord,8=join_telegram,9=daily_pay,10=invite_user
Url string `json:"url"` // 跳转链接 Url string `json:"url"` // 跳转链接
Status int8 `json:"status"` // 任务状态: 0=不启用1=启用 Sort int `json:"sort"` // 排序
StartAt string `json:"start_at"` // 开始时间 StartAt string `json:"start_at"` // 开始时间
EndAt string `json:"end_at"` // 结束时间 EndAt string `json:"end_at"` // 结束时间
HasFinishCount int `json:"has_finish_count"` // 当前完成进度
TotalCount int `json:"total_count"` // 总进度
FinishState int8 `json:"finish_state"` // 0:未完成 1:待校验 2:已完成未领取 3:已领取 FinishState int8 `json:"finish_state"` // 0:未完成 1:待校验 2:已完成未领取 3:已领取
} }
@@ -35,6 +51,11 @@ type TaskIdPath struct {
ID uint `path:"id"` // 任务ID ID uint `path:"id"` // 任务ID
} }
type VerifyTaskResultReq struct {
ID uint `form:"id"` // 任务ID
Params string `form:"params,optional"` // 额外的参数
}
type VerifyTaskResultResp struct { type VerifyTaskResultResp struct {
Finish bool `json:"finish"` // 是否完成 Finish bool `json:"finish"` // 是否完成
} }

View File

@@ -3,9 +3,11 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"github.com/zeromicro/go-zero/core/service"
"nova_task/internal/config" "nova_task/internal/config"
"nova_task/internal/handler" "nova_task/internal/handler"
"nova_task/internal/job"
"nova_task/internal/pkg/errs"
"nova_task/internal/svc" "nova_task/internal/svc"
"github.com/zeromicro/go-zero/core/conf" "github.com/zeromicro/go-zero/core/conf"
@@ -21,14 +23,19 @@ func main() {
conf.MustLoad(*configFile, &c) conf.MustLoad(*configFile, &c)
c.MustSetUp() c.MustSetUp()
server := rest.MustNewServer(c.RestConf)
defer server.Stop()
ctx := svc.NewServiceContext(c) ctx := svc.NewServiceContext(c)
defer ctx.Close() defer ctx.Close()
handler.RegisterHandlers(server, ctx) serviceGroup := service.NewServiceGroup()
defer serviceGroup.Stop()
jb := job.NewJob(ctx)
serviceGroup.Add(jb)
httpSvr := rest.MustNewServer(c.RestConf, rest.WithCors(), errs.WithUnauthorizedCallback())
handler.RegisterHandlers(httpSvr, ctx)
serviceGroup.Add(httpSvr)
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port) fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
server.Start() serviceGroup.Start()
} }