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 }