forked from AntonioVdlC/chat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhub.go
137 lines (119 loc) · 3.42 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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package main
import (
"database/sql"
"log"
"time"
"github.com/nicksnyder/go-i18n/i18n"
)
// Hub represents a chat room and holds a list of all connected
// clients. Besides, it has methods to broadcast messages, and
// register and unregister clients
type Hub struct {
clients map[*Client]bool
broadcast chan Message
register chan *Client
unregister chan *Client
T i18n.TranslateFunc
db *sql.DB
}
// newHub creates a returns a new Hub instance
func newHub(db *sql.DB) *Hub {
return &Hub{
broadcast: make(chan Message),
register: make(chan *Client),
unregister: make(chan *Client),
clients: make(map[*Client]bool),
db: db,
}
}
// setT adds the i18n TranslateFunc utility to the Hub
func (h *Hub) setT(T i18n.TranslateFunc) {
h.T = T
}
// run launches the Hub instance!
func (h *Hub) run() {
for {
select {
case client := <- h.register:
log.Println("[" + client.user.UserID + "] " + client.user.Name + " logged in.")
// Insert login in DB
id, err := insertMessage(h.db, Message{
UserID: client.user.UserID,
UserName: client.user.Name,
UserAvatar: client.user.AvatarURL,
Type: "notice",
Content: "login",
Date: time.Now().UTC(),
})
if err != nil {
log.Printf("Error: %v", err)
return
}
// Send notice to other clients that a new client logged in
message := Message{ID:id, Type:"notice", Content: h.T("chat_notice_login", client.user), Date: time.Now().UTC()}
for c := range h.clients {
c.send <- message
}
// Add the new client to the list of clients
h.clients[client] = true
// Send previous messages to new client
rows, err := selectPreviousMessage(h.db, client.user.UserID)
defer rows.Close()
if err != nil {
log.Printf("Error: %v", err)
return
}
for rows.Next() {
var message Message
if err := rows.Scan(&message.ID, &message.UserID, &message.UserName, &message.UserAvatar, &message.Type, &message.Content, &message.Date); err != nil {
log.Printf("Error: %v", err)
return
}
client.send <- message
}
case client := <- h.unregister:
if _, ok := h.clients[client]; ok {
log.Println("[" + client.user.UserID + "] " + client.user.Name + " logged out.")
// Insert logout in DB
id, err := insertMessage(h.db, Message{
UserID: client.user.UserID,
UserName: client.user.Name,
UserAvatar: client.user.AvatarURL,
Type: "notice",
Content: "logout",
Date: time.Now().UTC(),
})
if err != nil {
log.Printf("Error: %v", err)
return
}
// Send notice to other clients that this client logged out
message := Message{ID:id, Type:"notice", Content: h.T("chat_notice_logout", client.user), Date: time.Now().UTC()}
for c := range h.clients {
c.send <- message
}
// Remove the client from the list and close send chan
delete(h.clients, client)
close(client.send)
}
case message := <- h.broadcast:
log.Println("[" + message.UserID + "] " + message.UserName + " sent '" + message.Content + "'.")
// Insert message in DB
id, err := insertMessage(h.db, message)
if err != nil {
log.Printf("Error: %v", err)
return
}
message.ID = id
// Send message to all clients
for client := range h.clients {
select {
case client.send <- message:
default:
close(client.send)
delete(h.clients, client)
}
}
}
}
}