diff options
Diffstat (limited to 'hotline/chat.go')
| -rw-r--r-- | hotline/chat.go | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/hotline/chat.go b/hotline/chat.go new file mode 100644 index 0000000..6f2a4dd --- /dev/null +++ b/hotline/chat.go @@ -0,0 +1,137 @@ +package hotline + +import ( + "crypto/rand" + "github.com/stretchr/testify/mock" + "slices" + "sync" +) + +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 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) +} + +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 +} |