All checks were successful
itom-platform auto build image / build (push) Successful in 3m17s
160 lines
4.6 KiB
Go
160 lines
4.6 KiB
Go
package bot
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
chatmw "git.imall.cloud/openim/chat/internal/api/mw"
|
|
"git.imall.cloud/openim/chat/internal/api/util"
|
|
"git.imall.cloud/openim/chat/pkg/common/config"
|
|
"git.imall.cloud/openim/chat/pkg/common/kdisc"
|
|
disetcd "git.imall.cloud/openim/chat/pkg/common/kdisc/etcd"
|
|
adminclient "git.imall.cloud/openim/chat/pkg/protocol/admin"
|
|
botclient "git.imall.cloud/openim/chat/pkg/protocol/bot"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/openimsdk/tools/discovery/etcd"
|
|
"github.com/openimsdk/tools/errs"
|
|
"github.com/openimsdk/tools/mw"
|
|
"github.com/openimsdk/tools/system/program"
|
|
"github.com/openimsdk/tools/utils/datautil"
|
|
"github.com/openimsdk/tools/utils/runtimeenv"
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials/insecure"
|
|
"strings"
|
|
)
|
|
|
|
type Config struct {
|
|
ApiConfig config.APIBot
|
|
Discovery config.Discovery
|
|
Share config.Share
|
|
Redis config.Redis
|
|
|
|
RuntimeEnv string
|
|
}
|
|
|
|
func Start(ctx context.Context, index int, cfg *Config) error {
|
|
cfg.RuntimeEnv = runtimeenv.PrintRuntimeEnvironment()
|
|
apiPort, err := datautil.GetElemByIndex(cfg.ApiConfig.Api.Ports, index)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
client, err := kdisc.NewDiscoveryRegister(&cfg.Discovery, cfg.RuntimeEnv, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
botConn, err := client.GetConn(ctx, cfg.Discovery.RpcService.Bot, grpc.WithTransportCredentials(insecure.NewCredentials()), mw.GrpcClient())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
adminConn, err := client.GetConn(ctx, cfg.Discovery.RpcService.Admin, grpc.WithTransportCredentials(insecure.NewCredentials()), mw.GrpcClient())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
adminClient := adminclient.NewAdminClient(adminConn)
|
|
botClient := botclient.NewBotClient(botConn)
|
|
base := util.Api{
|
|
ImUserID: cfg.Share.OpenIM.AdminUserID,
|
|
ProxyHeader: cfg.Share.ProxyHeader,
|
|
ChatAdminUserID: cfg.Share.ChatAdmin[0],
|
|
}
|
|
botApi := New(botClient, &base)
|
|
mwApi := chatmw.New(adminClient)
|
|
gin.SetMode(gin.ReleaseMode)
|
|
engine := gin.New()
|
|
engine.Use(gin.Recovery(), mw.CorsHandler(), mw.GinParseOperationID(), func(c *gin.Context) {
|
|
// 确保 operationID 被正确设置到 context 中
|
|
operationID := c.GetHeader("operationid")
|
|
if operationID != "" {
|
|
c.Set("operationID", operationID)
|
|
}
|
|
c.Next()
|
|
})
|
|
|
|
// 可选的 Prometheus metrics 端点
|
|
// 支持配置文件或环境变量控制(环境变量优先)
|
|
prometheusEnable := cfg.ApiConfig.Prometheus.Enable
|
|
if envEnable := os.Getenv("PROMETHEUS_ENABLE"); envEnable != "" {
|
|
prometheusEnable = strings.ToLower(envEnable) == "true" || envEnable == "1"
|
|
}
|
|
if prometheusEnable {
|
|
metricsPath := cfg.ApiConfig.Prometheus.Path
|
|
if envPath := os.Getenv("PROMETHEUS_PATH"); envPath != "" {
|
|
metricsPath = envPath
|
|
}
|
|
if metricsPath == "" {
|
|
metricsPath = "/metrics"
|
|
}
|
|
engine.GET(metricsPath, gin.WrapH(promhttp.Handler()))
|
|
}
|
|
|
|
SetBotRoute(engine, botApi, mwApi)
|
|
|
|
var (
|
|
netDone = make(chan struct{}, 1)
|
|
netErr error
|
|
)
|
|
server := http.Server{Addr: fmt.Sprintf(":%d", apiPort), Handler: engine}
|
|
go func() {
|
|
err = server.ListenAndServe()
|
|
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
|
netErr = errs.WrapMsg(err, fmt.Sprintf("api start err: %s", server.Addr))
|
|
netDone <- struct{}{}
|
|
}
|
|
}()
|
|
if cfg.Discovery.Enable == kdisc.ETCDCONST {
|
|
cm := disetcd.NewConfigManager(client.(*etcd.SvcDiscoveryRegistryImpl).GetClient(),
|
|
[]string{
|
|
config.ChatAPIBotCfgFileName,
|
|
config.DiscoveryConfigFileName,
|
|
config.ShareFileName,
|
|
config.LogConfigFileName,
|
|
},
|
|
)
|
|
cm.Watch(ctx)
|
|
}
|
|
shutdown := func() error {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
|
defer cancel()
|
|
err := server.Shutdown(ctx)
|
|
if err != nil {
|
|
return errs.WrapMsg(err, "shutdown err")
|
|
}
|
|
return nil
|
|
}
|
|
disetcd.RegisterShutDown(shutdown)
|
|
|
|
sigs := make(chan os.Signal, 1)
|
|
signal.Notify(sigs, syscall.SIGTERM)
|
|
select {
|
|
case <-sigs:
|
|
program.SIGTERMExit()
|
|
if err := shutdown(); err != nil {
|
|
return err
|
|
}
|
|
case <-netDone:
|
|
close(netDone)
|
|
return netErr
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func SetBotRoute(router gin.IRouter, bot *Api, mw *chatmw.MW) {
|
|
account := router.Group("/agent")
|
|
account.POST("/create", mw.CheckAdmin, bot.CreateAgent)
|
|
account.POST("/delete", mw.CheckAdmin, bot.DeleteAgent)
|
|
account.POST("/update", mw.CheckAdmin, bot.UpdateAgent)
|
|
account.POST("/page", mw.CheckToken, bot.PageFindAgent)
|
|
|
|
imwebhook := router.Group("/im_callback")
|
|
imwebhook.POST("/callbackAfterSendSingleMsgCommand", bot.AfterSendSingleMsg)
|
|
imwebhook.POST("/callbackAfterSendGroupMsgCommand", bot.AfterSendGroupMsg)
|
|
}
|