diff --git a/Makefile b/Makefile
index c51bb8b..8ad7e2f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
TAGS=
-.PHONY: fmt vet get clean dev setdev
+.PHONY: fmt vet get clean dev setdev test
-all: fmt vet MovieNight MovieNight.exe static/main.wasm
+all: fmt vet test MovieNight MovieNight.exe static/main.wasm
setdev:
$(eval export TAGS=-tags "dev")
@@ -32,3 +32,6 @@ get:
vet:
go vet $(TAGS) ./...
GOOS=js GOARCH=wasm go vet $(TAGS) ./...
+
+test:
+ go test $(TAGS) ./...
\ No newline at end of file
diff --git a/chatclient.go b/chatclient.go
index edd9902..244daeb 100644
--- a/chatclient.go
+++ b/chatclient.go
@@ -10,6 +10,12 @@ import (
"github.com/zorchenhimer/MovieNight/common"
)
+var (
+ regexSpoiler = regexp.MustCompile(`\|\|(.*?)\|\|`)
+ spoilerStart = ``
+ spoilerEnd = ``
+)
+
type Client struct {
name string // Display name
conn *chatConnection
@@ -18,6 +24,7 @@ type Client struct {
CmdLevel common.CommandLevel
IsColorForced bool
IsNameForced bool
+ regexName *regexp.Regexp
}
//Client has a new message to broadcast
@@ -49,6 +56,10 @@ func (cl *Client) NewMsg(data common.ClientData) {
msg = removeDumbSpaces(msg)
msg = strings.Trim(msg, " ")
+ // Add the spoiler tag outside of the command vs message statement
+ // because the /me command outputs to the messages
+ msg = addSpoilerTags(msg)
+
// Don't send zero-length messages
if len(msg) == 0 {
return
@@ -94,7 +105,11 @@ func (cl *Client) NewMsg(data common.ClientData) {
func (cl *Client) SendChatData(data common.ChatData) error {
// Colorize name on chat messages
if data.Type == common.DTChat {
- data = replaceColorizedName(data, cl)
+ var err error
+ data = cl.replaceColorizedName(data)
+ if err != nil {
+ return fmt.Errorf("could not colorize name: %v", err)
+ }
}
cd, err := data.ToJSON()
@@ -164,6 +179,24 @@ func (cl *Client) Host() string {
return cl.conn.Host()
}
+func (cl *Client) setName(s string) error {
+ regex, err := regexp.Compile(fmt.Sprintf("(%s|@%s)", s, s))
+ if err != nil {
+ return fmt.Errorf("could not compile regex: %v", err)
+ }
+
+ cl.name = s
+ cl.regexName = regex
+ return nil
+}
+
+func (cl *Client) replaceColorizedName(chatData common.ChatData) common.ChatData {
+ data := chatData.Data.(common.DataMessage)
+ data.Message = cl.regexName.ReplaceAllString(data.Message, `$1`)
+ chatData.Data = data
+ return chatData
+}
+
var dumbSpaces = []string{
"\n",
"\t",
@@ -187,12 +220,6 @@ func removeDumbSpaces(msg string) string {
return newMsg
}
-func replaceColorizedName(chatData common.ChatData, client *Client) common.ChatData {
- data := chatData.Data.(common.DataMessage)
-
- data.Message = regexp.MustCompile(fmt.Sprintf(`(%s|@%s)`, client.name, client.name)).
- ReplaceAllString(data.Message, `$1`)
-
- chatData.Data = data
- return chatData
+func addSpoilerTags(msg string) string {
+ return regexSpoiler.ReplaceAllString(msg, fmt.Sprintf(`%s$1%s`, spoilerStart, spoilerEnd))
}
diff --git a/chatclient_test.go b/chatclient_test.go
new file mode 100644
index 0000000..d757cd1
--- /dev/null
+++ b/chatclient_test.go
@@ -0,0 +1,23 @@
+package main
+
+import "testing"
+
+func TestClient_addSpoilerTag(t *testing.T) {
+ data := [][]string{
+ {"||||", spoilerStart + spoilerEnd},
+ {"|||||", spoilerStart + spoilerEnd + "|"},
+ {"||||||", spoilerStart + spoilerEnd + "||"},
+ {"|||||||", spoilerStart + spoilerEnd + "|||"},
+ {"||||||||", spoilerStart + spoilerEnd + spoilerStart + spoilerEnd},
+ {"||test||", spoilerStart + "test" + spoilerEnd},
+ {"|| ||", spoilerStart + " " + spoilerEnd},
+ {"|s|||", "|s|||"},
+ }
+
+ for i := range data {
+ s := addSpoilerTags(data[i][0])
+ if s != data[i][1] {
+ t.Errorf("expected %#v, got %#v with %#v", data[i][1], s, data[i][0])
+ }
+ }
+}
diff --git a/chatroom.go b/chatroom.go
index aa720af..aebde3e 100644
--- a/chatroom.go
+++ b/chatroom.go
@@ -98,12 +98,16 @@ func (cr *ChatRoom) Join(name, uid string) (*Client, error) {
conn.clientName = name
client := &Client{
- name: name,
conn: conn,
belongsTo: cr,
color: common.RandomColor(),
}
+ err := client.setName(name)
+ if err != nil {
+ return nil, fmt.Errorf("could not set client name to %#v: %v", name, err)
+ }
+
host := client.Host()
if banned, names := settings.IsBanned(host); banned {
@@ -483,7 +487,10 @@ func (cr *ChatRoom) changeName(oldName, newName string, forced bool) error {
}
if currentClient != nil {
- currentClient.name = newName
+ err := currentClient.setName(newName)
+ if err != nil {
+ return fmt.Errorf("could not set client name to %#v: %v", newName, err)
+ }
common.LogDebugf("%q -> %q\n", oldName, newName)
if forced {
diff --git a/common/colors.go b/common/colors.go
index 32890b0..57fb7b1 100644
--- a/common/colors.go
+++ b/common/colors.go
@@ -42,6 +42,10 @@ var colors = []string{
"whitesmoke", "yellow", "yellowgreen",
}
+var (
+ regexColor = regexp.MustCompile(`^#([0-9A-Fa-f]{3}){1,2}$`)
+)
+
// 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
@@ -53,7 +57,7 @@ func IsValidColor(s string) bool {
}
}
- if regexp.MustCompile(`^#([0-9A-Fa-f]{3}){1,2}$`).MatchString(s) {
+ if regexColor.MatchString(s) {
c, err := colorful.Hex(s)
if err != nil {
return false
diff --git a/common/logging.go b/common/logging.go
index 8bbd5c1..01bf824 100644
--- a/common/logging.go
+++ b/common/logging.go
@@ -23,7 +23,6 @@ const (
logPrefixChat string = "[CHAT] "
logPrefixInfo string = "[INFO] "
logPrefixDebug string = "[DEBUG] "
- logPrefixDev string = "[DEV] "
)
var (
@@ -31,18 +30,8 @@ var (
logChat *log.Logger
logInfo *log.Logger
logDebug *log.Logger
- logDev *log.Logger
)
-//func ParseLogLevel(input string) LogLevel {
-// switch LogLevel(input) {
-// case LLError, LLChat, LLInfo, LLDebug:
-// return LogLevel(input)
-// default:
-// return LLError
-// }
-//}
-
func SetupLogging(level LogLevel, file string) error {
switch level {
case LLDebug:
diff --git a/common/logging_dev.go b/common/logging_dev.go
index 32c9646..1539835 100644
--- a/common/logging_dev.go
+++ b/common/logging_dev.go
@@ -2,18 +2,21 @@
package common
-func LogDevf(format string, v ...interface{}) {
- if logError == nil {
- panic("Logging not setup!")
- }
+import (
+ "log"
+ "os"
+)
- logError.Printf(format, v...)
+var logDev *log.Logger
+
+func init() {
+ logDev = log.New(os.Stdout, "[DEV]", log.LstdFlags)
+}
+
+func LogDevf(format string, v ...interface{}) {
+ logDev.Printf(format, v...)
}
func LogDevln(v ...interface{}) {
- if logError == nil {
- panic("Logging not setup!")
- }
-
- logError.Println(v...)
+ logDev.Println(v...)
}
diff --git a/settings.go b/settings.go
index dc47eb5..dccd9fb 100644
--- a/settings.go
+++ b/settings.go
@@ -49,7 +49,7 @@ func init() {
panic("Missing stream key is settings.json")
}
- if err = common.SetupLogging(settings.LogLevel, settings.LogFile); err != nil {
+ if err = settings.SetupLogging(); err != nil {
panic("Unable to setup logger: " + err.Error())
}
@@ -184,3 +184,7 @@ func (s *Settings) GetStreamKey() string {
}
return s.StreamKey
}
+
+func (s *Settings) SetupLogging() error {
+ return common.SetupLogging(s.LogLevel, s.LogFile)
+}
diff --git a/static/css/site.css b/static/css/site.css
index c708c98..7b53c86 100644
--- a/static/css/site.css
+++ b/static/css/site.css
@@ -116,6 +116,22 @@ span.svmsg {
color: var(--var-contrast-color);
}
+.spoiler {
+ border-radius: 3px;
+ padding: 0px 3px;
+}
+
+.spoiler *,
+.spoiler {
+ background: var(--var-popout-color);
+ color: var(--var-popout-color);
+}
+
+.spoiler-active {
+ background: var(--var-background-color);
+ color: aqua;
+}
+
.range-div {
margin-bottom: 5px;
display: flex;