package websocket import ( "sync" ) type Room struct { ID int64 Clients map[*Client]bool mu sync.RWMutex } func NewRoom(chatID int64) *Room { return &Room{ ID: chatID, Clients: make(map[*Client]bool), } } func (r *Room) AddClient(client *Client) { r.mu.Lock() defer r.mu.Unlock() r.Clients[client] = true client.JoinRoom(r.ID) } func (r *Room) RemoveClient(client *Client) { r.mu.Lock() defer r.mu.Unlock() if _, exists := r.Clients[client]; exists { delete(r.Clients, client) client.LeaveRoom(r.ID) } } func (r *Room) Broadcast(message []byte, excludeClient *Client) { r.mu.RLock() defer r.mu.RUnlock() for client := range r.Clients { if excludeClient != nil && client == excludeClient { continue } // Безопасная отправка с проверкой закрытого канала func() { defer func() { if r := recover(); r != nil { // Канал закрыт, игнорируем } }() select { case client.send <- message: default: // Канал заполнен или закрыт } }() } } func (r *Room) BroadcastToAll(message []byte) { r.Broadcast(message, nil) } func (r *Room) GetClientCount() int { r.mu.RLock() defer r.mu.RUnlock() return len(r.Clients) } func (r *Room) GetClients() []*Client { r.mu.RLock() defer r.mu.RUnlock() clients := make([]*Client, 0, len(r.Clients)) for client := range r.Clients { clients = append(clients, client) } return clients } func (r *Room) IsEmpty() bool { r.mu.RLock() defer r.mu.RUnlock() return len(r.Clients) == 0 } func (r *Room) HasClient(client *Client) bool { r.mu.RLock() defer r.mu.RUnlock() _, exists := r.Clients[client] return exists } func (r *Room) GetUserIDs() []int64 { r.mu.RLock() defer r.mu.RUnlock() userIDs := make([]int64, 0, len(r.Clients)) for client := range r.Clients { userIDs = append(userIDs, client.userID) } return userIDs } func (r *Room) HasClientByUserID(userID int64) bool { r.mu.RLock() defer r.mu.RUnlock() for client := range r.Clients { if client.userID == userID { return true } } return false }