118 lines
2.1 KiB
Go
118 lines
2.1 KiB
Go
|
|
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
|
|||
|
|
}
|