go-websockets-talk/code/hub.go

115 lines
2.3 KiB
Go

package main
import (
"fmt"
"strings"
"time"
"github.com/gorilla/websocket"
)
var usernames = make(map[*websocket.Conn]string)
var nameToConn = make(map[string]*websocket.Conn)
func handleIncomingMessage(sender *websocket.Conn, msg string) {
if _, ok := usernames[sender]; !ok {
username := strings.TrimSpace(msg)
if username == "" || username == "server" {
sender.WriteJSON(newError("You have an illegal username."))
return
}
if _, ok = nameToConn[username]; ok {
sender.WriteJSON(newError("The specified username is already taken."))
return
}
sendUserList(sender)
usernames[sender] = username
nameToConn[username] = sender
m := newMessage(msgJoin, "server", username)
m.dispatch()
return
}
sendChatMessage(sender, msg)
}
func handleDisconnection(sender *websocket.Conn) {
username, ok := usernames[sender]
if !ok {
fmt.Println("leave without registering")
return
}
m := newMessage(msgLeave, "server", username)
m.dispatch()
delete(usernames, sender)
delete(nameToConn, username)
}
type messageType string
const (
msgChat messageType = "message"
msgJoin messageType = "join"
msgLeave messageType = "leave"
msgErr messageType = "error"
msgUserList messageType = "users"
)
type message struct {
Type messageType `json:"type"`
Sender string `json:"sender"`
Content interface{} `json:"content"`
Date time.Time `json:"date"`
Success bool `json:"success"`
}
func newError(content string) message {
return message{
Type: msgErr,
Sender: "",
Content: content,
Date: time.Now().UTC(),
Success: false,
}
}
func newMessage(msgType messageType, sender string, content string) message {
return message{
Type: msgType,
Sender: sender,
Content: content,
Date: time.Now().UTC(),
Success: true,
}
}
func (m message) dispatch() {
for client := range usernames {
_ = client.WriteJSON(m)
}
}
func sendUserList(who *websocket.Conn) {
list := []string{}
for _, username := range usernames {
list = append(list, username)
}
m := message{
Type: msgUserList,
Sender: "",
Content: list,
Date: time.Now().UTC(),
Success: true,
}
_ = who.WriteJSON(m)
}
func sendChatMessage(sender *websocket.Conn, msg string) {
m := newMessage(msgChat, usernames[sender], msg)
m.dispatch()
}