package common
import (
"encoding/json"
"errors"
)
type DataInterface interface {
HTML() string
}
type ChatData struct {
Hidden bool
Type DataType
Data json.RawMessage
}
func (c ChatData) GetData() (DataInterface, error) {
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 DTError:
d := DataError{}
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
}
return data, err
}
func newChatData(hidden bool, dtype DataType, d DataInterface) (ChatData, error) {
rawData, err := json.Marshal(d)
return ChatData{
Hidden: hidden,
Type: dtype,
Data: rawData,
}, err
}
type ClientData struct {
Type ClientDataType
Message string
}
func (c ClientData) HTML() string {
// Client data is for client to server communication only, so clients should not see this
return `
The developer messed up. You should not be seeing this.
`
}
type DataError struct {
Message string
}
func (de DataError) HTML() string {
return `Error: ` + de.Message + `
`
}
type DataMessage struct {
From string
Color string
Message string
Type MessageType
}
// TODO: Read this HTML from a template somewhere
func (dc DataMessage) HTML() string {
switch dc.Type {
case MsgAction:
return `` + dc.From +
` ` + dc.Message + `
`
case MsgServer:
return `` + dc.Message + `
`
case MsgError:
return `` + dc.Message + `
`
default:
return `` + dc.From +
`: ` + dc.Message + `
`
}
}
type DataCommand struct {
Command CommandType
Arguments []string
}
func (de DataCommand) HTML() string {
return ""
}
type DataEvent struct {
Event EventType
User string
Color string
}
func (de DataEvent) HTML() string {
switch de.Event {
case EvKick:
return `` +
de.User + ` has been kicked.
`
case EvLeave:
return `` +
de.User + ` has left the chat.
`
case EvBan:
return `` +
de.User + ` has been banned.
`
case EvJoin:
return `` +
de.User + ` has joined the chat.
`
}
return ""
}
type ClientDataType int
const (
CdMessage ClientDataType = iota // a normal message from the client meant to be broadcast
CdUsers // get a list of users
)
type DataType int
// Data Types
const (
DTInvalid DataType = iota
DTChat // chat message
DTError // something went wrong with the previous request
DTCommand // non-chat function
DTEvent // join/leave/kick/ban events
DTClient // a message coming from the client
)
type CommandType int
// Command Types
const (
CmdPlaying CommandType = iota
CmdRefreshPlayer
CmdPurgeChat
CmdHelp
)
type EventType int
// Event Types
const (
EvJoin EventType = iota
EvLeave
EvKick
EvBan
EvServerMessage
)
type MessageType int
// Message Types
const (
MsgChat MessageType = iota // standard chat
MsgAction // /me command
MsgServer // server message
MsgError
)
func EncodeMessage(name, color, msg string, msgtype MessageType) (string, error) {
d, err := newChatData(false, DTChat, DataMessage{
From: name,
Color: color,
Message: msg,
Type: msgtype,
})
if err != nil {
return "", err
}
return jsonifyChatData(d)
}
func EncodeError(message string) (string, error) {
d, err := newChatData(false, DTError, DataError{Message: message})
if err != nil {
return "", err
}
return jsonifyChatData(d)
}
func EncodeCommand(command CommandType, args []string) (string, error) {
d, err := newChatData(false, DTCommand, DataCommand{
Command: command,
Arguments: args,
})
if err != nil {
return "", err
}
return jsonifyChatData(d)
}
func EncodeEvent(event EventType, name, color string) (string, error) {
d, err := newChatData(false, DTEvent, DataEvent{
Event: event,
User: name,
Color: color,
})
if err != nil {
return "", err
}
return jsonifyChatData(d)
}
func jsonifyChatData(data ChatData) (string, error) {
raw, err := json.Marshal(data)
if err != nil {
return "", err
}
return string(raw), nil
}
func DecodeData(rawjson string) (ChatData, error) {
var data ChatData
err := json.Unmarshal([]byte(rawjson), &data)
return data, err
}