From a480c514545162d79a2eec80b852b44672a037b4 Mon Sep 17 00:00:00 2001 From: joeyak Date: Fri, 22 Mar 2019 23:32:52 -0400 Subject: [PATCH 01/11] Added reconnecting when websocket connection closes or errors resolves #38 --- static/js/chat.js | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/static/js/chat.js b/static/js/chat.js index 392a997..960579b 100644 --- a/static/js/chat.js +++ b/static/js/chat.js @@ -89,7 +89,11 @@ function join() { } function websocketSend(data) { - ws.send(data); + if (ws.readyState == ws.OPEN) { + ws.send(data); + } else { + console.log("did not send data because websocket is not open", data); + } } function sendChat() { @@ -126,13 +130,34 @@ function help() { sendMessage("/help"); } +reconnectCount = 0 // Get the websocket setup in a function so it can be recalled function setupWebSocket() { ws = new WebSocket(getWsUri()); ws.onmessage = (m) => recieveMessage(m.data); - ws.onopen = (e) => console.log("Websocket Open:", e); - ws.onclose = () => closeChat(); - ws.onerror = (e) => console.log("Websocket Error:", e); + ws.onopen = () => console.log("Websocket Open"); + ws.onclose = () => { + closeChat(); + reconnectCount++ + setNotifyBox("Something went wrong with the connection. Trying to reconnect " + reconnectCount + "."); + if (reconnectCount <= 5) { + setTimeout(() => { + setupWebSocket(); + setTimeout(() => { + if (ws.readyState == ws.OPEN) { + join(); + reconnectCount = 0; + } + }, 2000); + }, 2000); + } else { + setNotifyBox("Tried to reconnect " + reconnectCount + " times. Please refresh page or contact admin.") + } + } + ws.onerror = (e) => { + console.log("Websocket Error:", e); + e.target.close(); + } } function setupEvents() { From da21234fca7e316ca4dd8a21d7a15f11e1ee35ae Mon Sep 17 00:00:00 2001 From: joeyak Date: Sat, 23 Mar 2019 08:49:00 -0400 Subject: [PATCH 02/11] Fix formatting of golang template to be consistant. --- static/main.html | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/static/main.html b/static/main.html index 01d7e49..d413e08 100644 --- a/static/main.html +++ b/static/main.html @@ -1,47 +1,47 @@ {{define "header"}} -{{ if .Chat }} +{{if .Chat}} -{{ end }} +{{end}} -{{ if .Video }} +{{if .Video}} -{{ if not .Chat }} +{{if not .Chat}} -{{ end }} -{{ end }} +{{end}} +{{end}} -{{ if and .Video .Chat }} +{{if and .Video .Chat}} -{{ end }} +{{end}} {{end}} {{define "body"}} -{{ if .Video }} +{{if .Video}} -{{ end }} +{{end}} -{{ if .Chat }} +{{if .Chat}}

@@ -78,5 +78,5 @@ -{{ end }} +{{end}} {{end}} \ No newline at end of file From 0036dde265daf9dd7970b9cb6588de12c729d368 Mon Sep 17 00:00:00 2001 From: Zorchenhimer Date: Sat, 23 Mar 2019 14:46:49 -0400 Subject: [PATCH 03/11] Fix some typos BroadCast() -> Broadcast() startRmptServer() -> startRmtpServer() --- chatroom.go | 4 ++-- main.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/chatroom.go b/chatroom.go index 29ea36c..d9ff1ae 100644 --- a/chatroom.go +++ b/chatroom.go @@ -48,7 +48,7 @@ func newChatRoom() (*ChatRoom, error) { fmt.Printf("Loaded %d emotes\n", num) //the "heartbeat" for broadcasting messages - go cr.BroadCast() + go cr.Broadcast() return cr, nil } @@ -307,7 +307,7 @@ func (cr *ChatRoom) UserCount() int { } //broadcasting all the messages in the queue in one block -func (cr *ChatRoom) BroadCast() { +func (cr *ChatRoom) Broadcast() { send := func(data common.ChatData, client *Client) { err := client.SendChatData(data) if err != nil { diff --git a/main.go b/main.go index 42c260f..517ff4f 100644 --- a/main.go +++ b/main.go @@ -54,12 +54,12 @@ func main() { fmt.Println("Listen and serve ", addr) go startServer() - go startRmptServer() + go startRmtpServer() <-exit } -func startRmptServer() { +func startRmtpServer() { server := &rtmp.Server{ HandlePlay: handlePlay, HandlePublish: handlePublish, From 62afc2eef9be60d681765c130dd05c661b5b3870 Mon Sep 17 00:00:00 2001 From: Zorchenhimer Date: Sat, 23 Mar 2019 14:50:47 -0400 Subject: [PATCH 04/11] Fixup ChatRoom.Broadcast() Use an RW Mutex for chatConnection and use some goroutines when sending data to clients in Broadcast(). This should prevent blocking on unresponsive clients. --- chatroom.go | 25 ++++++++++++++----------- connection.go | 10 ++++++---- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/chatroom.go b/chatroom.go index d9ff1ae..3744f75 100644 --- a/chatroom.go +++ b/chatroom.go @@ -320,20 +320,23 @@ func (cr *ChatRoom) Broadcast() { case msg := <-cr.queue: cr.clientsMtx.Lock() for _, client := range cr.clients { - send(msg, client) + go send(msg, client) } - for _, conn := range cr.tempConn { - data, err := msg.ToJSON() - if err != nil { - fmt.Printf("Error converting ChatData to ChatDataJSON: %v\n", err) - // Break out early because if one conversion fails, they all will fail - break - } - err = conn.WriteData(data) - if err != nil { - fmt.Printf("Error writing data to connection: %v\n", err) + + data, err := msg.ToJSON() + if err != nil { + fmt.Printf("Error converting ChatData to ChatDataJSON: %v\n", err) + } else { + for _, conn := range cr.tempConn { + go func(c *chatConnection) { + err = c.WriteData(data) + if err != nil { + fmt.Printf("Error writing data to connection: %v\n", err) + } + }(conn) } } + cr.clientsMtx.Unlock() case msg := <-cr.modqueue: cr.clientsMtx.Lock() diff --git a/connection.go b/connection.go index 82ac88c..aff7240 100644 --- a/connection.go +++ b/connection.go @@ -9,20 +9,22 @@ import ( type chatConnection struct { *websocket.Conn - mutex sync.Mutex + mutex sync.RWMutex forwardedFor string } func (cc *chatConnection) ReadData(data interface{}) error { - defer cc.mutex.Unlock() - cc.mutex.Lock() + cc.mutex.RLock() + defer cc.mutex.RUnlock() + stats.msgInInc() return cc.ReadJSON(data) } func (cc *chatConnection) WriteData(data interface{}) error { - defer cc.mutex.Unlock() cc.mutex.Lock() + defer cc.mutex.Unlock() + stats.msgOutInc() return cc.WriteJSON(data) } From f36a51bf2b932245d886e30a2183b2420904a42f Mon Sep 17 00:00:00 2001 From: Zorchenhimer Date: Sat, 23 Mar 2019 14:53:29 -0400 Subject: [PATCH 05/11] Fix clearing the title If no title is given with the /playing command, clear the title. --- chatcommands.go | 2 +- static/js/chat.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/chatcommands.go b/chatcommands.go index 1f86f41..f644f6f 100644 --- a/chatcommands.go +++ b/chatcommands.go @@ -139,7 +139,7 @@ var commands = &CommandControl{ // Clear/hide title if sent with no arguments. if len(args) == 0 { cl.belongsTo.ClearPlaying() - return "" + return "Title cleared" } link := "" title := "" diff --git a/static/js/chat.js b/static/js/chat.js index 960579b..ded0000 100644 --- a/static/js/chat.js +++ b/static/js/chat.js @@ -4,6 +4,9 @@ function setPlaying(title, link) { if (title !== "") { $('#playing').text(title); document.title = "Movie Night | " + title; + } else { + $('#playing').text(""); + document.title = "Movie Night"; } $('#playing').removeAttr('href'); From c0d3731b84715f70f8ddeed7d5a6cb14dcd10fa1 Mon Sep 17 00:00:00 2001 From: Zorchenhimer Date: Sat, 23 Mar 2019 13:30:04 -0400 Subject: [PATCH 06/11] Write correct IP in WriteData() error Return the correct IP address on error during chatConnection.WirteData(). If the server is behind a reverse proxy, the connection object will have "127.0.0.1" as the remote address. --- connection.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/connection.go b/connection.go index aff7240..b09ac79 100644 --- a/connection.go +++ b/connection.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "net" "sync" @@ -26,7 +27,11 @@ func (cc *chatConnection) WriteData(data interface{}) error { defer cc.mutex.Unlock() stats.msgOutInc() - return cc.WriteJSON(data) + err := cc.WriteJSON(data) + if err != nil { + return fmt.Errorf("Error writing data to %s: %v", cc.Host(), err) + } + return nil } func (cc *chatConnection) Host() string { From 8e395859681a1beb1131d542a22d995f0d421f18 Mon Sep 17 00:00:00 2001 From: Zorchenhimer Date: Sat, 23 Mar 2019 15:16:02 -0400 Subject: [PATCH 07/11] Prevent some zero length stuff Don't send zero length messages to the server, and ignore the /me command without any arguments. --- chatcommands.go | 4 +++- wasm/main.go | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/chatcommands.go b/chatcommands.go index f644f6f..e239dfd 100644 --- a/chatcommands.go +++ b/chatcommands.go @@ -26,7 +26,9 @@ var commands = &CommandControl{ common.CNMe.String(): Command{ HelpText: "Display an action message.", Function: func(client *Client, args []string) string { - client.Me(strings.Join(args, " ")) + if len(args) != 0 { + client.Me(strings.Join(args, " ")) + } return "" }, }, diff --git a/wasm/main.go b/wasm/main.go index 89334a4..297c3aa 100644 --- a/wasm/main.go +++ b/wasm/main.go @@ -224,6 +224,10 @@ func recieve(v []js.Value) { } func websocketSend(msg string, dataType common.ClientDataType) error { + if strings.TrimSpace(msg) == "" { + return nil + } + data, err := json.Marshal(common.ClientData{ Type: dataType, Message: msg, From 4864669df67f5b809e6b42adbc2fccc30fe7581f Mon Sep 17 00:00:00 2001 From: joeyak Date: Sat, 23 Mar 2019 15:37:48 -0400 Subject: [PATCH 08/11] Add color checking and removed autoreconnect closes issue #44 --- common/colors.go | 86 +++++++++++++++++++++++-------------- common/utils.go | 13 ------ static/css/site.css | 33 ++++++++++++++- static/js/chat.js | 100 +++++++++++++++++++++++++++++++++++--------- static/main.html | 40 ++++++++++++++---- 5 files changed, 197 insertions(+), 75 deletions(-) diff --git a/common/colors.go b/common/colors.go index a658234..32890b0 100644 --- a/common/colors.go +++ b/common/colors.go @@ -3,50 +3,72 @@ package common import ( "regexp" "strings" + + "github.com/lucasb-eyer/go-colorful" ) +// the values in colors must be lowercase so it matches with the color input +// this saves from having to call strings.ToLower(color) every time to check var colors = []string{ - "AliceBlue", "AntiqueWhite", "Aqua", "Aquamarine", "Azure", - "Beige", "Bisque", "Black", "BlanchedAlmond", "Blue", - "BlueViolet", "Brown", "BurlyWood", "CadetBlue", "Chartreuse", - "Chocolate", "Coral", "CornflowerBlue", "Cornsilk", "Crimson", - "Cyan", "DarkBlue", "DarkCyan", "DarkGoldenRod", "DarkGray", - "DarkGrey", "DarkGreen", "DarkKhaki", "DarkMagenta", "DarkOliveGreen", - "DarkOrange", "DarkOrchid", "DarkRed", "DarkSalmon", "DarkSeaGreen", - "DarkSlateBlue", "DarkSlateGray", "DarkSlateGrey", "DarkTurquoise", "DarkViolet", - "DeepPink", "DeepSkyBlue", "DimGray", "DimGrey", "DodgerBlue", - "FireBrick", "FloralWhite", "ForestGreen", "Fuchsia", "Gainsboro", - "GhostWhite", "Gold", "GoldenRod", "Gray", "Grey", - "Green", "GreenYellow", "HoneyDew", "HotPink", "IndianRed", - "Indigo", "Ivory", "Khaki", "Lavender", "LavenderBlush", - "LawnGreen", "LemonChiffon", "LightBlue", "LightCoral", "LightCyan", - "LightGoldenRodYellow", "LightGray", "LightGrey", "LightGreen", "LightPink", - "LightSalmon", "LightSeaGreen", "LightSkyBlue", "LightSlateGray", "LightSlateGrey", - "LightSteelBlue", "LightYellow", "Lime", "LimeGreen", "Linen", - "Magenta", "Maroon", "MediumAquaMarine", "MediumBlue", "MediumOrchid", - "MediumPurple", "MediumSeaGreen", "MediumSlateBlue", "MediumSpringGreen", "MediumTurquoise", - "MediumVioletRed", "MidnightBlue", "MintCream", "MistyRose", "Moccasin", - "NavajoWhite", "Navy", "OldLace", "Olive", "OliveDrab", - "Orange", "OrangeRed", "Orchid", "PaleGoldenRod", "PaleGreen", - "PaleTurquoise", "PaleVioletRed", "PapayaWhip", "PeachPuff", "Peru", - "Pink", "Plum", "PowderBlue", "Purple", "RebeccaPurple", - "Red", "RosyBrown", "RoyalBlue", "SaddleBrown", "Salmon", - "SandyBrown", "SeaGreen", "SeaShell", "Sienna", "Silver", - "SkyBlue", "SlateBlue", "SlateGray", "SlateGrey", "Snow", - "SpringGreen", "SteelBlue", "Tan", "Teal", "Thistle", - "Tomato", "Turquoise", "Violet", "Wheat", "White", - "WhiteSmoke", "Yellow", "YellowGreen", + "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", + "beige", "bisque", "black", "blanchedalmond", "blue", + "blueviolet", "brown", "burlywood", "cadetblue", "chartreuse", + "chocolate", "coral", "cornflowerblue", "cornsilk", "crimson", + "cyan", "darkblue", "darkcyan", "darkgoldenrod", "darkgray", + "darkgrey", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", + "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", + "darkslateblue", "darkslategray", "darkslategrey", "darkturquoise", "darkviolet", + "deeppink", "deepskyblue", "dimgray", "dimgrey", "dodgerblue", + "firebrick", "floralwhite", "forestgreen", "fuchsia", "gainsboro", + "ghostwhite", "gold", "goldenrod", "gray", "grey", + "green", "greenyellow", "honeydew", "hotpink", "indianred", + "indigo", "ivory", "khaki", "lavender", "lavenderblush", + "lawngreen", "lemonchiffon", "lightblue", "lightcoral", "lightcyan", + "lightgoldenrodyellow", "lightgray", "lightgrey", "lightgreen", "lightpink", + "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightslategrey", + "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", + "magenta", "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", + "mediumpurple", "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise", + "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin", + "navajowhite", "navy", "oldlace", "olive", "olivedrab", + "orange", "orangered", "orchid", "palegoldenrod", "palegreen", + "paleturquoise", "palevioletred", "papayawhip", "peachpuff", "peru", + "pink", "plum", "powderblue", "purple", "rebeccapurple", + "red", "rosybrown", "royalblue", "saddlebrown", "salmon", + "sandybrown", "seagreen", "seashell", "sienna", "silver", + "skyblue", "slateblue", "slategray", "slategrey", "snow", + "springgreen", "steelblue", "tan", "teal", "thistle", + "tomato", "turquoise", "violet", "wheat", "white", + "whitesmoke", "yellow", "yellowgreen", } // IsValidColor takes a string s and compares it against a list of css color names. // It also accepts hex codes in the form of #000 (RGB), to #00000000 (RRGGBBAA), with A // being the alpha value func IsValidColor(s string) bool { + s = strings.ToLower(s) for _, c := range colors { - if strings.ToLower(c) == strings.ToLower(s) { + if s == c { return true } } - return regexp.MustCompile(`^#[0-9A-Fa-f]{6}$`).MatchString(s) + if regexp.MustCompile(`^#([0-9A-Fa-f]{3}){1,2}$`).MatchString(s) { + c, err := colorful.Hex(s) + if err != nil { + return false + } + total := c.R + c.G + c.B + return total > 0.7 && c.B/total < 0.7 + } + return false +} + +// RandomColor returns a hex color code +func RandomColor() string { + var color colorful.Color + for !IsValidColor(color.Hex()) { + color = colorful.FastHappyColor() + } + return color.Hex() } diff --git a/common/utils.go b/common/utils.go index 5df441f..808af11 100644 --- a/common/utils.go +++ b/common/utils.go @@ -3,8 +3,6 @@ package common // Misc utils import ( - "fmt" - "math/rand" "regexp" ) @@ -16,14 +14,3 @@ func IsValidName(name string) bool { return 3 <= len(name) && len(name) <= 36 && usernameRegex.MatchString(name) && !IsValidColor(name) } - -// RandomColor returns a hex color code -func RandomColor() string { - nums := []int32{} - for i := 0; i < 6; i++ { - nums = append(nums, rand.Int31n(15)) - } - return fmt.Sprintf("#%X%X%X%X%X%X", - nums[0], nums[1], nums[2], - nums[3], nums[4], nums[5]) -} diff --git a/static/css/site.css b/static/css/site.css index b2de941..c708c98 100644 --- a/static/css/site.css +++ b/static/css/site.css @@ -4,6 +4,7 @@ --var-message-color: #f4f4f4; --var-contrast-color: #1bf7ec; --var-background-color: #0F0F11; + --var-popout-color: #393940; --var-max-height: 98vh; --var-max-width: 98vw; } @@ -111,6 +112,32 @@ span.svmsg { color: #B1B1B1; } +.contrast { + color: var(--var-contrast-color); +} + +.range-div { + margin-bottom: 5px; + display: flex; + justify-content: center; + align-items: center; + border-radius: 5px; + padding: 5px; +} + +.range-div>input[type=button] { + flex: 2; +} + +.hiddendiv { + display: none; + color: var(--var-message-color); + background: var(--var-popout-color); + padding: 2em; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; +} + #videoElement { position: relative; top: 50%; @@ -135,7 +162,7 @@ span.svmsg { right: 0px; margin: 0px 5px; padding: 3px; - background: #393940; + background: var(--var-popout-color); } #hidden:hover, @@ -239,4 +266,8 @@ span.svmsg { #helpbody { color: #b1b1b1; +} + +#colorSubmit:disabled { + display: none; } \ No newline at end of file diff --git a/static/js/chat.js b/static/js/chat.js index ded0000..8b3503b 100644 --- a/static/js/chat.js +++ b/static/js/chat.js @@ -133,7 +133,43 @@ function help() { sendMessage("/help"); } -reconnectCount = 0 +function showColors(show) { + $("#hiddencolor").css("display", show ? "block" : ""); +} + +function colorAsHex() { + let r = parseInt($("#colorRed").val()).toString(16).padStart(2, "0"); + let g = parseInt($("#colorGreen").val()).toString(16).padStart(2, "0"); + let b = parseInt($("#colorBlue").val()).toString(16).padStart(2, "0"); + return `#${r}${g}${b}` +} + +function updateColor() { + let r = $("#colorRed").val(); + let g = $("#colorGreen").val(); + let b = $("#colorBlue").val(); + + $("#colorRedLabel").text(r.padStart(3, "0")); + $("#colorGreenLabel").text(g.padStart(3, "0")); + $("#colorBlueLabel").text(b.padStart(3, "0")); + + $("#colorName").css("color", `rgb(${r}, ${g}, ${b})`); + + if (isValidColor(colorAsHex())) { + $("#colorWarning").text(""); + } else { + $("#colorWarning").text("Unreadable Color"); + } +} + +function changeColor() { + if (isValidColor(colorAsHex())) { + sendMessage("/color " + colorAsHex()); + showColors(false); + } +} + + // Get the websocket setup in a function so it can be recalled function setupWebSocket() { ws = new WebSocket(getWsUri()); @@ -141,21 +177,8 @@ function setupWebSocket() { ws.onopen = () => console.log("Websocket Open"); ws.onclose = () => { closeChat(); - reconnectCount++ - setNotifyBox("Something went wrong with the connection. Trying to reconnect " + reconnectCount + "."); - if (reconnectCount <= 5) { - setTimeout(() => { - setupWebSocket(); - setTimeout(() => { - if (ws.readyState == ws.OPEN) { - join(); - reconnectCount = 0; - } - }, 2000); - }, 2000); - } else { - setNotifyBox("Tried to reconnect " + reconnectCount + " times. Please refresh page or contact admin.") - } + setNotifyBox("The connection to the server has closed. Please refresh page to connect again."); + $("#joinbox").css("display", "none"); } ws.onerror = (e) => { console.log("Websocket Error:", e); @@ -187,10 +210,6 @@ function setupEvents() { input: () => processMessage(), }); - $("#hiddenColorPicker").on({ - change: () => sendMessage("/color " + $("#hiddenColorPicker").val()), - }); - $("#send").on({ click: () => $("#msg").focus(), }); @@ -200,6 +219,12 @@ function setupEvents() { ).observe($("#suggestions")[0], { childList: true }); } +function defaultValues() { + $("#colorRed").val(0).trigger("input"); + $("#colorGreen").val(0).trigger("input"); + $("#colorBlue").val(0).trigger("input"); +} + window.addEventListener("onresize", updateSuggestionCss); window.addEventListener("load", () => { @@ -207,7 +232,42 @@ window.addEventListener("load", () => { setupWebSocket(); startGo(); setupEvents(); + defaultValues(); // Make sure name is focused on start $("#name").focus(); }); + +function pleaseremovethis() { + colors = ["aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", + "beige", "bisque", "black", "blanchedalmond", "blue", + "blueviolet", "brown", "burlywood", "cadetblue", "chartreuse", + "chocolate", "coral", "cornflowerblue", "cornsilk", "crimson", + "cyan", "darkblue", "darkcyan", "darkgoldenrod", "darkgray", + "darkgrey", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", + "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", + "darkslateblue", "darkslategray", "darkslategrey", "darkturquoise", "darkviolet", + "deeppink", "deepskyblue", "dimgray", "dimgrey", "dodgerblue", + "firebrick", "floralwhite", "forestgreen", "fuchsia", "gainsboro", + "ghostwhite", "gold", "goldenrod", "gray", "grey", + "green", "greenyellow", "honeydew", "hotpink", "indianred", + "indigo", "ivory", "khaki", "lavender", "lavenderblush", + "lawngreen", "lemonchiffon", "lightblue", "lightcoral", "lightcyan", + "lightgoldenrodyellow", "lightgray", "lightgrey", "lightgreen", "lightpink", + "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightslategrey", + "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", + "magenta", "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", + "mediumpurple", "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise", + "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin", + "navajowhite", "navy", "oldlace", "olive", "olivedrab", + "orange", "orangered", "orchid", "palegoldenrod", "palegreen", + "paleturquoise", "palevioletred", "papayawhip", "peachpuff", "peru", + "pink", "plum", "powderblue", "purple", "rebeccapurple", + "red", "rosybrown", "royalblue", "saddlebrown", "salmon", + "sandybrown", "seagreen", "seashell", "sienna", "silver", + "skyblue", "slateblue", "slategray", "slategrey", "snow", + "springgreen", "steelblue", "tan", "teal", "thistle", + "tomato", "turquoise", "violet", "wheat", "white", + "whitesmoke", "yellow", "yellowgreen",] + +} \ No newline at end of file diff --git a/static/main.html b/static/main.html index d413e08..3a09f92 100644 --- a/static/main.html +++ b/static/main.html @@ -45,19 +45,41 @@
- +
@@ -73,8 +95,8 @@
Please enter your name
to join the chat
- - + +
From 6ef0d6f1a5d1f0afd4ede69cb757e14289dbd64a Mon Sep 17 00:00:00 2001 From: Zorchenhimer Date: Sat, 23 Mar 2019 16:09:47 -0400 Subject: [PATCH 09/11] Add some debugging info to the client connection --- chatroom.go | 1 + connection.go | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/chatroom.go b/chatroom.go index 3744f75..d62fe99 100644 --- a/chatroom.go +++ b/chatroom.go @@ -96,6 +96,7 @@ func (cr *ChatRoom) Join(name, uid string) (*Client, error) { } } + conn.clientName = name client := &Client{ name: name, conn: conn, diff --git a/connection.go b/connection.go index b09ac79..715b412 100644 --- a/connection.go +++ b/connection.go @@ -12,6 +12,7 @@ type chatConnection struct { *websocket.Conn mutex sync.RWMutex forwardedFor string + clientName string } func (cc *chatConnection) ReadData(data interface{}) error { @@ -29,7 +30,10 @@ func (cc *chatConnection) WriteData(data interface{}) error { stats.msgOutInc() err := cc.WriteJSON(data) if err != nil { - return fmt.Errorf("Error writing data to %s: %v", cc.Host(), err) + if operr, ok := err.(*net.OpError); ok { + fmt.Println("OpError: " + operr.Err.Error()) + } + return fmt.Errorf("Error writing data to %s %s: %v", cc.clientName, cc.Host(), err) } return nil } From 88365b6df5007ae53bb8d2826c56b55bc807a2e4 Mon Sep 17 00:00:00 2001 From: Zorchenhimer Date: Sat, 23 Mar 2019 16:53:36 -0400 Subject: [PATCH 10/11] Add /iplist to admin commands Lists all clients' UUID's, names, and IPs to console. --- chatcommands.go | 18 ++++++++++++++++++ common/chatcommands.go | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/chatcommands.go b/chatcommands.go index e239dfd..7354b59 100644 --- a/chatcommands.go +++ b/chatcommands.go @@ -293,6 +293,24 @@ var commands = &CommandControl{ return "Single use password: " + password }, }, + + common.CNIP.String(): Command{ + HelpText: "list users and IP in the server console", + Function: func(cl *Client, args []string) string { + cl.belongsTo.clientsMtx.Lock() + fmt.Println("Clients:") + for uuid, client := range cl.belongsTo.clients { + fmt.Printf(" [%s] %s %s\n", uuid, client.name, client.conn.Host()) + } + + fmt.Println("TmpConn:") + for uuid, conn := range cl.belongsTo.tempConn { + fmt.Printf(" [%s] %s\n", uuid, conn.Host()) + } + cl.belongsTo.clientsMtx.Unlock() + return "see console for output" + }, + }, }, } diff --git a/common/chatcommands.go b/common/chatcommands.go index c44f689..5257a8e 100644 --- a/common/chatcommands.go +++ b/common/chatcommands.go @@ -34,6 +34,7 @@ var ( CNReloadPlayer ChatCommandNames = []string{"reloadplayer"} CNReloadEmotes ChatCommandNames = []string{"reloademotes"} CNModpass ChatCommandNames = []string{"modpass"} + CNIP ChatCommandNames = []string{"iplist"} ) var ChatCommands = []ChatCommandNames{ @@ -42,7 +43,7 @@ var ChatCommands = []ChatCommandNames{ // Mod CNSv, CNPlaying, CNUnmod, CNKick, CNBan, CNUnban, CNPurge, // Admin - CNMod, CNReloadPlayer, CNReloadEmotes, CNModpass, + CNMod, CNReloadPlayer, CNReloadEmotes, CNModpass, CNIP, } func GetFullChatCommand(c string) string { From d734ec110e8198477cd363ce7a822fc39091f5e2 Mon Sep 17 00:00:00 2001 From: Zorchenhimer Date: Sat, 23 Mar 2019 16:54:05 -0400 Subject: [PATCH 11/11] Remove error'd temp connections If there's an error writing to a temp connection, remove it from the chatroom. --- chatroom.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/chatroom.go b/chatroom.go index d62fe99..8d128a4 100644 --- a/chatroom.go +++ b/chatroom.go @@ -124,8 +124,8 @@ func (cr *ChatRoom) Join(name, uid string) (*Client, error) { return client, nil } -// TODO: fix this up a bit. kick and leave are the same, incorrect, error: "That name was already used!" -//leaving the chatroom +// TODO: fix this up a bit. kick and leave are the same, incorrect, error: "That +// name was already used!" leaving the chatroom func (cr *ChatRoom) Leave(name, color string) { defer cr.clientsMtx.Unlock() cr.clientsMtx.Lock() //preventing simultaneous access to the `clients` map @@ -328,13 +328,14 @@ func (cr *ChatRoom) Broadcast() { if err != nil { fmt.Printf("Error converting ChatData to ChatDataJSON: %v\n", err) } else { - for _, conn := range cr.tempConn { - go func(c *chatConnection) { + for uuid, conn := range cr.tempConn { + go func(c *chatConnection, suid string) { err = c.WriteData(data) if err != nil { fmt.Printf("Error writing data to connection: %v\n", err) + delete(cr.tempConn, suid) } - }(conn) + }(conn, uuid) } }