]> git.r.bdr.sh - rbdr/mobius/blame - hotline/chat.go
Re-add UserList field to client
[rbdr/mobius] / hotline / chat.go
CommitLineData
d9bc63a1
JH
1package hotline
2
3import (
4 "crypto/rand"
5 "github.com/stretchr/testify/mock"
6 "slices"
7 "sync"
8)
9
10type PrivateChat struct {
11 Subject string
12 ClientConn map[[2]byte]*ClientConn
13}
14
15type ChatID [4]byte
16
17type ChatManager interface {
18 New(cc *ClientConn) ChatID
19 GetSubject(id ChatID) string
20 Join(id ChatID, cc *ClientConn)
21 Leave(id ChatID, clientID [2]byte)
22 SetSubject(id ChatID, subject string)
23 Members(id ChatID) []*ClientConn
24}
25
26type MockChatManager struct {
27 mock.Mock
28}
29
30func (m *MockChatManager) New(cc *ClientConn) ChatID {
31 args := m.Called(cc)
32
33 return args.Get(0).(ChatID)
34}
35
36func (m *MockChatManager) GetSubject(id ChatID) string {
37 args := m.Called(id)
38
39 return args.String(0)
40}
41
42func (m *MockChatManager) Join(id ChatID, cc *ClientConn) {
43 m.Called(id, cc)
44}
45
46func (m *MockChatManager) Leave(id ChatID, clientID [2]byte) {
47 m.Called(id, clientID)
48}
49
50func (m *MockChatManager) SetSubject(id ChatID, subject string) {
51 m.Called(id, subject)
52
53}
54
55func (m *MockChatManager) Members(id ChatID) []*ClientConn {
56 args := m.Called(id)
57
58 return args.Get(0).([]*ClientConn)
59}
60
61type MemChatManager struct {
62 chats map[ChatID]*PrivateChat
63
64 mu sync.Mutex
65}
66
67func NewMemChatManager() *MemChatManager {
68 return &MemChatManager{
69 chats: make(map[ChatID]*PrivateChat),
70 }
71}
72
73func (cm *MemChatManager) New(cc *ClientConn) ChatID {
74 cm.mu.Lock()
75 defer cm.mu.Unlock()
76
77 var randID [4]byte
78 _, _ = rand.Read(randID[:])
79
80 cm.chats[randID] = &PrivateChat{ClientConn: make(map[[2]byte]*ClientConn)}
81
82 cm.chats[randID].ClientConn[cc.ID] = cc
83
84 return randID
85}
86
87func (cm *MemChatManager) Join(id ChatID, cc *ClientConn) {
88 cm.mu.Lock()
89 defer cm.mu.Unlock()
90
91 chat := cm.chats[id]
92 chat.ClientConn[cc.ID] = cc
93}
94
95func (cm *MemChatManager) Leave(id ChatID, clientID [2]byte) {
96 cm.mu.Lock()
97 defer cm.mu.Unlock()
98
99 privChat, ok := cm.chats[id]
100 if !ok {
101 return
102 }
103
104 delete(privChat.ClientConn, clientID)
105}
106
107func (cm *MemChatManager) GetSubject(id ChatID) string {
108 cm.mu.Lock()
109 defer cm.mu.Unlock()
110
111 return cm.chats[id].Subject
112}
113
114func (cm *MemChatManager) Members(id ChatID) []*ClientConn {
115 cm.mu.Lock()
116 defer cm.mu.Unlock()
117
118 chat := cm.chats[id]
119
120 var members []*ClientConn
121 for _, cc := range chat.ClientConn {
122 members = append(members, cc)
123 }
124
125 slices.SortFunc(members, clientConnSortFunc)
126
127 return members
128}
129
130func (cm *MemChatManager) SetSubject(id ChatID, subject string) {
131 cm.mu.Lock()
132 defer cm.mu.Unlock()
133
134 chat := cm.chats[id]
135
136 chat.Subject = subject
137}