版本更新
This commit is contained in:
parent
1a66367ca9
commit
630c5ebd77
1
.gitignore
vendored
1
.gitignore
vendored
@ -12,3 +12,4 @@ log/*.log
|
||||
*.log
|
||||
runtime/*.db
|
||||
config/*
|
||||
unit/config/*
|
||||
BIN
GeoLite2-Country/GeoLite2-City.mmdb
Normal file
BIN
GeoLite2-Country/GeoLite2-City.mmdb
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 MiB |
@ -92,6 +92,7 @@ type ServerInfo struct {
|
||||
CreateTime int `json:"CreateTime" db:"CreateTime"`
|
||||
OpenServerTime int `json:"OpenServerTime" db:"OpenServerTime"`
|
||||
WsPort int `json:"WsPort" db:"ws_port"`
|
||||
Port int `json:"Port" db:"Port"`
|
||||
Host string `json:"Host" db:"Host"`
|
||||
StartTime int64 `json:"StartTime"`
|
||||
PlayerNum int `json:"PlayerNum" db:"Online"`
|
||||
@ -101,6 +102,7 @@ type ServerInfo struct {
|
||||
NodeTags string `json:"-" db:"node_tags"`
|
||||
Tags []string `json:"Tags" db:"-"`
|
||||
ECS int `json:"ECS" db:"ecs"`
|
||||
Latency int `json:"Latency" db:"latency"`
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
|
||||
100
alibaba/card.go
100
alibaba/card.go
@ -193,6 +193,9 @@ func SendZabbixMsg(data *Type.NotifyData) (_err error) {
|
||||
// 卡片接收人
|
||||
Recipients: []*string{},
|
||||
}
|
||||
if data.Severity != "Disaster" && data.Severity != "High" {
|
||||
return nil
|
||||
}
|
||||
if data.Severity == "Disaster" || data.Severity == "High" {
|
||||
imGroupOpenDeliverModel.Recipients = []*string{tea.String("035105216620273488")}
|
||||
imGroupOpenDeliverModel.AtUserIds = map[string]*string{
|
||||
@ -292,6 +295,9 @@ func SendZabbixRecoveryMsg(data *Type.NotifyRecoveryData) (_err error) {
|
||||
// 卡片接收人
|
||||
Recipients: []*string{},
|
||||
}
|
||||
if data.Severity != "Disaster" && data.Severity != "High" {
|
||||
return nil
|
||||
}
|
||||
imGroupOpenSpaceModelLastMessageI18n := map[string]*string{
|
||||
"ZH_CN": tea.String(lastMessage),
|
||||
}
|
||||
@ -458,6 +464,100 @@ func SendStandardMsg(title, content, color string) (_err error) {
|
||||
return _err
|
||||
}
|
||||
|
||||
func SendStandardMsg2(title, content, color string) (_err error) {
|
||||
client, _err := createCardClient()
|
||||
if _err != nil {
|
||||
return _err
|
||||
}
|
||||
|
||||
accessToken, _ := GetToken()
|
||||
robotCode := "dingrmgtodzxaik76jpc"
|
||||
userId := ""
|
||||
openConversationId := "cidivmW+tO/JGyIFM/XHNeQcA=="
|
||||
templateId := "843a23ff-29d2-4efc-b7f4-2dea2766d7db.schema"
|
||||
lastMessage := title
|
||||
searchIcon := ""
|
||||
searchDesc := ""
|
||||
|
||||
createAndDeliverHeaders := &dingtalkcard_1_0.CreateAndDeliverHeaders{}
|
||||
createAndDeliverHeaders.XAcsDingtalkAccessToken = tea.String(accessToken)
|
||||
|
||||
imGroupOpenDeliverModel := &dingtalkcard_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{
|
||||
RobotCode: tea.String(robotCode),
|
||||
// 卡片接收人
|
||||
Recipients: []*string{},
|
||||
AtUserIds: map[string]*string{
|
||||
"@ALL": tea.String("@ALL"),
|
||||
},
|
||||
}
|
||||
imGroupOpenSpaceModelLastMessageI18n := map[string]*string{
|
||||
"ZH_CN": tea.String(lastMessage),
|
||||
}
|
||||
imGroupOpenSpaceModelSearchSupport := &dingtalkcard_1_0.CreateAndDeliverRequestImGroupOpenSpaceModelSearchSupport{
|
||||
SearchIcon: tea.String(searchIcon),
|
||||
SearchDesc: tea.String(searchDesc),
|
||||
}
|
||||
imGroupOpenSpaceModel := &dingtalkcard_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{
|
||||
SupportForward: tea.Bool(true),
|
||||
LastMessageI18n: imGroupOpenSpaceModelLastMessageI18n,
|
||||
SearchSupport: imGroupOpenSpaceModelSearchSupport,
|
||||
}
|
||||
|
||||
// 此处使用了 MockData 作为测试数据,请结合真实场景设置卡片公有数据
|
||||
cardDataCardParamMap := map[string]any{
|
||||
"title": title,
|
||||
"markdown": content,
|
||||
"color": color,
|
||||
"config": map[string]any{
|
||||
"autoLayout": true,
|
||||
},
|
||||
}
|
||||
cardDataError := error(nil)
|
||||
_ = cardDataError
|
||||
cardData := &dingtalkcard_1_0.CreateAndDeliverRequestCardData{
|
||||
CardParamMap: convertJSONValuesToString(cardDataCardParamMap),
|
||||
}
|
||||
createAndDeliverRequest := &dingtalkcard_1_0.CreateAndDeliverRequest{
|
||||
UserId: tea.String(userId),
|
||||
CardTemplateId: tea.String(templateId),
|
||||
// 用于标识卡片的唯一 ID,业务需自行建立关联关系,用于后续的卡片更新
|
||||
OutTrackId: tea.String(fmt.Sprintf("standard-out-track-id-%d", time.Now().Unix())),
|
||||
CallbackType: tea.String("STREAM"),
|
||||
CardData: cardData,
|
||||
ImGroupOpenSpaceModel: imGroupOpenSpaceModel,
|
||||
ImGroupOpenDeliverModel: imGroupOpenDeliverModel,
|
||||
OpenSpaceId: tea.String(fmt.Sprintf("dtv1.card//im_group.%s", openConversationId)),
|
||||
UserIdType: tea.Int32(1),
|
||||
// CardAtUserIds: []*string{tea.String("all")},
|
||||
}
|
||||
tryErr := func() (_e error) {
|
||||
defer func() {
|
||||
if r := tea.Recover(recover()); r != nil {
|
||||
_e = r
|
||||
}
|
||||
}()
|
||||
_, _err = client.CreateAndDeliverWithOptions(createAndDeliverRequest, createAndDeliverHeaders, &util.RuntimeOptions{})
|
||||
if _err != nil {
|
||||
return _err
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
if tryErr != nil {
|
||||
var err = &tea.SDKError{}
|
||||
if _t, ok := tryErr.(*tea.SDKError); ok {
|
||||
err = _t
|
||||
} else {
|
||||
err.Message = tea.String(tryErr.Error())
|
||||
}
|
||||
if !tea.BoolValue(util.Empty(err.Code)) && !tea.BoolValue(util.Empty(err.Message)) {
|
||||
// err 中含有 code 和 message 属性,可帮助开发定位问题
|
||||
}
|
||||
}
|
||||
return _err
|
||||
}
|
||||
|
||||
func SendAliveMsg(title, content, color string) (_err error) {
|
||||
client, _err := createCardClient()
|
||||
if _err != nil {
|
||||
|
||||
@ -35,6 +35,7 @@ type SystemConfig struct {
|
||||
USOperationChatId string `yaml:"us_operation_chat_id"` // US运营群id
|
||||
ClientChatId string `yaml:"client_chat_id"` // 客户端群id
|
||||
Ssh bool `yaml:"ssh"` // 是否开启SSH连接
|
||||
Env string `yaml:"env"` // 环境变量
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@ -143,6 +144,10 @@ func GetSsh() bool {
|
||||
return config.System.Ssh
|
||||
}
|
||||
|
||||
func GetEnv() string {
|
||||
return config.System.Env
|
||||
}
|
||||
|
||||
func GetTranlaterConfig(account string) *TranlaterUser {
|
||||
for _, user := range tranlaterConfig.User {
|
||||
if user.Account == account {
|
||||
|
||||
@ -30,7 +30,7 @@ func AlibabaGameNotify(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
content := util.ParseTmpl("./template/alibaba_notify.tmpl", r)
|
||||
err := alibaba.SendStandardMsg("游戏服务报警通知", content, "red")
|
||||
err := alibaba.SendStandardMsg2("游戏服务报警通知", content, "red")
|
||||
if err != nil {
|
||||
log.Printf("failed to send notify message: %v", err)
|
||||
}
|
||||
|
||||
@ -241,7 +241,7 @@ func CopyOnline(c *gin.Context) {
|
||||
case 0:
|
||||
success(c, map[string]interface{}{
|
||||
"step": 1,
|
||||
"label": "关闭QA环境服务",
|
||||
"label": "复制数据库",
|
||||
"tips": []string{},
|
||||
"code": 0,
|
||||
})
|
||||
@ -259,7 +259,7 @@ func CopyOnline(c *gin.Context) {
|
||||
util.AddAdminLog(c, "文案自动化脚本", request)
|
||||
}
|
||||
|
||||
func CopyOnlineStep1(c *gin.Context) {
|
||||
func CopyOnlineStep2(c *gin.Context) {
|
||||
// 关闭QA环境服务
|
||||
time.Sleep(time.Second)
|
||||
servers := util.GetAllServersByAppId(2) // AppId=2 QA环境
|
||||
@ -278,14 +278,14 @@ func CopyOnlineStep1(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
success(c, map[string]interface{}{
|
||||
"step": 2,
|
||||
"label": "复制数据库",
|
||||
"step": 3,
|
||||
"label": "写入数据到QA环境",
|
||||
"tips": []string{},
|
||||
"code": 0,
|
||||
})
|
||||
}
|
||||
|
||||
func CopyOnlineStep2(c *gin.Context) {
|
||||
func CopyOnlineStep1(c *gin.Context) {
|
||||
// mysqldump 复制数据库
|
||||
nodeInfo := util.GetNodeByName("devops")
|
||||
SshClient, err := util.NewSshClient(nodeInfo)
|
||||
@ -303,8 +303,8 @@ func CopyOnlineStep2(c *gin.Context) {
|
||||
|
||||
time.Sleep(time.Second)
|
||||
success(c, map[string]interface{}{
|
||||
"step": 3,
|
||||
"label": "写入数据到QA环境",
|
||||
"step": 2,
|
||||
"label": "关闭QA环境服务",
|
||||
"tips": []string{},
|
||||
"code": 0,
|
||||
})
|
||||
|
||||
@ -98,6 +98,18 @@ func UserDetail(c *gin.Context) {
|
||||
order[k] = info
|
||||
}
|
||||
}
|
||||
|
||||
if user["FriendList"] != nil {
|
||||
friendList := user["FriendList"].([]interface{})
|
||||
for k, v := range friendList {
|
||||
info := v.(map[string]interface{})
|
||||
face_url := util.GetFaceURL(util.Int(info["Avatar"]))
|
||||
info["avatarUrl"] = face_url
|
||||
friendList[k] = info
|
||||
info["onlineStatus"] = util.Int(info["LoginTime"]) > util.Int(info["LogoutTime"])
|
||||
}
|
||||
user["FriendList"] = friendList
|
||||
}
|
||||
heat, _ := log.Heat()
|
||||
if err != nil {
|
||||
fmt.Print(err)
|
||||
|
||||
6
main.go
6
main.go
@ -164,8 +164,10 @@ func main() {
|
||||
//go util.ScheduleDailyTask()
|
||||
go server.Server()
|
||||
go model.InitToken() // 初始化 Token 列表
|
||||
go util.MonitorServerList() // 启动定时任务发送信息
|
||||
go monitor.UserAliveMonitor(0) // 用户存活监控
|
||||
if common.GetEnv() == "prod" { // 生产环境才启动监控
|
||||
go monitor.UserAliveMonitor(0) // 用户存活监控
|
||||
go util.MonitorServerList() // 启动定时任务发送信息
|
||||
}
|
||||
go monitor.ServerInfoMonitor() // 服务器信息监控
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
|
||||
@ -66,54 +66,12 @@ func (s *Statistics) StatisticsInfo() (interface{}, error) {
|
||||
if LogDb == nil {
|
||||
return nil, fmt.Errorf("failed to get mysql database")
|
||||
}
|
||||
StartTime, _ := util.GetZeroTimestamp(AppConfig.Tz, 0)
|
||||
EndTime, _ := util.GetZeroTimestamp(AppConfig.Tz, 1)
|
||||
|
||||
var Register int
|
||||
var TotalRegistger int
|
||||
var Recharge float64
|
||||
var TotalRecharge float64
|
||||
var RechargeUser int
|
||||
err = LogDb.Get(&Register, "select count(*) as sum from log_login where Event = 'register' and Timestamp >= ? and Timestamp <= ?", StartTime, EndTime)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get register count: %v", err)
|
||||
}
|
||||
|
||||
err = LogDb.Get(&TotalRegistger, "select count(*) as sum from log_login where Event = 'register'")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get total register count: %v", err)
|
||||
}
|
||||
|
||||
err = LogDb.Get(&Recharge, "select IFNULL(SUM(Price), 0) as sum from log_order where Timestamp >= ? and Timestamp <= ?", StartTime, EndTime)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get recharge count: %v", err)
|
||||
}
|
||||
|
||||
err = LogDb.Get(&TotalRecharge, "select IFNULL(SUM(Price), 0) as sum from log_order")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get total recharge count: %v", err)
|
||||
}
|
||||
// 充值人数统计
|
||||
err = LogDb.Get(&RechargeUser, "select count(distinct Uid) as sum from log_order where Timestamp >= ? and Timestamp <= ?", StartTime, EndTime)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get recharge count: %v", err)
|
||||
}
|
||||
|
||||
var TotalRechargeUser int
|
||||
// 充值总人数统计
|
||||
err = LogDb.Get(&TotalRechargeUser, "select count(distinct Uid) as sum from log_order")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get total recharge count: %v", err)
|
||||
}
|
||||
|
||||
type RemainCount struct {
|
||||
Register int `db:"register"`
|
||||
SecondRemain int `db:"SecondRemain"`
|
||||
}
|
||||
var rc RemainCount
|
||||
err = LogDb.Get(&rc, "select sum(`Register`) as register, sum(`SecondRemain`) as SecondRemain from remain")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get recharge count: %v", err)
|
||||
}
|
||||
|
||||
rechargeFloat, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", Recharge), 64)
|
||||
totalRechargeFloat, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", TotalRecharge), 64)
|
||||
@ -123,8 +81,8 @@ func (s *Statistics) StatisticsInfo() (interface{}, error) {
|
||||
"recharge": rechargeFloat,
|
||||
"totalRecharge": totalRechargeFloat,
|
||||
"rechargeUser": RechargeUser,
|
||||
"totalRechargeUser": TotalRechargeUser,
|
||||
"remain": util.FloatDecimals(100*float64(rc.SecondRemain)/float64(rc.Register), 2),
|
||||
"totalRechargeUser": 0,
|
||||
"remain": 0,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ type Mail struct {
|
||||
ContentPtBr string `json:"content_ptbr" db:"content_ptbr"`
|
||||
|
||||
TitleEsLatam string `json:"title_es_latam" db:"title_es_latam"`
|
||||
SubTitleEsLatam string `json:"subtitle_es_latam" db:"subTitle_es_latam"`
|
||||
SubTitleEsLatam string `json:"subtitle_es_latam" db:"subtitle_es_latam"`
|
||||
ContentEsLatam string `json:"content_es_latam" db:"content_es_latam"`
|
||||
|
||||
StartTime int64 `json:"start_time" db:"start_time"`
|
||||
@ -53,6 +53,9 @@ func (m *Mail) MailList() (*Result, error) {
|
||||
return nil, err
|
||||
}
|
||||
Db := util.MPool.GetMysqlDB(AppCfg, m.ServerId)
|
||||
if Db == nil {
|
||||
return nil, fmt.Errorf("failed to get mysql db")
|
||||
}
|
||||
defer Db.Close()
|
||||
var mail []*Mail
|
||||
err = Db.Select(&mail, "SELECT `mail_id`, `title`, `content`, `start_time`, `end_time`, `items`, `register_time`, `mail_type`,`send_type`, `to_uids`, `create_time`, `subTitle`, `subTitle_en`, `content_en`, `title_en`, `title_ptbr`,`subTitle_ptbr`, `content_ptbr`, `title_es_latam`, `subtitle_es_latam`, `content_es_latam` FROM system_mail_info")
|
||||
@ -80,14 +83,17 @@ func (m *Mail) SendMail() error {
|
||||
return err
|
||||
}
|
||||
Db := util.MPool.GetMysqlDB(AppCfg, m.ServerId)
|
||||
if Db == nil {
|
||||
return fmt.Errorf("failed to get mysql db")
|
||||
}
|
||||
defer Db.Close()
|
||||
_, err = Db.Exec("INSERT INTO system_mail_info (`title`, `content`, `title_en`, `content_en`, `start_time`, `end_time`, `items`, `register_time`, `mail_type`, `send_type`, `to_uids`, `create_time`, `subTitle`, `subTitle_en`, `title_ptbr`,`content_ptbr`,`subTitle_ptbr`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.Title, m.Content, m.TitleEn, m.ContentEn, m.StartTime, m.EndTime, m.Items, m.RegisterTime, m.MailType, m.SendType, m.ToUids, m.CreateTime, m.SubTitle, m.SubTitleEn, m.TitlePtBr, m.ContentPtBr, m.SubTitlePtBr)
|
||||
_, err = Db.Exec("INSERT INTO system_mail_info (`title`, `content`, `title_en`, `content_en`, `start_time`, `end_time`, `items`, `register_time`, `mail_type`, `send_type`, `to_uids`, `create_time`, `subTitle`, `subTitle_en`, `title_ptbr`,`content_ptbr`,`subTitle_ptbr`, `title_es_latam`, `subTitle_es_latam`, `content_es_latam`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.Title, m.Content, m.TitleEn, m.ContentEn, m.StartTime, m.EndTime, m.Items, m.RegisterTime, m.MailType, m.SendType, m.ToUids, m.CreateTime, m.SubTitle, m.SubTitleEn, m.TitlePtBr, m.ContentPtBr, m.SubTitlePtBr, m.TitleEsLatam, m.SubTitleEsLatam, m.ContentEsLatam)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to insert mail: %v", err)
|
||||
}
|
||||
ServerList := util.GetServerInfo(m.AppId, 0)
|
||||
for _, server := range ServerList {
|
||||
go func() {
|
||||
go func(serverInfo util.ServerConfig) {
|
||||
ws, err := util.GetWebsocket(m.AppId, server.ServerId)
|
||||
if err != nil {
|
||||
log.Printf("failed to get websocket: %v", err)
|
||||
@ -99,7 +105,8 @@ func (m *Mail) SendMail() error {
|
||||
if err != nil {
|
||||
log.Printf("failed to send admin message: %v", err)
|
||||
}
|
||||
}()
|
||||
log.Printf("sent reload mail message to server %d", server.ServerId)
|
||||
}(server)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -111,6 +118,9 @@ func (m *Mail) DeleteMail() error {
|
||||
return err
|
||||
}
|
||||
Db := util.MPool.GetMysqlDB(AppCfg, m.ServerId)
|
||||
if Db == nil {
|
||||
return fmt.Errorf("failed to get mysql db")
|
||||
}
|
||||
defer Db.Close()
|
||||
_, err = Db.Exec("DELETE FROM system_mail_info WHERE `mail_id` = ?", m.MailId)
|
||||
if err != nil {
|
||||
|
||||
@ -48,7 +48,7 @@ func (s *Server) ServerList() ([]*Type.ServerInfo, error) {
|
||||
Db := util.MPool.GetGameDB()
|
||||
var server []*Type.ServerInfo
|
||||
defer Db.Close()
|
||||
err := Db.Select(&server, "SELECT `AppId`, `ServerId`, `ServerName`, `Status`, `CreateTime`, `OpenServerTime`, `Online`, `cpu`, `free_mem`, `version`, `node_tags` FROM server where AppId = ? order by `ServerId`", s.AppId)
|
||||
err := Db.Select(&server, "SELECT `AppId`, `ServerId`, `ServerName`, `Status`, `CreateTime`, `OpenServerTime`, `Online`, `cpu`, `free_mem`, `version`, `node_tags`, `latency` FROM server where AppId = ? order by `ServerId`", s.AppId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to scan rows: %v", err)
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"backend/model"
|
||||
"backend/util"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -66,7 +67,7 @@ func monitorServerInfo() {
|
||||
Db := util.MPool.GetGameDB()
|
||||
var server []*Type.ServerInfo
|
||||
defer Db.Close()
|
||||
err := Db.Select(&server, "SELECT `AppId`, `ServerId`, `ServerName`, `Status`, `CreateTime`, `OpenServerTime` FROM server ")
|
||||
err := Db.Select(&server, "SELECT `AppId`, `ServerId`, `ServerName`, `Status`, `CreateTime`, `OpenServerTime`, `Host`, `Port` FROM server ")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -77,9 +78,21 @@ func monitorServerInfo() {
|
||||
go func(v *Type.ServerInfo) {
|
||||
tmpDb := util.MPool.GetGameDB()
|
||||
defer tmpDb.Close()
|
||||
// TCP ping test for server connectivity
|
||||
address := fmt.Sprintf("%s:%d", v.Host, v.Port) // adjust port as needed
|
||||
timeout := 3 * time.Second
|
||||
start := time.Now()
|
||||
conn, err := net.DialTimeout("tcp", address, timeout)
|
||||
latency := time.Since(start).Milliseconds()
|
||||
if err != nil {
|
||||
// Connection failed, mark server as offline
|
||||
tmpDb.Exec("update server set Status=0 where AppId=? and ServerId=?", v.AppId, v.ServerId)
|
||||
return
|
||||
}
|
||||
conn.Close()
|
||||
res, err := model.GetServerInfo(v.AppId, v.ServerId)
|
||||
if err != nil {
|
||||
tmpDb.Exec("update server set Status=0 where AppId=? and ServerId=?", v.AppId, v.ServerId)
|
||||
//tmpDb.Exec("update server set Status=0 where AppId=? and ServerId=?", v.AppId, v.ServerId)
|
||||
return
|
||||
}
|
||||
serverInfo := res.(map[string]interface{})
|
||||
@ -119,7 +132,7 @@ func monitorServerInfo() {
|
||||
// optionally store/update weight
|
||||
serverInfo["Weight"] = weight
|
||||
// Process serverInfo as needed
|
||||
tmpDb.Exec("update server set Status=1, Online=?,free_mem=?,cpu=?,weight=? where AppId=? and ServerId=?", util.Int(serverInfo["PlayerNum"]), usage_mem, cpu, weight, v.AppId, v.ServerId)
|
||||
tmpDb.Exec("update server set Status=1, Online=?,free_mem=?,cpu=?,weight=?,latency=? where AppId=? and ServerId=?", util.Int(serverInfo["PlayerNum"]), usage_mem, cpu, weight, latency, v.AppId, v.ServerId)
|
||||
}(v)
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,7 +72,6 @@ func main() {
|
||||
// 充值发货
|
||||
ChargeApi.POST("test/charge", test.Charge)
|
||||
ChargeApi.POST("tuyou/charge", tuyou.Charge)
|
||||
ChargeApi.GET("tuyou/charge", tuyou.Charge)
|
||||
}
|
||||
log.Printf("Ship SDK started on port %d", shipcommon.AppConf.Port)
|
||||
r.Run(fmt.Sprintf(":%d", shipcommon.AppConf.Port))
|
||||
|
||||
@ -37,15 +37,6 @@ func (p *Param) ChangeOrderStatus(Platform string, prodprice string) error {
|
||||
return err
|
||||
}
|
||||
if fmt.Sprintf("%.2f", price) != prodprice {
|
||||
// str := `
|
||||
// # 订单金额不匹配报警
|
||||
// - 项目名称: %s
|
||||
// - 订单ID: %s
|
||||
// - 数据库金额: %.2f
|
||||
// - 回调金额: %s
|
||||
// - 渠道订单ID: %s
|
||||
// - 充值ID: %d
|
||||
// `
|
||||
return fmt.Errorf("订单金额不匹配,数据库金额:%.2f,回调金额:%s; 订单id:%s, chargeid:%d", price, prodprice, p.OrderId, chargeId)
|
||||
}
|
||||
if paystatus != 0 {
|
||||
|
||||
17
unit/config_test.go
Normal file
17
unit/config_test.go
Normal file
@ -0,0 +1,17 @@
|
||||
package unit
|
||||
|
||||
import (
|
||||
"backend/util"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEmojiUrl(t *testing.T) {
|
||||
url := util.GetEmojiURL(1)
|
||||
fmt.Println("emoji url:", url)
|
||||
}
|
||||
|
||||
func TestFaceUrl(t *testing.T) {
|
||||
url := util.GetFaceURL(1)
|
||||
fmt.Println("face url:", url)
|
||||
}
|
||||
38
unit_test.go
38
unit_test.go
@ -234,3 +234,41 @@ func TestEs2(t *testing.T) {
|
||||
fmt.Println("服务器启动成功")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIP(t *testing.T) {
|
||||
country, city, err := util.GetGeoInfo("58.23.48.244")
|
||||
if err != nil {
|
||||
fmt.Println("获取地理位置信息失败:", err)
|
||||
} else {
|
||||
fmt.Printf("国家代码: %s, 城市: %s\n", country, city)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
client, _ := util.GetEsClient()
|
||||
var buf bytes.Buffer
|
||||
query := map[string]interface{}{
|
||||
"query": map[string]interface{}{
|
||||
"term": map[string]interface{}{
|
||||
"game.#event_name": map[string]interface{}{
|
||||
"value": "register",
|
||||
},
|
||||
},
|
||||
},
|
||||
"size": 10000,
|
||||
}
|
||||
if err := json.NewEncoder(&buf).Encode(query); err != nil {
|
||||
return
|
||||
}
|
||||
res, err := client.Search(
|
||||
client.Search.WithContext(ctx),
|
||||
client.Search.WithIndex(".ds-game-node-log*"),
|
||||
client.Search.WithBody(&buf),
|
||||
client.Search.WithTrackTotalHits(true),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Print(err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
}
|
||||
|
||||
19
util/es.go
19
util/es.go
@ -66,7 +66,7 @@ func DSlSearch(ctx context.Context, index string, query map[string]interface{},
|
||||
if err := json.NewEncoder(&buf).Encode(fullQuery); err != nil {
|
||||
return nil, fmt.Errorf("编码查询失败: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("%s", buf.String())
|
||||
res, err := client.Search(
|
||||
client.Search.WithContext(ctx),
|
||||
client.Search.WithIndex(index),
|
||||
@ -123,12 +123,12 @@ func SearchAssetByUid(app, _uid int, from, size int, start, end int64, itemid in
|
||||
mustCondition := []map[string]interface{}{
|
||||
{
|
||||
"term": map[string]interface{}{
|
||||
"game.#distinct_id": uid,
|
||||
"game.#distinct_id.keyword": uid,
|
||||
},
|
||||
},
|
||||
{
|
||||
"term": map[string]interface{}{
|
||||
"fields.region": region,
|
||||
"fields.environment": region,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -218,12 +218,12 @@ func SearchEventByUid(app, _uid int, from, size int, start, end int64, event_nam
|
||||
mustConditions := []map[string]interface{}{
|
||||
{
|
||||
"term": map[string]interface{}{
|
||||
"game.#distinct_id": uid,
|
||||
"game.#distinct_id.keyword": uid,
|
||||
},
|
||||
},
|
||||
{
|
||||
"term": map[string]interface{}{
|
||||
"fields.region": region,
|
||||
"fields.environment": region,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -265,7 +265,6 @@ func SearchEventByUid(app, _uid int, from, size int, start, end int64, event_nam
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
result, err := DSlSearch(ctx, "game-user-log*", query, from, size, sort)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
@ -328,7 +327,7 @@ func CountDistinctUidLastHour() (int64, int64, error) {
|
||||
"must": []map[string]interface{}{
|
||||
{
|
||||
"term": map[string]interface{}{
|
||||
"fields.region": "us-newyork",
|
||||
"fields.region.keyword": "us-newyork",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -367,7 +366,7 @@ func CountDistinctUidLastHour() (int64, int64, error) {
|
||||
"aggs": map[string]interface{}{
|
||||
"unique_users": map[string]interface{}{
|
||||
"cardinality": map[string]interface{}{
|
||||
"field": "game.#distinct_id",
|
||||
"field": "game.#distinct_id.keyword",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -384,7 +383,7 @@ func CountDistinctUidLastHour() (int64, int64, error) {
|
||||
"aggs": map[string]interface{}{
|
||||
"unique_users": map[string]interface{}{
|
||||
"cardinality": map[string]interface{}{
|
||||
"field": "game.#distinct_id",
|
||||
"field": "game.#distinct_id.keyword",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -396,9 +395,11 @@ func CountDistinctUidLastHour() (int64, int64, error) {
|
||||
if err := json.NewEncoder(&buf).Encode(query); err != nil {
|
||||
return 0, 0, fmt.Errorf("编码查询失败: %w", err)
|
||||
}
|
||||
fmt.Printf("%s", buf.String())
|
||||
res, err := client.Search(
|
||||
client.Search.WithContext(ctx),
|
||||
client.Search.WithIndex("game-user-log*"),
|
||||
client.Search.WithTrackTotalHits(true),
|
||||
client.Search.WithBody(&buf),
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
23
util/geoip.go
Normal file
23
util/geoip.go
Normal file
@ -0,0 +1,23 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/oschwald/geoip2-golang"
|
||||
)
|
||||
|
||||
func GetGeoInfo(ip string) (string, string, error) {
|
||||
// 这里可以使用第三方库或服务来获取地理位置信息
|
||||
// 例如,使用 "github.com/oschwald/geoip2-golang" 库读取 MaxMind 的 GeoIP 数据库
|
||||
// 或者调用第三方 API,如 ipinfo.io、ipstack.com 等
|
||||
db, err := geoip2.Open("./GeoLite2-Country/GeoLite2-City.mmdb")
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
defer db.Close()
|
||||
city, err := db.City(net.ParseIP(ip))
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return city.Country.Names["zh-CN"], city.City.Names["zh-CN"], nil // 返回国家代码或地理位置信息
|
||||
}
|
||||
@ -2,7 +2,6 @@ package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
@ -35,7 +34,7 @@ func LoginResponse(c *gin.Context, AppId, AreaCode int, Version string) {
|
||||
}
|
||||
|
||||
func GetUserInfo(AppId, AreaCode int, Uid, Version string) (int, string, int) {
|
||||
now := time.Now().UnixMilli()
|
||||
// now := time.Now().UnixMilli()
|
||||
lockUid(Uid)
|
||||
defer unlockUid(Uid)
|
||||
// Db := MPool.GetGameDB()
|
||||
@ -48,14 +47,6 @@ func GetUserInfo(AppId, AreaCode int, Uid, Version string) (int, string, int) {
|
||||
if len(ServerList) == 0 || Uid == "" || Version == "" {
|
||||
return 0, "", 0
|
||||
}
|
||||
// appConf, _ := GetAppConfig(AppId)
|
||||
// PlayerDb := MPool.GetMysqlDB(appConf, 1)
|
||||
// defer PlayerDb.Close()
|
||||
// var node int
|
||||
// err := PlayerDb.QueryRow("SELECT node FROM t_player_baseinfo WHERE user_name = ?", Uid).Scan(&node)
|
||||
// if err != nil {
|
||||
// fmt.Printf("GetUserInfo query node error: %v\n", err)
|
||||
// }
|
||||
node, err := GetUserConnectNode(Uid)
|
||||
if err != nil {
|
||||
node = 0
|
||||
@ -126,7 +117,7 @@ func GetUserInfo(AppId, AreaCode int, Uid, Version string) (int, string, int) {
|
||||
if err == nil {
|
||||
SaveUserConnectNode(Uid, ServerId)
|
||||
}
|
||||
log.Printf("GetUserInfo selected server %d for uid %s, cost time %dms\n", ServerId, Uid, time.Now().UnixMilli()-now)
|
||||
//log.Printf("GetUserInfo selected server %d for uid %s, cost time %dms\n", ServerId, Uid, time.Now().UnixMilli()-now)
|
||||
return Port, Host, ServerId
|
||||
}
|
||||
|
||||
|
||||
111
util/util.go
111
util/util.go
@ -34,6 +34,7 @@ var FrameData = make(map[string]interface{})
|
||||
var CardData = make(map[string]interface{})
|
||||
var CardCollectData = make(map[string]interface{})
|
||||
var NetAssetData = make(map[string]interface{})
|
||||
var ItemData = make(map[string]interface{})
|
||||
|
||||
func init() {
|
||||
data, err := os.ReadFile("config/MergeData.json")
|
||||
@ -91,6 +92,15 @@ func init() {
|
||||
NetAssetData = m
|
||||
}
|
||||
}
|
||||
data, err = os.ReadFile("config/Item.json")
|
||||
if err == nil {
|
||||
var m map[string]interface{}
|
||||
if err := json.Unmarshal(data, &m); err != nil {
|
||||
log.Printf("failed to unmarshal ItemData.json: %v", err)
|
||||
} else {
|
||||
ItemData = m
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取结构体名称
|
||||
@ -605,35 +615,19 @@ func GetLanguageImageURL(key string) string {
|
||||
// 头像
|
||||
reHead := regexp.MustCompile(`^Data_HeadName_(\d+)$`)
|
||||
if m := reHead.FindStringSubmatch(key); len(m) == 2 {
|
||||
if n, err := strconv.Atoi(m[1]); err == nil {
|
||||
pad := fmt.Sprintf("%03d", n)
|
||||
return fmt.Sprintf("UI/UISprites/Head/DefaultHead/head_pic_circle%s.png", pad)
|
||||
}
|
||||
id := Int(m[1])
|
||||
return GetFaceURL(id)
|
||||
}
|
||||
// 头像框
|
||||
reFrame := regexp.MustCompile(`^Data_HeadFrameName_(\d+)$`)
|
||||
if m := reFrame.FindStringSubmatch(key); len(m) == 2 {
|
||||
nameKey := m[0]
|
||||
for _, v := range FrameData {
|
||||
if v == nil {
|
||||
continue
|
||||
}
|
||||
entry, ok := v.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if String(entry["NameKey"]) == nameKey {
|
||||
icon := String(entry["Icon"])
|
||||
if icon != "" {
|
||||
return fmt.Sprintf("UI/UISprites/Head/Kuang_new/%s.png", icon)
|
||||
}
|
||||
}
|
||||
}
|
||||
id := Int(m[1])
|
||||
return GetFrameURL(id)
|
||||
}
|
||||
// Emoji
|
||||
reEmoji := regexp.MustCompile(`^Data_EmojiName_(\d+)$`)
|
||||
if m := reEmoji.FindStringSubmatch(key); len(m) == 2 {
|
||||
return fmt.Sprintf("UI/UISprites/Head/Emoji/cat_biaoqing_%s.png", m[1])
|
||||
return GetEmojiURL(Int(m[1]))
|
||||
}
|
||||
// 卡牌
|
||||
reCard := regexp.MustCompile(`^UI_MainCardPanel_cardName_`)
|
||||
@ -661,7 +655,7 @@ func GetLanguageImageURL(key string) string {
|
||||
if reCardCollect.MatchString(key) {
|
||||
parts := strings.Split(key, "_")
|
||||
name := strings.TrimSpace(parts[len(parts)-1])
|
||||
for k, v := range CardCollectData {
|
||||
for _, v := range CardCollectData {
|
||||
if v == nil {
|
||||
continue
|
||||
}
|
||||
@ -670,10 +664,7 @@ func GetLanguageImageURL(key string) string {
|
||||
continue
|
||||
}
|
||||
if String(entry["Name"]) == name {
|
||||
icon := "Card/Collect_icon_pethome" + k
|
||||
if icon != "" {
|
||||
return fmt.Sprintf("UI/UISprites/%s.png", icon)
|
||||
}
|
||||
return String(entry["ResourcesPath"])
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -724,8 +715,72 @@ func GetAppName(AppId int) string {
|
||||
func GetAppRegion(AppId int) string {
|
||||
switch AppId {
|
||||
case 0:
|
||||
return "us-newyork"
|
||||
return "prod"
|
||||
default:
|
||||
return "cn-shanghai"
|
||||
return "test"
|
||||
}
|
||||
}
|
||||
|
||||
func GetEmojiURL(EmojiId int) string {
|
||||
return _GetURL(EmojiId, 109)
|
||||
}
|
||||
|
||||
func GetFaceURL(HeadId int) string {
|
||||
return _GetURL(HeadId, 110)
|
||||
}
|
||||
|
||||
func GetFrameURL(FrameId int) string {
|
||||
return _GetURL(FrameId, 105)
|
||||
}
|
||||
|
||||
func _GetURL(Id, Type int) string {
|
||||
for _, v := range ItemData {
|
||||
info, ok := v.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if Int(info["IType"]) == Type {
|
||||
effect := String(info["Effect"])
|
||||
effectList := strings.Split(effect, ",")
|
||||
if Id == Int(effectList[0]) && len(effectList) > 0 {
|
||||
return info["FullResourcePath"].(string)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetCardURL(CardId string) string {
|
||||
info, ok := CardData[CardId]
|
||||
if ok && info != nil {
|
||||
entry, ok := info.(map[string]interface{})
|
||||
if ok {
|
||||
return String(entry["ResourcesPath"])
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetCardCollectURL(name string) string {
|
||||
for _, v := range CardCollectData {
|
||||
info, ok := v.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if String(info["Name"]) == name {
|
||||
return String(info["ResourcesPath"])
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetNetAssetURL(Key string) string {
|
||||
info, ok := NetAssetData[Key]
|
||||
if ok && info != nil {
|
||||
entry, ok := info.(map[string]interface{})
|
||||
if ok {
|
||||
return String(entry["Picture"])
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@ -16,13 +16,11 @@ func GetWebsocket(AppId, ServerId int) (*websocket.Conn, error) {
|
||||
if ServerConfig == nil {
|
||||
return nil, fmt.Errorf("server config not found for AppId %d and ServerId %d", AppId, ServerId)
|
||||
}
|
||||
|
||||
// if AppId == 0 {
|
||||
// ServerConfig.Host = "google.bywaystudios.com"
|
||||
// }
|
||||
nodeConfig := GetNodeById(ServerConfig.ECS)
|
||||
url := fmt.Sprintf("ws://%s:%d/", nodeConfig.Host, ServerConfig.WsPort)
|
||||
|
||||
// if common.GetEnv() == "dev" {
|
||||
// url = "ws://127.0.0.1:3567/" // 本地调试使用内网地址
|
||||
// }
|
||||
dialer := &websocket.Dialer{
|
||||
HandshakeTimeout: 5 * time.Second,
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user