Converting from conn.WriteMessage to conn.WriteJson
This takes away some of the work on the developers side to worry about parsing the object as a json string. Backend work for issue #7
This commit is contained in:
parent
28d43a726a
commit
a717c6ef38
|
@ -11,10 +11,6 @@ import (
|
|||
"github.com/zorchenhimer/MovieNight/common"
|
||||
)
|
||||
|
||||
func connSend(s string, c *websocket.Conn) {
|
||||
c.WriteMessage(websocket.TextMessage, []byte(s))
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
name string // Display name
|
||||
conn *websocket.Conn
|
||||
|
@ -56,12 +52,19 @@ func (cl *Client) NewMsg(data common.ClientData) {
|
|||
switch data.Type {
|
||||
case common.CdUsers:
|
||||
fmt.Printf("[chat|hidden] <%s> get list of users\n", cl.name)
|
||||
s, err := common.EncodeHiddenMessage(data.Type, chat.GetNames())
|
||||
if err != nil {
|
||||
fmt.Printf("[ERR] could not encode user list, %v", err)
|
||||
return
|
||||
|
||||
names := chat.GetNames()
|
||||
idx := -1
|
||||
for i := range names {
|
||||
if names[i] == cl.name {
|
||||
idx = i
|
||||
}
|
||||
}
|
||||
|
||||
err := cl.SendChatData(common.NewChatHiddenMessage(data.Type, append(names[:idx], names[idx+1:]...)))
|
||||
if err != nil {
|
||||
fmt.Printf("Error sending chat data: %v\n", err)
|
||||
}
|
||||
cl.Send(s)
|
||||
case common.CdMessage:
|
||||
msg := html.EscapeString(data.Message)
|
||||
msg = removeDumbSpaces(msg)
|
||||
|
@ -81,7 +84,10 @@ func (cl *Client) NewMsg(data common.ClientData) {
|
|||
|
||||
response := commands.RunCommand(cmd, args, cl)
|
||||
if response != "" {
|
||||
cl.ServerMessage(response)
|
||||
err := cl.SendServerMessage(ParseEmotes(msg))
|
||||
if err != nil {
|
||||
fmt.Printf("Error command results %v\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -103,6 +109,30 @@ func (cl *Client) NewMsg(data common.ClientData) {
|
|||
}
|
||||
}
|
||||
|
||||
func (cl *Client) SendChatData(newData common.NewChatDataFunc) error {
|
||||
cd, err := newData()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create chatdata of type %d: %v", cd.Type, err)
|
||||
}
|
||||
return cl.Send(cd)
|
||||
}
|
||||
|
||||
func (cl *Client) Send(data common.ChatData) error {
|
||||
err := cl.conn.WriteJSON(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not send message: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cl *Client) SendServerMessage(s string) error {
|
||||
err := cl.SendChatData(common.NewChatMessage("", ColorServerMessage, s, common.MsgServer))
|
||||
if err != nil {
|
||||
return fmt.Errorf("could send server message to %s: %s; Message: %s\n", cl.name, err, s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Make links clickable
|
||||
func formatLinks(input string) string {
|
||||
newMsg := []string{}
|
||||
|
@ -121,22 +151,6 @@ func (cl *Client) Exit() {
|
|||
cl.belongsTo.Leave(cl.name, cl.color)
|
||||
}
|
||||
|
||||
//Sending message block to the client
|
||||
func (cl *Client) Send(s string) {
|
||||
connSend(s, cl.conn)
|
||||
}
|
||||
|
||||
// Send server message to this client
|
||||
func (cl *Client) ServerMessage(msg string) {
|
||||
msg = ParseEmotes(msg)
|
||||
encoded, err := common.EncodeMessage("", "#ea6260", msg, common.MsgError)
|
||||
if err != nil {
|
||||
fmt.Printf("[ERR] could not server message to %s: %s; Message: %s\n", cl.name, err, msg)
|
||||
return
|
||||
}
|
||||
cl.Send(encoded)
|
||||
}
|
||||
|
||||
// Outgoing messages
|
||||
func (cl *Client) Message(msg string) {
|
||||
msg = ParseEmotes(msg)
|
||||
|
|
|
@ -229,7 +229,7 @@ var commands = &CommandControl{
|
|||
common.CNReloadEmotes.String(): Command{
|
||||
HelpText: "Reload the emotes on the server.",
|
||||
Function: func(cl *Client, args []string) string {
|
||||
cl.ServerMessage("Reloading emotes")
|
||||
cl.SendServerMessage("Reloading emotes")
|
||||
num, err := LoadEmotes()
|
||||
if err != nil {
|
||||
fmt.Printf("Unbale to reload emotes: %s\n", err)
|
||||
|
|
60
chatroom.go
60
chatroom.go
|
@ -18,8 +18,9 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
UsernameMaxLength int = 36
|
||||
UsernameMinLength int = 3
|
||||
UsernameMaxLength int = 36
|
||||
UsernameMinLength int = 3
|
||||
ColorServerMessage string = "#ea6260"
|
||||
)
|
||||
|
||||
var re_username *regexp.Regexp = regexp.MustCompile(`^[0-9a-zA-Z_-]+$`)
|
||||
|
@ -29,8 +30,8 @@ type ChatRoom struct {
|
|||
clientsMtx sync.Mutex
|
||||
tempConn map[string]*websocket.Conn
|
||||
|
||||
queue chan string
|
||||
modqueue chan string // mod and admin broadcast messages
|
||||
queue chan common.ChatData
|
||||
modqueue chan common.ChatData // mod and admin broadcast messages
|
||||
|
||||
playing string
|
||||
playingLink string
|
||||
|
@ -42,8 +43,8 @@ type ChatRoom struct {
|
|||
//initializing the chatroom
|
||||
func newChatRoom() (*ChatRoom, error) {
|
||||
cr := &ChatRoom{
|
||||
queue: make(chan string, 100),
|
||||
modqueue: make(chan string, 100),
|
||||
queue: make(chan common.ChatData, 100),
|
||||
modqueue: make(chan common.ChatData, 100),
|
||||
clients: make(map[string]*Client),
|
||||
tempConn: make(map[string]*websocket.Conn),
|
||||
}
|
||||
|
@ -159,7 +160,7 @@ func (cr *ChatRoom) Join(name, uid string) (*Client, error) {
|
|||
delete(cr.tempConn, uid)
|
||||
|
||||
fmt.Printf("[join] %s %s\n", host, name)
|
||||
playingCommand, err := common.EncodeCommand(common.CmdPlaying, []string{cr.playing, cr.playingLink})
|
||||
playingCommand, err := common.NewChatCommand(common.CmdPlaying, []string{cr.playing, cr.playingLink})()
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to encode playing command on join: %s\n", err)
|
||||
} else {
|
||||
|
@ -265,15 +266,9 @@ func (cr *ChatRoom) AddMsg(from *Client, isAction, isServer bool, msg string) {
|
|||
t = common.MsgServer
|
||||
}
|
||||
|
||||
data, err := common.EncodeMessage(
|
||||
from.name,
|
||||
from.color,
|
||||
msg,
|
||||
t)
|
||||
|
||||
data, err := common.NewChatMessage(from.name, from.color, msg, t)()
|
||||
if err != nil {
|
||||
fmt.Printf("Error encoding chat message: %s", err)
|
||||
cr.queue <- msg
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -285,8 +280,7 @@ func (cr *ChatRoom) AddMsg(from *Client, isAction, isServer bool, msg string) {
|
|||
}
|
||||
|
||||
func (cr *ChatRoom) AddCmdMsg(command common.CommandType, args []string) {
|
||||
data, err := common.EncodeCommand(command, args)
|
||||
|
||||
data, err := common.NewChatCommand(command, args)()
|
||||
if err != nil {
|
||||
fmt.Printf("Error encoding command: %s", err)
|
||||
return
|
||||
|
@ -300,7 +294,7 @@ func (cr *ChatRoom) AddCmdMsg(command common.CommandType, args []string) {
|
|||
}
|
||||
|
||||
func (cr *ChatRoom) AddModNotice(message string) {
|
||||
data, err := common.EncodeMessage("", "", message, common.MsgNotice)
|
||||
data, err := common.NewChatMessage("", "", message, common.MsgNotice)()
|
||||
if err != nil {
|
||||
fmt.Printf("Error encoding notice: %v", err)
|
||||
return
|
||||
|
@ -314,7 +308,7 @@ func (cr *ChatRoom) AddModNotice(message string) {
|
|||
}
|
||||
|
||||
func (cr *ChatRoom) AddEventMsg(event common.EventType, name, color string) {
|
||||
data, err := common.EncodeEvent(event, name, color)
|
||||
data, err := common.NewChatEvent(event, name, color)()
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Error encoding command: %s", err)
|
||||
|
@ -338,7 +332,7 @@ func (cr *ChatRoom) Unmod(name string) error {
|
|||
}
|
||||
|
||||
client.Unmod()
|
||||
client.ServerMessage(`You have been unmodded.`)
|
||||
client.SendServerMessage(`You have been unmodded.`)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -352,7 +346,7 @@ func (cr *ChatRoom) Mod(name string) error {
|
|||
}
|
||||
|
||||
client.IsMod = true
|
||||
client.ServerMessage(`You have been modded.`)
|
||||
client.SendServerMessage(`You have been modded.`)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -378,17 +372,14 @@ func (cr *ChatRoom) UserCount() int {
|
|||
func (cr *ChatRoom) BroadCast() {
|
||||
running := true
|
||||
for running {
|
||||
cr.clientsMtx.Lock()
|
||||
select {
|
||||
case msg := <-cr.queue:
|
||||
if len(msg) > 0 {
|
||||
cr.clientsMtx.Lock()
|
||||
for _, client := range cr.clients {
|
||||
client.Send(msg)
|
||||
}
|
||||
for _, conn := range cr.tempConn {
|
||||
connSend(msg, conn)
|
||||
}
|
||||
cr.clientsMtx.Unlock()
|
||||
for _, client := range cr.clients {
|
||||
client.Send(msg)
|
||||
}
|
||||
for _, conn := range cr.tempConn {
|
||||
conn.WriteJSON(msg)
|
||||
}
|
||||
default:
|
||||
// No messages to send
|
||||
|
@ -399,18 +390,15 @@ func (cr *ChatRoom) BroadCast() {
|
|||
// Mod queue
|
||||
select {
|
||||
case msg := <-cr.modqueue:
|
||||
if len(msg) > 0 {
|
||||
cr.clientsMtx.Lock()
|
||||
for _, client := range cr.clients {
|
||||
if client.IsMod || client.IsAdmin {
|
||||
client.Send(msg)
|
||||
}
|
||||
for _, client := range cr.clients {
|
||||
if client.IsMod || client.IsAdmin {
|
||||
client.Send(msg)
|
||||
}
|
||||
cr.clientsMtx.Unlock()
|
||||
}
|
||||
default:
|
||||
running = false
|
||||
}
|
||||
cr.clientsMtx.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ import (
|
|||
"fmt"
|
||||
)
|
||||
|
||||
type NewChatDataFunc func() (ChatData, error)
|
||||
|
||||
type DataInterface interface {
|
||||
HTML() string
|
||||
}
|
||||
|
@ -26,10 +28,6 @@ func (c ChatData) GetData() (DataInterface, error) {
|
|||
d := DataMessage{}
|
||||
err = json.Unmarshal(c.Data, &d)
|
||||
data = d
|
||||
case DTError:
|
||||
d := DataError{}
|
||||
err = json.Unmarshal(c.Data, &d)
|
||||
data = d
|
||||
case DTCommand:
|
||||
d := DataCommand{}
|
||||
err = json.Unmarshal(c.Data, &d)
|
||||
|
@ -71,22 +69,6 @@ func (c ClientData) HTML() string {
|
|||
return `<div style="color: red;"><span>The developer messed up. You should not be seeing this.</span></div>`
|
||||
}
|
||||
|
||||
type DataError struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
func (de DataError) HTML() string {
|
||||
return `<div class="svmsg"><b>Error</b>: ` + de.Message + `</div>`
|
||||
}
|
||||
|
||||
func EncodeError(message string) (string, error) {
|
||||
d, err := newChatData(DTError, DataError{Message: message})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return jsonifyChatData(d)
|
||||
}
|
||||
|
||||
type DataMessage struct {
|
||||
From string
|
||||
Color string
|
||||
|
@ -116,17 +98,15 @@ func (dc DataMessage) HTML() string {
|
|||
}
|
||||
}
|
||||
|
||||
func EncodeMessage(name, color, msg string, msgtype MessageType) (string, error) {
|
||||
d, err := newChatData(DTChat, DataMessage{
|
||||
From: name,
|
||||
Color: color,
|
||||
Message: msg,
|
||||
Type: msgtype,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
func NewChatMessage(name, color, msg string, msgtype MessageType) NewChatDataFunc {
|
||||
return func() (ChatData, error) {
|
||||
return newChatData(DTChat, DataMessage{
|
||||
From: name,
|
||||
Color: color,
|
||||
Message: msg,
|
||||
Type: msgtype,
|
||||
})
|
||||
}
|
||||
return jsonifyChatData(d)
|
||||
}
|
||||
|
||||
type DataCommand struct {
|
||||
|
@ -138,15 +118,13 @@ func (de DataCommand) HTML() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func EncodeCommand(command CommandType, args []string) (string, error) {
|
||||
d, err := newChatData(DTCommand, DataCommand{
|
||||
Command: command,
|
||||
Arguments: args,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
func NewChatCommand(command CommandType, args []string) NewChatDataFunc {
|
||||
return func() (ChatData, error) {
|
||||
return newChatData(DTCommand, DataCommand{
|
||||
Command: command,
|
||||
Arguments: args,
|
||||
})
|
||||
}
|
||||
return jsonifyChatData(d)
|
||||
}
|
||||
|
||||
type DataEvent struct {
|
||||
|
@ -173,16 +151,14 @@ func (de DataEvent) HTML() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func EncodeEvent(event EventType, name, color string) (string, error) {
|
||||
d, err := newChatData(DTEvent, DataEvent{
|
||||
Event: event,
|
||||
User: name,
|
||||
Color: color,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
func NewChatEvent(event EventType, name, color string) NewChatDataFunc {
|
||||
return func() (ChatData, error) {
|
||||
return newChatData(DTEvent, DataEvent{
|
||||
Event: event,
|
||||
User: name,
|
||||
Color: color,
|
||||
})
|
||||
}
|
||||
return jsonifyChatData(d)
|
||||
}
|
||||
|
||||
// DataHidden is for the server to send instructions and data
|
||||
|
@ -196,15 +172,13 @@ func (h HiddenMessage) HTML() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func EncodeHiddenMessage(clientType ClientDataType, data interface{}) (string, error) {
|
||||
d, err := newChatData(DTHidden, HiddenMessage{
|
||||
Type: clientType,
|
||||
Data: data,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
func NewChatHiddenMessage(clientType ClientDataType, data interface{}) NewChatDataFunc {
|
||||
return func() (ChatData, error) {
|
||||
return newChatData(DTHidden, HiddenMessage{
|
||||
Type: clientType,
|
||||
Data: data,
|
||||
})
|
||||
}
|
||||
return jsonifyChatData(d)
|
||||
}
|
||||
|
||||
func jsonifyChatData(data ChatData) (string, error) {
|
||||
|
|
|
@ -13,7 +13,6 @@ type DataType int
|
|||
const (
|
||||
DTInvalid DataType = iota
|
||||
DTChat // chat message
|
||||
DTError // something went wrong with the previous request
|
||||
DTCommand // non-chat function
|
||||
DTEvent // join/leave/kick/ban events
|
||||
DTClient // a message coming from the client
|
||||
|
@ -48,6 +47,6 @@ const (
|
|||
MsgChat MessageType = iota // standard chat
|
||||
MsgAction // /me command
|
||||
MsgServer // server message
|
||||
MsgError
|
||||
MsgNotice // Like MsgServer, but for mods and admins only.
|
||||
MsgError // something went wrong
|
||||
MsgNotice // Like MsgServer, but for mods and admins only.
|
||||
)
|
||||
|
|
|
@ -149,7 +149,7 @@ func wsHandler(w http.ResponseWriter, r *http.Request) {
|
|||
func handleIndexTemplate(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles("./static/index.html")
|
||||
if err != nil {
|
||||
fmt.Printf("[ERR] could not parse template file, %v\n", err)
|
||||
fmt.Printf("Error parsing template file, %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ func handleIndexTemplate(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
err = t.Execute(w, data)
|
||||
if err != nil {
|
||||
fmt.Printf("[ERR] could not execute file, %v", err)
|
||||
fmt.Printf("Error executing file, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,14 +3,15 @@ package main
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dennwc/dom/js"
|
||||
"github.com/zorchenhimer/MovieNight/common"
|
||||
)
|
||||
|
||||
var names []string
|
||||
var (
|
||||
names []js.Value
|
||||
)
|
||||
|
||||
func recieve(v []js.Value) {
|
||||
if len(v) == 0 {
|
||||
|
@ -37,19 +38,22 @@ func recieve(v []js.Value) {
|
|||
h := data.(common.HiddenMessage)
|
||||
switch h.Type {
|
||||
case common.CdUsers:
|
||||
names = nil
|
||||
var names []string
|
||||
for _, i := range h.Data.([]interface{}) {
|
||||
names = append(names, i.(string))
|
||||
}
|
||||
}
|
||||
case common.DTEvent:
|
||||
d := data.(common.DataEvent)
|
||||
if d.Event == common.EvJoin {
|
||||
if d.Event == common.EvJoin ||
|
||||
d.Event == common.EvBan ||
|
||||
d.Event == common.EvKick ||
|
||||
d.Event == common.EvLeave {
|
||||
websocketSend("", common.CdUsers)
|
||||
}
|
||||
// on join or leave, update list of possible user names
|
||||
fallthrough
|
||||
case common.DTChat, common.DTError:
|
||||
case common.DTChat:
|
||||
js.Call("appendMessages", data.HTML())
|
||||
case common.DTCommand:
|
||||
d := data.(common.DataCommand)
|
||||
|
@ -113,9 +117,9 @@ func showSendError(err error) {
|
|||
func main() {
|
||||
js.Set("recieveMessage", js.CallbackOf(recieve))
|
||||
js.Set("sendMessage", js.FuncOf(send))
|
||||
js.Set("getNames", js.FuncOf(func(_ js.Value, v []js.Value) interface{} {
|
||||
return strings.Join(names, ",")
|
||||
}))
|
||||
|
||||
// Get names on first run
|
||||
websocketSend("", common.CdUsers)
|
||||
|
||||
// This is needed so the goroutine does not end
|
||||
for {
|
||||
|
|
Loading…
Reference in New Issue