2019-03-13 06:09:24 +01:00
package common
import (
2020-11-11 20:51:29 +01:00
"bytes"
2019-03-13 06:09:24 +01:00
"encoding/json"
2019-03-14 20:21:53 +01:00
"errors"
2019-03-15 07:19:16 +01:00
"fmt"
2019-03-19 22:03:34 +01:00
"strings"
2020-11-11 20:51:29 +01:00
"text/template"
2019-03-13 06:09:24 +01:00
)
2019-03-14 20:21:53 +01:00
type DataInterface interface {
HTML ( ) string
2019-03-14 02:24:14 +01:00
}
2019-03-14 20:21:53 +01:00
type ChatData struct {
2019-03-21 13:47:40 +01:00
Type DataType
Data DataInterface
}
func ( c ChatData ) ToJSON ( ) ( ChatDataJSON , error ) {
rawData , err := json . Marshal ( c . Data )
return ChatDataJSON {
Type : c . Type ,
Data : rawData ,
} , err
}
type ChatDataJSON struct {
2019-03-15 07:19:16 +01:00
Type DataType
Data json . RawMessage
2019-03-14 20:21:53 +01:00
}
2019-03-21 13:47:40 +01:00
func ( c ChatDataJSON ) ToData ( ) ( ChatData , error ) {
data , err := c . GetData ( )
return ChatData {
Type : c . Type ,
Data : data ,
} , err
}
func ( c ChatDataJSON ) GetData ( ) ( DataInterface , error ) {
2019-03-14 20:21:53 +01:00
var data DataInterface
var err error
switch c . Type {
case DTInvalid :
return nil , errors . New ( "data type is invalid" )
case DTChat :
d := DataMessage { }
err = json . Unmarshal ( c . Data , & d )
data = d
case DTCommand :
d := DataCommand { }
err = json . Unmarshal ( c . Data , & d )
data = d
case DTEvent :
d := DataEvent { }
err = json . Unmarshal ( c . Data , & d )
data = d
case DTClient :
d := ClientData { }
err = json . Unmarshal ( c . Data , & d )
data = d
2019-03-15 07:19:16 +01:00
case DTHidden :
d := HiddenMessage { }
err = json . Unmarshal ( c . Data , & d )
data = d
default :
err = fmt . Errorf ( "unhandled data type: %d" , c . Type )
2019-03-14 20:21:53 +01:00
}
2019-03-14 02:24:14 +01:00
2019-03-14 20:21:53 +01:00
return data , err
2019-03-14 05:21:41 +01:00
}
type ClientData struct {
Type ClientDataType
Message string
}
2019-03-15 04:08:22 +01:00
func ( c ClientData ) HTML ( ) string {
// Client data is for client to server communication only, so clients should not see this
2019-03-29 01:25:46 +01:00
return ` <span style="color: red;">The developer messed up. You should not be seeing this.</span> `
2019-03-15 04:08:22 +01:00
}
2019-03-13 18:42:38 +01:00
type DataMessage struct {
From string
Color string
Message string
2019-03-16 23:11:20 +01:00
Level CommandLevel
2019-03-13 18:42:38 +01:00
Type MessageType
2019-03-13 06:09:24 +01:00
}
2020-11-11 20:51:29 +01:00
var (
cmdme = template . Must ( template . New ( "cmdme" ) . Parse ( ` <span style="color: {{ .Color }} "><span class="name"> {{ .From }} </span> <span class="cmdme"> {{ .Message }} </span></span> ` ) )
announcement = template . Must ( template . New ( "announcement" ) . Parse ( ` <span class="announcement"> {{ .Message }} </span> ` ) )
errormsg = template . Must ( template . New ( "error" ) . Parse ( ` <span class="error"> {{ .Message }} </span> ` ) )
notice = template . Must ( template . New ( "notice" ) . Parse ( ` <span class="notice"> {{ .Message }} </span> ` ) )
command = template . Must ( template . New ( "command" ) . Parse ( ` <span class="command"> {{ .Message }} </span> ` ) )
commanderror = template . Must ( template . New ( "commanderror" ) . Parse ( ` <span class="commanderror"> {{ .Message }} </span> ` ) )
cmdlMod = template . Must ( template . New ( "cmdlMod" ) . Parse ( ` <span><img src="/static/img/mod.png" class="badge" /><span class="name" style="color: {{ .Color }} "> {{ .From }} </span><b>:</b> <span class="msg"> {{ .Message }} </span></span> ` ) )
cmdlAdmin = template . Must ( template . New ( "CmdlAdmin" ) . Parse ( ` <span><img src="/static/img/admin.png" class="badge" /><span class="name" style="color: {{ .Color }} "> {{ .From }} </span><b>:</b> <span class="msg"> {{ .Message }} </span></span> ` ) )
defaultMsg = template . Must ( template . New ( "defaultMsg" ) . Parse ( ` <span><span class="name" style="color: {{ .Color }} "> {{ .From }} </span><b>:</b> <span class="msg"> {{ .Message }} </span></span> ` ) )
)
2019-03-15 04:08:22 +01:00
// TODO: Read this HTML from a template somewhere
func ( dc DataMessage ) HTML ( ) string {
2020-11-11 20:51:29 +01:00
buf := & bytes . Buffer { }
2019-03-15 04:08:22 +01:00
switch dc . Type {
case MsgAction :
2020-11-11 20:51:29 +01:00
cmdme . Execute ( buf , dc )
return buf . String ( )
2019-03-15 04:08:22 +01:00
case MsgServer :
2020-11-11 20:51:29 +01:00
announcement . Execute ( buf , dc )
return buf . String ( )
2019-03-15 04:08:22 +01:00
case MsgError :
2020-11-11 20:51:29 +01:00
errormsg . Execute ( buf , dc )
return buf . String ( )
2019-03-15 21:03:02 +01:00
case MsgNotice :
2020-11-11 20:51:29 +01:00
notice . Execute ( buf , dc )
return buf . String ( )
2019-03-16 19:37:12 +01:00
case MsgCommandResponse :
2020-11-11 20:51:29 +01:00
command . Execute ( buf , dc )
return buf . String ( )
2019-04-12 04:00:14 +02:00
case MsgCommandError :
2020-11-11 20:51:29 +01:00
commanderror . Execute ( buf , dc )
return buf . String ( )
2019-04-12 04:00:14 +02:00
2019-03-15 04:08:22 +01:00
default :
2019-03-16 23:11:20 +01:00
switch dc . Level {
2019-03-24 14:24:57 +01:00
case CmdlMod :
2020-11-11 20:51:29 +01:00
cmdlMod . Execute ( buf , dc )
2019-03-24 14:24:57 +01:00
case CmdlAdmin :
2020-11-11 20:51:29 +01:00
cmdlAdmin . Execute ( buf , dc )
default :
defaultMsg . Execute ( buf , dc )
2019-03-16 23:11:20 +01:00
}
2020-11-11 20:51:29 +01:00
return buf . String ( )
2019-03-15 04:08:22 +01:00
}
}
2019-03-21 13:47:40 +01:00
func NewChatMessage ( name , color , msg string , lvl CommandLevel , msgtype MessageType ) ChatData {
return ChatData {
Type : DTChat ,
Data : DataMessage {
2019-03-15 22:28:29 +01:00
From : name ,
Color : color ,
Message : msg ,
Type : msgtype ,
2019-03-16 23:11:20 +01:00
Level : lvl ,
2019-03-21 13:47:40 +01:00
} ,
2019-03-15 04:13:42 +01:00
}
}
2019-03-13 06:09:24 +01:00
type DataCommand struct {
Command CommandType
Arguments [ ] string
}
2019-03-15 04:08:22 +01:00
func ( de DataCommand ) HTML ( ) string {
2019-03-18 03:29:31 +01:00
switch de . Command {
case CmdPurgeChat :
2019-03-29 01:25:46 +01:00
return ` <span class="notice">Chat has been purged by a moderator.</span> `
2019-03-18 03:29:31 +01:00
default :
return ""
}
2019-03-15 04:08:22 +01:00
}
2019-03-21 13:47:40 +01:00
func NewChatCommand ( command CommandType , args [ ] string ) ChatData {
return ChatData {
Type : DTCommand ,
Data : DataCommand {
2019-03-15 22:28:29 +01:00
Command : command ,
Arguments : args ,
2019-03-21 13:47:40 +01:00
} ,
2019-03-15 04:13:42 +01:00
}
}
2019-03-13 06:09:24 +01:00
type DataEvent struct {
Event EventType
User string
Color string
2020-11-11 20:51:29 +01:00
Users [ ] string
2019-03-13 06:09:24 +01:00
}
2020-11-11 20:51:29 +01:00
var (
evKick = template . Must ( template . New ( "evKick" ) . Parse ( ` <span class="event"><span class="name" style="color: {{ .Color }} "> {{ .User }} </span> has been kicked.</span> ` ) )
evLeave = template . Must ( template . New ( "evLeave" ) . Parse ( ` <span class="event"><span class="name" style="color: {{ .Color }} "> {{ .User }} </span> has left the chat.</span> ` ) )
evBan = template . Must ( template . New ( "evBan" ) . Parse ( ` <span class="event"><span class="name" style="color: {{ .Color }} "> {{ .User }} </span> has been banned.</span> ` ) )
evJoin = template . Must ( template . New ( "evJoin" ) . Parse ( ` <span class="event"><span class="name" style="color: {{ .Color }} "> {{ .User }} </span> has joined the chat.</span> ` ) )
evNameChangeWC = template . Must ( template . New ( "evNameChangeWC" ) . Parse ( ` <span class="event">Somebody changed their name, but IDK who {{ . }} .</span> ` ) )
evNameChange = template . Must ( template . New ( "evNameChange" ) . Parse ( ` <span class="event"><span class="name" style="color: {{ .Color }} "> {{ index .Users 0 }} </span> has changed their name to <span class="name" style="color: {{ .Color }} "> {{ index .Users 1 }} </span>.</span> ` ) )
evNameChangeForced = template . Must ( template . New ( "evNameChangeForced" ) . Parse ( ` <span class="event"><span class="name" style="color: {{ .Color }} "> {{ index .Users 0 }} </span> has had their name changed to <span class="name" style="color: {{ .Color }} "> {{ index .Users 1 }} </span> by an admin.</span> ` ) )
evNameChangeForcedWC = template . Must ( template . New ( "evNameChangeForcedWC" ) . Parse ( ` <span class="event">An admin changed somebody's name, but IDK who {{ . }} .</span> ` ) )
)
2019-03-15 04:08:22 +01:00
func ( de DataEvent ) HTML ( ) string {
2020-11-11 20:51:29 +01:00
buf := & bytes . Buffer { }
2019-03-15 04:08:22 +01:00
switch de . Event {
case EvKick :
2020-11-11 20:51:29 +01:00
evKick . Execute ( buf , de )
return buf . String ( )
2019-03-15 04:08:22 +01:00
case EvLeave :
2020-11-11 20:51:29 +01:00
evLeave . Execute ( buf , de )
return buf . String ( )
2019-03-15 04:08:22 +01:00
case EvBan :
2020-11-11 20:51:29 +01:00
evBan . Execute ( buf , de )
return buf . String ( )
2019-03-15 04:08:22 +01:00
case EvJoin :
2020-11-11 20:51:29 +01:00
evJoin . Execute ( buf , de )
return buf . String ( )
2019-03-19 22:03:34 +01:00
case EvNameChange :
2020-11-11 20:51:29 +01:00
de . Users = strings . Split ( de . User , ":" )
if len ( de . Users ) < 2 {
evNameChangeWC . Execute ( buf , ParseEmotes ( "Jebaited" ) )
} else {
evNameChange . Execute ( buf , de )
2019-03-19 22:03:34 +01:00
}
2020-11-11 20:51:29 +01:00
return buf . String ( )
2019-03-19 22:03:34 +01:00
case EvNameChangeForced :
2020-11-11 20:51:29 +01:00
de . Users = strings . Split ( de . User , ":" )
if len ( de . Users ) < 2 {
evNameChangeForcedWC . Execute ( buf , ParseEmotes ( "Jebaited" ) )
} else {
evNameChangeForced . Execute ( buf , de )
2019-03-19 22:03:34 +01:00
}
2020-11-11 20:51:29 +01:00
return buf . String ( )
2019-03-15 04:08:22 +01:00
}
return ""
}
2019-03-21 13:47:40 +01:00
func NewChatEvent ( event EventType , name , color string ) ChatData {
return ChatData {
Type : DTEvent ,
Data : DataEvent {
2019-03-15 22:28:29 +01:00
Event : event ,
User : name ,
Color : color ,
2019-03-21 13:47:40 +01:00
} ,
2019-03-13 06:09:24 +01:00
}
}
2019-03-15 07:19:16 +01:00
// DataHidden is for the server to send instructions and data
// to the client without the purpose of outputting it on the chat
type HiddenMessage struct {
Type ClientDataType
Data interface { }
}
func ( h HiddenMessage ) HTML ( ) string {
return ""
}
2019-03-21 13:47:40 +01:00
func NewChatHiddenMessage ( clientType ClientDataType , data interface { } ) ChatData {
return ChatData {
Type : DTHidden ,
Data : HiddenMessage {
2019-03-15 22:28:29 +01:00
Type : clientType ,
Data : data ,
2019-03-21 13:47:40 +01:00
} ,
2019-03-13 06:09:24 +01:00
}
}
2019-03-21 13:47:40 +01:00
func DecodeData ( rawjson string ) ( ChatDataJSON , error ) {
var data ChatDataJSON
2019-03-14 20:21:53 +01:00
err := json . Unmarshal ( [ ] byte ( rawjson ) , & data )
return data , err
2019-03-13 06:09:24 +01:00
}
2019-04-13 19:12:08 +02:00
type JoinData struct {
Name string
Color string
}