221 lines
8.0 KiB
Go
221 lines
8.0 KiB
Go
package main
|
||
|
||
import (
|
||
"backend/common"
|
||
"backend/controller"
|
||
config "backend/global"
|
||
"backend/middleware"
|
||
"backend/middleware/feishu/server"
|
||
"backend/model"
|
||
"backend/monitor"
|
||
"backend/util"
|
||
"fmt"
|
||
"io"
|
||
"log"
|
||
"os"
|
||
"time"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
|
||
)
|
||
|
||
// GOOS=linux GOARCH=amd64 go build -o /data/backend/release/backend main.go
|
||
var (
|
||
rl *rotatelogs.RotateLogs
|
||
logWriter io.Writer
|
||
errWriter io.Writer
|
||
)
|
||
|
||
func init() {
|
||
// 确保日志目录存在
|
||
if err := os.MkdirAll("./log", 0755); err != nil {
|
||
log.Fatalf("failed to create log dir: %v", err)
|
||
}
|
||
|
||
// 使用按天轮转的日志文件,保留最近 30 个文件
|
||
var err error
|
||
rl, err = rotatelogs.New(
|
||
"./log/backend.%Y-%m-%d.log",
|
||
rotatelogs.WithRotationTime(24*time.Hour),
|
||
rotatelogs.WithRotationCount(30),
|
||
)
|
||
if err != nil {
|
||
log.Fatalf("failed to initialize log rotator: %v", err)
|
||
}
|
||
|
||
// 打开一个普通的最新日志文件(不使用 symlink),用于提供固定路径的最新日志
|
||
currFile, err := os.OpenFile("./log/backend.log", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
||
if err != nil {
|
||
// 如果打开失败,仍然继续使用轮转器+控制台
|
||
log.Printf("warning: failed to open current log file: %v", err)
|
||
logWriter = io.MultiWriter(rl, os.Stdout)
|
||
errWriter = io.MultiWriter(rl, os.Stderr)
|
||
} else {
|
||
// 同时输出到轮转日志、固定最新日志文件和控制台
|
||
logWriter = io.MultiWriter(rl, currFile)
|
||
errWriter = io.MultiWriter(rl, currFile, os.Stderr)
|
||
}
|
||
|
||
log.SetOutput(logWriter)
|
||
|
||
// 保持全局默认 writer(以兼容其他调用)
|
||
gin.DefaultWriter = logWriter
|
||
gin.DefaultErrorWriter = errWriter
|
||
|
||
util.InitBBolt()
|
||
common.Init()
|
||
common.InitTranlater()
|
||
}
|
||
|
||
func main() {
|
||
defer func() {
|
||
if err := recover(); err != nil {
|
||
log.Printf("Recovered from panic: %v", err)
|
||
// 这里可以添加更多的错误 handling 逻辑,比如发送通知等
|
||
// 重新启动服务器
|
||
fmt.Print("Restarting server...")
|
||
os.Exit(1)
|
||
}
|
||
}()
|
||
r := gin.Default()
|
||
loginApi := r.Group("/api/auth")
|
||
{
|
||
// 认证
|
||
loginApi.POST("/login", controller.Login)
|
||
loginApi.GET("/Codes", controller.Codes)
|
||
loginApi.POST("/phoneCode", controller.PhoneCode)
|
||
loginApi.POST("/phoneLogin", controller.LoginCode)
|
||
}
|
||
feishuApi := r.Group("/api/feishu")
|
||
{
|
||
// 飞书
|
||
feishuApi.POST("/sendInfo", controller.FeishuSendInfo)
|
||
feishuApi.POST("/sendInfo2", controller.FeishuSendInfo2) // US 运营数据
|
||
feishuApi.POST("/sendWeekInfo", controller.FeishuSendWeekInfo)
|
||
feishuApi.POST("/updateApp", controller.FeishuUpdateApp)
|
||
feishuApi.POST("/serverInfo", controller.FeishuServerInfo)
|
||
feishuApi.POST("/notify", controller.FeishuNotify) // 系统报警
|
||
feishuApi.POST("/notify/client", controller.FeishuNotifyClient) // 客户端报警
|
||
feishuApi.POST("/notify/order", controller.FeishuNotifyOrder) // 订单通知
|
||
}
|
||
alibabaApi := r.Group("/api/alibaba")
|
||
{
|
||
// 阿里云
|
||
alibabaApi.POST("/zabbix/notify", controller.AlibabaNotify) // 系统报警
|
||
alibabaApi.POST("/zabbix/recovery", controller.AlibabaRecovery) // 系统报警
|
||
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())
|
||
{
|
||
// 账号管理
|
||
api.POST("/admin/list", controller.AdminList)
|
||
api.POST("/admin/add", controller.AdminAdd)
|
||
api.POST("/admin/log/list", controller.AdminLogList)
|
||
api.POST("/admin/config/list", controller.AdminConfigList)
|
||
api.POST("/admin/config/add", controller.AdminConfigAdd)
|
||
api.POST("/admin/config/edit", controller.AdminConfigEdit)
|
||
// 玩家日志
|
||
api.POST("/log/user", controller.UserDetail)
|
||
api.POST("/log/asset", controller.Asset)
|
||
api.POST("/log/event", controller.Event)
|
||
api.POST("/log/loginCountByMonth", controller.LoginCountByMonth)
|
||
api.POST("/log/order", controller.Order)
|
||
|
||
// 玩家数据
|
||
api.POST("/user/list", controller.UserList)
|
||
api.GET("/user/info", controller.UserInfo)
|
||
api.POST("/user/gm", controller.UserGM)
|
||
api.POST("/user/ban", controller.UserBan)
|
||
|
||
api.POST("/server/list", controller.AppList)
|
||
api.POST("/server/serverList", controller.ServerList)
|
||
api.POST("/server/addServer", controller.AddServer)
|
||
api.POST("/server/nodeList", controller.NodeList)
|
||
api.POST("/server/addNode", controller.AddNode)
|
||
api.POST("/server/editServer", controller.EditServer)
|
||
|
||
api.POST("/server/updateApp", controller.UpdateApp)
|
||
api.POST("/server/updateAppReview", controller.UpdateAppReview)
|
||
api.POST("/server/updateAppFeishu", controller.UpdateAppFeishu)
|
||
api.POST("/server/restart", controller.RestartServer)
|
||
api.POST("/server/reload", controller.ReloadServer)
|
||
|
||
api.POST("/statistics/level", controller.StatisticsLevel)
|
||
api.POST("/statistics/order", controller.StatisticsOrder)
|
||
api.POST("/statistics/info", controller.StatisticsInfo)
|
||
api.POST("/statistics/heat", controller.StatisticsHeat)
|
||
|
||
//活动
|
||
api.POST("/activity/list", controller.ActivityList)
|
||
api.POST("/activity/edit", controller.ActivityEdit)
|
||
api.POST("/activity/add", controller.ActivityAdd)
|
||
api.POST("/activity/delete", controller.ActivityDelete)
|
||
api.POST("/activity/sync", controller.ActivitySync)
|
||
|
||
// 邮件
|
||
api.POST("/mail/send", controller.SendMail)
|
||
api.POST("/mail/list", controller.MailList)
|
||
api.POST("/mail/delete", controller.MailDelete)
|
||
// 运营功能
|
||
api.POST("/operation/copyUser", controller.CopyUser)
|
||
|
||
// 翻译
|
||
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.GET("/config/notification", controller.NotificationConfigGet)
|
||
api.PUT("/config/notification/update", controller.NotificationConfigSave)
|
||
|
||
}
|
||
// 自动化脚本
|
||
scripts := r.Group("/api/scripts", middleware.ValidateToken())
|
||
{
|
||
scripts.POST("/copywriting", controller.Copywriting) // 下载文案文件
|
||
scripts.POST("/copyonline", controller.CopyOnline) // 复制线上环境到QA
|
||
scripts.POST("/clientImageGitPull", controller.ClientImageGitPull) // 复制线下环境到QA
|
||
}
|
||
config.InitConfig()
|
||
//go util.ScheduleDailyTask()
|
||
go server.Server()
|
||
go model.InitToken() // 初始化 Token 列表
|
||
if common.GetEnv() == "prod" { // 生产环境才启动监控
|
||
go monitor.UserAliveMonitor(0) // 用户存活监控
|
||
go monitor.ServerInfoMonitor() // 服务器信息监控
|
||
}
|
||
go util.MonitorServerList() // 启动定时任务发送信息
|
||
defer func() {
|
||
if err := recover(); err != nil {
|
||
log.Printf("Recovered from panic: %v", err)
|
||
// 这里可以添加更多的错误处理逻辑,比如发送通知等
|
||
// 重新启动服务器
|
||
fmt.Print("Restarting server...")
|
||
os.Exit(1)
|
||
}
|
||
}()
|
||
// 启动 Gin 服务器
|
||
r.Run(":5320") // 在 0.0.0.0:5320 上监听并服务
|
||
}
|