Files
cid/main.go
2026-06-10 15:41:58 +08:00

139 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"cid/controller/dataengine"
"cid/controller/yidun"
serviceDataengine "cid/service/dataengine"
serviceYidun "cid/service/yidun"
"context"
"fmt"
"os"
"path/filepath"
"time"
_ "gitea.redpowerfuture.com/red-future/common/consul"
"gitea.redpowerfuture.com/red-future/common/http"
"gitea.redpowerfuture.com/red-future/common/jaeger"
_ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
func main() {
ctx := context.Background()
defer jaeger.ShutDown(ctx)
// 设置时区为东八区
loc, err := time.LoadLocation("Asia/Shanghai")
if err == nil {
time.Local = loc
}
// 关键:设置 PGTZ 环境变量lib/pq 驱动在连接 pg 时会自动设置 session timezone
// 确保从数据库读取 TIMESTAMPTZ 时返回的是东八区时间gtime.Time 序列化输出北京时间
os.Setenv("PGTZ", "Asia/Shanghai")
// 初始化易盾客户端
if err := serviceYidun.InitYidunClients(ctx); err != nil {
panic(fmt.Sprintf("初始化易盾客户端失败: %v", err))
}
g.Log().Info(ctx, "易盾客户端初始化成功")
// 启动内容送检定时任务
startContentCheckService(ctx)
// 获取前端目录
frontendDir := getFrontendDir()
// 注册前端静态文件路由(在使用 http.Httpserver 之前)
registerFrontendRoutes(frontendDir)
// 注册 API 路由并启动服务器
http.RouteRegister([]interface{}{
yidun.YidunController,
yidun.YidunCallback,
yidun.ContentCheck,
dataengine.MaterialVerify,
})
// 打印前端访问地址
port := g.Cfg().MustGet(ctx, "server.address", ":3001").String()
g.Log().Info(ctx, "============================================")
g.Log().Infof(ctx, "🌐 前端访问地址: http://localhost%s", port)
g.Log().Info(ctx, "============================================")
select {}
}
// getFrontendDir 获取前端目录路径
func getFrontendDir() string {
execPath, _ := os.Executable()
execDir := filepath.Dir(execPath)
frontendDir := filepath.Join(execDir, "resource", "frontend")
if _, err := os.Stat(frontendDir); os.IsNotExist(err) {
cwd, _ := os.Getwd()
frontendDir = filepath.Join(cwd, "resource", "frontend")
}
return frontendDir
}
// registerFrontendRoutes 注册前端静态文件路由
func registerFrontendRoutes(frontendDir string) {
if _, err := os.Stat(frontendDir); os.IsNotExist(err) {
g.Log().Warningf(context.Background(), "前端目录不存在: %s", frontendDir)
return
}
s := http.Httpserver
// 静态资源路由
s.BindHandler("/frontend/{file}", func(r *ghttp.Request) {
file := r.Get("file").String()
filePath := filepath.Join(frontendDir, file)
if _, err := os.Stat(filePath); err == nil {
r.Response.ServeFile(filePath)
} else {
r.Response.WriteStatus(404)
}
})
// 首页/主入口
s.BindHandler("/", func(r *ghttp.Request) {
indexFile := filepath.Join(frontendDir, "material-verify.html")
if _, err := os.Stat(indexFile); err == nil {
r.Response.ServeFile(indexFile)
} else {
r.Response.Write("<html><body><h1>CID Backend Service</h1><p>前端页面未找到</p></body></html>")
}
})
}
// startContentCheckService 启动内容送检服务
func startContentCheckService(ctx context.Context) {
// 检查是否启用定时送检任务
schedulerEnabled := g.Cfg().MustGet(ctx, "content_check.scheduler_enabled", true).Bool()
if !schedulerEnabled {
g.Log().Info(ctx, "定时送检任务已禁用scheduler_enabled=false仅支持API手动送检")
return
}
// 配置送检服务参数
config := serviceDataengine.ContentCheckConfig{
BatchSize: g.Cfg().MustGet(ctx, "content_check.batch_size", 10).Int(),
ImageEnabled: g.Cfg().MustGet(ctx, "content_check.image_enabled", true).Bool(),
VideoEnabled: g.Cfg().MustGet(ctx, "content_check.video_enabled", true).Bool(),
IntervalSeconds: g.Cfg().MustGet(ctx, "content_check.interval_seconds", 30).Int(),
}
serviceDataengine.TencentContentCheck.SetConfig(config)
// 启动服务
if err := serviceDataengine.TencentContentCheck.Start(ctx); err != nil {
g.Log().Errorf(ctx, "启动内容送检服务失败: %v", err)
} else {
g.Log().Info(ctx, "内容送检服务启动成功")
}
}