IP库增加制品管理/统计中相关区域名称可以显示别名

This commit is contained in:
刘祥超
2022-08-23 19:40:17 +08:00
parent 455952e9e4
commit c552eb3b0e
16 changed files with 479 additions and 18 deletions

View File

@@ -0,0 +1,140 @@
package models
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
stringutil "github.com/iwind/TeaGo/utils/string"
)
const (
IPLibraryArtifactStateEnabled = 1 // 已启用
IPLibraryArtifactStateDisabled = 0 // 已禁用
)
type IPLibraryArtifactDAO dbs.DAO
func NewIPLibraryArtifactDAO() *IPLibraryArtifactDAO {
return dbs.NewDAO(&IPLibraryArtifactDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeIPLibraryArtifacts",
Model: new(IPLibraryArtifact),
PkName: "id",
},
}).(*IPLibraryArtifactDAO)
}
var SharedIPLibraryArtifactDAO *IPLibraryArtifactDAO
func init() {
dbs.OnReady(func() {
SharedIPLibraryArtifactDAO = NewIPLibraryArtifactDAO()
})
}
// EnableIPLibraryArtifact 启用条目
func (this *IPLibraryArtifactDAO) EnableIPLibraryArtifact(tx *dbs.Tx, id int64) error {
_, err := this.Query(tx).
Pk(id).
Set("state", IPLibraryArtifactStateEnabled).
Update()
return err
}
// DisableIPLibraryArtifact 禁用条目
func (this *IPLibraryArtifactDAO) DisableIPLibraryArtifact(tx *dbs.Tx, id int64) error {
_, err := this.Query(tx).
Pk(id).
Set("state", IPLibraryArtifactStateDisabled).
Update()
return err
}
// FindEnabledIPLibraryArtifact 查找启用中的条目
func (this *IPLibraryArtifactDAO) FindEnabledIPLibraryArtifact(tx *dbs.Tx, id int64) (*IPLibraryArtifact, error) {
result, err := this.Query(tx).
Pk(id).
State(IPLibraryArtifactStateEnabled).
Find()
if result == nil {
return nil, err
}
return result.(*IPLibraryArtifact), err
}
// CreateArtifact 创建制品
func (this *IPLibraryArtifactDAO) CreateArtifact(tx *dbs.Tx, name string, fileId int64, libraryFileId int64, meta *iplibrary.Meta) (int64, error) {
var op = NewIPLibraryArtifactOperator()
op.Name = name
op.FileId = fileId
op.LibraryFileId = libraryFileId
metaJSON, err := json.Marshal(meta)
if err != nil {
return 0, err
}
op.Meta = metaJSON
op.State = IPLibraryArtifactStateEnabled
var code = stringutil.Md5(utils.Sha1RandomString())[:8]
meta.Code = code
op.Code = code // 要比较短,方便识别
return this.SaveInt64(tx, op)
}
// FindAllArtifacts 查找制品列表
func (this *IPLibraryArtifactDAO) FindAllArtifacts(tx *dbs.Tx) (result []*IPLibraryArtifact, err error) {
_, err = this.Query(tx).
State(IPLibraryArtifactStateEnabled).
DescPk().
Slice(&result).
FindAll()
return
}
// FindPublicArtifact 查找当前使用的制品
func (this *IPLibraryArtifactDAO) FindPublicArtifact(tx *dbs.Tx) (*IPLibraryArtifact, error) {
one, err := this.Query(tx).
State(IPLibraryArtifactStateEnabled).
Attr("isPublic", true).
Result("id", "fileId", "code").
Find()
if err != nil || one == nil {
return nil, err
}
return one.(*IPLibraryArtifact), nil
}
// UpdateArtifactPublic 使用某个制品
func (this *IPLibraryArtifactDAO) UpdateArtifactPublic(tx *dbs.Tx, artifactId int64, isPublic bool) error {
// 取消使用
if !isPublic {
return this.Query(tx).
Pk(artifactId).
Set("isPublic", false).
UpdateQuickly()
}
// 使用
// 先取消别的
err := this.Query(tx).
Neq("id", artifactId).
State(IPLibraryArtifactStateEnabled).
Attr("isPublic", true).
Set("isPublic", false).
UpdateQuickly()
if err != nil {
return err
}
return this.Query(tx).
Pk(artifactId).
Set("isPublic", true).
UpdateQuickly()
}

View File

@@ -0,0 +1,6 @@
package models_test
import (
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
)

View File

@@ -0,0 +1,32 @@
package models
import "github.com/iwind/TeaGo/dbs"
// IPLibraryArtifact IP库制品
type IPLibraryArtifact struct {
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 名称
FileId uint64 `field:"fileId"` // 文件ID
LibraryFileId uint32 `field:"libraryFileId"` // IP库文件ID
CreatedAt uint64 `field:"createdAt"` // 创建时间
Meta dbs.JSON `field:"meta"` // 元数据
IsPublic bool `field:"isPublic"` // 是否为公用
Code string `field:"code"` // 代号
State uint8 `field:"state"` // 状态
}
type IPLibraryArtifactOperator struct {
Id any // ID
Name any // 名称
FileId any // 文件ID
LibraryFileId any // IP库文件ID
CreatedAt any // 创建时间
Meta any // 元数据
IsPublic any // 是否为公用
Code any // 代号
State any // 状态
}
func NewIPLibraryArtifactOperator() *IPLibraryArtifactOperator {
return &IPLibraryArtifactOperator{}
}

View File

@@ -0,0 +1 @@
package models

View File

@@ -405,7 +405,7 @@ func (this *IPLibraryFileDAO) GenerateIPLibrary(tx *dbs.Tx, libraryFileId int64)
var libraryCode = utils.Sha1RandomString() // 每次都生成新的code var libraryCode = utils.Sha1RandomString() // 每次都生成新的code
var filePath = dir + "/" + this.composeFilename(libraryFileId, libraryCode) var filePath = dir + "/" + this.composeFilename(libraryFileId, libraryCode)
writer, err := iplibrary.NewFileWriter(filePath, &iplibrary.Meta{ var meta = &iplibrary.Meta{
Author: "", // 将来用户可以自行填写 Author: "", // 将来用户可以自行填写
CreatedAt: time.Now().Unix(), CreatedAt: time.Now().Unix(),
Countries: countries, Countries: countries,
@@ -413,13 +413,15 @@ func (this *IPLibraryFileDAO) GenerateIPLibrary(tx *dbs.Tx, libraryFileId int64)
Cities: cities, Cities: cities,
Towns: towns, Towns: towns,
Providers: providers, Providers: providers,
}) }
writer, err := iplibrary.NewFileWriter(filePath, meta)
if err != nil { if err != nil {
return err return err
} }
defer func() { defer func() {
_ = writer.Close() _ = writer.Close()
_ = os.Remove(filePath)
}() }()
err = writer.WriteMeta() err = writer.WriteMeta()
@@ -576,6 +578,12 @@ func (this *IPLibraryFileDAO) GenerateIPLibrary(tx *dbs.Tx, libraryFileId int64)
return err return err
} }
// 添加制品
_, err = SharedIPLibraryArtifactDAO.CreateArtifact(tx, libraryFile.Name, generatedFileId, libraryFileId, meta)
if err != nil {
return err
}
return nil return nil
} }

View File

@@ -89,7 +89,7 @@ func (this *APINode) Start() {
// 启动IP库 // 启动IP库
remotelogs.Println("API_NODE", "initializing ip library ...") remotelogs.Println("API_NODE", "initializing ip library ...")
err = iplibrary.Init() err = iplibrary.InitDefault()
if err != nil { if err != nil {
remotelogs.Error("API_NODE", "initialize ip library failed: "+err.Error()) remotelogs.Error("API_NODE", "initialize ip library failed: "+err.Error())
} }

View File

@@ -247,6 +247,11 @@ func (this *APINode) registerServices(server *grpc.Server) {
pb.RegisterIPLibraryFileServiceServer(server, instance) pb.RegisterIPLibraryFileServiceServer(server, instance)
this.rest(instance) this.rest(instance)
} }
{
var instance = this.serviceInstance(&services.IPLibraryArtifactService{}).(*services.IPLibraryArtifactService)
pb.RegisterIPLibraryArtifactServiceServer(server, instance)
this.rest(instance)
}
{ {
var instance = this.serviceInstance(&services.FileChunkService{}).(*services.FileChunkService) var instance = this.serviceInstance(&services.FileChunkService{}).(*services.FileChunkService)
pb.RegisterFileChunkServiceServer(server, instance) pb.RegisterFileChunkServiceServer(server, instance)

View File

@@ -0,0 +1,105 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package nodes
import (
"errors"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/goman"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/types"
"io"
"os"
"time"
)
func init() {
dbs.OnReady(func() {
goman.New(func() {
iplibrary.NewUpdater(NewIPLibraryUpdater(), 10*time.Minute).Start()
})
})
}
type IPLibraryUpdater struct {
}
func NewIPLibraryUpdater() *IPLibraryUpdater {
return &IPLibraryUpdater{}
}
// DataDir 文件目录
func (this *IPLibraryUpdater) DataDir() string {
// data/
var dir = Tea.Root + "/data"
stat, err := os.Stat(dir)
if err == nil && stat.IsDir() {
return dir
}
err = os.Mkdir(dir, 0666)
if err == nil {
return dir
}
remotelogs.Error("IP_LIBRARY_UPDATER", "create directory '"+dir+"' failed: "+err.Error())
// 如果不能创建 data/ 目录,那么使用临时目录
return os.TempDir()
}
// FindLatestFile 检查最新的IP库文件
func (this *IPLibraryUpdater) FindLatestFile() (code string, fileId int64, err error) {
artifact, err := models.SharedIPLibraryArtifactDAO.FindPublicArtifact(nil)
if err != nil {
return "", 0, err
}
if artifact == nil {
return "", 0, nil
}
return artifact.Code, int64(artifact.FileId), nil
}
// DownloadFile 下载文件
func (this *IPLibraryUpdater) DownloadFile(fileId int64, writer io.Writer) error {
if fileId <= 0 {
return errors.New("invalid fileId: " + types.String(fileId))
}
var tx *dbs.Tx
chunkIds, err := models.SharedFileChunkDAO.FindAllFileChunkIds(tx, fileId)
if err != nil {
return err
}
for _, chunkId := range chunkIds {
chunk, err := models.SharedFileChunkDAO.FindFileChunk(tx, chunkId)
if err != nil {
return err
}
if chunk == nil {
return errors.New("can not find file chunk with chunk id '" + types.String(chunkId) + "'")
}
_, err = writer.Write(chunk.Data)
if err != nil {
return err
}
}
return nil
}
// LogInfo 普通日志
func (this *IPLibraryUpdater) LogInfo(message string) {
remotelogs.Println("IP_LIBRARY_UPDATER", message)
}
// LogError 错误日志
func (this *IPLibraryUpdater) LogError(err error) {
if err == nil {
return
}
remotelogs.Error("IP_LIBRARY_UPDATER", err.Error())
}

View File

@@ -40,7 +40,7 @@ func (this *FileChunkService) CreateFileChunk(ctx context.Context, req *pb.Creat
// FindAllFileChunkIds 获取的一个文件的所有片段IDs // FindAllFileChunkIds 获取的一个文件的所有片段IDs
func (this *FileChunkService) FindAllFileChunkIds(ctx context.Context, req *pb.FindAllFileChunkIdsRequest) (*pb.FindAllFileChunkIdsResponse, error) { func (this *FileChunkService) FindAllFileChunkIds(ctx context.Context, req *pb.FindAllFileChunkIdsRequest) (*pb.FindAllFileChunkIdsResponse, error) {
// 校验请求 // 校验请求
_, _, err := this.ValidateNodeId(ctx, rpcutils.UserTypeNode, rpcutils.UserTypeAdmin, rpcutils.UserTypeUser) _, _, err := this.ValidateNodeId(ctx, rpcutils.UserTypeNode, rpcutils.UserTypeDNS, rpcutils.UserTypeAdmin, rpcutils.UserTypeUser)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -60,7 +60,7 @@ func (this *FileChunkService) FindAllFileChunkIds(ctx context.Context, req *pb.F
// DownloadFileChunk 下载文件片段 // DownloadFileChunk 下载文件片段
func (this *FileChunkService) DownloadFileChunk(ctx context.Context, req *pb.DownloadFileChunkRequest) (*pb.DownloadFileChunkResponse, error) { func (this *FileChunkService) DownloadFileChunk(ctx context.Context, req *pb.DownloadFileChunkRequest) (*pb.DownloadFileChunkResponse, error) {
// 校验请求 // 校验请求
_, _, err := this.ValidateNodeId(ctx, rpcutils.UserTypeNode, rpcutils.UserTypeAdmin, rpcutils.UserTypeUser) _, _, err := this.ValidateNodeId(ctx, rpcutils.UserTypeNode, rpcutils.UserTypeDNS, rpcutils.UserTypeAdmin, rpcutils.UserTypeUser)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -0,0 +1,164 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package services
import (
"context"
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
// IPLibraryArtifactService IP库制品
type IPLibraryArtifactService struct {
BaseService
}
// CreateIPLibraryArtifact 创建制品
func (this *IPLibraryArtifactService) CreateIPLibraryArtifact(ctx context.Context, req *pb.CreateIPLibraryArtifactRequest) (*pb.CreateIPLibraryArtifactResponse, error) {
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
var tx = this.NullTx()
var meta = &iplibrary.Meta{}
err = json.Unmarshal(req.MetaJSON, meta)
if err != nil {
return nil, errors.New("decode meta failed: " + err.Error())
}
artifactId, err := models.SharedIPLibraryArtifactDAO.CreateArtifact(tx, req.Name, req.FileId, 0, meta)
if err != nil {
return nil, err
}
return &pb.CreateIPLibraryArtifactResponse{IpLibraryArtifactId: artifactId}, nil
}
// UpdateIPLibraryArtifactIsPublic 使用/取消使用制品
func (this *IPLibraryArtifactService) UpdateIPLibraryArtifactIsPublic(ctx context.Context, req *pb.UpdateIPLibraryArtifactIsPublicRequest) (*pb.RPCSuccess, error) {
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
var tx = this.NullTx()
err = models.SharedIPLibraryArtifactDAO.UpdateArtifactPublic(tx, req.IpLibraryArtifactId, req.IsPublic)
if err != nil {
return nil, err
}
return this.Success()
}
// FindAllIPLibraryArtifacts 查询所有制品
func (this *IPLibraryArtifactService) FindAllIPLibraryArtifacts(ctx context.Context, req *pb.FindAllIPLibraryArtifactsRequest) (*pb.FindAllIPLibraryArtifactsResponse, error) {
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
var tx = this.NullTx()
artifacts, err := models.SharedIPLibraryArtifactDAO.FindAllArtifacts(tx)
if err != nil {
return nil, err
}
var pbArtifacts = []*pb.IPLibraryArtifact{}
for _, artifact := range artifacts {
pbArtifacts = append(pbArtifacts, &pb.IPLibraryArtifact{
Id: int64(artifact.Id),
Name: artifact.Name,
FileId: int64(artifact.FileId),
CreatedAt: int64(artifact.CreatedAt),
MetaJSON: artifact.Meta,
IsPublic: artifact.IsPublic,
Code: artifact.Code,
})
}
return &pb.FindAllIPLibraryArtifactsResponse{
IpLibraryArtifacts: pbArtifacts,
}, nil
}
// FindIPLibraryArtifact 查找当前正在使用的制品
func (this *IPLibraryArtifactService) FindIPLibraryArtifact(ctx context.Context, req *pb.FindIPLibraryArtifactRequest) (*pb.FindIPLibraryArtifactResponse, error) {
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
var tx = this.NullTx()
artifact, err := models.SharedIPLibraryArtifactDAO.FindEnabledIPLibraryArtifact(tx, req.IpLibraryArtifactId)
if err != nil {
return nil, err
}
if artifact == nil {
return &pb.FindIPLibraryArtifactResponse{
IpLibraryArtifact: nil,
}, nil
}
return &pb.FindIPLibraryArtifactResponse{
IpLibraryArtifact: &pb.IPLibraryArtifact{
Id: int64(artifact.Id),
FileId: int64(artifact.FileId),
CreatedAt: int64(artifact.CreatedAt),
MetaJSON: artifact.Meta,
IsPublic: artifact.IsPublic,
Code: artifact.Code,
},
}, nil
}
// FindPublicIPLibraryArtifact 查找当前正在使用的制品
func (this *IPLibraryArtifactService) FindPublicIPLibraryArtifact(ctx context.Context, req *pb.FindPublicIPLibraryArtifactRequest) (*pb.FindPublicIPLibraryArtifactResponse, error) {
_, _, err := this.ValidateNodeId(ctx, rpcutils.UserTypeNode, rpcutils.UserTypeDNS)
if err != nil {
return nil, err
}
var tx = this.NullTx()
artifact, err := models.SharedIPLibraryArtifactDAO.FindPublicArtifact(tx)
if err != nil {
return nil, err
}
if artifact == nil {
return &pb.FindPublicIPLibraryArtifactResponse{
IpLibraryArtifact: nil,
}, nil
}
return &pb.FindPublicIPLibraryArtifactResponse{
IpLibraryArtifact: &pb.IPLibraryArtifact{
Id: int64(artifact.Id),
FileId: int64(artifact.FileId),
CreatedAt: int64(artifact.CreatedAt),
MetaJSON: artifact.Meta,
IsPublic: artifact.IsPublic,
Code: artifact.Code,
},
}, nil
}
// DeleteIPLibraryArtifact 删除制品
func (this *IPLibraryArtifactService) DeleteIPLibraryArtifact(ctx context.Context, req *pb.DeleteIPLibraryArtifactRequest) (*pb.RPCSuccess, error) {
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
var tx = this.NullTx()
err = models.SharedIPLibraryArtifactDAO.DisableIPLibraryArtifact(tx, req.IpLibraryArtifactId)
if err != nil {
return nil, err
}
return this.Success()
}

View File

@@ -88,7 +88,7 @@ func (this *RegionProvinceService) FindAllRegionProvincesWithRegionCountryId(ctx
if err != nil { if err != nil {
return nil, err return nil, err
} }
result := []*pb.RegionProvince{} var result = []*pb.RegionProvince{}
for _, province := range provinces { for _, province := range provinces {
result = append(result, &pb.RegionProvince{ result = append(result, &pb.RegionProvince{
Id: int64(province.Id), Id: int64(province.Id),

View File

@@ -32,7 +32,7 @@ func (this *ServerRegionCityMonthlyStatService) FindTopServerRegionCityMonthlySt
if err != nil { if err != nil {
return nil, err return nil, err
} }
pbStats := []*pb.FindTopServerRegionCityMonthlyStatsResponse_Stat{} var pbStats = []*pb.FindTopServerRegionCityMonthlyStatsResponse_Stat{}
for _, stat := range statList { for _, stat := range statList {
pbStat := &pb.FindTopServerRegionCityMonthlyStatsResponse_Stat{ pbStat := &pb.FindTopServerRegionCityMonthlyStatsResponse_Stat{
Count: int64(stat.Count), Count: int64(stat.Count),
@@ -63,15 +63,15 @@ func (this *ServerRegionCityMonthlyStatService) FindTopServerRegionCityMonthlySt
} }
pbStat.RegionCountry = &pb.RegionCountry{ pbStat.RegionCountry = &pb.RegionCountry{
Id: int64(country.Id), Id: int64(country.Id),
Name: country.Name, Name: country.DisplayName(),
} }
pbStat.RegionProvince = &pb.RegionProvince{ pbStat.RegionProvince = &pb.RegionProvince{
Id: int64(province.Id), Id: int64(province.Id),
Name: province.Name, Name: province.DisplayName(),
} }
pbStat.RegionCity = &pb.RegionCity{ pbStat.RegionCity = &pb.RegionCity{
Id: int64(city.Id), Id: int64(city.Id),
Name: city.Name, Name: city.DisplayName(),
} }
pbStats = append(pbStats, pbStat) pbStats = append(pbStats, pbStat)
} }

View File

@@ -32,7 +32,7 @@ func (this *ServerRegionCountryMonthlyStatService) FindTopServerRegionCountryMon
if err != nil { if err != nil {
return nil, err return nil, err
} }
pbStats := []*pb.FindTopServerRegionCountryMonthlyStatsResponse_Stat{} var pbStats = []*pb.FindTopServerRegionCountryMonthlyStatsResponse_Stat{}
for _, stat := range statList { for _, stat := range statList {
pbStat := &pb.FindTopServerRegionCountryMonthlyStatsResponse_Stat{ pbStat := &pb.FindTopServerRegionCountryMonthlyStatsResponse_Stat{
Count: int64(stat.Count), Count: int64(stat.Count),
@@ -47,7 +47,7 @@ func (this *ServerRegionCountryMonthlyStatService) FindTopServerRegionCountryMon
} }
pbStat.RegionCountry = &pb.RegionCountry{ pbStat.RegionCountry = &pb.RegionCountry{
Id: int64(country.Id), Id: int64(country.Id),
Name: country.Name, Name: country.DisplayName(),
} }
pbStats = append(pbStats, pbStat) pbStats = append(pbStats, pbStat)

View File

@@ -32,7 +32,7 @@ func (this *ServerRegionProviderMonthlyStatService) FindTopServerRegionProviderM
if err != nil { if err != nil {
return nil, err return nil, err
} }
pbStats := []*pb.FindTopServerRegionProviderMonthlyStatsResponse_Stat{} var pbStats = []*pb.FindTopServerRegionProviderMonthlyStatsResponse_Stat{}
for _, stat := range statList { for _, stat := range statList {
pbStat := &pb.FindTopServerRegionProviderMonthlyStatsResponse_Stat{ pbStat := &pb.FindTopServerRegionProviderMonthlyStatsResponse_Stat{
Count: int64(stat.Count), Count: int64(stat.Count),
@@ -46,7 +46,7 @@ func (this *ServerRegionProviderMonthlyStatService) FindTopServerRegionProviderM
} }
pbStat.RegionProvider = &pb.RegionProvider{ pbStat.RegionProvider = &pb.RegionProvider{
Id: int64(provider.Id), Id: int64(provider.Id),
Name: provider.Name, Name: provider.DisplayName(),
} }
pbStats = append(pbStats, pbStat) pbStats = append(pbStats, pbStat)
} }

View File

@@ -32,7 +32,7 @@ func (this *ServerRegionProvinceMonthlyStatService) FindTopServerRegionProvinceM
if err != nil { if err != nil {
return nil, err return nil, err
} }
pbStats := []*pb.FindTopServerRegionProvinceMonthlyStatsResponse_Stat{} var pbStats = []*pb.FindTopServerRegionProvinceMonthlyStatsResponse_Stat{}
for _, stat := range statList { for _, stat := range statList {
pbStat := &pb.FindTopServerRegionProvinceMonthlyStatsResponse_Stat{ pbStat := &pb.FindTopServerRegionProvinceMonthlyStatsResponse_Stat{
Count: int64(stat.Count), Count: int64(stat.Count),
@@ -53,11 +53,11 @@ func (this *ServerRegionProvinceMonthlyStatService) FindTopServerRegionProvinceM
} }
pbStat.RegionCountry = &pb.RegionCountry{ pbStat.RegionCountry = &pb.RegionCountry{
Id: int64(country.Id), Id: int64(country.Id),
Name: country.Name, Name: country.DisplayName(),
} }
pbStat.RegionProvince = &pb.RegionProvince{ pbStat.RegionProvince = &pb.RegionProvince{
Id: int64(province.Id), Id: int64(province.Id),
Name: province.Name, Name: province.DisplayName(),
} }
pbStats = append(pbStats, pbStat) pbStats = append(pbStats, pbStat)
} }

File diff suppressed because one or more lines are too long