ab test and notification
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
parent
b926f1aab0
commit
ddae026231
@ -11,115 +11,187 @@ import (
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
)
|
||||
|
||||
const backendRPCTimeout = 3 * time.Second
|
||||
|
||||
type backendCallMeta struct {
|
||||
AppID int
|
||||
ServerID int
|
||||
Method string
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
type backendInvoker[T any] func(ctx context.Context, client msg.BackendClient) (T, error)
|
||||
|
||||
type backendMiddleware[T any] func(meta backendCallMeta, next backendInvoker[T]) backendInvoker[T]
|
||||
|
||||
type backendCodeResponse interface {
|
||||
GetCode() int32
|
||||
GetMsg() string
|
||||
}
|
||||
|
||||
func executeBackendCall[T any](appID, serverID int, method string, invoke backendInvoker[T], middlewares ...backendMiddleware[T]) (T, error) {
|
||||
var zero T
|
||||
|
||||
serverConfig, err := util.GetServerConfig(appID, serverID)
|
||||
if err != nil {
|
||||
return zero, fmt.Errorf("failed to get server config: %w", err)
|
||||
}
|
||||
if serverConfig == nil {
|
||||
return zero, fmt.Errorf("server config not found for AppId %d and ServerId %d", appID, serverID)
|
||||
}
|
||||
addr := fmt.Sprintf("%s:%d", serverConfig.Host, serverConfig.GrpcPort)
|
||||
// TODO 测试
|
||||
//addr = ":50051"
|
||||
conn, err := grpc.NewClient(
|
||||
addr,
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
)
|
||||
if err != nil {
|
||||
return zero, fmt.Errorf("failed to connect: %w", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
meta := backendCallMeta{
|
||||
AppID: appID,
|
||||
ServerID: serverID,
|
||||
Method: method,
|
||||
Timeout: backendRPCTimeout,
|
||||
}
|
||||
|
||||
wrapped := invoke
|
||||
for index := len(middlewares) - 1; index >= 0; index-- {
|
||||
wrapped = middlewares[index](meta, wrapped)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), meta.Timeout)
|
||||
defer cancel()
|
||||
|
||||
return wrapped(ctx, msg.NewBackendClient(conn))
|
||||
}
|
||||
|
||||
func wrapRPCError[T any](meta backendCallMeta, next backendInvoker[T]) backendInvoker[T] {
|
||||
return func(ctx context.Context, client msg.BackendClient) (T, error) {
|
||||
var zero T
|
||||
resp, err := next(ctx, client)
|
||||
if err != nil {
|
||||
return zero, fmt.Errorf("%s failed: %w", meta.Method, err)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
func ensureBackendCode[T backendCodeResponse](meta backendCallMeta, next backendInvoker[T]) backendInvoker[T] {
|
||||
return func(ctx context.Context, client msg.BackendClient) (T, error) {
|
||||
var zero T
|
||||
resp, err := next(ctx, client)
|
||||
if err != nil {
|
||||
return zero, fmt.Errorf("%s failed: %w", meta.Method, err)
|
||||
}
|
||||
if resp.GetCode() != 0 {
|
||||
return zero, fmt.Errorf("%s failed with code: %d, msg: %s", meta.Method, resp.GetCode(), resp.GetMsg())
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
func OrderShipping(AppId, ServerId int, req *msg.ReqOrderShipping) error {
|
||||
ServerConfig, err := util.GetServerConfig(AppId, ServerId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get server config: %v", err)
|
||||
}
|
||||
if ServerConfig == nil {
|
||||
return fmt.Errorf("server config not found for AppId %d and ServerId %d", AppId, ServerId)
|
||||
}
|
||||
conn, err := grpc.NewClient(fmt.Sprintf("%s:%d", ServerConfig.Host, ServerConfig.GrpcPort), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
client := msg.NewBackendClient(conn)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
resp, err := client.OrderShipping(ctx, req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("OrderShipping failed: %v", err)
|
||||
}
|
||||
|
||||
if resp.GetCode() != 0 {
|
||||
return fmt.Errorf("OrderShipping failed with code: %d, msg: %s", resp.GetCode(), resp.GetMsg())
|
||||
}
|
||||
return nil
|
||||
_, err := executeBackendCall(
|
||||
AppId,
|
||||
ServerId,
|
||||
"OrderShipping",
|
||||
func(ctx context.Context, client msg.BackendClient) (*msg.ResOrderShipping, error) {
|
||||
return client.OrderShipping(ctx, req)
|
||||
},
|
||||
ensureBackendCode[*msg.ResOrderShipping],
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func ActivityCfgReload(AppId, ServerId int, req *msg.ReqActivityCfgReload) error {
|
||||
ServerConfig, err := util.GetServerConfig(AppId, ServerId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get server config: %v", err)
|
||||
}
|
||||
if ServerConfig == nil {
|
||||
return fmt.Errorf("server config not found for AppId %d and ServerId %d", AppId, ServerId)
|
||||
}
|
||||
conn, err := grpc.NewClient(fmt.Sprintf("%s:%d", ServerConfig.Host, ServerConfig.GrpcPort), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
client := msg.NewBackendClient(conn)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
resp, err := client.ReloadActivity(ctx, req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ReloadActivity failed: %v", err)
|
||||
}
|
||||
|
||||
if resp.GetCode() != 0 {
|
||||
return fmt.Errorf("ReloadActivity failed with code: %d, msg: %s", resp.GetCode(), resp.GetMsg())
|
||||
}
|
||||
return nil
|
||||
func ReloadActivity(AppId, ServerId int, req *msg.ReqActivityCfgReload) error {
|
||||
_, err := executeBackendCall(
|
||||
AppId,
|
||||
ServerId,
|
||||
"ReloadActivity",
|
||||
func(ctx context.Context, client msg.BackendClient) (*msg.ResActivityCfgReload, error) {
|
||||
return client.ReloadActivity(ctx, req)
|
||||
},
|
||||
ensureBackendCode[*msg.ResActivityCfgReload],
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func GetUserInfo(AppId, ServerId int, req *msg.UserDetailParam) (*msg.ResUserDetailInfo, error) {
|
||||
ServerConfig, err := util.GetServerConfig(AppId, ServerId)
|
||||
func UserDetail(AppId, ServerId int, req *msg.UserDetailParam) (*msg.ResUserDetailInfo, error) {
|
||||
resp, err := executeBackendCall(
|
||||
AppId,
|
||||
ServerId,
|
||||
"UserDetail",
|
||||
func(ctx context.Context, client msg.BackendClient) (*msg.ResUserDetail, error) {
|
||||
return client.UserDetail(ctx, req)
|
||||
},
|
||||
ensureBackendCode[*msg.ResUserDetail],
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get server config: %v", err)
|
||||
}
|
||||
if ServerConfig == nil {
|
||||
return nil, fmt.Errorf("server config not found for AppId %d and ServerId %d", AppId, ServerId)
|
||||
}
|
||||
conn, err := grpc.NewClient(fmt.Sprintf("%s:%d", ServerConfig.Host, ServerConfig.GrpcPort), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
// TODO : 目前先连接本地,后续改为连接对应服务器
|
||||
// conn, err := grpc.NewClient("127.0.0.1:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to connect: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
client := msg.NewBackendClient(conn)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
resp, err := client.UserDetail(ctx, req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetUserInfo failed: %v", err)
|
||||
}
|
||||
|
||||
if resp.GetCode() != 0 {
|
||||
return nil, fmt.Errorf("GetUserInfo failed with code: %d, msg: %s", resp.GetCode(), resp.GetMsg())
|
||||
return nil, err
|
||||
}
|
||||
return resp.GetInfo(), nil
|
||||
}
|
||||
|
||||
func GetServerInfo(AppId, ServerId int, req *msg.ReqServerInfo) (*msg.ResServerInfo, error) {
|
||||
ServerConfig, err := util.GetServerConfig(AppId, ServerId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get server config: %v", err)
|
||||
}
|
||||
if ServerConfig == nil {
|
||||
return nil, fmt.Errorf("server config not found for AppId %d and ServerId %d", AppId, ServerId)
|
||||
}
|
||||
conn, err := grpc.NewClient(fmt.Sprintf("%s:%d", ServerConfig.Host, ServerConfig.GrpcPort), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
// TODO : 目前先连接本地,后续改为连接对应服务器
|
||||
//conn, err := grpc.NewClient("127.0.0.1:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to connect: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
client := msg.NewBackendClient(conn)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
resp, err := client.ServerInfo(ctx, req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ServerInfo failed: %v", err)
|
||||
}
|
||||
return resp, nil
|
||||
return executeBackendCall(
|
||||
AppId,
|
||||
ServerId,
|
||||
"ServerInfo",
|
||||
func(ctx context.Context, client msg.BackendClient) (*msg.ResServerInfo, error) {
|
||||
return client.ServerInfo(ctx, req)
|
||||
},
|
||||
wrapRPCError[*msg.ResServerInfo],
|
||||
)
|
||||
}
|
||||
|
||||
func PlayerGm(AppId, ServerId int, req *msg.ReqAdminGm) (*msg.ResAdminGm, error) {
|
||||
return executeBackendCall(
|
||||
AppId,
|
||||
ServerId,
|
||||
"PlayerGm",
|
||||
func(ctx context.Context, client msg.BackendClient) (*msg.ResAdminGm, error) {
|
||||
return client.PlayerGm(ctx, req)
|
||||
},
|
||||
wrapRPCError[*msg.ResAdminGm],
|
||||
)
|
||||
}
|
||||
|
||||
func ServerReload(AppId, ServerId int, req *msg.ReqReload) (*msg.ResBackend, error) {
|
||||
return executeBackendCall(
|
||||
AppId,
|
||||
ServerId,
|
||||
"ServerReload",
|
||||
func(ctx context.Context, client msg.BackendClient) (*msg.ResBackend, error) {
|
||||
return client.ServerReload(ctx, req)
|
||||
},
|
||||
wrapRPCError[*msg.ResBackend],
|
||||
)
|
||||
}
|
||||
|
||||
func BanPlayer(AppId, ServerId int, req *msg.ReqAdminBan) (*msg.ResBackend, error) {
|
||||
return executeBackendCall(
|
||||
AppId,
|
||||
ServerId,
|
||||
"BanPlayer",
|
||||
func(ctx context.Context, client msg.BackendClient) (*msg.ResBackend, error) {
|
||||
return client.BanPlayer(ctx, req)
|
||||
},
|
||||
wrapRPCError[*msg.ResBackend],
|
||||
)
|
||||
}
|
||||
|
||||
func ReloadMail(AppId, ServerId int, req *msg.ReqReloadServerMail) (*msg.ResBackend, error) {
|
||||
return executeBackendCall(
|
||||
AppId,
|
||||
ServerId,
|
||||
"ReloadMail",
|
||||
func(ctx context.Context, client msg.BackendClient) (*msg.ResBackend, error) {
|
||||
return client.ReloadMail(ctx, req)
|
||||
},
|
||||
wrapRPCError[*msg.ResBackend],
|
||||
)
|
||||
}
|
||||
|
||||
687
controller/experiment.go
Normal file
687
controller/experiment.go
Normal file
@ -0,0 +1,687 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"backend/util"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
abtestdao "backend/sdk/abtest/dao"
|
||||
abtestmodel "backend/sdk/abtest/model"
|
||||
abtestservice "backend/sdk/abtest/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var (
|
||||
experimentServiceOnce sync.Once
|
||||
experimentService *abtestservice.Service
|
||||
experimentServiceErr error
|
||||
)
|
||||
|
||||
type experimentCreateVariantRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Description string `json:"description"`
|
||||
Weight int `json:"weight"`
|
||||
Params json.RawMessage `json:"params"`
|
||||
}
|
||||
|
||||
type experimentCreateWhitelistRequest struct {
|
||||
UserID string `json:"user_id" binding:"required"`
|
||||
VariantName string `json:"variant_name" binding:"required"`
|
||||
}
|
||||
|
||||
type experimentCreateRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Description string `json:"description"`
|
||||
StartTime string `json:"start_time"`
|
||||
EndTime string `json:"end_time"`
|
||||
Status *int `json:"status"`
|
||||
Variants []experimentCreateVariantRequest `json:"variants"`
|
||||
Whitelist []experimentCreateWhitelistRequest `json:"whitelist"`
|
||||
}
|
||||
|
||||
type optionalStringField struct {
|
||||
Set bool
|
||||
Value *string
|
||||
}
|
||||
|
||||
func (f *optionalStringField) UnmarshalJSON(data []byte) error {
|
||||
f.Set = true
|
||||
if string(data) == "null" {
|
||||
f.Value = nil
|
||||
return nil
|
||||
}
|
||||
var value string
|
||||
if err := json.Unmarshal(data, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
f.Value = &value
|
||||
return nil
|
||||
}
|
||||
|
||||
type experimentUpdateRequest struct {
|
||||
Name *string `json:"name"`
|
||||
Description *string `json:"description"`
|
||||
StartTime optionalStringField `json:"start_time"`
|
||||
EndTime optionalStringField `json:"end_time"`
|
||||
Status *int `json:"status"`
|
||||
Variants []experimentCreateVariantRequest `json:"variants"`
|
||||
Whitelist []experimentCreateWhitelistRequest `json:"whitelist"`
|
||||
}
|
||||
|
||||
func getExperimentService() (*abtestservice.Service, error) {
|
||||
experimentServiceOnce.Do(func() {
|
||||
db, err := util.ConnectMysql("log", "abtest")
|
||||
if err != nil {
|
||||
experimentServiceErr = err
|
||||
return
|
||||
}
|
||||
experimentService = abtestservice.New(abtestdao.New(db))
|
||||
})
|
||||
return experimentService, experimentServiceErr
|
||||
}
|
||||
|
||||
func ExperimentList(c *gin.Context) {
|
||||
svc, err := getExperimentService()
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
var statusPtr *int
|
||||
if statusRaw := c.Query("status"); statusRaw != "" {
|
||||
status, convErr := strconv.Atoi(statusRaw)
|
||||
if convErr != nil {
|
||||
failed(c, "invalid status")
|
||||
return
|
||||
}
|
||||
statusPtr = &status
|
||||
}
|
||||
|
||||
list, total, err := svc.ListExperiments(statusPtr, page, pageSize)
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
success(c, gin.H{"list": list, "total": total, "page": page, "page_size": pageSize})
|
||||
}
|
||||
|
||||
func ExperimentCreate(c *gin.Context) {
|
||||
svc, err := getExperimentService()
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var req experimentCreateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
result, err := createExperimentAggregate(svc, &req)
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
util.AddAdminLog(c, "创建AB实验", req)
|
||||
success(c, result)
|
||||
}
|
||||
|
||||
func createExperimentAggregate(svc *abtestservice.Service, req *experimentCreateRequest) (gin.H, error) {
|
||||
name := strings.TrimSpace(req.Name)
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("name is required")
|
||||
}
|
||||
|
||||
startTime, err := parseExperimentTime(req.StartTime)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid start_time: %w", err)
|
||||
}
|
||||
endTime, err := parseExperimentTime(req.EndTime)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid end_time: %w", err)
|
||||
}
|
||||
if startTime != nil && endTime != nil && startTime.After(*endTime) {
|
||||
return nil, fmt.Errorf("start_time must be earlier than end_time")
|
||||
}
|
||||
|
||||
experiment, err := svc.CreateExperiment(&abtestmodel.CreateExperimentReq{
|
||||
Name: name,
|
||||
Description: req.Description,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
shouldRollback := true
|
||||
defer func() {
|
||||
if shouldRollback {
|
||||
_ = svc.DeleteExperiment(experiment.ID)
|
||||
}
|
||||
}()
|
||||
|
||||
if req.Status != nil || startTime != nil || endTime != nil {
|
||||
experiment, err = svc.UpdateExperiment(experiment.ID, &abtestmodel.UpdateExperimentReq{
|
||||
Status: req.Status,
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
variants := make([]*abtestmodel.Variant, 0, len(req.Variants))
|
||||
variantsByName := make(map[string]*abtestmodel.Variant, len(req.Variants))
|
||||
for _, variantReq := range req.Variants {
|
||||
variantName := strings.TrimSpace(variantReq.Name)
|
||||
if variantName == "" {
|
||||
return nil, fmt.Errorf("variant name is required")
|
||||
}
|
||||
if _, exists := variantsByName[variantName]; exists {
|
||||
return nil, fmt.Errorf("duplicate variant name: %s", variantName)
|
||||
}
|
||||
variant, createErr := svc.CreateVariant(experiment.ID, &abtestmodel.CreateVariantReq{
|
||||
Name: variantName,
|
||||
Description: variantReq.Description,
|
||||
Weight: variantReq.Weight,
|
||||
Params: variantReq.Params,
|
||||
})
|
||||
if createErr != nil {
|
||||
return nil, createErr
|
||||
}
|
||||
variants = append(variants, variant)
|
||||
variantsByName[variant.Name] = variant
|
||||
}
|
||||
|
||||
whitelist := make([]*abtestmodel.Whitelist, 0, len(req.Whitelist))
|
||||
for _, whitelistReq := range req.Whitelist {
|
||||
userID := strings.TrimSpace(whitelistReq.UserID)
|
||||
variantName := strings.TrimSpace(whitelistReq.VariantName)
|
||||
if userID == "" {
|
||||
return nil, fmt.Errorf("whitelist user_id is required")
|
||||
}
|
||||
variant, exists := variantsByName[variantName]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("whitelist variant_name not found: %s", variantName)
|
||||
}
|
||||
entry, addErr := svc.AddWhitelist(experiment.ID, &abtestmodel.CreateWhitelistReq{
|
||||
UserID: userID,
|
||||
VariantID: variant.ID,
|
||||
})
|
||||
if addErr != nil {
|
||||
return nil, addErr
|
||||
}
|
||||
whitelist = append(whitelist, entry)
|
||||
}
|
||||
|
||||
shouldRollback = false
|
||||
return gin.H{
|
||||
"experiment": experiment,
|
||||
"variants": variants,
|
||||
"whitelist": whitelist,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseExperimentTime(raw string) (*time.Time, error) {
|
||||
raw = strings.TrimSpace(raw)
|
||||
if raw == "" {
|
||||
return nil, nil
|
||||
}
|
||||
layouts := []string{
|
||||
"2006-01-02 15:04:05",
|
||||
time.RFC3339,
|
||||
"2006-01-02T15:04:05",
|
||||
}
|
||||
for _, layout := range layouts {
|
||||
parsed, err := time.ParseInLocation(layout, raw, time.Local)
|
||||
if err == nil {
|
||||
return &parsed, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported time format")
|
||||
}
|
||||
|
||||
func ExperimentUpdate(c *gin.Context) {
|
||||
svc, err := getExperimentService()
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
failed(c, "invalid id")
|
||||
return
|
||||
}
|
||||
|
||||
var req experimentUpdateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
experiment, err := updateExperimentAggregate(svc, id, &req)
|
||||
if err != nil {
|
||||
status := http.StatusBadRequest
|
||||
if err == abtestservice.ErrExperimentNotFound {
|
||||
status = http.StatusNotFound
|
||||
}
|
||||
c.JSON(status, gin.H{"code": 1, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
util.AddAdminLog(c, "更新AB实验", gin.H{"id": id, "payload": req})
|
||||
success(c, experiment)
|
||||
}
|
||||
|
||||
func updateExperimentAggregate(svc *abtestservice.Service, experimentID int64, req *experimentUpdateRequest) (*abtestmodel.Experiment, error) {
|
||||
if _, err := svc.GetExperiment(experimentID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
updateReq := &abtestmodel.UpdateExperimentReq{
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
Status: req.Status,
|
||||
}
|
||||
|
||||
if req.StartTime.Set {
|
||||
if req.StartTime.Value == nil {
|
||||
updateReq.ClearStartTime = true
|
||||
} else {
|
||||
parsed, err := parseExperimentTime(*req.StartTime.Value)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid start_time: %w", err)
|
||||
}
|
||||
updateReq.StartTime = parsed
|
||||
}
|
||||
}
|
||||
if req.EndTime.Set {
|
||||
if req.EndTime.Value == nil {
|
||||
updateReq.ClearEndTime = true
|
||||
} else {
|
||||
parsed, err := parseExperimentTime(*req.EndTime.Value)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid end_time: %w", err)
|
||||
}
|
||||
updateReq.EndTime = parsed
|
||||
}
|
||||
}
|
||||
if updateReq.StartTime != nil && updateReq.EndTime != nil && updateReq.StartTime.After(*updateReq.EndTime) {
|
||||
return nil, fmt.Errorf("start_time must be earlier than end_time")
|
||||
}
|
||||
|
||||
experiment, err := svc.UpdateExperiment(experimentID, updateReq)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
variantsProvided := req.Variants != nil
|
||||
whitelistProvided := req.Whitelist != nil
|
||||
if !variantsProvided && !whitelistProvided {
|
||||
return experiment, nil
|
||||
}
|
||||
|
||||
var variants []*abtestmodel.Variant
|
||||
variantsByName := make(map[string]*abtestmodel.Variant)
|
||||
|
||||
if variantsProvided {
|
||||
if err := svc.ResetExperimentRelations(experimentID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, variantReq := range req.Variants {
|
||||
variantName := strings.TrimSpace(variantReq.Name)
|
||||
if variantName == "" {
|
||||
return nil, fmt.Errorf("variant name is required")
|
||||
}
|
||||
if _, exists := variantsByName[variantName]; exists {
|
||||
return nil, fmt.Errorf("duplicate variant name: %s", variantName)
|
||||
}
|
||||
variant, createErr := svc.CreateVariant(experimentID, &abtestmodel.CreateVariantReq{
|
||||
Name: variantName,
|
||||
Description: variantReq.Description,
|
||||
Weight: variantReq.Weight,
|
||||
Params: variantReq.Params,
|
||||
})
|
||||
if createErr != nil {
|
||||
return nil, createErr
|
||||
}
|
||||
variants = append(variants, variant)
|
||||
variantsByName[variant.Name] = variant
|
||||
}
|
||||
} else if whitelistProvided {
|
||||
variants, err = svc.ListVariants(experimentID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, variant := range variants {
|
||||
variantsByName[variant.Name] = variant
|
||||
}
|
||||
if err := svc.ClearWhitelist(experimentID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if whitelistProvided {
|
||||
for _, whitelistReq := range req.Whitelist {
|
||||
userID := strings.TrimSpace(whitelistReq.UserID)
|
||||
variantName := strings.TrimSpace(whitelistReq.VariantName)
|
||||
if userID == "" {
|
||||
return nil, fmt.Errorf("whitelist user_id is required")
|
||||
}
|
||||
variant, exists := variantsByName[variantName]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("whitelist variant_name not found: %s", variantName)
|
||||
}
|
||||
if _, err := svc.AddWhitelist(experimentID, &abtestmodel.CreateWhitelistReq{
|
||||
UserID: userID,
|
||||
VariantID: variant.ID,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return svc.GetExperiment(experimentID)
|
||||
}
|
||||
|
||||
func ExperimentDelete(c *gin.Context) {
|
||||
svc, err := getExperimentService()
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
failed(c, "invalid id")
|
||||
return
|
||||
}
|
||||
|
||||
if err := svc.DeleteExperiment(id); err != nil {
|
||||
status := http.StatusBadRequest
|
||||
if err == abtestservice.ErrExperimentNotFound {
|
||||
status = http.StatusNotFound
|
||||
}
|
||||
c.JSON(status, gin.H{"code": 1, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
util.AddAdminLog(c, "删除AB实验", gin.H{"id": id})
|
||||
success(c, nil)
|
||||
}
|
||||
|
||||
func ExperimentVariantList(c *gin.Context) {
|
||||
svc, err := getExperimentService()
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
failed(c, "invalid id")
|
||||
return
|
||||
}
|
||||
|
||||
list, err := svc.ListVariants(id)
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
success(c, list)
|
||||
}
|
||||
|
||||
func ExperimentVariantCreate(c *gin.Context) {
|
||||
svc, err := getExperimentService()
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
failed(c, "invalid id")
|
||||
return
|
||||
}
|
||||
|
||||
var req abtestmodel.CreateVariantReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
variant, err := svc.CreateVariant(id, &req)
|
||||
if err != nil {
|
||||
status := http.StatusBadRequest
|
||||
if err == abtestservice.ErrExperimentNotFound {
|
||||
status = http.StatusNotFound
|
||||
}
|
||||
c.JSON(status, gin.H{"code": 1, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
util.AddAdminLog(c, "创建AB实验变体", gin.H{"experiment_id": id, "payload": req})
|
||||
success(c, variant)
|
||||
}
|
||||
|
||||
func ExperimentVariantUpdate(c *gin.Context) {
|
||||
svc, err := getExperimentService()
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
variantID, err := strconv.ParseInt(c.Param("variantId"), 10, 64)
|
||||
if err != nil {
|
||||
failed(c, "invalid variantId")
|
||||
return
|
||||
}
|
||||
|
||||
var req abtestmodel.UpdateVariantReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
variant, err := svc.UpdateVariant(variantID, &req)
|
||||
if err != nil {
|
||||
status := http.StatusBadRequest
|
||||
if err == abtestservice.ErrVariantNotFound {
|
||||
status = http.StatusNotFound
|
||||
}
|
||||
c.JSON(status, gin.H{"code": 1, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
util.AddAdminLog(c, "更新AB实验变体", gin.H{"variant_id": variantID, "payload": req})
|
||||
success(c, variant)
|
||||
}
|
||||
|
||||
func ExperimentVariantDelete(c *gin.Context) {
|
||||
svc, err := getExperimentService()
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
variantID, err := strconv.ParseInt(c.Param("variantId"), 10, 64)
|
||||
if err != nil {
|
||||
failed(c, "invalid variantId")
|
||||
return
|
||||
}
|
||||
|
||||
if err := svc.DeleteVariant(variantID); err != nil {
|
||||
status := http.StatusBadRequest
|
||||
if err == abtestservice.ErrVariantNotFound {
|
||||
status = http.StatusNotFound
|
||||
}
|
||||
c.JSON(status, gin.H{"code": 1, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
util.AddAdminLog(c, "删除AB实验变体", gin.H{"variant_id": variantID})
|
||||
success(c, nil)
|
||||
}
|
||||
|
||||
func ExperimentWhitelistList(c *gin.Context) {
|
||||
svc, err := getExperimentService()
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
failed(c, "invalid id")
|
||||
return
|
||||
}
|
||||
|
||||
list, err := svc.ListWhitelist(id)
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
success(c, list)
|
||||
}
|
||||
|
||||
func ExperimentWhitelistCreate(c *gin.Context) {
|
||||
svc, err := getExperimentService()
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
failed(c, "invalid id")
|
||||
return
|
||||
}
|
||||
|
||||
var req abtestmodel.CreateWhitelistReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
entry, err := svc.AddWhitelist(id, &req)
|
||||
if err != nil {
|
||||
status := http.StatusBadRequest
|
||||
if err == abtestservice.ErrExperimentNotFound || err == abtestservice.ErrVariantNotFound {
|
||||
status = http.StatusNotFound
|
||||
}
|
||||
c.JSON(status, gin.H{"code": 1, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
util.AddAdminLog(c, "新增AB白名单", gin.H{"experiment_id": id, "payload": req})
|
||||
success(c, entry)
|
||||
}
|
||||
|
||||
func ExperimentWhitelistBatchCreate(c *gin.Context) {
|
||||
svc, err := getExperimentService()
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
failed(c, "invalid id")
|
||||
return
|
||||
}
|
||||
|
||||
var req abtestmodel.BatchCreateWhitelistReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
list, err := svc.BatchAddWhitelist(id, &req)
|
||||
if err != nil {
|
||||
status := http.StatusBadRequest
|
||||
if err == abtestservice.ErrExperimentNotFound || err == abtestservice.ErrVariantNotFound {
|
||||
status = http.StatusNotFound
|
||||
}
|
||||
c.JSON(status, gin.H{"code": 1, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
util.AddAdminLog(c, "批量新增AB白名单", gin.H{"experiment_id": id, "payload": req})
|
||||
success(c, list)
|
||||
}
|
||||
|
||||
func ExperimentWhitelistDelete(c *gin.Context) {
|
||||
svc, err := getExperimentService()
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
failed(c, "invalid id")
|
||||
return
|
||||
}
|
||||
|
||||
userID := c.Param("userId")
|
||||
if userID == "" {
|
||||
failed(c, "invalid userId")
|
||||
return
|
||||
}
|
||||
|
||||
if err := svc.RemoveWhitelist(id, userID); err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
util.AddAdminLog(c, "删除AB白名单", gin.H{"experiment_id": id, "user_id": userID})
|
||||
success(c, nil)
|
||||
}
|
||||
|
||||
func ExperimentResult(c *gin.Context) {
|
||||
svc, err := getExperimentService()
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
failed(c, "invalid id")
|
||||
return
|
||||
}
|
||||
|
||||
result, err := svc.GetExperimentResult(id)
|
||||
if err != nil {
|
||||
status := http.StatusBadRequest
|
||||
if err == abtestservice.ErrExperimentNotFound {
|
||||
status = http.StatusNotFound
|
||||
}
|
||||
c.JSON(status, gin.H{"code": 1, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
success(c, result)
|
||||
}
|
||||
|
||||
func UserExperimentGroups(c *gin.Context) {
|
||||
svc, err := getExperimentService()
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
userID := strings.TrimSpace(c.Param("userId"))
|
||||
if userID == "" {
|
||||
failed(c, "invalid userId")
|
||||
return
|
||||
}
|
||||
|
||||
groups, err := svc.GetUserGroups(userID)
|
||||
if err != nil {
|
||||
failed(c, err.Error())
|
||||
return
|
||||
}
|
||||
success(c, groups)
|
||||
}
|
||||
48
controller/notification.go
Normal file
48
controller/notification.go
Normal file
@ -0,0 +1,48 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"backend/middleware/alibaba"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const notificationTemplatePath = `D:\Github\common\sdk\tuyou\notification.json`
|
||||
|
||||
type notificationConfigUpdateRequest struct {
|
||||
Config string `json:"config" binding:"required"`
|
||||
}
|
||||
|
||||
func NotificationConfigGet(c *gin.Context) {
|
||||
ossConfig, err := alibaba.GetNotificationConfig()
|
||||
if err != nil {
|
||||
failed(c, "获取通知配置失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
success(c, gin.H{
|
||||
"config": ossConfig.Config,
|
||||
"updated_at": ossConfig.LastModified,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func NotificationConfigSave(c *gin.Context) {
|
||||
var req notificationConfigUpdateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
failed(c, "Invalid input: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
raw := strings.TrimSpace(req.Config)
|
||||
if raw == "" {
|
||||
failed(c, "config is required")
|
||||
return
|
||||
}
|
||||
|
||||
alibaba.Osscreate(req.Config)
|
||||
|
||||
success(c, gin.H{
|
||||
"code": 0,
|
||||
})
|
||||
}
|
||||
@ -390,4 +390,7 @@ func ClientImageGitPull(c *gin.Context) {
|
||||
scritp_fail(c, "执行更新翻译图标失败: "+err.Error()+": "+output)
|
||||
return
|
||||
}
|
||||
success(c, map[string]interface{}{
|
||||
"code": 0,
|
||||
})
|
||||
}
|
||||
|
||||
54
go.mod
54
go.mod
@ -4,6 +4,7 @@ go 1.25.5
|
||||
|
||||
require (
|
||||
github.com/Ullaakut/nmap v2.0.2+incompatible
|
||||
github.com/abtest v0.0.0
|
||||
github.com/alibabacloud-go/cloudauth-20190307/v4 v4.9.2
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.9
|
||||
github.com/alibabacloud-go/dingtalk v1.6.97
|
||||
@ -13,8 +14,8 @@ require (
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.7
|
||||
github.com/aliyun/credentials-go v1.4.6
|
||||
github.com/elastic/go-elasticsearch/v8 v8.19.1
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/gin-gonic/gin v1.12.0
|
||||
github.com/go-sql-driver/mysql v1.9.3
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/jmoiron/sqlx v1.4.0
|
||||
@ -25,18 +26,24 @@ require (
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/xuri/excelize/v2 v2.10.0
|
||||
go.etcd.io/bbolt v1.4.3
|
||||
golang.org/x/crypto v0.46.0
|
||||
golang.org/x/crypto v0.48.0
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c // indirect
|
||||
google.golang.org/grpc v1.67.3
|
||||
google.golang.org/protobuf v1.36.11
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
require github.com/nacos-group/nacos-sdk-go/v2 v2.3.5
|
||||
require (
|
||||
gitea.bywaystudios.com/pet_home/nacos v0.0.0-20260422063809-d6268b6aa6e3
|
||||
github.com/aliyun/alibabacloud-oss-go-sdk-v2 v1.4.1
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/nacos-group/nacos-sdk-go/v2 v2.3.5
|
||||
)
|
||||
|
||||
replace github.com/abtest => ./sdk/abtest
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
gitea.bywaystudios.com/pet_home/nacos v0.0.0-20260422063809-d6268b6aa6e3 // indirect
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6 // indirect
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect
|
||||
github.com/alibabacloud-go/darabonba-array v0.1.0 // indirect
|
||||
@ -58,34 +65,33 @@ require (
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1800 // indirect
|
||||
github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.5.1 // indirect
|
||||
github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.8 // indirect
|
||||
github.com/aliyun/alibabacloud-oss-go-sdk-v2 v1.4.1 // indirect
|
||||
github.com/aliyun/aliyun-secretsmanager-client-go v1.1.5 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/bytedance/sonic v1.11.6 // indirect
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/bytedance/gopkg v0.1.3 // indirect
|
||||
github.com/bytedance/sonic v1.15.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.5.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||
github.com/deckarep/golang-set v1.7.1 // indirect
|
||||
github.com/elastic/elastic-transport-go/v8 v8.8.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
|
||||
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/go-playground/validator/v10 v10.30.1 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/goccy/go-yaml v1.19.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
|
||||
github.com/joho/godotenv v1.5.1 // indirect
|
||||
github.com/jonboulle/clockwork v0.5.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/lestrrat-go/strftime v1.1.1 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
@ -94,20 +100,23 @@ require (
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/orcaman/concurrent-map v0.0.0-20210501183033-44dafcb38ecc // indirect
|
||||
github.com/oschwald/maxminddb-golang v1.13.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus/client_golang v1.12.2 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/quic-go/qpack v0.6.0 // indirect
|
||||
github.com/quic-go/quic-go v0.59.0 // indirect
|
||||
github.com/richardlehane/mscfb v1.0.4 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.4 // indirect
|
||||
github.com/tiendc/go-deepcopy v1.7.1 // indirect
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/ugorji/go/codec v1.3.1 // indirect
|
||||
github.com/xuri/efp v0.0.1 // indirect
|
||||
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/otel v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.39.0 // indirect
|
||||
@ -115,13 +124,12 @@ require (
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
go.uber.org/zap v1.21.0 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/net v0.48.0 // indirect
|
||||
golang.org/x/arch v0.22.0 // indirect
|
||||
golang.org/x/net v0.51.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.39.0 // indirect
|
||||
golang.org/x/text v0.32.0 // indirect
|
||||
golang.org/x/sys v0.41.0 // indirect
|
||||
golang.org/x/text v0.34.0 // indirect
|
||||
golang.org/x/time v0.4.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
95
go.sum
95
go.sum
@ -146,10 +146,12 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
|
||||
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
||||
github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE=
|
||||
github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k=
|
||||
github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE=
|
||||
github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
@ -162,10 +164,8 @@ github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn
|
||||
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
|
||||
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
|
||||
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
@ -180,12 +180,12 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
|
||||
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
||||
github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8=
|
||||
github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@ -206,13 +206,16 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
|
||||
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w=
|
||||
github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
|
||||
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
|
||||
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
@ -307,10 +310,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
@ -359,8 +360,8 @@ github.com/oschwald/geoip2-golang v1.13.0 h1:Q44/Ldc703pasJeP5V9+aFSZFmBN7DKHbNs
|
||||
github.com/oschwald/geoip2-golang v1.13.0/go.mod h1:P9zG+54KPEFOliZ29i7SeYZ/GM6tfEL+rgSn03hYuUo=
|
||||
github.com/oschwald/maxminddb-golang v1.13.0 h1:R8xBorY71s84yO06NgTmQvqvTvlS/bnYZrrWX1MElnU=
|
||||
github.com/oschwald/maxminddb-golang v1.13.0/go.mod h1:BU0z8BfFVhi1LQaonTwwGQlsHUEu9pWNdMfmq4ztm0o=
|
||||
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.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@ -389,6 +390,10 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
||||
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
|
||||
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
|
||||
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
@ -418,9 +423,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/tiendc/go-deepcopy v1.7.1 h1:LnubftI6nYaaMOcaz0LphzwraqN8jiWTwm416sitff4=
|
||||
@ -430,8 +434,8 @@ github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
|
||||
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||
github.com/xuri/efp v0.0.1 h1:fws5Rv3myXyYni8uwj2qKjVaRP30PdjeYe2Y6FDsCL8=
|
||||
github.com/xuri/efp v0.0.1/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
||||
github.com/xuri/excelize/v2 v2.10.0 h1:8aKsP7JD39iKLc6dH5Tw3dgV3sPRh8uRVXu/fMstfW4=
|
||||
@ -447,6 +451,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
|
||||
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
@ -466,13 +472,14 @@ go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
|
||||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI=
|
||||
golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
@ -491,8 +498,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@ -576,8 +583,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
||||
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@ -656,8 +663,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@ -671,8 +678,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
|
||||
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
|
||||
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
|
||||
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
|
||||
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -687,14 +694,12 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
|
||||
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY=
|
||||
golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -866,8 +871,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
|
||||
26
main.go
26
main.go
@ -106,6 +106,26 @@ func main() {
|
||||
alibabaApi.POST("/game/notify", controller.AlibabaGameNotify) // 游戏报警
|
||||
alibabaApi.POST("/notify/order", controller.AlibabaNotifyOrder) // 订单通知
|
||||
}
|
||||
abtestApi := r.Group("/api/v1", middleware.ValidateToken())
|
||||
{
|
||||
experiments := abtestApi.Group("/experiments")
|
||||
{
|
||||
experiments.GET("", controller.ExperimentList)
|
||||
experiments.POST("", controller.ExperimentCreate)
|
||||
experiments.PUT("/:id", controller.ExperimentUpdate)
|
||||
experiments.DELETE("/:id", controller.ExperimentDelete)
|
||||
experiments.GET("/:id/variants", controller.ExperimentVariantList)
|
||||
experiments.POST("/:id/variants", controller.ExperimentVariantCreate)
|
||||
experiments.PUT("/:id/variants/:variantId", controller.ExperimentVariantUpdate)
|
||||
experiments.DELETE("/:id/variants/:variantId", controller.ExperimentVariantDelete)
|
||||
experiments.GET("/:id/whitelist", controller.ExperimentWhitelistList)
|
||||
experiments.POST("/:id/whitelist", controller.ExperimentWhitelistCreate)
|
||||
experiments.POST("/:id/whitelist/batch", controller.ExperimentWhitelistBatchCreate)
|
||||
experiments.DELETE("/:id/whitelist/:userId", controller.ExperimentWhitelistDelete)
|
||||
experiments.GET("/:id/results", controller.ExperimentResult)
|
||||
}
|
||||
abtestApi.GET("/users/:userId/groups", controller.UserExperimentGroups)
|
||||
}
|
||||
api := r.Group("/api", middleware.ValidateToken())
|
||||
{
|
||||
// 账号管理
|
||||
@ -164,8 +184,10 @@ func main() {
|
||||
api.POST("/language/list", controller.Language)
|
||||
api.POST("/language/export", controller.LanguageExport)
|
||||
api.POST("/language/save", controller.LanguageSave)
|
||||
api.POST("language/add", controller.LanguageAdd)
|
||||
api.POST("language/delete", controller.LanguageDelete)
|
||||
api.POST("/language/add", controller.LanguageAdd)
|
||||
api.POST("/language/delete", controller.LanguageDelete)
|
||||
api.GET("/config/notification", controller.NotificationConfigGet)
|
||||
api.PUT("/config/notification/update", controller.NotificationConfigSave)
|
||||
|
||||
}
|
||||
// 自动化脚本
|
||||
|
||||
@ -1,26 +1,25 @@
|
||||
package alibaba
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/nacos"
|
||||
|
||||
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
|
||||
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultOSSRegion = "cn-hangzhou"
|
||||
defaultOSSBucket = "merge-pet-elastic"
|
||||
defaultOSSObjectKey = "example-object.txt"
|
||||
defaultOSSRegion = "us-west-1"
|
||||
defaultOSSBucket = "merge-pet-us"
|
||||
defaultOSSObjectKey = "static/notification.json"
|
||||
defaultNacosDataID = "oss.json"
|
||||
defaultNacosGroup = "server"
|
||||
defaultNacosLogDir = "./log/nacos"
|
||||
@ -45,9 +44,20 @@ var (
|
||||
globalOSSRuntime ossRuntime
|
||||
ossInitOnce sync.Once
|
||||
dotenvLoadOnce sync.Once
|
||||
ossCnf ossConfig
|
||||
)
|
||||
|
||||
func Osscreate() {
|
||||
type OSSObjectContent struct {
|
||||
Bucket string `json:"bucket"`
|
||||
Key string `json:"key"`
|
||||
Region string `json:"region"`
|
||||
Config map[string]interface{} `json:"config"`
|
||||
ContentType string `json:"contentType,omitempty"`
|
||||
ETag string `json:"etag,omitempty"`
|
||||
LastModified string `json:"lastModified,omitempty"`
|
||||
}
|
||||
|
||||
func Osscreate(content string) {
|
||||
config, err := initOSSConfig()
|
||||
if err != nil {
|
||||
log.Fatalf("加载 OSS 配置失败: %v", err)
|
||||
@ -59,7 +69,7 @@ func Osscreate() {
|
||||
|
||||
client := oss.NewClient(cfg)
|
||||
|
||||
body := strings.NewReader("Hello OSS from Go SDK V2!")
|
||||
body := strings.NewReader(content)
|
||||
|
||||
request := &oss.PutObjectRequest{
|
||||
Bucket: oss.Ptr(config.Bucket),
|
||||
@ -75,225 +85,95 @@ func Osscreate() {
|
||||
log.Printf("上传成功! ETag: %s\n", *result.ETag)
|
||||
}
|
||||
|
||||
func initOSSConfig() (ossConfig, error) {
|
||||
loadDotEnv()
|
||||
|
||||
var initErr error
|
||||
ossInitOnce.Do(func() {
|
||||
config, err := loadOSSConfig()
|
||||
if err != nil {
|
||||
initErr = err
|
||||
return
|
||||
}
|
||||
globalOSSRuntime.set(config)
|
||||
|
||||
if err := watchOSSConfigChanges(); err != nil {
|
||||
log.Printf("监听 Nacos OSS 配置失败,继续使用当前配置: %v", err)
|
||||
}
|
||||
})
|
||||
if initErr != nil {
|
||||
return ossConfig{}, initErr
|
||||
}
|
||||
|
||||
config, ok := globalOSSRuntime.get()
|
||||
if !ok {
|
||||
return ossConfig{}, fmt.Errorf("oss config is not initialized")
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func loadDotEnv() {
|
||||
dotenvLoadOnce.Do(func() {
|
||||
if err := godotenv.Load(); err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
log.Printf("加载 .env 失败,继续使用现有环境变量: %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func loadOSSConfig() (ossConfig, error) {
|
||||
baseConfig := loadOSSConfigFromEnv()
|
||||
config := baseConfig
|
||||
|
||||
nacosConfig, err := loadOSSConfigFromNacos()
|
||||
func GetNotificationConfig() (*OSSObjectContent, error) {
|
||||
config, err := initOSSConfig()
|
||||
if err != nil {
|
||||
log.Printf("从 Nacos 读取 OSS 配置失败,回退环境变量: %v", err)
|
||||
return nil, fmt.Errorf("加载 OSS 配置失败: %w", err)
|
||||
}
|
||||
|
||||
cfg := oss.LoadDefaultConfig().
|
||||
WithCredentialsProvider(credentials.NewStaticCredentialsProvider(config.AccessKeyID, config.AccessKeySecret, config.SessionToken)).
|
||||
WithRegion(config.Region)
|
||||
|
||||
client := oss.NewClient(cfg)
|
||||
|
||||
request := &oss.GetObjectRequest{
|
||||
Bucket: oss.Ptr(config.Bucket),
|
||||
Key: oss.Ptr(config.ObjectKey),
|
||||
}
|
||||
|
||||
result, err := client.GetObject(context.TODO(), request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取 OSS 文件失败: %w", err)
|
||||
}
|
||||
defer result.Body.Close()
|
||||
body, err := io.ReadAll(result.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("读取 OSS 文件内容失败: %w", err)
|
||||
}
|
||||
|
||||
content := bytes.TrimSpace(body)
|
||||
log.Printf("获取 OSS 文件成功: bucket=%s key=%s size=%d", config.Bucket, config.ObjectKey, len(content))
|
||||
var data map[string]interface{}
|
||||
if err := json.Unmarshal(content, &data); err != nil {
|
||||
log.Printf("解析 OSS 文件内容失败: %v", err)
|
||||
} else {
|
||||
config = mergeOSSConfig(baseConfig, nacosConfig)
|
||||
log.Printf("OSS 文件内容解析成功: %v", data)
|
||||
}
|
||||
|
||||
return normalizeOSSConfig(config)
|
||||
response := &OSSObjectContent{
|
||||
Bucket: config.Bucket,
|
||||
Key: config.ObjectKey,
|
||||
Region: config.Region,
|
||||
Config: data,
|
||||
}
|
||||
if result.ContentType != nil {
|
||||
response.ContentType = *result.ContentType
|
||||
}
|
||||
if result.ETag != nil {
|
||||
response.ETag = *result.ETag
|
||||
}
|
||||
if result.LastModified != nil {
|
||||
response.LastModified = result.LastModified.Format(time.RFC3339)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func loadOSSConfigFromEnv() ossConfig {
|
||||
return ossConfig{
|
||||
Region: strings.TrimSpace(os.Getenv("OSS_REGION")),
|
||||
Bucket: strings.TrimSpace(os.Getenv("OSS_BUCKET")),
|
||||
ObjectKey: strings.TrimSpace(os.Getenv("OSS_OBJECT_KEY")),
|
||||
AccessKeyID: strings.TrimSpace(os.Getenv("OSS_ACCESS_KEY_ID")),
|
||||
AccessKeySecret: strings.TrimSpace(os.Getenv("OSS_ACCESS_KEY_SECRET")),
|
||||
SessionToken: strings.TrimSpace(os.Getenv("OSS_SESSION_TOKEN")),
|
||||
}
|
||||
}
|
||||
|
||||
func loadOSSConfigFromNacos() (ossConfig, error) {
|
||||
client, err := newNacosClient()
|
||||
if err != nil {
|
||||
return ossConfig{}, err
|
||||
}
|
||||
|
||||
var config ossConfig
|
||||
dataID := getEnvOrDefault("OSS_NACOS_DATA_ID", defaultNacosDataID)
|
||||
group := getEnvOrDefault("OSS_NACOS_GROUP", getEnvOrDefault("NACOS_GROUP", defaultNacosGroup))
|
||||
if err := client.GetJSON(dataID, group, &config); err != nil {
|
||||
return ossConfig{}, err
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func watchOSSConfigChanges() error {
|
||||
client, err := newNacosClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataID := getEnvOrDefault("OSS_NACOS_DATA_ID", defaultNacosDataID)
|
||||
group := getEnvOrDefault("OSS_NACOS_GROUP", getEnvOrDefault("NACOS_GROUP", defaultNacosGroup))
|
||||
return client.Listen(dataID, group, func(event nacos.ChangeEvent) {
|
||||
var nacosConfig ossConfig
|
||||
if err := json.Unmarshal([]byte(event.Content), &nacosConfig); err != nil {
|
||||
log.Printf("解析 Nacos OSS 配置变更失败: %v", err)
|
||||
return
|
||||
func initOSSConfig() (ossConfig, error) {
|
||||
ossInitOnce.Do(func() {
|
||||
nacosClient, err := nacos.GetNacosClient()
|
||||
ossCnf = ossConfig{
|
||||
Region: defaultOSSRegion,
|
||||
Bucket: defaultOSSBucket,
|
||||
ObjectKey: defaultOSSObjectKey,
|
||||
}
|
||||
|
||||
mergedConfig, err := normalizeOSSConfig(mergeOSSConfig(loadOSSConfigFromEnv(), nacosConfig))
|
||||
if err != nil {
|
||||
log.Printf("Nacos OSS 配置变更无效,保留旧配置: %v", err)
|
||||
log.Printf("创建 Nacos 客户端失败: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
globalOSSRuntime.set(mergedConfig)
|
||||
log.Printf("OSS 配置已从 Nacos 热更新: group=%s dataId=%s", event.Group, event.DataID)
|
||||
})
|
||||
}
|
||||
|
||||
func newNacosClient() (*nacos.Client, error) {
|
||||
serverAddrs := strings.TrimSpace(os.Getenv("NACOS_SERVER_ADDRS"))
|
||||
if serverAddrs == "" {
|
||||
return nil, fmt.Errorf("NACOS_SERVER_ADDRS is empty")
|
||||
}
|
||||
|
||||
return nacos.NewClient(nacos.Options{
|
||||
Servers: parseNacosServers(serverAddrs),
|
||||
Username: strings.TrimSpace(os.Getenv("NACOS_USERNAME")),
|
||||
Password: strings.TrimSpace(os.Getenv("NACOS_PASSWORD")),
|
||||
NamespaceID: strings.TrimSpace(os.Getenv("NACOS_NAMESPACE_ID")),
|
||||
TimeoutMs: parseUintEnv("NACOS_TIMEOUT_MS", 5000),
|
||||
LogDir: getEnvOrDefault("NACOS_LOG_DIR", defaultNacosLogDir),
|
||||
CacheDir: getEnvOrDefault("NACOS_CACHE_DIR", defaultNacosCacheDir),
|
||||
LogLevel: getEnvOrDefault("NACOS_LOG_LEVEL", "info"),
|
||||
NotLoadCacheAtStart: true,
|
||||
DefaultGroup: getEnvOrDefault("NACOS_GROUP", defaultNacosGroup),
|
||||
})
|
||||
}
|
||||
|
||||
func normalizeOSSConfig(config ossConfig) (ossConfig, error) {
|
||||
if strings.TrimSpace(config.Region) == "" {
|
||||
config.Region = defaultOSSRegion
|
||||
}
|
||||
if strings.TrimSpace(config.Bucket) == "" {
|
||||
config.Bucket = defaultOSSBucket
|
||||
}
|
||||
if strings.TrimSpace(config.ObjectKey) == "" {
|
||||
config.ObjectKey = defaultOSSObjectKey
|
||||
}
|
||||
if strings.TrimSpace(config.AccessKeyID) == "" || strings.TrimSpace(config.AccessKeySecret) == "" {
|
||||
return ossConfig{}, fmt.Errorf("oss access key is empty after nacos and environment fallback")
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func mergeOSSConfig(base ossConfig, override ossConfig) ossConfig {
|
||||
if strings.TrimSpace(override.Region) != "" {
|
||||
base.Region = strings.TrimSpace(override.Region)
|
||||
}
|
||||
if strings.TrimSpace(override.Bucket) != "" {
|
||||
base.Bucket = strings.TrimSpace(override.Bucket)
|
||||
}
|
||||
if strings.TrimSpace(override.ObjectKey) != "" {
|
||||
base.ObjectKey = strings.TrimSpace(override.ObjectKey)
|
||||
}
|
||||
if strings.TrimSpace(override.AccessKeyID) != "" {
|
||||
base.AccessKeyID = strings.TrimSpace(override.AccessKeyID)
|
||||
}
|
||||
if strings.TrimSpace(override.AccessKeySecret) != "" {
|
||||
base.AccessKeySecret = strings.TrimSpace(override.AccessKeySecret)
|
||||
}
|
||||
if strings.TrimSpace(override.SessionToken) != "" {
|
||||
base.SessionToken = strings.TrimSpace(override.SessionToken)
|
||||
}
|
||||
return base
|
||||
}
|
||||
|
||||
func parseNacosServers(raw string) []nacos.Server {
|
||||
parts := strings.Split(raw, ",")
|
||||
servers := make([]nacos.Server, 0, len(parts))
|
||||
for _, part := range parts {
|
||||
item := strings.TrimSpace(part)
|
||||
if item == "" {
|
||||
continue
|
||||
err = nacosClient.GetJSON(defaultNacosDataID, defaultNacosGroup, &ossCnf)
|
||||
if err != nil {
|
||||
log.Printf("从 Nacos 获取 OSS 配置失败: %v", err)
|
||||
}
|
||||
|
||||
server := nacos.Server{IPAddr: item}
|
||||
if strings.Contains(item, ":") {
|
||||
host, port, found := strings.Cut(item, ":")
|
||||
if found {
|
||||
server.IPAddr = strings.TrimSpace(host)
|
||||
if parsedPort, convErr := strconv.ParseUint(strings.TrimSpace(port), 10, 64); convErr == nil {
|
||||
server.Port = parsedPort
|
||||
}
|
||||
} else {
|
||||
server.IPAddr = item
|
||||
if ossCnf.Region == "" {
|
||||
ossCnf.Region = defaultOSSRegion
|
||||
}
|
||||
if ossCnf.Bucket == "" {
|
||||
ossCnf.Bucket = defaultOSSBucket
|
||||
}
|
||||
if ossCnf.ObjectKey == "" {
|
||||
ossCnf.ObjectKey = defaultOSSObjectKey
|
||||
}
|
||||
nacosClient.Listen(defaultNacosDataID, defaultNacosGroup, func(event nacos.ChangeEvent) {
|
||||
err = nacosClient.GetJSON(defaultNacosDataID, defaultNacosGroup, &ossCnf)
|
||||
if err != nil {
|
||||
log.Printf("从 Nacos 获取 OSS 配置失败: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
servers = append(servers, server)
|
||||
}
|
||||
return servers
|
||||
}
|
||||
log.Printf("Nacos 配置已更新: %v", ossCnf)
|
||||
})
|
||||
})
|
||||
|
||||
func (r *ossRuntime) set(config ossConfig) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
r.config = config
|
||||
}
|
||||
|
||||
func (r *ossRuntime) get() (ossConfig, bool) {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
if strings.TrimSpace(r.config.AccessKeyID) == "" || strings.TrimSpace(r.config.AccessKeySecret) == "" {
|
||||
return ossConfig{}, false
|
||||
}
|
||||
return r.config, true
|
||||
}
|
||||
|
||||
func parseUintEnv(key string, defaultValue uint64) uint64 {
|
||||
raw := strings.TrimSpace(os.Getenv(key))
|
||||
if raw == "" {
|
||||
return defaultValue
|
||||
}
|
||||
value, err := strconv.ParseUint(raw, 10, 64)
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func getEnvOrDefault(key string, defaultValue string) string {
|
||||
value := strings.TrimSpace(os.Getenv(key))
|
||||
if value == "" {
|
||||
return defaultValue
|
||||
}
|
||||
return value
|
||||
return ossCnf, nil
|
||||
}
|
||||
|
||||
@ -23,8 +23,10 @@ func ValidateToken() gin.HandlerFunc {
|
||||
c.Set("admin", tokenInfo.UserName)
|
||||
}
|
||||
|
||||
// 获取请求路径和方法
|
||||
path := c.Request.URL.Path
|
||||
path := c.FullPath()
|
||||
if path == "" {
|
||||
path = c.Request.URL.Path
|
||||
}
|
||||
|
||||
// 验证用户权限
|
||||
if tokenInfo != nil {
|
||||
|
||||
@ -55,7 +55,7 @@ func GetUserList(AppId, ServerId, PageSize, CurrentPage, Uid, StartTime, EndTime
|
||||
}
|
||||
|
||||
func UserDetail2(appId, uid, node int) (*msg.ResUserDetailInfo, error) {
|
||||
r, err := client.GetUserInfo(appId, node, &msg.UserDetailParam{
|
||||
r, err := client.UserDetail(appId, node, &msg.UserDetailParam{
|
||||
Uid: int64(uid),
|
||||
})
|
||||
if err != nil {
|
||||
@ -64,24 +64,6 @@ func UserDetail2(appId, uid, node int) (*msg.ResUserDetailInfo, error) {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func UserDetail(appId, uid, node int) (map[string]interface{}, error) {
|
||||
req := &msg.ReqAdminInfo{
|
||||
Uid: int64(uid),
|
||||
}
|
||||
ws, err := util.GetWebsocket(appId, node)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get websocket: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
r, err := util.SendAdminMsg(ws, req)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to send admin message: %v", err)
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func UserGM(AppId, ServerId, Uid int, Command string) (interface{}, error) {
|
||||
req := &msg.ReqAdminGm{
|
||||
Uid: int64(Uid),
|
||||
@ -93,17 +75,11 @@ func UserGM(AppId, ServerId, Uid int, Command string) (interface{}, error) {
|
||||
defer db.Close()
|
||||
node := 0
|
||||
err = db.Get(&node, "SELECT `node` FROM t_player_baseinfo WHERE dwUin = ? ", Uid)
|
||||
ws, err := util.GetWebsocket(AppId, node)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get websocket: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
r, err := util.SendAdminMsg(ws, req)
|
||||
resp, err := client.PlayerGm(AppId, node, req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to send admin message: %v", err)
|
||||
}
|
||||
return r, nil
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func UserBan(AppId, ServerId, Uid int, Day int, Reason string) (interface{}, error) {
|
||||
@ -114,15 +90,9 @@ func UserBan(AppId, ServerId, Uid int, Day int, Reason string) (interface{}, err
|
||||
Reason: Reason,
|
||||
}
|
||||
AppId, ServerId = util.ParseUid(Uid)
|
||||
ws, err := util.GetWebsocket(AppId, ServerId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get websocket: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
r, err := util.SendAdminMsg(ws, req)
|
||||
resp, err := client.BanPlayer(AppId, ServerId, req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to send admin message: %v", err)
|
||||
}
|
||||
return r, nil
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@ -142,7 +142,7 @@ func (a *ActivityMod) reloadCfg() error {
|
||||
ServerList := util.GetServerInfo(a.AppId, 0)
|
||||
for _, server := range ServerList {
|
||||
go func(serverInfo util.ServerConfig) {
|
||||
err := client.ActivityCfgReload(serverInfo.AppId, serverInfo.ServerId, nil)
|
||||
err := client.ReloadActivity(serverInfo.AppId, serverInfo.ServerId, nil)
|
||||
if err != nil {
|
||||
log.Printf("failed to sync activity cfg: %v", err)
|
||||
}
|
||||
|
||||
@ -194,36 +194,46 @@ func SendPhoneCode(phone string) error {
|
||||
}
|
||||
|
||||
var PermissionList = map[string][]string{
|
||||
"/api/admin/list": {"super", "admin"},
|
||||
"/api/admin/add": {"super"},
|
||||
"/api/admin/log/list": {"super", "admin"},
|
||||
"/api/log/user": {"super", "admin", "user"},
|
||||
"/api/log/asset": {"super", "admin", "user"},
|
||||
"/api/log/event": {"super", "admin", "user"},
|
||||
"/api/log/order": {"super", "admin", "user"},
|
||||
"/api/user/list": {"super", "admin", "user"},
|
||||
"/api/user/gm": {"super", "admin"},
|
||||
"/api/user/ban": {"super", "admin"},
|
||||
"/api/server/list": {"super", "admin"},
|
||||
"/api/server/serverList": {"super", "admin"},
|
||||
"/api/server/addServer": {"super"},
|
||||
"/api/server/nodeList": {"super"},
|
||||
"/api/server/addNode": {"super"},
|
||||
"/api/server/updateApp": {"super", "admin"},
|
||||
"/api/server/restart": {"super", "admin"},
|
||||
"/api/server/reload": {"super", "admin"},
|
||||
"/api/statistics/level": {"super", "admin"},
|
||||
"/api/statistics/order": {"super", "admin"},
|
||||
"/api/statistics/info": {"super", "admin"},
|
||||
"/api/statistics/heat": {"super", "admin"},
|
||||
"/api/mail/send": {"super", "admin"},
|
||||
"/api/mail/list": {"super", "admin"},
|
||||
"/api/mail/delete": {"super", "admin"},
|
||||
"/api/language/list": {"super", "admin", "wb_transfer"},
|
||||
"/api/language/export": {"super", "admin", "wb_transfer"},
|
||||
"/api/language/save": {"super", "admin", "wb_transfer"},
|
||||
"/api/language/add": {"super", "admin", "wb_transfer"},
|
||||
"/api/language/delete": {"super", "admin"},
|
||||
"/api/admin/list": {"super", "admin"},
|
||||
"/api/admin/add": {"super"},
|
||||
"/api/admin/log/list": {"super", "admin"},
|
||||
"/api/log/user": {"super", "admin", "user"},
|
||||
"/api/log/asset": {"super", "admin", "user"},
|
||||
"/api/log/event": {"super", "admin", "user"},
|
||||
"/api/log/order": {"super", "admin", "user"},
|
||||
"/api/user/list": {"super", "admin", "user"},
|
||||
"/api/user/gm": {"super", "admin"},
|
||||
"/api/user/ban": {"super", "admin"},
|
||||
"/api/server/list": {"super", "admin"},
|
||||
"/api/server/serverList": {"super", "admin"},
|
||||
"/api/server/addServer": {"super"},
|
||||
"/api/server/nodeList": {"super"},
|
||||
"/api/server/addNode": {"super"},
|
||||
"/api/server/updateApp": {"super", "admin"},
|
||||
"/api/server/restart": {"super", "admin"},
|
||||
"/api/server/reload": {"super", "admin"},
|
||||
"/api/statistics/level": {"super", "admin"},
|
||||
"/api/statistics/order": {"super", "admin"},
|
||||
"/api/statistics/info": {"super", "admin"},
|
||||
"/api/statistics/heat": {"super", "admin"},
|
||||
"/api/mail/send": {"super", "admin"},
|
||||
"/api/mail/list": {"super", "admin"},
|
||||
"/api/mail/delete": {"super", "admin"},
|
||||
"/api/language/list": {"super", "admin", "wb_transfer"},
|
||||
"/api/language/export": {"super", "admin", "wb_transfer"},
|
||||
"/api/language/save": {"super", "admin", "wb_transfer"},
|
||||
"/api/language/add": {"super", "admin", "wb_transfer"},
|
||||
"/api/language/delete": {"super", "admin"},
|
||||
"/api/client/notification": {"super", "admin"},
|
||||
"/api/v1/experiments": {"super", "admin"},
|
||||
"/api/v1/experiments/:id": {"super", "admin"},
|
||||
"/api/v1/experiments/:id/variants": {"super", "admin"},
|
||||
"/api/v1/experiments/:id/variants/:variantId": {"super", "admin"},
|
||||
"/api/v1/experiments/:id/whitelist": {"super", "admin"},
|
||||
"/api/v1/experiments/:id/whitelist/batch": {"super", "admin"},
|
||||
"/api/v1/experiments/:id/whitelist/:userId": {"super", "admin"},
|
||||
"/api/v1/experiments/:id/results": {"super", "admin"},
|
||||
"/api/v1/users/:userId/groups": {"super", "admin"},
|
||||
}
|
||||
|
||||
func CheckUserPermission(username, path string) bool {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"backend/client"
|
||||
"backend/msg"
|
||||
util "backend/util"
|
||||
"fmt"
|
||||
@ -96,18 +97,12 @@ func (m *Mail) SendMail() error {
|
||||
ServerList := util.GetServerInfo(m.AppId, 0)
|
||||
for _, server := range ServerList {
|
||||
go func(serverInfo util.ServerConfig) {
|
||||
ws, err := util.GetWebsocket(m.AppId, server.ServerId)
|
||||
if err != nil {
|
||||
log.Printf("failed to get websocket: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
req := &msg.ReqReloadServerMail{}
|
||||
_, err = util.SendAdminMsg(ws, req)
|
||||
_, err := client.ReloadMail(serverInfo.AppId, serverInfo.ServerId, req)
|
||||
if err != nil {
|
||||
log.Printf("failed to send admin message: %v", err)
|
||||
}
|
||||
log.Printf("sent reload mail message to server %d", server.ServerId)
|
||||
log.Printf("sent reload mail message to server %d", serverInfo.ServerId)
|
||||
}(server)
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ package model
|
||||
|
||||
import (
|
||||
"backend/Type"
|
||||
"backend/client"
|
||||
"backend/middleware/alibaba"
|
||||
"backend/middleware/feishu"
|
||||
"backend/msg"
|
||||
@ -365,14 +366,8 @@ func (s *Server) ReloadServer() (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ws, err := util.GetWebsocket(s.AppId, s.ServerId)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get websocket: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
req := &msg.ReqReload{}
|
||||
_, err = util.SendAdminMsg(ws, req)
|
||||
_, err = client.ServerReload(s.AppId, s.ServerId, req)
|
||||
if err != nil {
|
||||
log.Printf("failed to send admin message: %v", err)
|
||||
}
|
||||
|
||||
@ -30648,6 +30648,110 @@ func (x *ResServerInfo) GetVersion() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type ResAdminGm struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Code int32 `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"`
|
||||
Msg string `protobuf:"bytes,2,opt,name=Msg,proto3" json:"Msg,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ResAdminGm) Reset() {
|
||||
*x = ResAdminGm{}
|
||||
mi := &file_proto_Gameapi_proto_msgTypes[518]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ResAdminGm) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ResAdminGm) ProtoMessage() {}
|
||||
|
||||
func (x *ResAdminGm) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_Gameapi_proto_msgTypes[518]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ResAdminGm.ProtoReflect.Descriptor instead.
|
||||
func (*ResAdminGm) Descriptor() ([]byte, []int) {
|
||||
return file_proto_Gameapi_proto_rawDescGZIP(), []int{518}
|
||||
}
|
||||
|
||||
func (x *ResAdminGm) GetCode() int32 {
|
||||
if x != nil {
|
||||
return x.Code
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ResAdminGm) GetMsg() string {
|
||||
if x != nil {
|
||||
return x.Msg
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ResBackend struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Code int32 `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"`
|
||||
Msg string `protobuf:"bytes,2,opt,name=Msg,proto3" json:"Msg,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ResBackend) Reset() {
|
||||
*x = ResBackend{}
|
||||
mi := &file_proto_Gameapi_proto_msgTypes[519]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ResBackend) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ResBackend) ProtoMessage() {}
|
||||
|
||||
func (x *ResBackend) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_Gameapi_proto_msgTypes[519]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ResBackend.ProtoReflect.Descriptor instead.
|
||||
func (*ResBackend) Descriptor() ([]byte, []int) {
|
||||
return file_proto_Gameapi_proto_rawDescGZIP(), []int{519}
|
||||
}
|
||||
|
||||
func (x *ResBackend) GetCode() int32 {
|
||||
if x != nil {
|
||||
return x.Code
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ResBackend) GetMsg() string {
|
||||
if x != nil {
|
||||
return x.Msg
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_proto_Gameapi_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_proto_Gameapi_proto_rawDesc = "" +
|
||||
@ -32927,7 +33031,15 @@ const file_proto_Gameapi_proto_rawDesc = "" +
|
||||
"\fNumGoroutine\x18\t \x01(\x05R\fNumGoroutine\x12\x1a\n" +
|
||||
"\bUsageMem\x18\n" +
|
||||
" \x01(\x04R\bUsageMem\x12\x18\n" +
|
||||
"\aVersion\x18\v \x01(\tR\aVersion*\xab\f\n" +
|
||||
"\aVersion\x18\v \x01(\tR\aVersion\"2\n" +
|
||||
"\n" +
|
||||
"ResAdminGm\x12\x12\n" +
|
||||
"\x04Code\x18\x01 \x01(\x05R\x04Code\x12\x10\n" +
|
||||
"\x03Msg\x18\x02 \x01(\tR\x03Msg\"2\n" +
|
||||
"\n" +
|
||||
"ResBackend\x12\x12\n" +
|
||||
"\x04Code\x18\x01 \x01(\x05R\x04Code\x12\x10\n" +
|
||||
"\x03Msg\x18\x02 \x01(\tR\x03Msg*\xab\f\n" +
|
||||
"\x0eITEM_POP_LABEL\x12\f\n" +
|
||||
"\bPlayroom\x10\x00\x12\r\n" +
|
||||
"\tPiggyBank\x10\x01\x12\n" +
|
||||
@ -33175,14 +33287,19 @@ const file_proto_Gameapi_proto_rawDesc = "" +
|
||||
"\x1cFRIEND_REPLY_HANDLE_ERR_TYPE\x12\b\n" +
|
||||
"\x04NONE\x10\x00\x12\n" +
|
||||
"\n" +
|
||||
"\x06CATNIP\x10\x012\xa6\x02\n" +
|
||||
"\x06CATNIP\x10\x012\x96\x04\n" +
|
||||
"\aBackend\x12P\n" +
|
||||
"\x0eReloadActivity\x12\x1e.tutorial.ReqActivityCfgReload\x1a\x1e.tutorial.ResActivityCfgReload\x12G\n" +
|
||||
"\rOrderShipping\x12\x1a.tutorial.ReqOrderShipping\x1a\x1a.tutorial.ResOrderShipping\x12@\n" +
|
||||
"\n" +
|
||||
"UserDetail\x12\x19.tutorial.UserDetailParam\x1a\x17.tutorial.ResUserDetail\x12>\n" +
|
||||
"\n" +
|
||||
"ServerInfo\x12\x17.tutorial.ReqServerInfo\x1a\x17.tutorial.ResServerInfoB\bZ\x06../msgb\x06proto3"
|
||||
"ServerInfo\x12\x17.tutorial.ReqServerInfo\x1a\x17.tutorial.ResServerInfo\x126\n" +
|
||||
"\bPlayerGm\x12\x14.tutorial.ReqAdminGm\x1a\x14.tutorial.ResAdminGm\x128\n" +
|
||||
"\tBanPlayer\x12\x15.tutorial.ReqAdminBan\x1a\x14.tutorial.ResBackend\x12A\n" +
|
||||
"\n" +
|
||||
"ReloadMail\x12\x1d.tutorial.ReqReloadServerMail\x1a\x14.tutorial.ResBackend\x129\n" +
|
||||
"\fServerReload\x12\x13.tutorial.ReqReload\x1a\x14.tutorial.ResBackendB\bZ\x06../msgb\x06proto3"
|
||||
|
||||
var (
|
||||
file_proto_Gameapi_proto_rawDescOnce sync.Once
|
||||
@ -33197,7 +33314,7 @@ func file_proto_Gameapi_proto_rawDescGZIP() []byte {
|
||||
}
|
||||
|
||||
var file_proto_Gameapi_proto_enumTypes = make([]protoimpl.EnumInfo, 14)
|
||||
var file_proto_Gameapi_proto_msgTypes = make([]protoimpl.MessageInfo, 594)
|
||||
var file_proto_Gameapi_proto_msgTypes = make([]protoimpl.MessageInfo, 596)
|
||||
var file_proto_Gameapi_proto_goTypes = []any{
|
||||
(ITEM_POP_LABEL)(0), // 0: tutorial.ITEM_POP_LABEL
|
||||
(HANDLE_TYPE)(0), // 1: tutorial.HANDLE_TYPE
|
||||
@ -33731,120 +33848,122 @@ var file_proto_Gameapi_proto_goTypes = []any{
|
||||
(*UserDetailOrderInfoChess)(nil), // 529: tutorial.UserDetailOrderInfoChess
|
||||
(*ResUserDetailInfo)(nil), // 530: tutorial.ResUserDetailInfo
|
||||
(*ResServerInfo)(nil), // 531: tutorial.ResServerInfo
|
||||
nil, // 532: tutorial.ResChessColorData.MChessColorDataEntry
|
||||
nil, // 533: tutorial.UpdateBaseItemInfo.MUpdateItemEntry
|
||||
nil, // 534: tutorial.ResPlayerChessData.MChessDataEntry
|
||||
nil, // 535: tutorial.ReqPutPartInBag.MChessDataEntry
|
||||
nil, // 536: tutorial.UpdatePlayerChessData.MChessDataEntry
|
||||
nil, // 537: tutorial.ReqSeparateChess.MChessDataEntry
|
||||
nil, // 538: tutorial.ReqUpgradeChess.MChessDataEntry
|
||||
nil, // 539: tutorial.ReqGetChessFromBuff.MChessDataEntry
|
||||
nil, // 540: tutorial.ReqChessEx.MChessDataEntry
|
||||
nil, // 541: tutorial.ReqSourceChest.MChessDataEntry
|
||||
nil, // 542: tutorial.ReqPlayroomOutline.MChessDataEntry
|
||||
nil, // 543: tutorial.ReqPutChessInBag.MChessDataEntry
|
||||
nil, // 544: tutorial.ReqTakeChessOutBag.MChessDataEntry
|
||||
nil, // 545: tutorial.ResPlayerBriefProfileData.SetEmojiEntry
|
||||
nil, // 546: tutorial.UserInfo.SetEmojiEntry
|
||||
nil, // 547: tutorial.ReqRewardOrder.MChessDataEntry
|
||||
nil, // 548: tutorial.ResCardInfo.AllCardEntry
|
||||
nil, // 549: tutorial.ResCardInfo.HandbookEntry
|
||||
nil, // 550: tutorial.ResGuideInfo.RewardEntry
|
||||
nil, // 551: tutorial.ResGuideTask.TaskEntry
|
||||
nil, // 552: tutorial.ResDailyTask.WeekRewardEntry
|
||||
nil, // 553: tutorial.ResDailyTask.DailyTaskEntry
|
||||
nil, // 554: tutorial.ResLimitEvent.LimitEventListEntry
|
||||
nil, // 555: tutorial.ResLimitEventProgress.ProgressRewardEntry
|
||||
nil, // 556: tutorial.LimitEvent.ParamEntry
|
||||
nil, // 557: tutorial.ReqLimitEventLuckyCat.MChessDataEntry
|
||||
nil, // 558: tutorial.ResFriendPlayerSimple.EmojiEntry
|
||||
nil, // 559: tutorial.ResFriendPlayerSimple.PlayroomEntry
|
||||
nil, // 560: tutorial.ResFriendPlayerSimple.DressSetEntry
|
||||
nil, // 561: tutorial.ResFriendPlayerSimple.PhysiologyEntry
|
||||
nil, // 562: tutorial.ResPlayerSimple.EmojiEntry
|
||||
nil, // 563: tutorial.ResPlayerRank.PlayroomSetEntry
|
||||
nil, // 564: tutorial.ResPlayerRank.DressSetEntry
|
||||
nil, // 565: tutorial.ResKv.KvEntry
|
||||
nil, // 566: tutorial.ResRank.RankListEntry
|
||||
nil, // 567: tutorial.ResMailList.MailListEntry
|
||||
nil, // 568: tutorial.ResCharge.SpecialShopEntry
|
||||
nil, // 569: tutorial.ResCharge.ChessShopEntry
|
||||
nil, // 570: tutorial.ResCharge.GiftEntry
|
||||
nil, // 571: tutorial.ResCharge.WeeklyDiscountEntry
|
||||
nil, // 572: tutorial.ReqBuyChessShop2.MChessDataEntry
|
||||
nil, // 573: tutorial.ResEndless.EndlessListEntry
|
||||
nil, // 574: tutorial.ResChampshipRank.RankListEntry
|
||||
nil, // 575: tutorial.ResChampshipPreRank.RankListEntry
|
||||
nil, // 576: tutorial.ResNotifyCard.CardEntry
|
||||
nil, // 577: tutorial.ResNotifyCard.MasterEntry
|
||||
nil, // 578: tutorial.ResNotifyCard.HandbookEntry
|
||||
nil, // 579: tutorial.ResMining.MapEntry
|
||||
nil, // 580: tutorial.ResMining.PassRewardEntry
|
||||
nil, // 581: tutorial.ReqMiningTake.MapEntry
|
||||
nil, // 582: tutorial.ResActRed.RedEntry
|
||||
nil, // 583: tutorial.ResItem.ItemEntry
|
||||
nil, // 584: tutorial.ItemNotify.ItemEntry
|
||||
nil, // 585: tutorial.ResGuessColor.OMapEntry
|
||||
nil, // 586: tutorial.ReqGuessColorTake.OMapEntry
|
||||
nil, // 587: tutorial.GuessColorInfo.MapEntry
|
||||
nil, // 588: tutorial.ResPlayroom.PlayroomEntry
|
||||
nil, // 589: tutorial.ResPlayroom.MoodEntry
|
||||
nil, // 590: tutorial.ResPlayroom.PhysiologyEntry
|
||||
nil, // 591: tutorial.ResPlayroom.DressEntry
|
||||
nil, // 592: tutorial.ResPlayroom.DressSetEntry
|
||||
nil, // 593: tutorial.ResPlayroom.WeeklyDiscountEntry
|
||||
nil, // 594: tutorial.ReqPlayroomDressSet.DressSetEntry
|
||||
nil, // 595: tutorial.NotifyPlayroomMood.MoodEntry
|
||||
nil, // 596: tutorial.NotifyPlayroomMood.PhysiologyEntry
|
||||
nil, // 597: tutorial.ResPlayroomInfo.PlayroomEntry
|
||||
nil, // 598: tutorial.ResPlayroomInfo.ItemsEntry
|
||||
nil, // 599: tutorial.ResPlayroomInfo.FlipEntry
|
||||
nil, // 600: tutorial.ResPlayroomInfo.EmojiEntry
|
||||
nil, // 601: tutorial.ResPlayroomInfo.DressSetEntry
|
||||
nil, // 602: tutorial.ResPlayroomGame.ItemsEntry
|
||||
nil, // 603: tutorial.ReqPlayroomSetRoom.PlayroomEntry
|
||||
nil, // 604: tutorial.MiningCfg.GemEntry
|
||||
nil, // 605: tutorial.MiningCfg.JackpotEntry
|
||||
nil, // 606: tutorial.MiningCfg.PassEntry
|
||||
nil, // 607: tutorial.ResUserDetailInfo.ChessMapEntry
|
||||
(*ResAdminGm)(nil), // 532: tutorial.ResAdminGm
|
||||
(*ResBackend)(nil), // 533: tutorial.ResBackend
|
||||
nil, // 534: tutorial.ResChessColorData.MChessColorDataEntry
|
||||
nil, // 535: tutorial.UpdateBaseItemInfo.MUpdateItemEntry
|
||||
nil, // 536: tutorial.ResPlayerChessData.MChessDataEntry
|
||||
nil, // 537: tutorial.ReqPutPartInBag.MChessDataEntry
|
||||
nil, // 538: tutorial.UpdatePlayerChessData.MChessDataEntry
|
||||
nil, // 539: tutorial.ReqSeparateChess.MChessDataEntry
|
||||
nil, // 540: tutorial.ReqUpgradeChess.MChessDataEntry
|
||||
nil, // 541: tutorial.ReqGetChessFromBuff.MChessDataEntry
|
||||
nil, // 542: tutorial.ReqChessEx.MChessDataEntry
|
||||
nil, // 543: tutorial.ReqSourceChest.MChessDataEntry
|
||||
nil, // 544: tutorial.ReqPlayroomOutline.MChessDataEntry
|
||||
nil, // 545: tutorial.ReqPutChessInBag.MChessDataEntry
|
||||
nil, // 546: tutorial.ReqTakeChessOutBag.MChessDataEntry
|
||||
nil, // 547: tutorial.ResPlayerBriefProfileData.SetEmojiEntry
|
||||
nil, // 548: tutorial.UserInfo.SetEmojiEntry
|
||||
nil, // 549: tutorial.ReqRewardOrder.MChessDataEntry
|
||||
nil, // 550: tutorial.ResCardInfo.AllCardEntry
|
||||
nil, // 551: tutorial.ResCardInfo.HandbookEntry
|
||||
nil, // 552: tutorial.ResGuideInfo.RewardEntry
|
||||
nil, // 553: tutorial.ResGuideTask.TaskEntry
|
||||
nil, // 554: tutorial.ResDailyTask.WeekRewardEntry
|
||||
nil, // 555: tutorial.ResDailyTask.DailyTaskEntry
|
||||
nil, // 556: tutorial.ResLimitEvent.LimitEventListEntry
|
||||
nil, // 557: tutorial.ResLimitEventProgress.ProgressRewardEntry
|
||||
nil, // 558: tutorial.LimitEvent.ParamEntry
|
||||
nil, // 559: tutorial.ReqLimitEventLuckyCat.MChessDataEntry
|
||||
nil, // 560: tutorial.ResFriendPlayerSimple.EmojiEntry
|
||||
nil, // 561: tutorial.ResFriendPlayerSimple.PlayroomEntry
|
||||
nil, // 562: tutorial.ResFriendPlayerSimple.DressSetEntry
|
||||
nil, // 563: tutorial.ResFriendPlayerSimple.PhysiologyEntry
|
||||
nil, // 564: tutorial.ResPlayerSimple.EmojiEntry
|
||||
nil, // 565: tutorial.ResPlayerRank.PlayroomSetEntry
|
||||
nil, // 566: tutorial.ResPlayerRank.DressSetEntry
|
||||
nil, // 567: tutorial.ResKv.KvEntry
|
||||
nil, // 568: tutorial.ResRank.RankListEntry
|
||||
nil, // 569: tutorial.ResMailList.MailListEntry
|
||||
nil, // 570: tutorial.ResCharge.SpecialShopEntry
|
||||
nil, // 571: tutorial.ResCharge.ChessShopEntry
|
||||
nil, // 572: tutorial.ResCharge.GiftEntry
|
||||
nil, // 573: tutorial.ResCharge.WeeklyDiscountEntry
|
||||
nil, // 574: tutorial.ReqBuyChessShop2.MChessDataEntry
|
||||
nil, // 575: tutorial.ResEndless.EndlessListEntry
|
||||
nil, // 576: tutorial.ResChampshipRank.RankListEntry
|
||||
nil, // 577: tutorial.ResChampshipPreRank.RankListEntry
|
||||
nil, // 578: tutorial.ResNotifyCard.CardEntry
|
||||
nil, // 579: tutorial.ResNotifyCard.MasterEntry
|
||||
nil, // 580: tutorial.ResNotifyCard.HandbookEntry
|
||||
nil, // 581: tutorial.ResMining.MapEntry
|
||||
nil, // 582: tutorial.ResMining.PassRewardEntry
|
||||
nil, // 583: tutorial.ReqMiningTake.MapEntry
|
||||
nil, // 584: tutorial.ResActRed.RedEntry
|
||||
nil, // 585: tutorial.ResItem.ItemEntry
|
||||
nil, // 586: tutorial.ItemNotify.ItemEntry
|
||||
nil, // 587: tutorial.ResGuessColor.OMapEntry
|
||||
nil, // 588: tutorial.ReqGuessColorTake.OMapEntry
|
||||
nil, // 589: tutorial.GuessColorInfo.MapEntry
|
||||
nil, // 590: tutorial.ResPlayroom.PlayroomEntry
|
||||
nil, // 591: tutorial.ResPlayroom.MoodEntry
|
||||
nil, // 592: tutorial.ResPlayroom.PhysiologyEntry
|
||||
nil, // 593: tutorial.ResPlayroom.DressEntry
|
||||
nil, // 594: tutorial.ResPlayroom.DressSetEntry
|
||||
nil, // 595: tutorial.ResPlayroom.WeeklyDiscountEntry
|
||||
nil, // 596: tutorial.ReqPlayroomDressSet.DressSetEntry
|
||||
nil, // 597: tutorial.NotifyPlayroomMood.MoodEntry
|
||||
nil, // 598: tutorial.NotifyPlayroomMood.PhysiologyEntry
|
||||
nil, // 599: tutorial.ResPlayroomInfo.PlayroomEntry
|
||||
nil, // 600: tutorial.ResPlayroomInfo.ItemsEntry
|
||||
nil, // 601: tutorial.ResPlayroomInfo.FlipEntry
|
||||
nil, // 602: tutorial.ResPlayroomInfo.EmojiEntry
|
||||
nil, // 603: tutorial.ResPlayroomInfo.DressSetEntry
|
||||
nil, // 604: tutorial.ResPlayroomGame.ItemsEntry
|
||||
nil, // 605: tutorial.ReqPlayroomSetRoom.PlayroomEntry
|
||||
nil, // 606: tutorial.MiningCfg.GemEntry
|
||||
nil, // 607: tutorial.MiningCfg.JackpotEntry
|
||||
nil, // 608: tutorial.MiningCfg.PassEntry
|
||||
nil, // 609: tutorial.ResUserDetailInfo.ChessMapEntry
|
||||
}
|
||||
var file_proto_Gameapi_proto_depIdxs = []int32{
|
||||
532, // 0: tutorial.ResChessColorData.mChessColorData:type_name -> tutorial.ResChessColorData.MChessColorDataEntry
|
||||
534, // 0: tutorial.ResChessColorData.mChessColorData:type_name -> tutorial.ResChessColorData.MChessColorDataEntry
|
||||
5, // 1: tutorial.ReqLogin.type:type_name -> tutorial.LOGIN_TYPE
|
||||
2, // 2: tutorial.ResId2Verify.ResultCode:type_name -> tutorial.RES_CODE
|
||||
533, // 3: tutorial.UpdateBaseItemInfo.mUpdateItem:type_name -> tutorial.UpdateBaseItemInfo.MUpdateItemEntry
|
||||
534, // 4: tutorial.ResPlayerChessData.mChessData:type_name -> tutorial.ResPlayerChessData.MChessDataEntry
|
||||
535, // 3: tutorial.UpdateBaseItemInfo.mUpdateItem:type_name -> tutorial.UpdateBaseItemInfo.MUpdateItemEntry
|
||||
536, // 4: tutorial.ResPlayerChessData.mChessData:type_name -> tutorial.ResPlayerChessData.MChessDataEntry
|
||||
74, // 5: tutorial.ResPlayerChessInfo.ChessBag:type_name -> tutorial.ChessBag
|
||||
55, // 6: tutorial.ResPlayerChessInfo.PartBag:type_name -> tutorial.PartBag
|
||||
2, // 7: tutorial.ResGetChessRetireReward.code:type_name -> tutorial.RES_CODE
|
||||
56, // 8: tutorial.PartBag.PartBagGrids:type_name -> tutorial.PartBagGrid
|
||||
535, // 9: tutorial.ReqPutPartInBag.mChessData:type_name -> tutorial.ReqPutPartInBag.MChessDataEntry
|
||||
537, // 9: tutorial.ReqPutPartInBag.mChessData:type_name -> tutorial.ReqPutPartInBag.MChessDataEntry
|
||||
2, // 10: tutorial.ResPutPartInBag.code:type_name -> tutorial.RES_CODE
|
||||
1, // 11: tutorial.ChessHandle.type:type_name -> tutorial.HANDLE_TYPE
|
||||
536, // 12: tutorial.UpdatePlayerChessData.mChessData:type_name -> tutorial.UpdatePlayerChessData.MChessDataEntry
|
||||
538, // 12: tutorial.UpdatePlayerChessData.mChessData:type_name -> tutorial.UpdatePlayerChessData.MChessDataEntry
|
||||
59, // 13: tutorial.UpdatePlayerChessData.mChessHandle:type_name -> tutorial.ChessHandle
|
||||
2, // 14: tutorial.ResUpdatePlayerChessData.code:type_name -> tutorial.RES_CODE
|
||||
537, // 15: tutorial.ReqSeparateChess.mChessData:type_name -> tutorial.ReqSeparateChess.MChessDataEntry
|
||||
539, // 15: tutorial.ReqSeparateChess.mChessData:type_name -> tutorial.ReqSeparateChess.MChessDataEntry
|
||||
2, // 16: tutorial.ResSeparateChess.code:type_name -> tutorial.RES_CODE
|
||||
538, // 17: tutorial.ReqUpgradeChess.mChessData:type_name -> tutorial.ReqUpgradeChess.MChessDataEntry
|
||||
540, // 17: tutorial.ReqUpgradeChess.mChessData:type_name -> tutorial.ReqUpgradeChess.MChessDataEntry
|
||||
2, // 18: tutorial.ResUpgradeChess.code:type_name -> tutorial.RES_CODE
|
||||
539, // 19: tutorial.ReqGetChessFromBuff.mChessData:type_name -> tutorial.ReqGetChessFromBuff.MChessDataEntry
|
||||
541, // 19: tutorial.ReqGetChessFromBuff.mChessData:type_name -> tutorial.ReqGetChessFromBuff.MChessDataEntry
|
||||
2, // 20: tutorial.ResGetChessFromBuff.code:type_name -> tutorial.RES_CODE
|
||||
7, // 21: tutorial.ReqChessEx.Type:type_name -> tutorial.CHESS_EX_TYPE
|
||||
540, // 22: tutorial.ReqChessEx.mChessData:type_name -> tutorial.ReqChessEx.MChessDataEntry
|
||||
542, // 22: tutorial.ReqChessEx.mChessData:type_name -> tutorial.ReqChessEx.MChessDataEntry
|
||||
2, // 23: tutorial.ResChessEx.code:type_name -> tutorial.RES_CODE
|
||||
541, // 24: tutorial.ReqSourceChest.mChessData:type_name -> tutorial.ReqSourceChest.MChessDataEntry
|
||||
543, // 24: tutorial.ReqSourceChest.mChessData:type_name -> tutorial.ReqSourceChest.MChessDataEntry
|
||||
2, // 25: tutorial.ResSourceChest.code:type_name -> tutorial.RES_CODE
|
||||
542, // 26: tutorial.ReqPlayroomOutline.mChessData:type_name -> tutorial.ReqPlayroomOutline.MChessDataEntry
|
||||
544, // 26: tutorial.ReqPlayroomOutline.mChessData:type_name -> tutorial.ReqPlayroomOutline.MChessDataEntry
|
||||
2, // 27: tutorial.ResPlayroomOutline.code:type_name -> tutorial.RES_CODE
|
||||
75, // 28: tutorial.ChessBag.ChessBagGrids:type_name -> tutorial.ChessBagGrid
|
||||
543, // 29: tutorial.ReqPutChessInBag.mChessData:type_name -> tutorial.ReqPutChessInBag.MChessDataEntry
|
||||
545, // 29: tutorial.ReqPutChessInBag.mChessData:type_name -> tutorial.ReqPutChessInBag.MChessDataEntry
|
||||
2, // 30: tutorial.ResPutChessInBag.code:type_name -> tutorial.RES_CODE
|
||||
544, // 31: tutorial.ReqTakeChessOutBag.mChessData:type_name -> tutorial.ReqTakeChessOutBag.MChessDataEntry
|
||||
546, // 31: tutorial.ReqTakeChessOutBag.mChessData:type_name -> tutorial.ReqTakeChessOutBag.MChessDataEntry
|
||||
2, // 32: tutorial.ResTakeChessOutBag.code:type_name -> tutorial.RES_CODE
|
||||
2, // 33: tutorial.ResTakeChessOutBagToHonor.code:type_name -> tutorial.RES_CODE
|
||||
2, // 34: tutorial.ResBuyChessBagGrid.code:type_name -> tutorial.RES_CODE
|
||||
545, // 35: tutorial.ResPlayerBriefProfileData.SetEmoji:type_name -> tutorial.ResPlayerBriefProfileData.SetEmojiEntry
|
||||
547, // 35: tutorial.ResPlayerBriefProfileData.SetEmoji:type_name -> tutorial.ResPlayerBriefProfileData.SetEmojiEntry
|
||||
2, // 36: tutorial.ResSetEnergyMul.ResultCode:type_name -> tutorial.RES_CODE
|
||||
8, // 37: tutorial.ReqLang.Lang:type_name -> tutorial.LANG_TYPE
|
||||
2, // 38: tutorial.ResLang.ResultCode:type_name -> tutorial.RES_CODE
|
||||
@ -33852,7 +33971,7 @@ var file_proto_Gameapi_proto_depIdxs = []int32{
|
||||
195, // 40: tutorial.UserInfo.AvatarList:type_name -> tutorial.AvatarInfo
|
||||
191, // 41: tutorial.UserInfo.FaceList:type_name -> tutorial.FaceInfo
|
||||
198, // 42: tutorial.UserInfo.EmojiList:type_name -> tutorial.EmojiInfo
|
||||
546, // 43: tutorial.UserInfo.SetEmoji:type_name -> tutorial.UserInfo.SetEmojiEntry
|
||||
548, // 43: tutorial.UserInfo.SetEmoji:type_name -> tutorial.UserInfo.SetEmojiEntry
|
||||
2, // 44: tutorial.ResSetName.ResultCode:type_name -> tutorial.RES_CODE
|
||||
2, // 45: tutorial.ResSetPetName.ResultCode:type_name -> tutorial.RES_CODE
|
||||
2, // 46: tutorial.ResBuyEnergy.Code:type_name -> tutorial.RES_CODE
|
||||
@ -33860,7 +33979,7 @@ var file_proto_Gameapi_proto_depIdxs = []int32{
|
||||
2, // 48: tutorial.ResGetHandbookReward.Code:type_name -> tutorial.RES_CODE
|
||||
105, // 49: tutorial.Handbook.Handbooks:type_name -> tutorial.HandbookInfo
|
||||
2, // 50: tutorial.ResHandbookAllReward.Code:type_name -> tutorial.RES_CODE
|
||||
547, // 51: tutorial.ReqRewardOrder.mChessData:type_name -> tutorial.ReqRewardOrder.MChessDataEntry
|
||||
549, // 51: tutorial.ReqRewardOrder.mChessData:type_name -> tutorial.ReqRewardOrder.MChessDataEntry
|
||||
2, // 52: tutorial.ResRewardOrder.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 53: tutorial.ResDelOrder.Code:type_name -> tutorial.RES_CODE
|
||||
171, // 54: tutorial.Order.Items:type_name -> tutorial.ItemInfo
|
||||
@ -33871,8 +33990,8 @@ var file_proto_Gameapi_proto_depIdxs = []int32{
|
||||
2, // 59: tutorial.ResDecorateAll.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 60: tutorial.ResAreaReward.Code:type_name -> tutorial.RES_CODE
|
||||
127, // 61: tutorial.ResCardInfo.CardList:type_name -> tutorial.Card
|
||||
548, // 62: tutorial.ResCardInfo.AllCard:type_name -> tutorial.ResCardInfo.AllCardEntry
|
||||
549, // 63: tutorial.ResCardInfo.Handbook:type_name -> tutorial.ResCardInfo.HandbookEntry
|
||||
550, // 62: tutorial.ResCardInfo.AllCard:type_name -> tutorial.ResCardInfo.AllCardEntry
|
||||
551, // 63: tutorial.ResCardInfo.Handbook:type_name -> tutorial.ResCardInfo.HandbookEntry
|
||||
2, // 64: tutorial.ResCardSeasonFirstReward.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 65: tutorial.ResCardHandbookReward.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 66: tutorial.ResMasterCard.Code:type_name -> tutorial.RES_CODE
|
||||
@ -33891,16 +34010,16 @@ var file_proto_Gameapi_proto_depIdxs = []int32{
|
||||
2, // 79: tutorial.ResGetFriendCard.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 80: tutorial.ResGuideReward.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 81: tutorial.ResGuidePlayroom.Code:type_name -> tutorial.RES_CODE
|
||||
550, // 82: tutorial.ResGuideInfo.Reward:type_name -> tutorial.ResGuideInfo.RewardEntry
|
||||
552, // 82: tutorial.ResGuideInfo.Reward:type_name -> tutorial.ResGuideInfo.RewardEntry
|
||||
171, // 83: tutorial.ResItemPop.Items:type_name -> tutorial.ItemInfo
|
||||
173, // 84: tutorial.ResItemPop.CardPacks:type_name -> tutorial.CardPack
|
||||
171, // 85: tutorial.ItemList.List:type_name -> tutorial.ItemInfo
|
||||
551, // 86: tutorial.ResGuideTask.Task:type_name -> tutorial.ResGuideTask.TaskEntry
|
||||
553, // 86: tutorial.ResGuideTask.Task:type_name -> tutorial.ResGuideTask.TaskEntry
|
||||
183, // 87: tutorial.GuideTask.Progress:type_name -> tutorial.QuestProgress
|
||||
2, // 88: tutorial.ResGetGuideTaskReward.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 89: tutorial.ResGetGuideActiveReward.Code:type_name -> tutorial.RES_CODE
|
||||
552, // 90: tutorial.ResDailyTask.WeekReward:type_name -> tutorial.ResDailyTask.WeekRewardEntry
|
||||
553, // 91: tutorial.ResDailyTask.DailyTask:type_name -> tutorial.ResDailyTask.DailyTaskEntry
|
||||
554, // 90: tutorial.ResDailyTask.WeekReward:type_name -> tutorial.ResDailyTask.WeekRewardEntry
|
||||
555, // 91: tutorial.ResDailyTask.DailyTask:type_name -> tutorial.ResDailyTask.DailyTaskEntry
|
||||
171, // 92: tutorial.DailyWeek.Items:type_name -> tutorial.ItemInfo
|
||||
183, // 93: tutorial.DailyTask.Progress:type_name -> tutorial.QuestProgress
|
||||
171, // 94: tutorial.DailyTask.Items:type_name -> tutorial.ItemInfo
|
||||
@ -33922,33 +34041,33 @@ var file_proto_Gameapi_proto_depIdxs = []int32{
|
||||
208, // 110: tutorial.ResActivity.ActiveList:type_name -> tutorial.ActivityInfo
|
||||
2, // 111: tutorial.ResActivityReward.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 112: tutorial.ResAddGiftReward.Code:type_name -> tutorial.RES_CODE
|
||||
554, // 113: tutorial.ResLimitEvent.LimitEventList:type_name -> tutorial.ResLimitEvent.LimitEventListEntry
|
||||
555, // 114: tutorial.ResLimitEventProgress.ProgressReward:type_name -> tutorial.ResLimitEventProgress.ProgressRewardEntry
|
||||
556, // 113: tutorial.ResLimitEvent.LimitEventList:type_name -> tutorial.ResLimitEvent.LimitEventListEntry
|
||||
557, // 114: tutorial.ResLimitEventProgress.ProgressReward:type_name -> tutorial.ResLimitEventProgress.ProgressRewardEntry
|
||||
2, // 115: tutorial.ResLimitEventReward.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 116: tutorial.ResSelectLimitEvent.Code:type_name -> tutorial.RES_CODE
|
||||
556, // 117: tutorial.LimitEvent.Param:type_name -> tutorial.LimitEvent.ParamEntry
|
||||
557, // 118: tutorial.ReqLimitEventLuckyCat.mChessData:type_name -> tutorial.ReqLimitEventLuckyCat.MChessDataEntry
|
||||
558, // 117: tutorial.LimitEvent.Param:type_name -> tutorial.LimitEvent.ParamEntry
|
||||
559, // 118: tutorial.ReqLimitEventLuckyCat.mChessData:type_name -> tutorial.ReqLimitEventLuckyCat.MChessDataEntry
|
||||
2, // 119: tutorial.ResLimitEventLuckyCat.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 120: tutorial.ResLimitSenceReward.Code:type_name -> tutorial.RES_CODE
|
||||
171, // 121: tutorial.ResChessRainReward.Items:type_name -> tutorial.ItemInfo
|
||||
2, // 122: tutorial.ResFastProduceReward.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 123: tutorial.ResCatTrickReward.Code:type_name -> tutorial.RES_CODE
|
||||
237, // 124: tutorial.ResSearchPlayer.List:type_name -> tutorial.ResPlayerSimple
|
||||
558, // 125: tutorial.ResFriendPlayerSimple.Emoji:type_name -> tutorial.ResFriendPlayerSimple.EmojiEntry
|
||||
559, // 126: tutorial.ResFriendPlayerSimple.Playroom:type_name -> tutorial.ResFriendPlayerSimple.PlayroomEntry
|
||||
560, // 127: tutorial.ResFriendPlayerSimple.DressSet:type_name -> tutorial.ResFriendPlayerSimple.DressSetEntry
|
||||
560, // 125: tutorial.ResFriendPlayerSimple.Emoji:type_name -> tutorial.ResFriendPlayerSimple.EmojiEntry
|
||||
561, // 126: tutorial.ResFriendPlayerSimple.Playroom:type_name -> tutorial.ResFriendPlayerSimple.PlayroomEntry
|
||||
562, // 127: tutorial.ResFriendPlayerSimple.DressSet:type_name -> tutorial.ResFriendPlayerSimple.DressSetEntry
|
||||
238, // 128: tutorial.ResFriendPlayerSimple.Last:type_name -> tutorial.ActLog
|
||||
561, // 129: tutorial.ResFriendPlayerSimple.Physiology:type_name -> tutorial.ResFriendPlayerSimple.PhysiologyEntry
|
||||
562, // 130: tutorial.ResPlayerSimple.Emoji:type_name -> tutorial.ResPlayerSimple.EmojiEntry
|
||||
563, // 131: tutorial.ResPlayerRank.PlayroomSet:type_name -> tutorial.ResPlayerRank.PlayroomSetEntry
|
||||
564, // 132: tutorial.ResPlayerRank.DressSet:type_name -> tutorial.ResPlayerRank.DressSetEntry
|
||||
563, // 129: tutorial.ResFriendPlayerSimple.Physiology:type_name -> tutorial.ResFriendPlayerSimple.PhysiologyEntry
|
||||
564, // 130: tutorial.ResPlayerSimple.Emoji:type_name -> tutorial.ResPlayerSimple.EmojiEntry
|
||||
565, // 131: tutorial.ResPlayerRank.PlayroomSet:type_name -> tutorial.ResPlayerRank.PlayroomSetEntry
|
||||
566, // 132: tutorial.ResPlayerRank.DressSet:type_name -> tutorial.ResPlayerRank.DressSetEntry
|
||||
238, // 133: tutorial.ResPlayerRank.Last:type_name -> tutorial.ActLog
|
||||
237, // 134: tutorial.ResFriendLog.Player:type_name -> tutorial.ResPlayerSimple
|
||||
240, // 135: tutorial.NotifyFriendLog.info:type_name -> tutorial.ResFriendLog
|
||||
242, // 136: tutorial.NotifyFriendLog.Bubble:type_name -> tutorial.FriendBubbleInfo
|
||||
171, // 137: tutorial.FriendBubbleInfo.Items:type_name -> tutorial.ItemInfo
|
||||
244, // 138: tutorial.NotifyFriendCard.Info:type_name -> tutorial.ResFriendCard
|
||||
565, // 139: tutorial.ResKv.kv:type_name -> tutorial.ResKv.KvEntry
|
||||
567, // 139: tutorial.ResKv.kv:type_name -> tutorial.ResKv.KvEntry
|
||||
2, // 140: tutorial.ResFriendByCode.Code:type_name -> tutorial.RES_CODE
|
||||
237, // 141: tutorial.ResFriendByCode.Player:type_name -> tutorial.ResPlayerSimple
|
||||
237, // 142: tutorial.ResFriendRecommend.List:type_name -> tutorial.ResPlayerSimple
|
||||
@ -33977,27 +34096,27 @@ var file_proto_Gameapi_proto_depIdxs = []int32{
|
||||
237, // 165: tutorial.ResAgreeFriend.Player:type_name -> tutorial.ResPlayerSimple
|
||||
2, // 166: tutorial.ResRefuseFriend.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 167: tutorial.ResDelFriend.Code:type_name -> tutorial.RES_CODE
|
||||
566, // 168: tutorial.ResRank.RankList:type_name -> tutorial.ResRank.RankListEntry
|
||||
567, // 169: tutorial.ResMailList.MailList:type_name -> tutorial.ResMailList.MailListEntry
|
||||
568, // 168: tutorial.ResRank.RankList:type_name -> tutorial.ResRank.RankListEntry
|
||||
569, // 169: tutorial.ResMailList.MailList:type_name -> tutorial.ResMailList.MailListEntry
|
||||
171, // 170: tutorial.MailInfo.Items:type_name -> tutorial.ItemInfo
|
||||
293, // 171: tutorial.MailNotify.Info:type_name -> tutorial.MailInfo
|
||||
2, // 172: tutorial.ResReadMail.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 173: tutorial.ResGetMailReward.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 174: tutorial.ResDeleteMail.Code:type_name -> tutorial.RES_CODE
|
||||
568, // 175: tutorial.ResCharge.SpecialShop:type_name -> tutorial.ResCharge.SpecialShopEntry
|
||||
569, // 176: tutorial.ResCharge.ChessShop:type_name -> tutorial.ResCharge.ChessShopEntry
|
||||
570, // 177: tutorial.ResCharge.Gift:type_name -> tutorial.ResCharge.GiftEntry
|
||||
570, // 175: tutorial.ResCharge.SpecialShop:type_name -> tutorial.ResCharge.SpecialShopEntry
|
||||
571, // 176: tutorial.ResCharge.ChessShop:type_name -> tutorial.ResCharge.ChessShopEntry
|
||||
572, // 177: tutorial.ResCharge.Gift:type_name -> tutorial.ResCharge.GiftEntry
|
||||
304, // 178: tutorial.ResCharge.Wish:type_name -> tutorial.WishList
|
||||
571, // 179: tutorial.ResCharge.WeeklyDiscount:type_name -> tutorial.ResCharge.WeeklyDiscountEntry
|
||||
573, // 179: tutorial.ResCharge.WeeklyDiscount:type_name -> tutorial.ResCharge.WeeklyDiscountEntry
|
||||
2, // 180: tutorial.ResAddWish.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 181: tutorial.ResGetWish.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 182: tutorial.ResSendWishBeg.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 183: tutorial.ResFreeShop.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 184: tutorial.ResBuyChessShop.Code:type_name -> tutorial.RES_CODE
|
||||
572, // 185: tutorial.ReqBuyChessShop2.mChessData:type_name -> tutorial.ReqBuyChessShop2.MChessDataEntry
|
||||
574, // 185: tutorial.ReqBuyChessShop2.mChessData:type_name -> tutorial.ReqBuyChessShop2.MChessDataEntry
|
||||
2, // 186: tutorial.ResBuyChessShop2.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 187: tutorial.ResRefreshChessShop.Code:type_name -> tutorial.RES_CODE
|
||||
573, // 188: tutorial.ResEndless.EndlessList:type_name -> tutorial.ResEndless.EndlessListEntry
|
||||
575, // 188: tutorial.ResEndless.EndlessList:type_name -> tutorial.ResEndless.EndlessListEntry
|
||||
171, // 189: tutorial.ResEndlessInfo.Items:type_name -> tutorial.ItemInfo
|
||||
2, // 190: tutorial.ResEndlessReward.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 191: tutorial.ResPiggyBankReward.Code:type_name -> tutorial.RES_CODE
|
||||
@ -34010,12 +34129,12 @@ var file_proto_Gameapi_proto_depIdxs = []int32{
|
||||
171, // 198: tutorial.ChampionshipCfgRank.Items:type_name -> tutorial.ItemInfo
|
||||
2, // 199: tutorial.ResChampshipReward.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 200: tutorial.ResChampshipRankReward.Code:type_name -> tutorial.RES_CODE
|
||||
574, // 201: tutorial.ResChampshipRank.RankList:type_name -> tutorial.ResChampshipRank.RankListEntry
|
||||
575, // 202: tutorial.ResChampshipPreRank.RankList:type_name -> tutorial.ResChampshipPreRank.RankListEntry
|
||||
576, // 201: tutorial.ResChampshipRank.RankList:type_name -> tutorial.ResChampshipRank.RankListEntry
|
||||
577, // 202: tutorial.ResChampshipPreRank.RankList:type_name -> tutorial.ResChampshipPreRank.RankListEntry
|
||||
337, // 203: tutorial.ResChampshipPreRank.Cfg:type_name -> tutorial.ChampionshipCfg
|
||||
576, // 204: tutorial.ResNotifyCard.Card:type_name -> tutorial.ResNotifyCard.CardEntry
|
||||
577, // 205: tutorial.ResNotifyCard.Master:type_name -> tutorial.ResNotifyCard.MasterEntry
|
||||
578, // 206: tutorial.ResNotifyCard.Handbook:type_name -> tutorial.ResNotifyCard.HandbookEntry
|
||||
578, // 204: tutorial.ResNotifyCard.Card:type_name -> tutorial.ResNotifyCard.CardEntry
|
||||
579, // 205: tutorial.ResNotifyCard.Master:type_name -> tutorial.ResNotifyCard.MasterEntry
|
||||
580, // 206: tutorial.ResNotifyCard.Handbook:type_name -> tutorial.ResNotifyCard.HandbookEntry
|
||||
2, // 207: tutorial.ResSetFacebookUrl.Code:type_name -> tutorial.RES_CODE
|
||||
364, // 208: tutorial.CatReturnGiftCfg.RewardList:type_name -> tutorial.CatReturnGiftCfgReward
|
||||
171, // 209: tutorial.CatReturnGiftCfgReward.Reward:type_name -> tutorial.ItemInfo
|
||||
@ -34023,22 +34142,22 @@ var file_proto_Gameapi_proto_depIdxs = []int32{
|
||||
2, // 211: tutorial.ResCatReturnGiftScore.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 212: tutorial.ResCatReturnGiftReward.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 213: tutorial.ResCatReturnGiftRewardGift.Code:type_name -> tutorial.RES_CODE
|
||||
579, // 214: tutorial.ResMining.Map:type_name -> tutorial.ResMining.MapEntry
|
||||
580, // 215: tutorial.ResMining.PassReward:type_name -> tutorial.ResMining.PassRewardEntry
|
||||
581, // 216: tutorial.ReqMiningTake.Map:type_name -> tutorial.ReqMiningTake.MapEntry
|
||||
581, // 214: tutorial.ResMining.Map:type_name -> tutorial.ResMining.MapEntry
|
||||
582, // 215: tutorial.ResMining.PassReward:type_name -> tutorial.ResMining.PassRewardEntry
|
||||
583, // 216: tutorial.ReqMiningTake.Map:type_name -> tutorial.ReqMiningTake.MapEntry
|
||||
2, // 217: tutorial.ResMiningTake.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 218: tutorial.ResMiningReward.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 219: tutorial.ResActPassReward.Code:type_name -> tutorial.RES_CODE
|
||||
582, // 220: tutorial.ResActRed.Red:type_name -> tutorial.ResActRed.RedEntry
|
||||
584, // 220: tutorial.ResActRed.Red:type_name -> tutorial.ResActRed.RedEntry
|
||||
208, // 221: tutorial.ActivityNotify.Info:type_name -> tutorial.ActivityInfo
|
||||
583, // 222: tutorial.ResItem.Item:type_name -> tutorial.ResItem.ItemEntry
|
||||
584, // 223: tutorial.ItemNotify.Item:type_name -> tutorial.ItemNotify.ItemEntry
|
||||
585, // 222: tutorial.ResItem.Item:type_name -> tutorial.ResItem.ItemEntry
|
||||
586, // 223: tutorial.ItemNotify.Item:type_name -> tutorial.ItemNotify.ItemEntry
|
||||
391, // 224: tutorial.ResGuessColor.MapList:type_name -> tutorial.GuessColorInfo
|
||||
585, // 225: tutorial.ResGuessColor.OMap:type_name -> tutorial.ResGuessColor.OMapEntry
|
||||
587, // 225: tutorial.ResGuessColor.OMap:type_name -> tutorial.ResGuessColor.OMapEntry
|
||||
389, // 226: tutorial.ResGuessColor.Opponent:type_name -> tutorial.opponent
|
||||
391, // 227: tutorial.ReqGuessColorTake.Map:type_name -> tutorial.GuessColorInfo
|
||||
586, // 228: tutorial.ReqGuessColorTake.OMap:type_name -> tutorial.ReqGuessColorTake.OMapEntry
|
||||
587, // 229: tutorial.GuessColorInfo.Map:type_name -> tutorial.GuessColorInfo.MapEntry
|
||||
588, // 228: tutorial.ReqGuessColorTake.OMap:type_name -> tutorial.ReqGuessColorTake.OMapEntry
|
||||
589, // 229: tutorial.GuessColorInfo.Map:type_name -> tutorial.GuessColorInfo.MapEntry
|
||||
2, // 230: tutorial.ResGuessColorTake.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 231: tutorial.ResGuessColorReward.Code:type_name -> tutorial.RES_CODE
|
||||
397, // 232: tutorial.ResRace.Opponent:type_name -> tutorial.raceopponent
|
||||
@ -34049,19 +34168,19 @@ var file_proto_Gameapi_proto_depIdxs = []int32{
|
||||
171, // 237: tutorial.ResPlayroom.Items:type_name -> tutorial.ItemInfo
|
||||
438, // 238: tutorial.ResPlayroom.Opponent:type_name -> tutorial.RoomOpponent
|
||||
437, // 239: tutorial.ResPlayroom.Friend:type_name -> tutorial.FriendRoom
|
||||
588, // 240: tutorial.ResPlayroom.Playroom:type_name -> tutorial.ResPlayroom.PlayroomEntry
|
||||
590, // 240: tutorial.ResPlayroom.Playroom:type_name -> tutorial.ResPlayroom.PlayroomEntry
|
||||
423, // 241: tutorial.ResPlayroom.collect:type_name -> tutorial.PlayroomCollectInfo
|
||||
589, // 242: tutorial.ResPlayroom.Mood:type_name -> tutorial.ResPlayroom.MoodEntry
|
||||
591, // 242: tutorial.ResPlayroom.Mood:type_name -> tutorial.ResPlayroom.MoodEntry
|
||||
171, // 243: tutorial.ResPlayroom.LoseItem:type_name -> tutorial.ItemInfo
|
||||
433, // 244: tutorial.ResPlayroom.Chip:type_name -> tutorial.ChipInfo
|
||||
590, // 245: tutorial.ResPlayroom.Physiology:type_name -> tutorial.ResPlayroom.PhysiologyEntry
|
||||
591, // 246: tutorial.ResPlayroom.Dress:type_name -> tutorial.ResPlayroom.DressEntry
|
||||
592, // 247: tutorial.ResPlayroom.DressSet:type_name -> tutorial.ResPlayroom.DressSetEntry
|
||||
592, // 245: tutorial.ResPlayroom.Physiology:type_name -> tutorial.ResPlayroom.PhysiologyEntry
|
||||
593, // 246: tutorial.ResPlayroom.Dress:type_name -> tutorial.ResPlayroom.DressEntry
|
||||
594, // 247: tutorial.ResPlayroom.DressSet:type_name -> tutorial.ResPlayroom.DressSetEntry
|
||||
422, // 248: tutorial.ResPlayroom.PetAir:type_name -> tutorial.PlayroomAirInfo
|
||||
182, // 249: tutorial.ResPlayroom.DailyTask:type_name -> tutorial.DailyTask
|
||||
435, // 250: tutorial.ResPlayroom.AdItem:type_name -> tutorial.AdItem
|
||||
437, // 251: tutorial.ResPlayroom.Target:type_name -> tutorial.FriendRoom
|
||||
593, // 252: tutorial.ResPlayroom.WeeklyDiscount:type_name -> tutorial.ResPlayroom.WeeklyDiscountEntry
|
||||
595, // 252: tutorial.ResPlayroom.WeeklyDiscount:type_name -> tutorial.ResPlayroom.WeeklyDiscountEntry
|
||||
182, // 253: tutorial.NotifyPlayroomTask.DailyTask:type_name -> tutorial.DailyTask
|
||||
237, // 254: tutorial.NotifyPlayroomBroken.Player:type_name -> tutorial.ResPlayerSimple
|
||||
2, // 255: tutorial.ResPlayroomTask.Code:type_name -> tutorial.RES_CODE
|
||||
@ -34069,28 +34188,28 @@ var file_proto_Gameapi_proto_depIdxs = []int32{
|
||||
2, // 257: tutorial.ResPlayroomUnlock.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 258: tutorial.ResPlayroomUpvote.Code:type_name -> tutorial.RES_CODE
|
||||
421, // 259: tutorial.PlayroomDress.List:type_name -> tutorial.PlayroomDressInfo
|
||||
594, // 260: tutorial.ReqPlayroomDressSet.DressSet:type_name -> tutorial.ReqPlayroomDressSet.DressSetEntry
|
||||
596, // 260: tutorial.ReqPlayroomDressSet.DressSet:type_name -> tutorial.ReqPlayroomDressSet.DressSetEntry
|
||||
2, // 261: tutorial.ResPlayroomDressSet.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 262: tutorial.ResPlayroomPetAirSet.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 263: tutorial.ResPlayroomWorkOutline.Code:type_name -> tutorial.RES_CODE
|
||||
171, // 264: tutorial.NotifyPlayroomLose.LoseItem:type_name -> tutorial.ItemInfo
|
||||
433, // 265: tutorial.NotifyPlayroomLose.Chip:type_name -> tutorial.ChipInfo
|
||||
595, // 266: tutorial.NotifyPlayroomMood.Mood:type_name -> tutorial.NotifyPlayroomMood.MoodEntry
|
||||
596, // 267: tutorial.NotifyPlayroomMood.Physiology:type_name -> tutorial.NotifyPlayroomMood.PhysiologyEntry
|
||||
597, // 266: tutorial.NotifyPlayroomMood.Mood:type_name -> tutorial.NotifyPlayroomMood.MoodEntry
|
||||
598, // 267: tutorial.NotifyPlayroomMood.Physiology:type_name -> tutorial.NotifyPlayroomMood.PhysiologyEntry
|
||||
435, // 268: tutorial.NotifyPlayroomMood.AdItem:type_name -> tutorial.AdItem
|
||||
597, // 269: tutorial.ResPlayroomInfo.Playroom:type_name -> tutorial.ResPlayroomInfo.PlayroomEntry
|
||||
598, // 270: tutorial.ResPlayroomInfo.Items:type_name -> tutorial.ResPlayroomInfo.ItemsEntry
|
||||
599, // 271: tutorial.ResPlayroomInfo.flip:type_name -> tutorial.ResPlayroomInfo.FlipEntry
|
||||
600, // 272: tutorial.ResPlayroomInfo.Emoji:type_name -> tutorial.ResPlayroomInfo.EmojiEntry
|
||||
601, // 273: tutorial.ResPlayroomInfo.DressSet:type_name -> tutorial.ResPlayroomInfo.DressSetEntry
|
||||
599, // 269: tutorial.ResPlayroomInfo.Playroom:type_name -> tutorial.ResPlayroomInfo.PlayroomEntry
|
||||
600, // 270: tutorial.ResPlayroomInfo.Items:type_name -> tutorial.ResPlayroomInfo.ItemsEntry
|
||||
601, // 271: tutorial.ResPlayroomInfo.flip:type_name -> tutorial.ResPlayroomInfo.FlipEntry
|
||||
602, // 272: tutorial.ResPlayroomInfo.Emoji:type_name -> tutorial.ResPlayroomInfo.EmojiEntry
|
||||
603, // 273: tutorial.ResPlayroomInfo.DressSet:type_name -> tutorial.ResPlayroomInfo.DressSetEntry
|
||||
2, // 274: tutorial.ResPlayroomFlip.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 275: tutorial.ResPlayroomGuide.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 276: tutorial.ResPlayroomFlipReward.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 277: tutorial.ResPlayroomGame.Code:type_name -> tutorial.RES_CODE
|
||||
602, // 278: tutorial.ResPlayroomGame.Items:type_name -> tutorial.ResPlayroomGame.ItemsEntry
|
||||
604, // 278: tutorial.ResPlayroomGame.Items:type_name -> tutorial.ResPlayroomGame.ItemsEntry
|
||||
171, // 279: tutorial.ResPlayroomGameShowReward.Items:type_name -> tutorial.ItemInfo
|
||||
2, // 280: tutorial.ResPlayroomInteract.Code:type_name -> tutorial.RES_CODE
|
||||
603, // 281: tutorial.ReqPlayroomSetRoom.Playroom:type_name -> tutorial.ReqPlayroomSetRoom.PlayroomEntry
|
||||
605, // 281: tutorial.ReqPlayroomSetRoom.Playroom:type_name -> tutorial.ReqPlayroomSetRoom.PlayroomEntry
|
||||
2, // 282: tutorial.ResPlayroomSetRoom.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 283: tutorial.ResPlayroomSelectReward.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 284: tutorial.ResPlayroomLose.Code:type_name -> tutorial.RES_CODE
|
||||
@ -34121,16 +34240,16 @@ var file_proto_Gameapi_proto_depIdxs = []int32{
|
||||
2, // 309: tutorial.ResCatnipGrandReward.Code:type_name -> tutorial.RES_CODE
|
||||
2, // 310: tutorial.ResCatnipEmoji.Code:type_name -> tutorial.RES_CODE
|
||||
171, // 311: tutorial.MiningCfg.itemCost:type_name -> tutorial.ItemInfo
|
||||
604, // 312: tutorial.MiningCfg.Gem:type_name -> tutorial.MiningCfg.GemEntry
|
||||
605, // 313: tutorial.MiningCfg.Jackpot:type_name -> tutorial.MiningCfg.JackpotEntry
|
||||
606, // 314: tutorial.MiningCfg.Pass:type_name -> tutorial.MiningCfg.PassEntry
|
||||
606, // 312: tutorial.MiningCfg.Gem:type_name -> tutorial.MiningCfg.GemEntry
|
||||
607, // 313: tutorial.MiningCfg.Jackpot:type_name -> tutorial.MiningCfg.JackpotEntry
|
||||
608, // 314: tutorial.MiningCfg.Pass:type_name -> tutorial.MiningCfg.PassEntry
|
||||
171, // 315: tutorial.MiningCfgJackpot.Items:type_name -> tutorial.ItemInfo
|
||||
171, // 316: tutorial.MiningCfgPass.Items:type_name -> tutorial.ItemInfo
|
||||
521, // 317: tutorial.ReqActivityCfgReload.List:type_name -> tutorial.ActivityCfg
|
||||
530, // 318: tutorial.ResUserDetail.info:type_name -> tutorial.ResUserDetailInfo
|
||||
529, // 319: tutorial.UserDetailOrderInfo.Chess:type_name -> tutorial.UserDetailOrderInfoChess
|
||||
529, // 320: tutorial.UserDetailOrderInfo.ChessId:type_name -> tutorial.UserDetailOrderInfoChess
|
||||
607, // 321: tutorial.ResUserDetailInfo.ChessMap:type_name -> tutorial.ResUserDetailInfo.ChessMapEntry
|
||||
609, // 321: tutorial.ResUserDetailInfo.ChessMap:type_name -> tutorial.ResUserDetailInfo.ChessMapEntry
|
||||
238, // 322: tutorial.ResUserDetailInfo.ActLog:type_name -> tutorial.ActLog
|
||||
527, // 323: tutorial.ResUserDetailInfo.FriendList:type_name -> tutorial.UserDetailFriendInfo
|
||||
528, // 324: tutorial.ResUserDetailInfo.Order:type_name -> tutorial.UserDetailOrderInfo
|
||||
@ -34158,12 +34277,20 @@ var file_proto_Gameapi_proto_depIdxs = []int32{
|
||||
523, // 346: tutorial.Backend.OrderShipping:input_type -> tutorial.ReqOrderShipping
|
||||
525, // 347: tutorial.Backend.UserDetail:input_type -> tutorial.UserDetailParam
|
||||
515, // 348: tutorial.Backend.ServerInfo:input_type -> tutorial.ReqServerInfo
|
||||
522, // 349: tutorial.Backend.ReloadActivity:output_type -> tutorial.ResActivityCfgReload
|
||||
524, // 350: tutorial.Backend.OrderShipping:output_type -> tutorial.ResOrderShipping
|
||||
526, // 351: tutorial.Backend.UserDetail:output_type -> tutorial.ResUserDetail
|
||||
531, // 352: tutorial.Backend.ServerInfo:output_type -> tutorial.ResServerInfo
|
||||
349, // [349:353] is the sub-list for method output_type
|
||||
345, // [345:349] is the sub-list for method input_type
|
||||
517, // 349: tutorial.Backend.PlayerGm:input_type -> tutorial.ReqAdminGm
|
||||
518, // 350: tutorial.Backend.BanPlayer:input_type -> tutorial.ReqAdminBan
|
||||
514, // 351: tutorial.Backend.ReloadMail:input_type -> tutorial.ReqReloadServerMail
|
||||
516, // 352: tutorial.Backend.ServerReload:input_type -> tutorial.ReqReload
|
||||
522, // 353: tutorial.Backend.ReloadActivity:output_type -> tutorial.ResActivityCfgReload
|
||||
524, // 354: tutorial.Backend.OrderShipping:output_type -> tutorial.ResOrderShipping
|
||||
526, // 355: tutorial.Backend.UserDetail:output_type -> tutorial.ResUserDetail
|
||||
531, // 356: tutorial.Backend.ServerInfo:output_type -> tutorial.ResServerInfo
|
||||
532, // 357: tutorial.Backend.PlayerGm:output_type -> tutorial.ResAdminGm
|
||||
533, // 358: tutorial.Backend.BanPlayer:output_type -> tutorial.ResBackend
|
||||
533, // 359: tutorial.Backend.ReloadMail:output_type -> tutorial.ResBackend
|
||||
533, // 360: tutorial.Backend.ServerReload:output_type -> tutorial.ResBackend
|
||||
353, // [353:361] is the sub-list for method output_type
|
||||
345, // [345:353] is the sub-list for method input_type
|
||||
345, // [345:345] is the sub-list for extension type_name
|
||||
345, // [345:345] is the sub-list for extension extendee
|
||||
0, // [0:345] is the sub-list for field type_name
|
||||
@ -34180,7 +34307,7 @@ func file_proto_Gameapi_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_Gameapi_proto_rawDesc), len(file_proto_Gameapi_proto_rawDesc)),
|
||||
NumEnums: 14,
|
||||
NumMessages: 594,
|
||||
NumMessages: 596,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
||||
@ -23,6 +23,10 @@ const (
|
||||
Backend_OrderShipping_FullMethodName = "/tutorial.Backend/OrderShipping"
|
||||
Backend_UserDetail_FullMethodName = "/tutorial.Backend/UserDetail"
|
||||
Backend_ServerInfo_FullMethodName = "/tutorial.Backend/ServerInfo"
|
||||
Backend_PlayerGm_FullMethodName = "/tutorial.Backend/PlayerGm"
|
||||
Backend_BanPlayer_FullMethodName = "/tutorial.Backend/BanPlayer"
|
||||
Backend_ReloadMail_FullMethodName = "/tutorial.Backend/ReloadMail"
|
||||
Backend_ServerReload_FullMethodName = "/tutorial.Backend/ServerReload"
|
||||
)
|
||||
|
||||
// BackendClient is the client API for Backend service.
|
||||
@ -33,6 +37,10 @@ type BackendClient interface {
|
||||
OrderShipping(ctx context.Context, in *ReqOrderShipping, opts ...grpc.CallOption) (*ResOrderShipping, error)
|
||||
UserDetail(ctx context.Context, in *UserDetailParam, opts ...grpc.CallOption) (*ResUserDetail, error)
|
||||
ServerInfo(ctx context.Context, in *ReqServerInfo, opts ...grpc.CallOption) (*ResServerInfo, error)
|
||||
PlayerGm(ctx context.Context, in *ReqAdminGm, opts ...grpc.CallOption) (*ResAdminGm, error)
|
||||
BanPlayer(ctx context.Context, in *ReqAdminBan, opts ...grpc.CallOption) (*ResBackend, error)
|
||||
ReloadMail(ctx context.Context, in *ReqReloadServerMail, opts ...grpc.CallOption) (*ResBackend, error)
|
||||
ServerReload(ctx context.Context, in *ReqReload, opts ...grpc.CallOption) (*ResBackend, error)
|
||||
}
|
||||
|
||||
type backendClient struct {
|
||||
@ -83,6 +91,46 @@ func (c *backendClient) ServerInfo(ctx context.Context, in *ReqServerInfo, opts
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *backendClient) PlayerGm(ctx context.Context, in *ReqAdminGm, opts ...grpc.CallOption) (*ResAdminGm, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ResAdminGm)
|
||||
err := c.cc.Invoke(ctx, Backend_PlayerGm_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *backendClient) BanPlayer(ctx context.Context, in *ReqAdminBan, opts ...grpc.CallOption) (*ResBackend, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ResBackend)
|
||||
err := c.cc.Invoke(ctx, Backend_BanPlayer_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *backendClient) ReloadMail(ctx context.Context, in *ReqReloadServerMail, opts ...grpc.CallOption) (*ResBackend, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ResBackend)
|
||||
err := c.cc.Invoke(ctx, Backend_ReloadMail_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *backendClient) ServerReload(ctx context.Context, in *ReqReload, opts ...grpc.CallOption) (*ResBackend, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ResBackend)
|
||||
err := c.cc.Invoke(ctx, Backend_ServerReload_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// BackendServer is the server API for Backend service.
|
||||
// All implementations must embed UnimplementedBackendServer
|
||||
// for forward compatibility.
|
||||
@ -91,6 +139,10 @@ type BackendServer interface {
|
||||
OrderShipping(context.Context, *ReqOrderShipping) (*ResOrderShipping, error)
|
||||
UserDetail(context.Context, *UserDetailParam) (*ResUserDetail, error)
|
||||
ServerInfo(context.Context, *ReqServerInfo) (*ResServerInfo, error)
|
||||
PlayerGm(context.Context, *ReqAdminGm) (*ResAdminGm, error)
|
||||
BanPlayer(context.Context, *ReqAdminBan) (*ResBackend, error)
|
||||
ReloadMail(context.Context, *ReqReloadServerMail) (*ResBackend, error)
|
||||
ServerReload(context.Context, *ReqReload) (*ResBackend, error)
|
||||
mustEmbedUnimplementedBackendServer()
|
||||
}
|
||||
|
||||
@ -113,6 +165,18 @@ func (UnimplementedBackendServer) UserDetail(context.Context, *UserDetailParam)
|
||||
func (UnimplementedBackendServer) ServerInfo(context.Context, *ReqServerInfo) (*ResServerInfo, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ServerInfo not implemented")
|
||||
}
|
||||
func (UnimplementedBackendServer) PlayerGm(context.Context, *ReqAdminGm) (*ResAdminGm, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method PlayerGm not implemented")
|
||||
}
|
||||
func (UnimplementedBackendServer) BanPlayer(context.Context, *ReqAdminBan) (*ResBackend, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method BanPlayer not implemented")
|
||||
}
|
||||
func (UnimplementedBackendServer) ReloadMail(context.Context, *ReqReloadServerMail) (*ResBackend, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ReloadMail not implemented")
|
||||
}
|
||||
func (UnimplementedBackendServer) ServerReload(context.Context, *ReqReload) (*ResBackend, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ServerReload not implemented")
|
||||
}
|
||||
func (UnimplementedBackendServer) mustEmbedUnimplementedBackendServer() {}
|
||||
func (UnimplementedBackendServer) testEmbeddedByValue() {}
|
||||
|
||||
@ -206,6 +270,78 @@ func _Backend_ServerInfo_Handler(srv interface{}, ctx context.Context, dec func(
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Backend_PlayerGm_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ReqAdminGm)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BackendServer).PlayerGm(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Backend_PlayerGm_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BackendServer).PlayerGm(ctx, req.(*ReqAdminGm))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Backend_BanPlayer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ReqAdminBan)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BackendServer).BanPlayer(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Backend_BanPlayer_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BackendServer).BanPlayer(ctx, req.(*ReqAdminBan))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Backend_ReloadMail_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ReqReloadServerMail)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BackendServer).ReloadMail(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Backend_ReloadMail_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BackendServer).ReloadMail(ctx, req.(*ReqReloadServerMail))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Backend_ServerReload_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ReqReload)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BackendServer).ServerReload(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Backend_ServerReload_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BackendServer).ServerReload(ctx, req.(*ReqReload))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Backend_ServiceDesc is the grpc.ServiceDesc for Backend service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@ -229,6 +365,22 @@ var Backend_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "ServerInfo",
|
||||
Handler: _Backend_ServerInfo_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "PlayerGm",
|
||||
Handler: _Backend_PlayerGm_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "BanPlayer",
|
||||
Handler: _Backend_BanPlayer_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ReloadMail",
|
||||
Handler: _Backend_ReloadMail_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ServerReload",
|
||||
Handler: _Backend_ServerReload_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "proto/Gameapi.proto",
|
||||
|
||||
BIN
release/abtest_service/abtest_service
Normal file
BIN
release/abtest_service/abtest_service
Normal file
Binary file not shown.
4
release/abtest_service/conf/app.yml
Normal file
4
release/abtest_service/conf/app.yml
Normal file
@ -0,0 +1,4 @@
|
||||
name: "Admin Backend"
|
||||
version: "1.0.0"
|
||||
debug: true
|
||||
port: 5240
|
||||
74
release/abtest_service/conf/server.yml
Normal file
74
release/abtest_service/conf/server.yml
Normal file
@ -0,0 +1,74 @@
|
||||
system:
|
||||
nmap: false
|
||||
feishu_url: 'https://open.feishu.cn/open-apis/bot/v2/hook/70e24a79-b019-434a-b4d1-4592bbf7c311'
|
||||
notice_url: 'https://open.feishu.cn/open-apis/bot/v2/hook/64bad1f3-3a41-4dca-9037-399067ffb252'
|
||||
operation_url: 'https://open.feishu.cn/open-apis/bot/v2/hook/64bad1f3-3a41-4dca-9037-399067ffb252'
|
||||
operation_chat_id: 'oc_f6e10a55f28f31e2a5677bdcb6aed599'
|
||||
us_operation_chat_id: 'oc_a3d1268f63573563fdaea3dedb3bf78d'
|
||||
client_chat_id: 'oc_f6e10a55f28f31e2a5677bdcb6aed599'
|
||||
ssh: true
|
||||
mysqls:
|
||||
- host: '127.0.0.1'
|
||||
name: 'merge_pet_test'
|
||||
port: 3306
|
||||
user: 'root'
|
||||
password: 'GWFj1cHaqjpzvcsHBWTFtLWtm8MUZKROx_wvbV6jPg=='
|
||||
database: 'pet_home_%d'
|
||||
idleTimeout: Infinity
|
||||
- host: '127.0.0.1'
|
||||
name: 'merge_pet_audit'
|
||||
port: 3306
|
||||
user: 'root'
|
||||
password: 'GWFj1cHaqjpzvcsHBWTFtLWtm8MUZKROx_wvbV6jPg=='
|
||||
database: 'merge_pet_audit_%d'
|
||||
idleTimeout: Infinity
|
||||
- host: '127.0.0.1'
|
||||
name: 'merge_pet_sdk'
|
||||
port: 3306
|
||||
user: 'root'
|
||||
password: 'GWFj1cHaqjpzvcsHBWTFtLWtm8MUZKROx_wvbV6jPg=='
|
||||
database: 'Merge_Pet_sdk'
|
||||
idleTimeout: Infinity
|
||||
- host: '127.0.0.1'
|
||||
name: 'merge_pet_london'
|
||||
port: 3306
|
||||
user: 'root'
|
||||
password: 'GWFj1cHaqjpzvcsHBWTFtLWtm8MUZKROx_wvbV6jPg=='
|
||||
database: 'merge_pet_london_%d'
|
||||
idleTimeout: Infinity
|
||||
- host: '127.0.0.1'
|
||||
name: 'merge_pet_online'
|
||||
port: 3306
|
||||
user: 'root'
|
||||
password: 'pUf9tft9GOPjV1z855Jf2DpB5NUpGEc_'
|
||||
database: 'merge_pet_%d'
|
||||
idleTimeout: Infinity
|
||||
- host: 'rm-f8zd2030feam53n43io.mysql.rds.aliyuncs.com'
|
||||
name: 'log'
|
||||
port: 3306
|
||||
user: 'root'
|
||||
password: 'GWFj1cHaqjpzvcsHBWTFtLWtm8MUZKROx_wvbV6jPg=='
|
||||
database: 'game'
|
||||
idleTimeout: Infinity
|
||||
|
||||
servers:
|
||||
- name: 'server1'
|
||||
host: '1.15.182.107'
|
||||
port: 22
|
||||
username: 'root'
|
||||
password: 'r_vcLRGHPm1bEZDKU1L5TTr_-u_expNKgsCBuXNHmA=='
|
||||
- name: 'server2'
|
||||
host: '47.254.83.25'
|
||||
port: 22
|
||||
username: 'root'
|
||||
password: 'ynAMWcS4YpHozPHuudywcIZuBnTiSSaWF2iLoSlRVA=='
|
||||
- name: 'london'
|
||||
host: '8.208.47.208'
|
||||
port: 22
|
||||
username: 'root'
|
||||
password: 'dhzyiIMG0LkzSmY0lVEukdbM1uIt8OY8qljhgUJnBT8='
|
||||
- name: 'log'
|
||||
host: '8.155.14.94'
|
||||
port: 22
|
||||
username: 'root'
|
||||
password: 'gDcfdjgyq60A-8q_cZ_CbSQnTlY0YakpiYVyTmFTEkk='
|
||||
2
release/abtest_service/pack.sh
Normal file
2
release/abtest_service/pack.sh
Normal file
@ -0,0 +1,2 @@
|
||||
cd /data/admin_backend
|
||||
GOOS=linux GOARCH=amd64 go build -o /data/admin_backend/release/abtest_service/abtest_service sdk/abtest/main.go
|
||||
@ -30,7 +30,7 @@ func (m *MySQLConfig) DSN() string {
|
||||
func Load() *Config {
|
||||
return &Config{
|
||||
Server: ServerConfig{
|
||||
Port: getEnv("SERVER_PORT", "8080"),
|
||||
Port: getEnv("SERVER_PORT", "5360"),
|
||||
},
|
||||
MySQL: MySQLConfig{
|
||||
Host: getEnv("MYSQL_HOST", "ga-bp1s4q4jo935fmnxs474f.aliyunga0018.com"),
|
||||
|
||||
@ -1,19 +1,64 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/abtest/model"
|
||||
"backend/sdk/abtest/model"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
type DAO struct {
|
||||
db *sql.DB
|
||||
type scannedTime struct {
|
||||
Time time.Time
|
||||
Valid bool
|
||||
}
|
||||
|
||||
func New(db *sql.DB) *DAO {
|
||||
func (t *scannedTime) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
t.Valid = false
|
||||
t.Time = time.Time{}
|
||||
return nil
|
||||
}
|
||||
|
||||
switch v := value.(type) {
|
||||
case time.Time:
|
||||
t.Time = v
|
||||
t.Valid = true
|
||||
return nil
|
||||
case []byte:
|
||||
return t.parse(string(v))
|
||||
case string:
|
||||
return t.parse(v)
|
||||
default:
|
||||
return fmt.Errorf("unsupported time scan type %T", value)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *scannedTime) parse(raw string) error {
|
||||
layouts := []string{
|
||||
"2006-01-02 15:04:05",
|
||||
time.RFC3339,
|
||||
"2006-01-02T15:04:05",
|
||||
}
|
||||
for _, layout := range layouts {
|
||||
parsed, err := time.ParseInLocation(layout, raw, time.Local)
|
||||
if err == nil {
|
||||
t.Time = parsed
|
||||
t.Valid = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("invalid time value %q", raw)
|
||||
}
|
||||
|
||||
type DAO struct {
|
||||
db *sqlx.DB
|
||||
}
|
||||
|
||||
func New(db *sqlx.DB) *DAO {
|
||||
return &DAO{db: db}
|
||||
}
|
||||
|
||||
@ -35,9 +80,9 @@ func (d *DAO) GetExperiment(id int64) (*model.Experiment, error) {
|
||||
"SELECT id, name, description, status, start_time, end_time, created_at, updated_at FROM experiments WHERE id = ?", id,
|
||||
)
|
||||
exp := &model.Experiment{}
|
||||
var startTime, endTime model.NullTime
|
||||
var startTime, endTime, createdAt, updatedAt scannedTime
|
||||
if err := row.Scan(&exp.ID, &exp.Name, &exp.Description, &exp.Status,
|
||||
&startTime, &endTime, &exp.CreatedAt, &exp.UpdatedAt); err != nil {
|
||||
&startTime, &endTime, &createdAt, &updatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if startTime.Valid {
|
||||
@ -46,6 +91,12 @@ func (d *DAO) GetExperiment(id int64) (*model.Experiment, error) {
|
||||
if endTime.Valid {
|
||||
exp.EndTime = &endTime.Time
|
||||
}
|
||||
if createdAt.Valid {
|
||||
exp.CreatedAt = createdAt.Time
|
||||
}
|
||||
if updatedAt.Valid {
|
||||
exp.UpdatedAt = updatedAt.Time
|
||||
}
|
||||
return exp, nil
|
||||
}
|
||||
|
||||
@ -74,9 +125,9 @@ func (d *DAO) ListExperiments(status *int, offset, limit int) ([]*model.Experime
|
||||
var list []*model.Experiment
|
||||
for rows.Next() {
|
||||
exp := &model.Experiment{}
|
||||
var startTime, endTime model.NullTime
|
||||
var startTime, endTime, createdAt, updatedAt scannedTime
|
||||
if err := rows.Scan(&exp.ID, &exp.Name, &exp.Description, &exp.Status,
|
||||
&startTime, &endTime, &exp.CreatedAt, &exp.UpdatedAt); err != nil {
|
||||
&startTime, &endTime, &createdAt, &updatedAt); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if startTime.Valid {
|
||||
@ -85,6 +136,12 @@ func (d *DAO) ListExperiments(status *int, offset, limit int) ([]*model.Experime
|
||||
if endTime.Valid {
|
||||
exp.EndTime = &endTime.Time
|
||||
}
|
||||
if createdAt.Valid {
|
||||
exp.CreatedAt = createdAt.Time
|
||||
}
|
||||
if updatedAt.Valid {
|
||||
exp.UpdatedAt = updatedAt.Time
|
||||
}
|
||||
list = append(list, exp)
|
||||
}
|
||||
return list, total, nil
|
||||
@ -105,10 +162,16 @@ func (d *DAO) UpdateExperiment(id int64, req *model.UpdateExperimentReq) error {
|
||||
sets = append(sets, "status = ?")
|
||||
args = append(args, *req.Status)
|
||||
}
|
||||
if req.ClearStartTime {
|
||||
sets = append(sets, "start_time = NULL")
|
||||
}
|
||||
if req.StartTime != nil {
|
||||
sets = append(sets, "start_time = ?")
|
||||
args = append(args, *req.StartTime)
|
||||
}
|
||||
if req.ClearEndTime {
|
||||
sets = append(sets, "end_time = NULL")
|
||||
}
|
||||
if req.EndTime != nil {
|
||||
sets = append(sets, "end_time = ?")
|
||||
args = append(args, *req.EndTime)
|
||||
@ -123,6 +186,34 @@ func (d *DAO) UpdateExperiment(id int64, req *model.UpdateExperimentReq) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *DAO) ResetExperimentRelations(experimentID int64) error {
|
||||
tx, err := d.db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
if _, err := tx.Exec("DELETE FROM events WHERE experiment_id = ?", experimentID); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tx.Exec("DELETE FROM user_assignments WHERE experiment_id = ?", experimentID); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tx.Exec("DELETE FROM whitelist WHERE experiment_id = ?", experimentID); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tx.Exec("DELETE FROM variants WHERE experiment_id = ?", experimentID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (d *DAO) DeleteWhitelistByExperiment(experimentID int64) error {
|
||||
_, err := d.db.Exec("DELETE FROM whitelist WHERE experiment_id = ?", experimentID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *DAO) DeleteExperiment(id int64) error {
|
||||
tx, err := d.db.Begin()
|
||||
if err != nil {
|
||||
@ -171,13 +262,20 @@ func (d *DAO) GetVariant(id int64) (*model.Variant, error) {
|
||||
)
|
||||
v := &model.Variant{}
|
||||
var params []byte
|
||||
var createdAt, updatedAt scannedTime
|
||||
if err := row.Scan(&v.ID, &v.ExperimentID, &v.Name, &v.Description, &v.Weight,
|
||||
¶ms, &v.CreatedAt, &v.UpdatedAt); err != nil {
|
||||
¶ms, &createdAt, &updatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if params != nil {
|
||||
v.Params = json.RawMessage(params)
|
||||
}
|
||||
if createdAt.Valid {
|
||||
v.CreatedAt = createdAt.Time
|
||||
}
|
||||
if updatedAt.Valid {
|
||||
v.UpdatedAt = updatedAt.Time
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
@ -194,13 +292,20 @@ func (d *DAO) ListVariantsByExperiment(experimentID int64) ([]*model.Variant, er
|
||||
for rows.Next() {
|
||||
v := &model.Variant{}
|
||||
var params []byte
|
||||
var createdAt, updatedAt scannedTime
|
||||
if err := rows.Scan(&v.ID, &v.ExperimentID, &v.Name, &v.Description, &v.Weight,
|
||||
¶ms, &v.CreatedAt, &v.UpdatedAt); err != nil {
|
||||
¶ms, &createdAt, &updatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if params != nil {
|
||||
v.Params = json.RawMessage(params)
|
||||
}
|
||||
if createdAt.Valid {
|
||||
v.CreatedAt = createdAt.Time
|
||||
}
|
||||
if updatedAt.Valid {
|
||||
v.UpdatedAt = updatedAt.Time
|
||||
}
|
||||
list = append(list, v)
|
||||
}
|
||||
return list, nil
|
||||
@ -248,9 +353,13 @@ func (d *DAO) GetAssignment(experimentID int64, userID string) (*model.UserAssig
|
||||
experimentID, userID,
|
||||
)
|
||||
a := &model.UserAssignment{}
|
||||
if err := row.Scan(&a.ID, &a.ExperimentID, &a.UserID, &a.VariantID, &a.AssignedAt); err != nil {
|
||||
var assignedAt scannedTime
|
||||
if err := row.Scan(&a.ID, &a.ExperimentID, &a.UserID, &a.VariantID, &assignedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if assignedAt.Valid {
|
||||
a.AssignedAt = assignedAt.Time
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
@ -310,9 +419,9 @@ func (d *DAO) ListRunningExperiments() ([]*model.Experiment, error) {
|
||||
var list []*model.Experiment
|
||||
for rows.Next() {
|
||||
exp := &model.Experiment{}
|
||||
var startTime, endTime model.NullTime
|
||||
var startTime, endTime, createdAt, updatedAt scannedTime
|
||||
if err := rows.Scan(&exp.ID, &exp.Name, &exp.Description, &exp.Status,
|
||||
&startTime, &endTime, &exp.CreatedAt, &exp.UpdatedAt); err != nil {
|
||||
&startTime, &endTime, &createdAt, &updatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if startTime.Valid {
|
||||
@ -321,6 +430,12 @@ func (d *DAO) ListRunningExperiments() ([]*model.Experiment, error) {
|
||||
if endTime.Valid {
|
||||
exp.EndTime = &endTime.Time
|
||||
}
|
||||
if createdAt.Valid {
|
||||
exp.CreatedAt = createdAt.Time
|
||||
}
|
||||
if updatedAt.Valid {
|
||||
exp.UpdatedAt = updatedAt.Time
|
||||
}
|
||||
list = append(list, exp)
|
||||
}
|
||||
return list, nil
|
||||
@ -400,9 +515,13 @@ func (d *DAO) GetWhitelistEntry(experimentID int64, userID string) (*model.White
|
||||
experimentID, userID,
|
||||
)
|
||||
w := &model.Whitelist{}
|
||||
if err := row.Scan(&w.ID, &w.ExperimentID, &w.UserID, &w.VariantID, &w.CreatedAt); err != nil {
|
||||
var createdAt scannedTime
|
||||
if err := row.Scan(&w.ID, &w.ExperimentID, &w.UserID, &w.VariantID, &createdAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if createdAt.Valid {
|
||||
w.CreatedAt = createdAt.Time
|
||||
}
|
||||
return w, nil
|
||||
}
|
||||
|
||||
@ -438,9 +557,13 @@ func (d *DAO) ListWhitelistByExperiment(experimentID int64) ([]*model.Whitelist,
|
||||
var list []*model.Whitelist
|
||||
for rows.Next() {
|
||||
w := &model.Whitelist{}
|
||||
if err := rows.Scan(&w.ID, &w.ExperimentID, &w.UserID, &w.VariantID, &w.CreatedAt); err != nil {
|
||||
var createdAt scannedTime
|
||||
if err := rows.Scan(&w.ID, &w.ExperimentID, &w.UserID, &w.VariantID, &createdAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if createdAt.Valid {
|
||||
w.CreatedAt = createdAt.Time
|
||||
}
|
||||
list = append(list, w)
|
||||
}
|
||||
return list, nil
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
module github.com/abtest
|
||||
|
||||
go 1.25.5
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/bytedance/gopkg v0.1.3 // indirect
|
||||
github.com/bytedance/sonic v1.15.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.5.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
|
||||
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||
github.com/gin-gonic/gin v1.12.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.30.1 // indirect
|
||||
github.com/go-sql-driver/mysql v1.9.3 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/goccy/go-yaml v1.19.2 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/quic-go/qpack v0.6.0 // indirect
|
||||
github.com/quic-go/quic-go v0.59.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.3.1 // indirect
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
|
||||
golang.org/x/arch v0.22.0 // indirect
|
||||
golang.org/x/crypto v0.48.0 // indirect
|
||||
golang.org/x/net v0.51.0 // indirect
|
||||
golang.org/x/sys v0.41.0 // indirect
|
||||
golang.org/x/text v0.34.0 // indirect
|
||||
google.golang.org/protobuf v1.36.10 // indirect
|
||||
)
|
||||
@ -1,82 +0,0 @@
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
|
||||
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
||||
github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE=
|
||||
github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k=
|
||||
github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE=
|
||||
github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
|
||||
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
|
||||
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
|
||||
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
||||
github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8=
|
||||
github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w=
|
||||
github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM=
|
||||
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
|
||||
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
|
||||
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
||||
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
|
||||
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
|
||||
golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI=
|
||||
golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
||||
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@ -5,8 +5,9 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/abtest/model"
|
||||
"github.com/abtest/service"
|
||||
"backend/sdk/abtest/model"
|
||||
"backend/sdk/abtest/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
|
||||
@ -1,24 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/abtest/config"
|
||||
"github.com/abtest/dao"
|
||||
"github.com/abtest/handler"
|
||||
"github.com/abtest/router"
|
||||
"github.com/abtest/service"
|
||||
"backend/common"
|
||||
"backend/util"
|
||||
|
||||
"backend/sdk/abtest/config"
|
||||
|
||||
"backend/sdk/abtest/dao"
|
||||
"backend/sdk/abtest/handler"
|
||||
"backend/sdk/abtest/router"
|
||||
"backend/sdk/abtest/service"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cfg := config.Load()
|
||||
|
||||
// 连接 MySQL
|
||||
db, err := sql.Open("mysql", cfg.MySQL.DSN())
|
||||
common.Init()
|
||||
db, err := util.ConnectMysql("log", "abtest")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open mysql: %v", err)
|
||||
}
|
||||
|
||||
@ -67,11 +67,13 @@ type CreateExperimentReq struct {
|
||||
}
|
||||
|
||||
type UpdateExperimentReq struct {
|
||||
Name *string `json:"name"`
|
||||
Description *string `json:"description"`
|
||||
Status *int `json:"status"`
|
||||
StartTime *time.Time `json:"start_time"`
|
||||
EndTime *time.Time `json:"end_time"`
|
||||
Name *string `json:"name"`
|
||||
Description *string `json:"description"`
|
||||
Status *int `json:"status"`
|
||||
StartTime *time.Time `json:"start_time"`
|
||||
EndTime *time.Time `json:"end_time"`
|
||||
ClearStartTime bool
|
||||
ClearEndTime bool
|
||||
}
|
||||
|
||||
type CreateVariantReq struct {
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/abtest/handler"
|
||||
"backend/sdk/abtest/handler"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@ -18,17 +19,17 @@ func Setup(h *handler.Handler) *gin.Engine {
|
||||
// 实验管理
|
||||
experiments := api.Group("/experiments")
|
||||
{
|
||||
experiments.POST("", h.CreateExperiment)
|
||||
experiments.GET("", h.ListExperiments)
|
||||
experiments.GET("/:id", h.GetExperiment)
|
||||
experiments.PUT("/:id", h.UpdateExperiment)
|
||||
experiments.DELETE("/:id", h.DeleteExperiment)
|
||||
// experiments.POST("", h.CreateExperiment)
|
||||
// experiments.GET("", h.ListExperiments)
|
||||
// experiments.GET("/:id", h.GetExperiment)
|
||||
// experiments.PUT("/:id", h.UpdateExperiment)
|
||||
// experiments.DELETE("/:id", h.DeleteExperiment)
|
||||
|
||||
// 变体管理
|
||||
experiments.POST("/:id/variants", h.CreateVariant)
|
||||
experiments.GET("/:id/variants", h.ListVariants)
|
||||
experiments.PUT("/:id/variants/:variantId", h.UpdateVariant)
|
||||
experiments.DELETE("/:id/variants/:variantId", h.DeleteVariant)
|
||||
// // 变体管理
|
||||
// experiments.POST("/:id/variants", h.CreateVariant)
|
||||
// experiments.GET("/:id/variants", h.ListVariants)
|
||||
// experiments.PUT("/:id/variants/:variantId", h.UpdateVariant)
|
||||
// experiments.DELETE("/:id/variants/:variantId", h.DeleteVariant)
|
||||
|
||||
// 用户分流
|
||||
experiments.POST("/:id/assign", h.AssignUser)
|
||||
|
||||
@ -7,8 +7,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/abtest/dao"
|
||||
"github.com/abtest/model"
|
||||
"backend/sdk/abtest/dao"
|
||||
"backend/sdk/abtest/model"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -80,6 +80,20 @@ func (s *Service) DeleteExperiment(id int64) error {
|
||||
return s.dao.DeleteExperiment(id)
|
||||
}
|
||||
|
||||
func (s *Service) ResetExperimentRelations(experimentID int64) error {
|
||||
if _, err := s.GetExperiment(experimentID); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.dao.ResetExperimentRelations(experimentID)
|
||||
}
|
||||
|
||||
func (s *Service) ClearWhitelist(experimentID int64) error {
|
||||
if _, err := s.GetExperiment(experimentID); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.dao.DeleteWhitelistByExperiment(experimentID)
|
||||
}
|
||||
|
||||
// ==================== Variant ====================
|
||||
|
||||
func (s *Service) CreateVariant(experimentID int64, req *model.CreateVariantReq) (*model.Variant, error) {
|
||||
|
||||
159
unit_test.go
159
unit_test.go
@ -140,9 +140,9 @@ func TestEncrypt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDecrypt(t *testing.T) {
|
||||
str := "Z4rf7eZZe500dxa"
|
||||
str := "linyiling123"
|
||||
enc, _ := util.Encrypt(str)
|
||||
dec, _ := util.Decrypt("XGXZ_ID17eupWm0sVAarKaFjwAI_2Ve7dMb3")
|
||||
dec, _ := util.Decrypt("mz-AJj2wjQ5F6MY5hbxiqsfqcwjRj8P85w==")
|
||||
fmt.Printf("enc:%s\ndec:%s\n", enc, dec)
|
||||
}
|
||||
|
||||
@ -534,5 +534,160 @@ func TestAlibabaOss(t *testing.T) {
|
||||
err := common.Init()
|
||||
if err != nil {
|
||||
fmt.Println("Error initializing common:", err)
|
||||
return
|
||||
}
|
||||
content := `
|
||||
{
|
||||
"schedules": [
|
||||
{
|
||||
"id": 10001,
|
||||
"scheduleType": 0,
|
||||
"deltaTime": {
|
||||
"ticks": 1728000000000
|
||||
},
|
||||
"repeats": false,
|
||||
"fireTime": {
|
||||
"ticks": 639086752456801235
|
||||
},
|
||||
"repeatInterval": 0,
|
||||
"cancelType": 1,
|
||||
"cancelValue": 3
|
||||
},
|
||||
{
|
||||
"id": 10002,
|
||||
"scheduleType": 1,
|
||||
"deltaTime": {
|
||||
"ticks": 0
|
||||
},
|
||||
"repeats": false,
|
||||
"fireTime": {
|
||||
"ticks": 639337539300000000
|
||||
},
|
||||
"repeatInterval": 0,
|
||||
"cancelType": 0,
|
||||
"cancelValue": 0
|
||||
},
|
||||
{
|
||||
"id": 10000,
|
||||
"scheduleType": 0,
|
||||
"deltaTime": {
|
||||
"ticks": 1200000000
|
||||
},
|
||||
"repeats": true,
|
||||
"fireTime": {
|
||||
"ticks": 639086752456846041
|
||||
},
|
||||
"repeatInterval": 0,
|
||||
"cancelType": 1,
|
||||
"cancelValue": 0
|
||||
}
|
||||
],
|
||||
"presentations": [
|
||||
{
|
||||
"id": 90001,
|
||||
"titles": [
|
||||
{
|
||||
"language": 10,
|
||||
"locText": "Merry Christmas",
|
||||
"param": 0
|
||||
},
|
||||
{
|
||||
"language": 40,
|
||||
"locText": "圣诞快乐",
|
||||
"param": 0
|
||||
}
|
||||
],
|
||||
"infos": [
|
||||
{
|
||||
"language": 10,
|
||||
"locText": "Merry Christmas!",
|
||||
"param": 0
|
||||
},
|
||||
{
|
||||
"language": 40,
|
||||
"locText": "圣诞快乐!",
|
||||
"param": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 90002,
|
||||
"titles": [
|
||||
{
|
||||
"language": 10,
|
||||
"locText": "{0} is waiting for you to come home",
|
||||
"param": 1
|
||||
},
|
||||
{
|
||||
"language": 40,
|
||||
"locText": "{0}正在等你回家",
|
||||
"param": 1
|
||||
}
|
||||
],
|
||||
"infos": [
|
||||
{
|
||||
"language": 10,
|
||||
"locText": "{0} is hungry and misses you - come back soon!",
|
||||
"param": 1
|
||||
},
|
||||
{
|
||||
"language": 40,
|
||||
"locText": "{0}肚子饿了,很想你,快回来看看吧",
|
||||
"param": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 90000,
|
||||
"titles": [
|
||||
{
|
||||
"language": 10,
|
||||
"locText": "Test",
|
||||
"param": 0
|
||||
},
|
||||
{
|
||||
"language": 40,
|
||||
"locText": "测试",
|
||||
"param": 0
|
||||
}
|
||||
],
|
||||
"infos": [
|
||||
{
|
||||
"language": 10,
|
||||
"locText": "UserName: {0} is testing",
|
||||
"param": 2
|
||||
},
|
||||
{
|
||||
"language": 40,
|
||||
"locText": "用户{0}测试中",
|
||||
"param": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"activeNotis": [
|
||||
{
|
||||
"id": 60000000,
|
||||
"scheduleId": 10000,
|
||||
"conditionId": 40001,
|
||||
"presentationId": 90000
|
||||
}
|
||||
],
|
||||
"inactiveNotis": [
|
||||
{
|
||||
"id": 60000001,
|
||||
"scheduleId": 10001,
|
||||
"conditionId": 40002,
|
||||
"presentationId": 90002
|
||||
},
|
||||
{
|
||||
"id": 60000002,
|
||||
"scheduleId": 10002,
|
||||
"conditionId": 40001,
|
||||
"presentationId": 90001
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
alibaba.Osscreate(content)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user