]>
Commit | Line | Data |
---|---|---|
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 MemChatManager struct { | |
27 | chats map[ChatID]*PrivateChat | |
28 | ||
29 | mu sync.Mutex | |
30 | } | |
31 | ||
32 | func NewMemChatManager() *MemChatManager { | |
33 | return &MemChatManager{ | |
34 | chats: make(map[ChatID]*PrivateChat), | |
35 | } | |
36 | } | |
37 | ||
38 | func (cm *MemChatManager) New(cc *ClientConn) ChatID { | |
39 | cm.mu.Lock() | |
40 | defer cm.mu.Unlock() | |
41 | ||
42 | var randID [4]byte | |
43 | _, _ = rand.Read(randID[:]) | |
44 | ||
45 | cm.chats[randID] = &PrivateChat{ClientConn: make(map[[2]byte]*ClientConn)} | |
46 | ||
47 | cm.chats[randID].ClientConn[cc.ID] = cc | |
48 | ||
49 | return randID | |
50 | } | |
51 | ||
52 | func (cm *MemChatManager) Join(id ChatID, cc *ClientConn) { | |
53 | cm.mu.Lock() | |
54 | defer cm.mu.Unlock() | |
55 | ||
56 | chat := cm.chats[id] | |
57 | chat.ClientConn[cc.ID] = cc | |
58 | } | |
59 | ||
60 | func (cm *MemChatManager) Leave(id ChatID, clientID [2]byte) { | |
61 | cm.mu.Lock() | |
62 | defer cm.mu.Unlock() | |
63 | ||
64 | privChat, ok := cm.chats[id] | |
65 | if !ok { | |
66 | return | |
67 | } | |
68 | ||
69 | delete(privChat.ClientConn, clientID) | |
70 | } | |
71 | ||
72 | func (cm *MemChatManager) GetSubject(id ChatID) string { | |
73 | cm.mu.Lock() | |
74 | defer cm.mu.Unlock() | |
75 | ||
76 | return cm.chats[id].Subject | |
77 | } | |
78 | ||
79 | func (cm *MemChatManager) Members(id ChatID) []*ClientConn { | |
80 | cm.mu.Lock() | |
81 | defer cm.mu.Unlock() | |
82 | ||
83 | chat := cm.chats[id] | |
84 | ||
85 | var members []*ClientConn | |
86 | for _, cc := range chat.ClientConn { | |
87 | members = append(members, cc) | |
88 | } | |
89 | ||
90 | slices.SortFunc(members, clientConnSortFunc) | |
91 | ||
92 | return members | |
93 | } | |
94 | ||
95 | func (cm *MemChatManager) SetSubject(id ChatID, subject string) { | |
96 | cm.mu.Lock() | |
97 | defer cm.mu.Unlock() | |
98 | ||
99 | chat := cm.chats[id] | |
100 | ||
101 | chat.Subject = subject | |
102 | } | |
103 | ||
104 | type MockChatManager struct { | |
105 | mock.Mock | |
106 | } | |
107 | ||
108 | func (m *MockChatManager) New(cc *ClientConn) ChatID { | |
109 | args := m.Called(cc) | |
110 | ||
111 | return args.Get(0).(ChatID) | |
112 | } | |
113 | ||
114 | func (m *MockChatManager) GetSubject(id ChatID) string { | |
115 | args := m.Called(id) | |
116 | ||
117 | return args.String(0) | |
118 | } | |
119 | ||
120 | func (m *MockChatManager) Join(id ChatID, cc *ClientConn) { | |
121 | m.Called(id, cc) | |
122 | } | |
123 | ||
124 | func (m *MockChatManager) Leave(id ChatID, clientID [2]byte) { | |
125 | m.Called(id, clientID) | |
126 | } | |
127 | ||
128 | func (m *MockChatManager) SetSubject(id ChatID, subject string) { | |
129 | m.Called(id, subject) | |
130 | ||
131 | } | |
132 | ||
133 | func (m *MockChatManager) Members(id ChatID) []*ClientConn { | |
134 | args := m.Called(id) | |
135 | ||
136 | return args.Get(0).([]*ClientConn) | |
137 | } |