From 21bf1ad1479c45f332f16a318560676da101cb2e Mon Sep 17 00:00:00 2001
From: empathetic-alligator <willipovell@gmail.com>
Date: Sun, 14 Dec 2014 02:44:39 -0500
Subject: [PATCH 1/6] Updated locks to work with next embedded mutex.

---
 server.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/server.go b/server.go
index fe6d220..77235c5 100644
--- a/server.go
+++ b/server.go
@@ -237,9 +237,9 @@ func (s *Server) Op(fingerprint string) {
 
 func (s *Server) Whitelist(fingerprint string) {
 	logger.Infof("Adding whitelist: %s", fingerprint)
-	s.lock.Lock()
+	s.Lock()
 	s.whitelist[fingerprint] = struct{}{}
-	s.lock.Unlock()
+	s.Unlock()
 }
 
 func (s *Server) Uptime() string {

From c88c30391d8c51616713b514651d766e8f6d14f6 Mon Sep 17 00:00:00 2001
From: empathetic-alligator <willipovell@gmail.com>
Date: Sun, 14 Dec 2014 03:11:59 -0500
Subject: [PATCH 2/6] Added /colors command to toggle coloring.

---
 client.go | 23 ++++++++++++++++++++++-
 colors.go |  9 ++++++++-
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/client.go b/client.go
index 9b5166e..2e07b38 100644
--- a/client.go
+++ b/client.go
@@ -59,6 +59,7 @@ type Client struct {
 	silencedUntil time.Time
 	lastTX        time.Time
 	beepMe        bool
+	colorMe		  bool
 }
 
 func NewClient(server *Server, conn *ssh.ServerConn) *Client {
@@ -70,6 +71,7 @@ func NewClient(server *Server, conn *ssh.ServerConn) *Client {
 		Msg:    make(chan string, MSG_BUFFER),
 		ready:  make(chan struct{}, 1),
 		lastTX: time.Now(),
+		colorMe: true,
 	}
 }
 
@@ -82,6 +84,9 @@ func (c *Client) SysMsg(msg string, args ...interface{}) {
 }
 
 func (c *Client) Write(msg string) {
+	if(!c.colorMe) {
+		msg = DeColorString(msg)
+	}
 	c.term.Write([]byte(msg + "\r\n"))
 }
 
@@ -129,7 +134,15 @@ func (c *Client) Resize(width int, height int) error {
 
 func (c *Client) Rename(name string) {
 	c.Name = name
-	c.term.SetPrompt(fmt.Sprintf("[%s] ", c.ColoredName()))
+	var prompt string
+
+	if(c.colorMe) {
+		prompt = c.ColoredName()
+	} else {
+		prompt = c.Name
+	}
+
+	c.term.SetPrompt(fmt.Sprintf("[%s] ", prompt))
 }
 
 func (c *Client) Fingerprint() string {
@@ -324,6 +337,14 @@ func (c *Client) handleShell(channel ssh.Channel) {
 					c.Server.SetMotd(c, newmotd)
 					c.Server.MotdBroadcast(c)
 				}
+			case "/color":
+				c.colorMe = !c.colorMe
+				c.Rename(c.Name)
+				if c.colorMe {
+					c.SysMsg("Turned on color chat")
+				} else {
+					c.SysMsg("Turned off color chat")
+				}
 
 			default:
 				c.SysMsg("Invalid command: %s", line)
diff --git a/colors.go b/colors.go
index 1e85441..29877d8 100644
--- a/colors.go
+++ b/colors.go
@@ -5,6 +5,7 @@ import (
 	"strings"
     "math/rand"
 	"time"
+	"regexp"
 )
 
 const RESET string =     "\033[0m"
@@ -16,6 +17,12 @@ const BLINK string =     "\033[5m"
 const INVERT string =    "\033[7m"
 
 var colors = []string { "31", "32", "33", "34", "35", "36", "37", "91", "92", "93", "94", "95", "96", "97" }
+var r *regexp.Regexp = regexp.MustCompile("\033\\[[\\d;]+m")
+
+func DeColorString(s string) string {
+	s = r.ReplaceAllString(s, "")
+	return s
+}
 
 func RandomColor256() string {
 	return fmt.Sprintf("38;05;%d", rand.Intn(256))
@@ -38,4 +45,4 @@ func RandomColorInit() {
 // This is not HTML where you can just do a </style> to resume your previous formatting!
 func ContinuousFormat(format string, str string) string {
 	return SYSTEM_MESSAGE_FORMAT + strings.Replace(str, RESET, format, -1) + RESET
-}
+}
\ No newline at end of file

From 0fd74cb163d3c8d5710eed7e8bd26e01ad874580 Mon Sep 17 00:00:00 2001
From: empathetic-alligator <willipovell@gmail.com>
Date: Sun, 14 Dec 2014 04:39:20 -0500
Subject: [PATCH 3/6] Changed /color to /theme and made mono theme default.

---
 client.go | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/client.go b/client.go
index 2e07b38..827f436 100644
--- a/client.go
+++ b/client.go
@@ -71,7 +71,6 @@ func NewClient(server *Server, conn *ssh.ServerConn) *Client {
 		Msg:    make(chan string, MSG_BUFFER),
 		ready:  make(chan struct{}, 1),
 		lastTX: time.Now(),
-		colorMe: true,
 	}
 }
 
@@ -337,13 +336,17 @@ func (c *Client) handleShell(channel ssh.Channel) {
 					c.Server.SetMotd(c, newmotd)
 					c.Server.MotdBroadcast(c)
 				}
-			case "/color":
-				c.colorMe = !c.colorMe
-				c.Rename(c.Name)
-				if c.colorMe {
-					c.SysMsg("Turned on color chat")
+			case "/theme":
+				if len(parts) < 2 {
+					c.SysMsg("Missing $THEME from: /theme $THEME")
+					c.SysMsg("Choose either color or mono")
 				} else {
-					c.SysMsg("Turned off color chat")
+					if parts[1] == "mono" {
+						c.colorMe = false
+					} else if parts[1] == "color" {
+						c.colorMe = true
+					}
+					c.Rename(c.Name)
 				}
 
 			default:

From d0ea3f2ca6a7844afd647726fec4f14962b503da Mon Sep 17 00:00:00 2001
From: empathetic-alligator <willipovell@gmail.com>
Date: Sun, 14 Dec 2014 11:04:29 -0500
Subject: [PATCH 4/6] Added comments and /shutdown command.

---
 client.go | 20 ++++++++++++++++++++
 colors.go |  5 +++--
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/client.go b/client.go
index 827f436..ecf6292 100644
--- a/client.go
+++ b/client.go
@@ -308,6 +308,24 @@ func (c *Client) handleShell(channel ssh.Channel) {
 						client.SysMsg("Silenced for %s by %s.", duration, c.ColoredName())
 					}
 				}
+			case "/shutdown":
+				if !c.Server.IsOp(c) {
+					c.SysMsg("You're not an admin.")
+				} else {
+					var split []string = strings.SplitN(line, " ", 2)
+					var msg string
+					if len(split) > 1 {
+						msg = split[1]
+					} else {
+						msg = ""
+					}
+					// Shutdown after 5 seconds
+					go func() {
+						c.Server.Broadcast(ColorString("31", msg), nil)
+						time.Sleep(time.Second * 5)
+						c.Server.Stop()
+					}()
+				}
 			case "/msg": /* Send a PM */
 				/* Make sure we have a recipient and a message */
 				if len(parts) < 2 {
@@ -341,11 +359,13 @@ func (c *Client) handleShell(channel ssh.Channel) {
 					c.SysMsg("Missing $THEME from: /theme $THEME")
 					c.SysMsg("Choose either color or mono")
 				} else {
+					// Sets colorMe attribute of client
 					if parts[1] == "mono" {
 						c.colorMe = false
 					} else if parts[1] == "color" {
 						c.colorMe = true
 					}
+					// Rename to reset prompt
 					c.Rename(c.Name)
 				}
 
diff --git a/colors.go b/colors.go
index 29877d8..5f16a68 100644
--- a/colors.go
+++ b/colors.go
@@ -17,10 +17,11 @@ const BLINK string =     "\033[5m"
 const INVERT string =    "\033[7m"
 
 var colors = []string { "31", "32", "33", "34", "35", "36", "37", "91", "92", "93", "94", "95", "96", "97" }
-var r *regexp.Regexp = regexp.MustCompile("\033\\[[\\d;]+m")
+// For removing ANSI Escapes
+var deColor *regexp.Regexp = regexp.MustCompile("\033\\[[\\d;]+m")
 
 func DeColorString(s string) string {
-	s = r.ReplaceAllString(s, "")
+	s = deColor.ReplaceAllString(s, "")
 	return s
 }
 

From 2f5dbc939151b52b5fd2b74d6db80bbdae17a14d Mon Sep 17 00:00:00 2001
From: empathetic-alligator <willipovell@gmail.com>
Date: Sun, 14 Dec 2014 17:39:08 -0500
Subject: [PATCH 5/6] Fixed formatting and made color default.

---
 client.go | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/client.go b/client.go
index 673b94c..cf4b665 100644
--- a/client.go
+++ b/client.go
@@ -60,7 +60,7 @@ type Client struct {
 	silencedUntil time.Time
 	lastTX        time.Time
 	beepMe        bool
-	colorMe		  bool
+	colorMe       bool
 }
 
 func NewClient(server *Server, conn *ssh.ServerConn) *Client {
@@ -72,6 +72,7 @@ func NewClient(server *Server, conn *ssh.ServerConn) *Client {
 		Msg:    make(chan string, MSG_BUFFER),
 		ready:  make(chan struct{}, 1),
 		lastTX: time.Now(),
+		colorMe: true,
 	}
 }
 

From 95ccbe2922e2a814282b2939440d37533c80ce83 Mon Sep 17 00:00:00 2001
From: empathetic-alligator <willipovell@gmail.com>
Date: Sun, 14 Dec 2014 18:05:39 -0500
Subject: [PATCH 6/6] Added /shutdown and /theme to help text.

---
 client.go | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/client.go b/client.go
index cf4b665..805fa5c 100644
--- a/client.go
+++ b/client.go
@@ -23,6 +23,7 @@ const HELP_TEXT string = SYSTEM_MESSAGE_FORMAT + `-> Available commands:
    /whois $NAME         - Display information about another connected user.
    /msg $NAME $MESSAGE  - Sends a private message to a user.
    /motd                - Prints the Message of the Day
+   /theme [color|mono]  - Set client theme
 ` + RESET
 
 const OP_HELP_TEXT string = SYSTEM_MESSAGE_FORMAT + `-> Available operator commands:
@@ -30,6 +31,7 @@ const OP_HELP_TEXT string = SYSTEM_MESSAGE_FORMAT + `-> Available operator comma
    /kick $NAME               - Kick em' out.
    /op $NAME                 - Promote a user to server operator.
    /silence $NAME            - Revoke a user's ability to speak.
+   /shutdown $MESSAGE        - Broadcast message and shutdown server
    /motd $MESSAGE            - Sets the Message of the Day
    /whitelist $FINGERPRINT   - Adds pubkey fingerprint to the connection whitelist
 ` + RESET