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:
parent
d419f64379
commit
86207ecd48
7
Makefile
7
Makefile
@ -1,8 +1,8 @@
|
|||||||
TAGS=
|
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:
|
setdev:
|
||||||
$(eval export TAGS=-tags "dev")
|
$(eval export TAGS=-tags "dev")
|
||||||
@ -32,3 +32,6 @@ get:
|
|||||||
vet:
|
vet:
|
||||||
go vet $(TAGS) ./...
|
go vet $(TAGS) ./...
|
||||||
GOOS=js GOARCH=wasm go vet $(TAGS) ./...
|
GOOS=js GOARCH=wasm go vet $(TAGS) ./...
|
||||||
|
|
||||||
|
test:
|
||||||
|
go test $(TAGS) ./...
|
@ -10,6 +10,12 @@ import (
|
|||||||
"github.com/zorchenhimer/MovieNight/common"
|
"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 {
|
type Client struct {
|
||||||
name string // Display name
|
name string // Display name
|
||||||
conn *chatConnection
|
conn *chatConnection
|
||||||
@ -18,6 +24,7 @@ type Client struct {
|
|||||||
CmdLevel common.CommandLevel
|
CmdLevel common.CommandLevel
|
||||||
IsColorForced bool
|
IsColorForced bool
|
||||||
IsNameForced bool
|
IsNameForced bool
|
||||||
|
regexName *regexp.Regexp
|
||||||
}
|
}
|
||||||
|
|
||||||
//Client has a new message to broadcast
|
//Client has a new message to broadcast
|
||||||
@ -49,6 +56,10 @@ func (cl *Client) NewMsg(data common.ClientData) {
|
|||||||
msg = removeDumbSpaces(msg)
|
msg = removeDumbSpaces(msg)
|
||||||
msg = strings.Trim(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
|
// Don't send zero-length messages
|
||||||
if len(msg) == 0 {
|
if len(msg) == 0 {
|
||||||
return
|
return
|
||||||
@ -94,7 +105,11 @@ func (cl *Client) NewMsg(data common.ClientData) {
|
|||||||
func (cl *Client) SendChatData(data common.ChatData) error {
|
func (cl *Client) SendChatData(data common.ChatData) error {
|
||||||
// Colorize name on chat messages
|
// Colorize name on chat messages
|
||||||
if data.Type == common.DTChat {
|
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()
|
cd, err := data.ToJSON()
|
||||||
@ -164,6 +179,24 @@ func (cl *Client) Host() string {
|
|||||||
return cl.conn.Host()
|
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{
|
var dumbSpaces = []string{
|
||||||
"\n",
|
"\n",
|
||||||
"\t",
|
"\t",
|
||||||
@ -187,12 +220,6 @@ func removeDumbSpaces(msg string) string {
|
|||||||
return newMsg
|
return newMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
func replaceColorizedName(chatData common.ChatData, client *Client) common.ChatData {
|
func addSpoilerTags(msg string) string {
|
||||||
data := chatData.Data.(common.DataMessage)
|
return regexSpoiler.ReplaceAllString(msg, fmt.Sprintf(`%s$1%s`, spoilerStart, spoilerEnd))
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
23
chatclient_test.go
Normal file
23
chatclient_test.go
Normal 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])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
chatroom.go
11
chatroom.go
@ -98,12 +98,16 @@ func (cr *ChatRoom) Join(name, uid string) (*Client, error) {
|
|||||||
|
|
||||||
conn.clientName = name
|
conn.clientName = name
|
||||||
client := &Client{
|
client := &Client{
|
||||||
name: name,
|
|
||||||
conn: conn,
|
conn: conn,
|
||||||
belongsTo: cr,
|
belongsTo: cr,
|
||||||
color: common.RandomColor(),
|
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()
|
host := client.Host()
|
||||||
|
|
||||||
if banned, names := settings.IsBanned(host); banned {
|
if banned, names := settings.IsBanned(host); banned {
|
||||||
@ -483,7 +487,10 @@ func (cr *ChatRoom) changeName(oldName, newName string, forced bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if currentClient != nil {
|
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)
|
common.LogDebugf("%q -> %q\n", oldName, newName)
|
||||||
|
|
||||||
if forced {
|
if forced {
|
||||||
|
@ -42,6 +42,10 @@ var colors = []string{
|
|||||||
"whitesmoke", "yellow", "yellowgreen",
|
"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.
|
// 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
|
// It also accepts hex codes in the form of #000 (RGB), to #00000000 (RRGGBBAA), with A
|
||||||
// being the alpha value
|
// 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)
|
c, err := colorful.Hex(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
|
@ -23,7 +23,6 @@ const (
|
|||||||
logPrefixChat string = "[CHAT] "
|
logPrefixChat string = "[CHAT] "
|
||||||
logPrefixInfo string = "[INFO] "
|
logPrefixInfo string = "[INFO] "
|
||||||
logPrefixDebug string = "[DEBUG] "
|
logPrefixDebug string = "[DEBUG] "
|
||||||
logPrefixDev string = "[DEV] "
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -31,18 +30,8 @@ var (
|
|||||||
logChat *log.Logger
|
logChat *log.Logger
|
||||||
logInfo *log.Logger
|
logInfo *log.Logger
|
||||||
logDebug *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 {
|
func SetupLogging(level LogLevel, file string) error {
|
||||||
switch level {
|
switch level {
|
||||||
case LLDebug:
|
case LLDebug:
|
||||||
|
@ -2,18 +2,21 @@
|
|||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
func LogDevf(format string, v ...interface{}) {
|
import (
|
||||||
if logError == nil {
|
"log"
|
||||||
panic("Logging not setup!")
|
"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{}) {
|
func LogDevln(v ...interface{}) {
|
||||||
if logError == nil {
|
logDev.Println(v...)
|
||||||
panic("Logging not setup!")
|
|
||||||
}
|
|
||||||
|
|
||||||
logError.Println(v...)
|
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ func init() {
|
|||||||
panic("Missing stream key is settings.json")
|
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())
|
panic("Unable to setup logger: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,3 +184,7 @@ func (s *Settings) GetStreamKey() string {
|
|||||||
}
|
}
|
||||||
return s.StreamKey
|
return s.StreamKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Settings) SetupLogging() error {
|
||||||
|
return common.SetupLogging(s.LogLevel, s.LogFile)
|
||||||
|
}
|
||||||
|
@ -116,6 +116,22 @@ span.svmsg {
|
|||||||
color: var(--var-contrast-color);
|
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 {
|
.range-div {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
Loading…
Reference in New Issue
Block a user