]> git.r.bdr.sh - rbdr/mobius/blob - hotline/chat.go
Delete docs/Screenshot 2024-05-03 at 4.40.09 PM.png
[rbdr/mobius] / hotline / chat.go
1 package hotline
2
3 import (
4 "crypto/rand"
5 "github.com/stretchr/testify/mock"
6 "slices"
7 "sync"
8 )
9
10 type PrivateChat struct {
11 Subject string
12 ClientConn map[[2]byte]*ClientConn
13 }
14
15 type ChatID [4]byte
16
17 type 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
26 type MockChatManager struct {
27 mock.Mock
28 }
29
30 func (m *MockChatManager) New(cc *ClientConn) ChatID {
31 args := m.Called(cc)
32
33 return args.Get(0).(ChatID)
34 }
35
36 func (m *MockChatManager) GetSubject(id ChatID) string {
37 args := m.Called(id)
38
39 return args.String(0)
40 }
41
42 func (m *MockChatManager) Join(id ChatID, cc *ClientConn) {
43 m.Called(id, cc)
44 }
45
46 func (m *MockChatManager) Leave(id ChatID, clientID [2]byte) {
47 m.Called(id, clientID)
48 }
49
50 func (m *MockChatManager) SetSubject(id ChatID, subject string) {
51 m.Called(id, subject)
52
53 }
54
55 func (m *MockChatManager) Members(id ChatID) []*ClientConn {
56 args := m.Called(id)
57
58 return args.Get(0).([]*ClientConn)
59 }
60
61 type MemChatManager struct {
62 chats map[ChatID]*PrivateChat
63
64 mu sync.Mutex
65 }
66
67 func NewMemChatManager() *MemChatManager {
68 return &MemChatManager{
69 chats: make(map[ChatID]*PrivateChat),
70 }
71 }
72
73 func (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
87 func (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
95 func (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
107 func (cm *MemChatManager) GetSubject(id ChatID) string {
108 cm.mu.Lock()
109 defer cm.mu.Unlock()
110
111 return cm.chats[id].Subject
112 }
113
114 func (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
130 func (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 }