From 23576211d5e4aba9abf416a1ad1ead454b969a5f Mon Sep 17 00:00:00 2001 From: jager Date: Tue, 6 May 2025 20:36:39 +0800 Subject: [PATCH] tribally report --- doc/sql/novatask.sql | 26 ++++- internal/consts/consts.go | 5 +- internal/handler/routes.go | 2 +- internal/job/corns.go | 1 + internal/job/tribally_report/cron.go | 41 +++++++ .../logic/task/verify_task_result_logic.go | 24 +++- .../transfer_castile_to_game_list_logic.go | 4 +- .../transfer_castile_to_game_logic.go | 5 +- internal/model/nh_global_data_model.go | 45 ++++++++ internal/model/nh_global_data_model_gen.go | 105 ++++++++++++++++++ internal/model/nh_tribally_user_model.go | 54 +++++++++ internal/model/nh_tribally_user_model_gen.go | 104 +++++++++++++++++ internal/svc/model.go | 6 + internal/types/types.go | 2 +- 14 files changed, 409 insertions(+), 15 deletions(-) create mode 100644 internal/job/tribally_report/cron.go create mode 100755 internal/model/nh_global_data_model.go create mode 100755 internal/model/nh_global_data_model_gen.go create mode 100755 internal/model/nh_tribally_user_model.go create mode 100755 internal/model/nh_tribally_user_model_gen.go diff --git a/doc/sql/novatask.sql b/doc/sql/novatask.sql index 251d019..385ecce 100644 --- a/doc/sql/novatask.sql +++ b/doc/sql/novatask.sql @@ -169,4 +169,28 @@ CREATE TABLE `nh_castile_token_log` PRIMARY KEY (`id`), KEY `uid` (`uid`) USING BTREE, KEY `role_id` (`role_id`) USING BTREE -) COMMENT ='CASTILE代币提取记录表'; \ No newline at end of file +) COMMENT ='CASTILE代币提取记录表'; + +CREATE TABLE `nh_tribally_user` +( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `uid` int unsigned NOT NULL COMMENT '用户id', + `chapter` int NOT NULL DEFAULT 0 COMMENT '章节', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY (`uid`), + INDEX (`chapter`) +) COMMENT ='Tribally平台绑定表'; + +CREATE TABLE `nh_global_data` +( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `key` varchar(128) NOT NULL COMMENT 'key', + `value` varchar(128) NOT NULL DEFAULT '' COMMENT 'value', + `remark` varchar(256) NOT NULL DEFAULT '' COMMENT '备注', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY (`key`) +) COMMENT ='nova_task全局数据'; \ No newline at end of file diff --git a/internal/consts/consts.go b/internal/consts/consts.go index d69c015..7716264 100644 --- a/internal/consts/consts.go +++ b/internal/consts/consts.go @@ -14,6 +14,7 @@ const ( AdminSecret = "admin_secret" NftHolderApiConf = "nft_holder_api_conf" TriballyApiKey = "tribally_api_key" + TriballyReportTime = "tribally_report_time" ) type AssetType string @@ -32,10 +33,6 @@ const ( RewardCastile = 2 // 代币 ) -const ( - FORMATDATETIME = "2006-01-02 15:04:05" // 日期时间 -) - func GetAssetType(rewardType int8) AssetType { switch rewardType { case RewardTypePoints: diff --git a/internal/handler/routes.go b/internal/handler/routes.go index f4c0b02..254a135 100644 --- a/internal/handler/routes.go +++ b/internal/handler/routes.go @@ -1,5 +1,5 @@ // Code generated by goctl. DO NOT EDIT. -// goctl 1.7.3 +// goctl 1.7.6 package handler diff --git a/internal/job/corns.go b/internal/job/corns.go index 4c17c42..ae144f3 100644 --- a/internal/job/corns.go +++ b/internal/job/corns.go @@ -19,6 +19,7 @@ var cronList = []func(context.Context, *svc.ServiceContext) cron.Job{ stake_settle.NewCron, //game_notify.NewCron, check_points_stake.NewCron, + //tribally_report.NewCron, } type Corns struct { diff --git a/internal/job/tribally_report/cron.go b/internal/job/tribally_report/cron.go new file mode 100644 index 0000000..547318f --- /dev/null +++ b/internal/job/tribally_report/cron.go @@ -0,0 +1,41 @@ +package tribally_report + +import ( + "context" + "github.com/robfig/cron/v3" + "github.com/zeromicro/go-zero/core/logx" + "nova_task/internal/consts" + "nova_task/internal/svc" + "time" +) + +type Cron struct { + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewCron(ctx context.Context, svcCtx *svc.ServiceContext) cron.Job { + return &Cron{ctx: ctx, svcCtx: svcCtx} +} + +func (c *Cron) Spec() string { + return "@every 30s" +} + +func (c *Cron) Run() { + tr, err := c.svcCtx.GlobalDataModel.GetValue(c.ctx, consts.TriballyReportTime) + if err != nil { + logx.Errorw("get tribally report time failed", logx.Field("err", err)) + return + } + var updateTime time.Time + if tr != "" { + updateTime, err = time.Parse(time.DateTime, tr) + if err != nil { + logx.Errorw("parse tribally report time failed", logx.Field("err", err)) + return + } + } + + c.svcCtx.TriballyUserModel.FindUpdateTriballyUsers(c.ctx, updateTime, 100) +} diff --git a/internal/logic/task/verify_task_result_logic.go b/internal/logic/task/verify_task_result_logic.go index 4e3c8ff..05d3be5 100644 --- a/internal/logic/task/verify_task_result_logic.go +++ b/internal/logic/task/verify_task_result_logic.go @@ -92,10 +92,26 @@ func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.VerifyTaskResultReq) 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 + } + 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 + } + _, err = l.svcCtx.TriballyUserModel.FindOneByUid(l.ctx, uint(uid)) + if err != nil { + if errors.Is(err, model.ErrNotFound) { + // TriballyUser表中不存在此用户,插入 + _, err = l.svcCtx.TriballyUserModel.Insert(l.ctx, &model.NhTriballyUser{ + Uid: uint(uid), + Chapter: -1, + }) + if err != nil { + l.Errorw("insert tribally user error", logx.Field("err", err), logx.Field("uid", uid)) + return nil, errs.New(errs.ErrDatabaseOperate, err) + } + } else { + l.Errorw("find tribally user error", logx.Field("err", err), logx.Field("uid", uid)) + return nil, errs.New(errs.ErrDatabaseOperate, err) } } default: diff --git a/internal/logic/transfercastile/transfer_castile_to_game_list_logic.go b/internal/logic/transfercastile/transfer_castile_to_game_list_logic.go index f601f47..346e977 100644 --- a/internal/logic/transfercastile/transfer_castile_to_game_list_logic.go +++ b/internal/logic/transfercastile/transfer_castile_to_game_list_logic.go @@ -2,9 +2,9 @@ package transfercastile import ( "context" - "nova_task/internal/consts" "nova_task/internal/pkg/errs" "nova_task/internal/pkg/utils" + "time" "nova_task/internal/svc" "nova_task/internal/types" @@ -42,7 +42,7 @@ func (l *TransferCastileToGameListLogic) TransferCastileToGameList(req *types.Tr RoleID: int64(ll.RoleId), Amount: int64(ll.Amount), Status: int64(ll.CallbackStatus), - CreatedAt: ll.CreatedAt.Format(consts.FORMATDATETIME), + CreatedAt: ll.CreatedAt.Format(time.DateTime), }) } return &types.TransferCastileToGameListResp{ diff --git a/internal/logic/transfercastile/transfer_castile_to_game_logic.go b/internal/logic/transfercastile/transfer_castile_to_game_logic.go index d12eedd..e789dae 100644 --- a/internal/logic/transfercastile/transfer_castile_to_game_logic.go +++ b/internal/logic/transfercastile/transfer_castile_to_game_logic.go @@ -12,6 +12,7 @@ import ( "nova_task/internal/pkg/utils" "nova_task/internal/svc" "nova_task/internal/types" + "time" ) type TransferCastileToGameLogic struct { @@ -111,7 +112,7 @@ func (l *TransferCastileToGameLogic) TransferCastileToGame(req *types.TransferCa data, _ := jsonx.MarshalToString(itemList) //给多角色发邮件 - _, err = l.svcCtx.GameAction(l.ctx, int64(req.RoleID), consts.GameActionSendNoticeAward, map[string]any{ + _, err = l.svcCtx.GameAction(l.ctx, req.RoleID, consts.GameActionSendNoticeAward, map[string]any{ "role_ids": req.RoleID, "item_list": data, "template_id": 120338, @@ -142,6 +143,6 @@ func (l *TransferCastileToGameLogic) TransferCastileToGame(req *types.TransferCa RoleID: int64(res.RoleId), Amount: int64(res.Amount), Status: int64(res.CallbackStatus), - CreatedAt: res.CreatedAt.Format(consts.FORMATDATETIME), + CreatedAt: res.CreatedAt.Format(time.DateTime), }, nil } diff --git a/internal/model/nh_global_data_model.go b/internal/model/nh_global_data_model.go new file mode 100755 index 0000000..f782e93 --- /dev/null +++ b/internal/model/nh_global_data_model.go @@ -0,0 +1,45 @@ +package model + +import ( + "context" + "errors" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ NhGlobalDataModel = (*customNhGlobalDataModel)(nil) + +type ( + // NhGlobalDataModel is an interface to be customized, add more methods here, + // and implement the added methods in customNhGlobalDataModel. + NhGlobalDataModel interface { + nhGlobalDataModel + withSession(session sqlx.Session) NhGlobalDataModel + GetValue(ctx context.Context, key string) (string, error) + } + + customNhGlobalDataModel struct { + *defaultNhGlobalDataModel + } +) + +func (m *customNhGlobalDataModel) GetValue(ctx context.Context, key string) (string, error) { + result, err := m.FindOneByKey(ctx, key) + if err != nil { + if errors.Is(err, ErrNotFound) { + return "", nil + } + return "", err + } + return result.Value, nil +} + +// NewNhGlobalDataModel returns a model for the database table. +func NewNhGlobalDataModel(conn sqlx.SqlConn) NhGlobalDataModel { + return &customNhGlobalDataModel{ + defaultNhGlobalDataModel: newNhGlobalDataModel(conn), + } +} + +func (m *customNhGlobalDataModel) withSession(session sqlx.Session) NhGlobalDataModel { + return NewNhGlobalDataModel(sqlx.NewSqlConnFromSession(session)) +} diff --git a/internal/model/nh_global_data_model_gen.go b/internal/model/nh_global_data_model_gen.go new file mode 100755 index 0000000..506b212 --- /dev/null +++ b/internal/model/nh_global_data_model_gen.go @@ -0,0 +1,105 @@ +// Code generated by goctl. DO NOT EDIT. +// versions: +// goctl version: 1.7.6 + +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 ( + nhGlobalDataFieldNames = builder.RawFieldNames(&NhGlobalData{}) + nhGlobalDataRows = strings.Join(nhGlobalDataFieldNames, ",") + nhGlobalDataRowsExpectAutoSet = strings.Join(stringx.Remove(nhGlobalDataFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",") + nhGlobalDataRowsWithPlaceHolder = strings.Join(stringx.Remove(nhGlobalDataFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?" +) + +type ( + nhGlobalDataModel interface { + Insert(ctx context.Context, data *NhGlobalData) (sql.Result, error) + FindOne(ctx context.Context, id uint) (*NhGlobalData, error) + FindOneByKey(ctx context.Context, key string) (*NhGlobalData, error) + Update(ctx context.Context, data *NhGlobalData) error + Delete(ctx context.Context, id uint) error + } + + defaultNhGlobalDataModel struct { + conn sqlx.SqlConn + table string + } + + NhGlobalData struct { + Id uint `db:"id"` + Key string `db:"key"` // key + Value string `db:"value"` // value + Remark string `db:"remark"` // 备注 + CreatedAt time.Time `db:"created_at"` // 创建时间 + UpdatedAt time.Time `db:"updated_at"` // 修改时间 + } +) + +func newNhGlobalDataModel(conn sqlx.SqlConn) *defaultNhGlobalDataModel { + return &defaultNhGlobalDataModel{ + conn: conn, + table: "`nh_global_data`", + } +} + +func (m *defaultNhGlobalDataModel) 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 *defaultNhGlobalDataModel) FindOne(ctx context.Context, id uint) (*NhGlobalData, error) { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhGlobalDataRows, m.table) + var resp NhGlobalData + 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 *defaultNhGlobalDataModel) FindOneByKey(ctx context.Context, key string) (*NhGlobalData, error) { + var resp NhGlobalData + query := fmt.Sprintf("select %s from %s where `key` = ? limit 1", nhGlobalDataRows, m.table) + err := m.conn.QueryRowCtx(ctx, &resp, query, key) + switch err { + case nil: + return &resp, nil + case sqlx.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultNhGlobalDataModel) Insert(ctx context.Context, data *NhGlobalData) (sql.Result, error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?)", m.table, nhGlobalDataRowsExpectAutoSet) + ret, err := m.conn.ExecCtx(ctx, query, data.Key, data.Value, data.Remark) + return ret, err +} + +func (m *defaultNhGlobalDataModel) Update(ctx context.Context, newData *NhGlobalData) error { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhGlobalDataRowsWithPlaceHolder) + _, err := m.conn.ExecCtx(ctx, query, newData.Key, newData.Value, newData.Remark, newData.Id) + return err +} + +func (m *defaultNhGlobalDataModel) tableName() string { + return m.table +} diff --git a/internal/model/nh_tribally_user_model.go b/internal/model/nh_tribally_user_model.go new file mode 100755 index 0000000..d7cdd78 --- /dev/null +++ b/internal/model/nh_tribally_user_model.go @@ -0,0 +1,54 @@ +package model + +import ( + "context" + "errors" + "fmt" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "time" +) + +var _ NhTriballyUserModel = (*customNhTriballyUserModel)(nil) + +type ( + // NhTriballyUserModel is an interface to be customized, add more methods here, + // and implement the added methods in customNhTriballyUserModel. + NhTriballyUserModel interface { + nhTriballyUserModel + withSession(session sqlx.Session) NhTriballyUserModel + FindUpdateTriballyUsers(ctx context.Context, t time.Time, count int) ([]*TriballyUserChapter, error) + } + + customNhTriballyUserModel struct { + *defaultNhTriballyUserModel + } + + TriballyUserChapter struct { + Id uint `db:"id"` + Uid uint `db:"uid"` // 用户id + Chapter int `db:"chapter"` // 章节 + MaxChapter int `db:"max_chapter"` // 最大章节 + UpdatedAt time.Time `db:"updated_at"` // 修改时间 + } +) + +func (m *customNhTriballyUserModel) FindUpdateTriballyUsers(ctx context.Context, t time.Time, count int) ([]*TriballyUserChapter, error) { + query := fmt.Sprintf("SELECT t.uid, t.chapter, MAX(g.chapter) as max_chapter, g.updated_at FROM nh_tribally_user t JOIN nh_game_report g ON t.uid = g.uid WHERE g.updated_at >= ? GROUP BY uid LIMIT ?") + var result []*TriballyUserChapter + err := m.conn.QueryRowsCtx(ctx, &result, query, t, count) + if err != nil && !errors.Is(err, sqlx.ErrNotFound) { + return nil, err + } + return result, nil +} + +// NewNhTriballyUserModel returns a model for the database table. +func NewNhTriballyUserModel(conn sqlx.SqlConn) NhTriballyUserModel { + return &customNhTriballyUserModel{ + defaultNhTriballyUserModel: newNhTriballyUserModel(conn), + } +} + +func (m *customNhTriballyUserModel) withSession(session sqlx.Session) NhTriballyUserModel { + return NewNhTriballyUserModel(sqlx.NewSqlConnFromSession(session)) +} diff --git a/internal/model/nh_tribally_user_model_gen.go b/internal/model/nh_tribally_user_model_gen.go new file mode 100755 index 0000000..4ba0082 --- /dev/null +++ b/internal/model/nh_tribally_user_model_gen.go @@ -0,0 +1,104 @@ +// Code generated by goctl. DO NOT EDIT. +// versions: +// goctl version: 1.7.6 + +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 ( + nhTriballyUserFieldNames = builder.RawFieldNames(&NhTriballyUser{}) + nhTriballyUserRows = strings.Join(nhTriballyUserFieldNames, ",") + nhTriballyUserRowsExpectAutoSet = strings.Join(stringx.Remove(nhTriballyUserFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",") + nhTriballyUserRowsWithPlaceHolder = strings.Join(stringx.Remove(nhTriballyUserFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?" +) + +type ( + nhTriballyUserModel interface { + Insert(ctx context.Context, data *NhTriballyUser) (sql.Result, error) + FindOne(ctx context.Context, id uint) (*NhTriballyUser, error) + FindOneByUid(ctx context.Context, uid uint) (*NhTriballyUser, error) + Update(ctx context.Context, data *NhTriballyUser) error + Delete(ctx context.Context, id uint) error + } + + defaultNhTriballyUserModel struct { + conn sqlx.SqlConn + table string + } + + NhTriballyUser struct { + Id uint `db:"id"` + Uid uint `db:"uid"` // 用户id + Chapter int `db:"chapter"` // 章节 + CreatedAt time.Time `db:"created_at"` // 创建时间 + UpdatedAt time.Time `db:"updated_at"` // 修改时间 + } +) + +func newNhTriballyUserModel(conn sqlx.SqlConn) *defaultNhTriballyUserModel { + return &defaultNhTriballyUserModel{ + conn: conn, + table: "`nh_tribally_user`", + } +} + +func (m *defaultNhTriballyUserModel) 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 *defaultNhTriballyUserModel) FindOne(ctx context.Context, id uint) (*NhTriballyUser, error) { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhTriballyUserRows, m.table) + var resp NhTriballyUser + 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 *defaultNhTriballyUserModel) FindOneByUid(ctx context.Context, uid uint) (*NhTriballyUser, error) { + var resp NhTriballyUser + query := fmt.Sprintf("select %s from %s where `uid` = ? limit 1", nhTriballyUserRows, m.table) + err := m.conn.QueryRowCtx(ctx, &resp, query, uid) + switch err { + case nil: + return &resp, nil + case sqlx.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultNhTriballyUserModel) Insert(ctx context.Context, data *NhTriballyUser) (sql.Result, error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?)", m.table, nhTriballyUserRowsExpectAutoSet) + ret, err := m.conn.ExecCtx(ctx, query, data.Uid, data.Chapter) + return ret, err +} + +func (m *defaultNhTriballyUserModel) Update(ctx context.Context, newData *NhTriballyUser) error { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTriballyUserRowsWithPlaceHolder) + _, err := m.conn.ExecCtx(ctx, query, newData.Uid, newData.Chapter, newData.Id) + return err +} + +func (m *defaultNhTriballyUserModel) tableName() string { + return m.table +} diff --git a/internal/svc/model.go b/internal/svc/model.go index 2f0b43d..f314dcc 100644 --- a/internal/svc/model.go +++ b/internal/svc/model.go @@ -47,6 +47,9 @@ type dbModel struct { CastileTokenModel model.NhCastileTokenModel CastileTokenLogModel model.NhCastileTokenLogModel + + TriballyUserModel model.NhTriballyUserModel + GlobalDataModel model.NhGlobalDataModel } func newDBModel(dbConn, gameConn sqlx.SqlConn, configModel model.NhSystemConfigModel) *dbModel { @@ -88,5 +91,8 @@ func newDBModel(dbConn, gameConn sqlx.SqlConn, configModel model.NhSystemConfigM CastileTokenModel: model.NewNhCastileTokenModel(dbConn), CastileTokenLogModel: model.NewNhCastileTokenLogModel(dbConn), + + TriballyUserModel: model.NewNhTriballyUserModel(dbConn), + GlobalDataModel: model.NewNhGlobalDataModel(dbConn), } } diff --git a/internal/types/types.go b/internal/types/types.go index acd34f5..042dab4 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -1,5 +1,5 @@ // Code generated by goctl. DO NOT EDIT. -// goctl 1.7.3 +// goctl 1.7.6 package types