精简: 去掉 Telegram 机器人+通知: tgbot 包/stats-notify 与 hash 清理 job/登录通知/backuptotgbot/testTgBot/全部 tg* 设置/locale Bot 本地化/SecretClears 机制; 连带清理 Swagger/外部流量/邮件/2FA 的残留测试

This commit is contained in:
Muse
2026-10-20 10:11:35 +00:00
parent 1498d58f14
commit e42b5d770d
37 changed files with 32 additions and 5471 deletions
+8 -135
View File
@@ -31,7 +31,6 @@ import (
"github.com/mhsanaei/3x-ui/v3/internal/web/runtime"
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
"github.com/mhsanaei/3x-ui/v3/internal/web/service/panel"
"github.com/mhsanaei/3x-ui/v3/internal/web/service/tgbot"
"github.com/mhsanaei/3x-ui/v3/internal/web/websocket"
"github.com/mhsanaei/3x-ui/v3/internal/xray"
@@ -119,7 +118,6 @@ type Server struct {
xrayService service.XrayService
settingService service.SettingService
tgbotService tgbot.Tgbot
wsHub *websocket.Hub
@@ -220,7 +218,7 @@ func (s *Server) initRouter() (*gin.Engine, error) {
// init i18n — still used by backend strings (errors, log messages,
// SubPage menu entries) even though the Go template engine is gone.
err = locale.InitLocalizer(i18nFS, &s.settingService)
err = locale.InitLocalizer(i18nFS)
if err != nil {
return nil, err
}
@@ -371,36 +369,6 @@ func (s *Server) startTask(restartXray bool, loc *time.Location) {
// Check monthly reset days at midnight
_, _ = s.cron.AddJob("@daily", job.NewPeriodicTrafficResetJob("monthly", loc))
// Telegram-bot–dependent jobs: periodic stats report + callback-hash cleanup.
isTgbotenabled, err := s.settingService.GetTgbotEnabled()
if (err == nil) && isTgbotenabled {
runtime, err := s.settingService.GetTgbotRuntime()
if err != nil {
logger.Warningf("Add NewStatsNotifyJob: failed to load runtime: %v; using default @daily", err)
runtime = "@daily"
} else if strings.TrimSpace(runtime) == "" {
logger.Warning("Add NewStatsNotifyJob runtime is empty, using default @daily")
runtime = "@daily"
}
logger.Infof("Tg notify enabled,run at %s", runtime)
if _, err = s.cron.AddJob(runtime, job.NewStatsNotifyJob()); err != nil {
logger.Warningf("Add NewStatsNotifyJob: failed to schedule runtime %q: %v", runtime, err)
}
// check for Telegram bot callback query hash storage reset
_, _ = s.cron.AddJob(cadenceCheckHash, job.NewCheckHashStorageJob())
}
// CPU monitor publishes cpu.high events; register it whenever any notifier
// (Telegram or Email) wants them, independent of the Telegram bot being on.
if s.cpuAlarmWanted() {
_, _ = s.cron.AddJob(cadenceCPUAlarm, job.NewCheckCpuJob())
}
// Memory monitor publishes memory.high events; register it whenever any notifier wants them.
if s.memoryAlarmWanted() {
_, _ = s.cron.AddJob(cadenceMemoryAlarm, job.NewCheckMemJob())
}
if mins := sys.MemoryReleaseIntervalMinutes(); mins > 0 {
_, _ = s.cron.AddJob(fmt.Sprintf("@every %dm", mins), job.NewMemoryReleaseJob())
go func() {
@@ -410,63 +378,16 @@ func (s *Server) startTask(restartXray bool, loc *time.Location) {
}
}
// cpuAlarmWanted reports whether any notifier is configured to receive cpu.high
// alerts, so the minute-long blocking CPU sampler only runs when it's needed.
func (s *Server) cpuAlarmWanted() bool {
wants := func(events string, threshold int) bool {
if threshold <= 0 {
return false
}
for e := range strings.SplitSeq(events, ",") {
if strings.TrimSpace(e) == string(eventbus.EventCPUHigh) {
return true
}
}
return false
}
if on, _ := s.settingService.GetTgbotEnabled(); on {
events, _ := s.settingService.GetTgEnabledEvents()
cpu, _ := s.settingService.GetTgCpu()
if wants(events, cpu) {
return true
}
}
return false
}
// memoryAlarmWanted reports whether any notifier is configured to receive memory.high alerts.
func (s *Server) memoryAlarmWanted() bool {
wants := func(events string, threshold int) bool {
if threshold <= 0 {
return false
}
for e := range strings.SplitSeq(events, ",") {
if strings.TrimSpace(e) == string(eventbus.EventMemoryHigh) {
return true
}
}
return false
}
if on, _ := s.settingService.GetTgbotEnabled(); on {
events, _ := s.settingService.GetTgEnabledEvents()
mem, _ := s.settingService.GetTgMemory()
if wants(events, mem) {
return true
}
}
return false
}
// Start initializes and starts the web server with configured settings, routes, and background jobs.
func (s *Server) Start() (err error) {
return s.start(true, true)
return s.start(true)
}
func (s *Server) StartPanelOnly() (err error) {
return s.start(false, true)
return s.start(false)
}
func (s *Server) start(restartXray bool, startTgBot bool) (err error) {
func (s *Server) start(restartXray bool) (err error) {
// This is an anonymous function, no function name
defer func() {
if err != nil {
@@ -589,7 +510,6 @@ func (s *Server) start(restartXray bool, startTgBot bool) (err error) {
s.bus = eventbus.New(eventbus.DefaultBufferSize)
service.SetEventBus(s.bus)
job.EventBus = s.bus
tgbot.EventBus = s.bus
// Wire xray crash callback BEFORE startTask so it's ready
xray.OnCrash = func(err error) {
@@ -601,65 +521,21 @@ func (s *Server) start(restartXray bool, startTgBot bool) (err error) {
}
}
// Wire Telegram test function to controller
controller.SetTestTgFunc(func() error {
if !s.tgbotService.IsRunning() {
return fmt.Errorf("telegram bot is not running (check token and chat ID)")
}
if err := s.tgbotService.TestConnection(); err != nil {
return fmt.Errorf("telegram API test failed: %w", err)
}
s.tgbotService.SendMsgToTgbotAdmins("✅ Test message from 3x-ui")
return nil
})
controller.SetReloadTgbotFunc(func() {
enabled, err := s.settingService.GetTgbotEnabled()
if err != nil || !enabled {
if s.tgbotService.IsRunning() {
s.tgbotService.Stop()
}
if s.bus != nil {
s.bus.Unsubscribe("tg-notifier")
}
return
}
// Start() stops any previous receiver first, so it is safe whether or not the bot is already running.
tgBot := s.tgbotService.NewTgbot()
if startErr := tgBot.Start(i18nFS); startErr != nil {
logger.Warning("reload Telegram bot failed:", startErr)
return
}
if s.bus != nil {
s.bus.Subscribe("tg-notifier", s.tgbotService.HandleEvent)
}
})
s.startTask(restartXray, loc)
if startTgBot {
isTgbotenabled, err := s.settingService.GetTgbotEnabled()
if (err == nil) && isTgbotenabled {
tgBot := s.tgbotService.NewTgbot()
_ = tgBot.Start(i18nFS)
// Subscribe Telegram notifications for event bus
s.bus.Subscribe("tg-notifier", s.tgbotService.HandleEvent)
}
}
return nil
}
// Stop gracefully shuts down the web server, stops Xray, cron jobs, and Telegram bot.
// Stop gracefully shuts down the web server, stops Xray, and cron jobs.
func (s *Server) Stop() error {
return s.stop(true, true)
return s.stop(true)
}
func (s *Server) StopPanelOnly() error {
return s.stop(false, true)
return s.stop(false)
}
func (s *Server) stop(stopXray bool, stopTgBot bool) error {
func (s *Server) stop(stopXray bool) error {
s.cancel()
if stopXray {
_ = s.xrayService.StopXray()
@@ -678,9 +554,6 @@ func (s *Server) stop(stopXray bool, stopTgBot bool) error {
if stopXray {
service.StopTrafficWriter()
}
if stopTgBot && s.tgbotService.IsRunning() {
s.tgbotService.Stop()
}
// Gracefully stop WebSocket hub
if s.wsHub != nil {
s.wsHub.Stop()