package webservices import ( "fmt" "stream-bot/internal/db" "stream-bot/internal/logger" "sync" ) type Manager struct { services map[int]Service mu sync.RWMutex globalMessageChan chan ChatMessage globalEventChan chan AlertEvent } func NewManager() *Manager { m := &Manager{ services: make(map[int]Service), globalMessageChan: make(chan ChatMessage, 1000), globalEventChan: make(chan AlertEvent, 1000), } m.startDispatchers() return m } func (m *Manager) startDispatchers() { go func() { for msg := range m.globalMessageChan { m.mu.RLock() for _, srv := range m.services { if chatSrv, ok := srv.(*ChatService); ok { chatSrv.SendToClients(msg) } } m.mu.RUnlock() } }() go func() { for ev := range m.globalEventChan { m.mu.RLock() for _, srv := range m.services { if alertSrv, ok := srv.(*AlertService); ok { alertSrv.SendToClients(ev) } } m.mu.RUnlock() } }() } func (m *Manager) StartAll() error { list, err := db.GetAllWebServices() if err != nil { return err } for _, ws := range list { if !ws.Enabled { continue } if err := m.startServiceFromDB(ws); err != nil { logger.Error("Failed to start service %d: %v", ws.ID, err) } } return nil } func (m *Manager) startServiceFromDB(ws db.WebService) error { var srv Service switch ws.Type { case "chat": cfg, err := ws.GetChatConfig() if err != nil { return err } srv = NewChatService(ws.Port, cfg) case "alert": cfg, err := ws.GetAlertConfig() if err != nil { return err } srv = NewAlertService(ws.Port, cfg) default: return fmt.Errorf("unknown service type: %s", ws.Type) } if err := srv.Start(); err != nil { return err } m.mu.Lock() m.services[ws.ID] = srv m.mu.Unlock() _ = db.SetWebServiceRunning(ws.ID, true) return nil } func (m *Manager) AddService(serviceType string, port int, config interface{}) (int, error) { id, err := db.CreateWebService(serviceType, port, config) if err != nil { return 0, err } return id, nil } func (m *Manager) StartService(id int) error { ws, err := db.GetWebService(id) if err != nil { return err } return m.startServiceFromDB(*ws) } func (m *Manager) StopService(id int) error { m.mu.Lock() srv, ok := m.services[id] delete(m.services, id) m.mu.Unlock() if !ok { return nil } if err := srv.Stop(); err != nil { return err } _ = db.SetWebServiceRunning(id, false) return nil } func (m *Manager) UpdateConfig(id int, config interface{}) error { ws, err := db.GetWebService(id) if err != nil { return err } if err := db.UpdateWebService(id, ws.Port, config, ws.Enabled); err != nil { return err } m.mu.RLock() srv, ok := m.services[id] m.mu.RUnlock() if ok { return srv.ReloadConfig(config) } return nil } func (m *Manager) DeleteService(id int) error { _ = m.StopService(id) return db.DeleteWebService(id) } // Эти два метода должны быть ТОЛЬКО ОДИН РАЗ! func (m *Manager) SendChatMessage(msg ChatMessage) { select { case m.globalMessageChan <- msg: default: logger.Warn("Chat message buffer full") } } func (m *Manager) SendAlertEvent(event AlertEvent) { select { case m.globalEventChan <- event: default: logger.Warn("Alert event buffer full") } } func (m *Manager) GetService(id int) Service { m.mu.RLock() defer m.mu.RUnlock() return m.services[id] } func (m *Manager) GetAllServices() map[int]Service { m.mu.RLock() defer m.mu.RUnlock() out := make(map[int]Service) for k, v := range m.services { out[k] = v } return out }