This commit is contained in:
xiabin 2025-01-20 17:36:03 +08:00
parent e2bff25b45
commit 22ec38db77
20 changed files with 105 additions and 31 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
.idea .idea
data/ data/
game_open_api/logs/

View File

@ -19,7 +19,7 @@ services:
- ./data/mysql/data:/var/lib/mysql - ./data/mysql/data:/var/lib/mysql
- ./data/mysql/logs:/var/log/mysql - ./data/mysql/logs:/var/log/mysql
##初始化的脚本初始化我们存放的init.sql文件 ##初始化的脚本初始化我们存放的init.sql文件
- ./sql:/docker-entrypoint-initdb.d/ - ./data/sql:/docker-entrypoint-initdb.d/
- ./data/mysql/conf:/etc/mysql/conf.d - ./data/mysql/conf:/etc/mysql/conf.d
ports: ports:
- "3306:3306" - "3306:3306"

View File

@ -4,6 +4,7 @@ import (
"game.api" "game.api"
"douyin.api" "douyin.api"
"wechat.api" "wechat.api"
"common.api"
) )
type UserId { type UserId {
@ -24,6 +25,6 @@ type SetAppUserRequest {
) )
service game_open_api-api { service game_open_api-api {
@handler appUserSetUser @handler appUserSetUser
post /set_app_account (SetAppUserRequest) returns (UserId) post /set_app_account (SetAppUserRequest) returns (Base)
} }

View File

@ -1,6 +0,0 @@
syntax = "v1"
type Auth {
Token string `json:"token"`
}

12
game_open_api/common.api Normal file
View File

@ -0,0 +1,12 @@
syntax = "v1"
type Auth {
Base
Token string `json:"token"`
}
type Base {
Code int `json:"code"`
Message string `json:"message,omitempty"`
}

View File

@ -1,6 +1,6 @@
syntax = "v1" syntax = "v1"
import "auth.api" import "common.api"
type DouyinCode2UserIdRequest { type DouyinCode2UserIdRequest {
AppId string `form:"appId"` AppId string `form:"appId"`

View File

@ -9,4 +9,10 @@ Cache:
Auth: Auth:
AccessSecret: youtu123! AccessSecret: youtu123!
AccessExpire: 3600 AccessExpire: 86400
Log:
Level: debug
# Mode: file
Path: ./logs
MaxSize: 100

View File

@ -1,5 +1,7 @@
syntax = "v1" syntax = "v1"
import "common.api"
type SetUserGameScoreRequest { type SetUserGameScoreRequest {
Score uint64 `json:"score"` Score uint64 `json:"score"`
} }
@ -27,6 +29,6 @@ service game_open_api-api {
get /ranking/list returns ([]RankingData) get /ranking/list returns ([]RankingData)
@handler rankingSetScore @handler rankingSetScore
post /ranking/set_score (SetUserGameScoreRequest) post /ranking/set_score (SetUserGameScoreRequest) returns (Base)
} }

View File

@ -3,7 +3,6 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"youtu_server/game_open_api/internal/config" "youtu_server/game_open_api/internal/config"
"youtu_server/game_open_api/internal/handler" "youtu_server/game_open_api/internal/handler"
"youtu_server/game_open_api/internal/svc" "youtu_server/game_open_api/internal/svc"

View File

@ -20,6 +20,7 @@ func AppUserSetUserHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
l := app_user.NewAppUserSetUserLogic(r.Context(), svcCtx) l := app_user.NewAppUserSetUserLogic(r.Context(), svcCtx)
resp, err := l.AppUserSetUser(&req) resp, err := l.AppUserSetUser(&req)
if err != nil { if err != nil {
resp.Code = -1
httpx.ErrorCtx(r.Context(), w, err) httpx.ErrorCtx(r.Context(), w, err)
} else { } else {
httpx.OkJsonCtx(r.Context(), w, resp) httpx.OkJsonCtx(r.Context(), w, resp)

View File

@ -20,6 +20,7 @@ func DouyinCode2UserIdHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
l := douyin.NewDouyinCode2UserIdLogic(r.Context(), svcCtx) l := douyin.NewDouyinCode2UserIdLogic(r.Context(), svcCtx)
resp, err := l.DouyinCode2UserId(&req) resp, err := l.DouyinCode2UserId(&req)
if err != nil { if err != nil {
resp.Code = -1
httpx.ErrorCtx(r.Context(), w, err) httpx.ErrorCtx(r.Context(), w, err)
} else { } else {
httpx.OkJsonCtx(r.Context(), w, resp) httpx.OkJsonCtx(r.Context(), w, resp)

View File

@ -18,11 +18,12 @@ func RankingSetScoreHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
} }
l := game.NewRankingSetScoreLogic(r.Context(), svcCtx) l := game.NewRankingSetScoreLogic(r.Context(), svcCtx)
err := l.RankingSetScore(&req) resp, err := l.RankingSetScore(&req)
if err != nil { if err != nil {
resp.Code = -1
httpx.ErrorCtx(r.Context(), w, err) httpx.ErrorCtx(r.Context(), w, err)
} else { } else {
httpx.Ok(w) httpx.OkJsonCtx(r.Context(), w, resp)
} }
} }
} }

View File

@ -20,6 +20,7 @@ func WechatCode2UserIdHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
l := wechat.NewWechatCode2UserIdLogic(r.Context(), svcCtx) l := wechat.NewWechatCode2UserIdLogic(r.Context(), svcCtx)
resp, err := l.WechatCode2UserId(&req) resp, err := l.WechatCode2UserId(&req)
if err != nil { if err != nil {
resp.Code = -1
httpx.ErrorCtx(r.Context(), w, err) httpx.ErrorCtx(r.Context(), w, err)
} else { } else {
httpx.OkJsonCtx(r.Context(), w, resp) httpx.OkJsonCtx(r.Context(), w, resp)

View File

@ -24,7 +24,8 @@ func NewAppUserSetUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Ap
} }
} }
func (l *AppUserSetUserLogic) AppUserSetUser(req *types.SetAppUserRequest) (resp *types.UserId, err error) { func (l *AppUserSetUserLogic) AppUserSetUser(req *types.SetAppUserRequest) (resp *types.Base, err error) {
resp = &types.Base{}
at, err := svc.GetCtxToken(l.ctx) at, err := svc.GetCtxToken(l.ctx)
if err != nil { if err != nil {
return return

View File

@ -2,7 +2,6 @@ package douyin
import ( import (
"context" "context"
"errors"
"github.com/golang-jwt/jwt/v4" "github.com/golang-jwt/jwt/v4"
"time" "time"
"youtu_server/game_open_api/internal/app_api_helper" "youtu_server/game_open_api/internal/app_api_helper"
@ -43,7 +42,7 @@ func (l *DouyinCode2UserIdLogic) DouyinCode2UserId(req *types.DouyinCode2UserIdR
} }
if res.Errcode != 0 { if res.Errcode != 0 {
err = errors.New(res.Errmsg) resp.Message = res.Errmsg
return return
} }

View File

@ -2,6 +2,8 @@ package game
import ( import (
"context" "context"
"errors"
"github.com/zeromicro/go-zero/core/stores/sqlc"
"youtu_server/game_open_api/model" "youtu_server/game_open_api/model"
"youtu_server/game_open_api/internal/svc" "youtu_server/game_open_api/internal/svc"
@ -24,16 +26,31 @@ func NewRankingSetScoreLogic(ctx context.Context, svcCtx *svc.ServiceContext) *R
} }
} }
func (l *RankingSetScoreLogic) RankingSetScore(req *types.SetUserGameScoreRequest) error { func (l *RankingSetScoreLogic) RankingSetScore(req *types.SetUserGameScoreRequest) (resp *types.Base, err error) {
resp = &types.Base{}
at, err := svc.GetCtxToken(l.ctx) at, err := svc.GetCtxToken(l.ctx)
if err != nil { if err != nil {
return err return
} }
oldScore, err := l.svcCtx.GameScore.FindUserScore(l.ctx, at.AppId, at.UserId)
if err != nil && !errors.Is(err, sqlc.ErrNotFound) {
return
}
if oldScore != nil && req.Score <= oldScore.Score {
return
}
if oldScore != nil {
err = l.svcCtx.GameScore.UpdateScore(l.ctx, at.AppId, at.UserId, req.Score)
} else {
_, err = l.svcCtx.GameScore.Insert(l.ctx, &model.GameScore{ _, err = l.svcCtx.GameScore.Insert(l.ctx, &model.GameScore{
AppUserId: at.UserId, AppUserId: at.UserId,
AppAccount: at.AppId, AppAccount: at.AppId,
Score: req.Score, Score: req.Score,
}) })
}
return err return
} }

View File

@ -4,9 +4,15 @@
package types package types
type Auth struct { type Auth struct {
Base
Token string `json:"token"` Token string `json:"token"`
} }
type Base struct {
Code int `json:"code"`
Message string `json:"message,omitempty"`
}
type DouyinCode2UserIdRequest struct { type DouyinCode2UserIdRequest struct {
AppId string `form:"appId"` AppId string `form:"appId"`
Code string `form:"code,optional"` Code string `form:"code,optional"`

View File

@ -2,6 +2,7 @@ package model
import ( import (
"context" "context"
"database/sql"
"errors" "errors"
"fmt" "fmt"
"github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/core/stores/cache"
@ -15,6 +16,7 @@ var _ GameScoreModel = (*customGameScoreModel)(nil)
const ( const (
cacheEcpmRankListPrefix = "cache:ecpm:game:rankList:appId:" cacheEcpmRankListPrefix = "cache:ecpm:game:rankList:appId:"
cacheEcpmUserRankPrefix = "cache:ecpm:game:userRank:userId:" cacheEcpmUserRankPrefix = "cache:ecpm:game:userRank:userId:"
cacheEcpmGameScoreAppUserIdAppAccountPrefix = "cache:ecpm:gameScore:"
) )
type ( type (
@ -24,6 +26,8 @@ type (
gameScoreModel gameScoreModel
GetRankList(ctx context.Context, appId uint64, userId uint64) ([]types.RankingData, error) GetRankList(ctx context.Context, appId uint64, userId uint64) ([]types.RankingData, error)
GetUserRank(ctx context.Context, appId uint64, userId uint64) (*types.RankingData, error) GetUserRank(ctx context.Context, appId uint64, userId uint64) (*types.RankingData, error)
FindUserScore(ctx context.Context, appId uint64, userId uint64) (*GameScore, error)
UpdateScore(ctx context.Context, appId uint64, userId uint64, score uint64) error
} }
customGameScoreModel struct { customGameScoreModel struct {
@ -92,3 +96,32 @@ WHERE
return nil, err return nil, err
} }
} }
func (m *defaultGameScoreModel) FindUserScore(ctx context.Context, appId uint64, userId uint64) (*GameScore, error) {
ecpmGameScoreAppUserIdKey := fmt.Sprintf("%sappId:%d:userId:%d", cacheEcpmGameScoreAppUserIdAppAccountPrefix, appId, userId)
var (
resp GameScore
err error
)
err = m.QueryRowCtx(ctx, &resp, ecpmGameScoreAppUserIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error {
query := fmt.Sprintf("select %s from %s where `app_user_id` = ? and app_account = ? limit 1", gameScoreRows, m.table)
return conn.QueryRowCtx(ctx, v, query, userId, appId)
})
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultGameScoreModel) UpdateScore(ctx context.Context, appId uint64, userId uint64, score uint64) error {
ecpmGameScoreAppUserIdAppAccountKey := fmt.Sprintf("%sappId:%d:userId:%d", cacheEcpmGameScoreAppUserIdAppAccountPrefix, appId, userId)
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set `score` = ? where `app_account` = ? and `app_user_id` = ?", m.table)
return conn.ExecCtx(ctx, query, score, appId, userId)
}, ecpmGameScoreAppUserIdAppAccountKey)
return err
}

View File

@ -24,7 +24,6 @@ var (
gameScoreRowsWithPlaceHolder = strings.Join(stringx.Remove(gameScoreFieldNames, "`app_user_id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?" gameScoreRowsWithPlaceHolder = strings.Join(stringx.Remove(gameScoreFieldNames, "`app_user_id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
cacheEcpmGameScoreAppUserIdPrefix = "cache:ecpm:gameScore:appUserId:" cacheEcpmGameScoreAppUserIdPrefix = "cache:ecpm:gameScore:appUserId:"
cacheEcpmGameScoreAppUserIdAppAccountPrefix = "cache:ecpm:gameScore:appUserId:appAccount:"
) )
type ( type (

View File

@ -1,6 +1,6 @@
syntax = "v1" syntax = "v1"
import "auth.api" import "common.api"
type WechatCode2UserIdRequest { type WechatCode2UserIdRequest {