/
hub.go
117 lines (98 loc) · 2.38 KB
/
hub.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package domain
import (
"fmt"
command "github.com/lean-enjoyers/catchat/pkg/command/base"
)
type Hub struct {
// Registered Clients.
clients map[*Client]bool
// Register channel
register chan *Client
// Unregister channel
unregister chan *Client
// Messages to send to all clients.
broadcast chan []byte
}
// Creates a new empty hub
func MakeHub() *Hub {
return &Hub{
clients: make(map[*Client]bool),
register: make(chan *Client),
unregister: make(chan *Client),
broadcast: make(chan []byte),
}
}
// Registers the client by sending the client into the register channel.
func (h *Hub) RegisterClient(client *Client) {
h.register <- client
}
// Unregisters the client by sending the client into the unregister channel
func (h *Hub) UnregisterClient(client *Client) {
h.unregister <- client
}
// Adds a client to the hub.
func (h *Hub) AddClient(client *Client) {
h.clients[client] = true
}
// Removes the client from the hub.
func (h *Hub) DeleteClient(client *Client) {
delete(h.clients, client)
close(client.send)
}
func (h *Hub) BroadcastToClient(payload []byte, targetUserID string) {
for client := range h.clients {
if client.userID == targetUserID {
select {
case client.send <- payload:
default:
h.DeleteClient(client)
}
}
}
}
func (h *Hub) BroadcastMessage(message string) {
payload := []byte(fmt.Sprintf("<div hx-swap-oob='beforeend:#chat_body'><p>%s</p></div>", message))
for client := range h.clients {
select {
// Forward the message to all other clients.
case client.send <- payload:
// Failed sending to the client, terminate the client.
default:
h.DeleteClient(client)
}
}
}
func (h *Hub) HandleCommand(cmd string) {
args := command.GetArgs(cmd)
commandName := args.GetCommand()
if len(commandName) > 0 {
p := command.Commands.Get(commandName)
if p != nil {
p.Execute(args, h)
} else {
h.BroadcastMessage("Error: command not found")
}
}
}
func (h *Hub) Run() {
for {
select {
case client := <-h.register:
h.AddClient(client)
case client := <-h.unregister:
if _, ok := h.clients[client]; ok {
h.DeleteClient(client)
}
// Message received from client.
case message := <-h.broadcast:
h.HandleMessage(string(message))
}
}
}
func (h *Hub) HandleMessage(message string) {
if len(message) > 0 && message[0] == '/' {
h.HandleCommand(message[1:])
} else {
h.BroadcastMessage(message)
}
}