Added spoilers in chat

If a user clicks the spoiler, it will change color and the background will revert.
closes #62
This commit is contained in:
joeyak 2019-03-24 23:43:30 -04:00
parent d419f64379
commit 86207ecd48
9 changed files with 112 additions and 36 deletions

View File

@ -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) ./...

View File

@ -10,6 +10,12 @@ import (
"github.com/zorchenhimer/MovieNight/common"
)
var (
regexSpoiler = regexp.MustCompile(`\|\|(.*?)\|\|`)
spoilerStart = `<span class="spoiler" onclick='$(this).removeClass("spoiler").addClass("spoiler-active")'>`
spoilerEnd = `</span>`
)
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, `<span class="mention">$1</span>`)
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, `<span class="mention">$1</span>`)
chatData.Data = data
return chatData
func addSpoilerTags(msg string) string {
return regexSpoiler.ReplaceAllString(msg, fmt.Sprintf(`%s$1%s`, spoilerStart, spoilerEnd))
}

23
chatclient_test.go Normal file
View File

@ -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])
}
}
}

View File

@ -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 {

View File

@ -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

View File

@ -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:

View File

@ -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...)
}

View File

@ -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)
}

View File

@ -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;