| Current Path : /home/hotlineuser/mobius/hotline/ |
| Current File : //home/hotlineuser/mobius/hotline/chat.go |
package hotline
import (
"crypto/rand"
"slices"
"sync"
"github.com/stretchr/testify/mock"
)
type PrivateChat struct {
Subject string
ClientConn map[[2]byte]*ClientConn
}
type ChatID [4]byte
type ChatManager interface {
New(cc *ClientConn) ChatID
GetSubject(id ChatID) string
Join(id ChatID, cc *ClientConn)
Leave(id ChatID, clientID [2]byte)
SetSubject(id ChatID, subject string)
Members(id ChatID) []*ClientConn
}
type MemChatManager struct {
chats map[ChatID]*PrivateChat
mu sync.Mutex
}
func NewMemChatManager() *MemChatManager {
return &MemChatManager{
chats: make(map[ChatID]*PrivateChat),
}
}
func (cm *MemChatManager) New(cc *ClientConn) ChatID {
cm.mu.Lock()
defer cm.mu.Unlock()
var randID [4]byte
_, _ = rand.Read(randID[:])
cm.chats[randID] = &PrivateChat{ClientConn: make(map[[2]byte]*ClientConn)}
cm.chats[randID].ClientConn[cc.ID] = cc
return randID
}
func (cm *MemChatManager) Join(id ChatID, cc *ClientConn) {
cm.mu.Lock()
defer cm.mu.Unlock()
chat := cm.chats[id]
chat.ClientConn[cc.ID] = cc
}
func (cm *MemChatManager) Leave(id ChatID, clientID [2]byte) {
cm.mu.Lock()
defer cm.mu.Unlock()
privChat, ok := cm.chats[id]
if !ok {
return
}
delete(privChat.ClientConn, clientID)
}
func (cm *MemChatManager) GetSubject(id ChatID) string {
cm.mu.Lock()
defer cm.mu.Unlock()
return cm.chats[id].Subject
}
func (cm *MemChatManager) Members(id ChatID) []*ClientConn {
cm.mu.Lock()
defer cm.mu.Unlock()
chat := cm.chats[id]
var members []*ClientConn
for _, cc := range chat.ClientConn {
members = append(members, cc)
}
slices.SortFunc(members, clientConnSortFunc)
return members
}
func (cm *MemChatManager) SetSubject(id ChatID, subject string) {
cm.mu.Lock()
defer cm.mu.Unlock()
chat := cm.chats[id]
chat.Subject = subject
}
type MockChatManager struct {
mock.Mock
}
func (m *MockChatManager) New(cc *ClientConn) ChatID {
args := m.Called(cc)
return args.Get(0).(ChatID)
}
func (m *MockChatManager) GetSubject(id ChatID) string {
args := m.Called(id)
return args.String(0)
}
func (m *MockChatManager) Join(id ChatID, cc *ClientConn) {
m.Called(id, cc)
}
func (m *MockChatManager) Leave(id ChatID, clientID [2]byte) {
m.Called(id, clientID)
}
func (m *MockChatManager) SetSubject(id ChatID, subject string) {
m.Called(id, subject)
}
func (m *MockChatManager) Members(id ChatID) []*ClientConn {
args := m.Called(id)
return args.Get(0).([]*ClientConn)
}