-
-
Notifications
You must be signed in to change notification settings - Fork 87
/
Copy pathchatdata.go
277 lines (244 loc) · 7.83 KB
/
chatdata.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
package common
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"strings"
"text/template"
)
const htmlConversionErrSpan = `<span class="error">Could not process %s.</span>`
type DataInterface interface {
HTML() string
}
type ChatData struct {
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 {
Type DataType
Data json.RawMessage
}
func (c ChatDataJSON) ToData() (ChatData, error) {
data, err := c.GetData()
return ChatData{
Type: c.Type,
Data: data,
}, err
}
func (c ChatDataJSON) 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 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
case DTHidden:
d := HiddenMessage{}
err = json.Unmarshal(c.Data, &d)
data = d
default:
err = fmt.Errorf("unhandled data type: %d", c.Type)
}
return data, 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 `<span style="color: red;">The developer messed up. You should not be seeing this.</span>`
}
type DataMessage struct {
From string
Color string
Message string
Level CommandLevel
Type MessageType
}
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>`))
)
// TODO: Read this HTML from a template somewhere
func (dc DataMessage) HTML() string {
var err error
buf := &bytes.Buffer{}
switch dc.Type {
case MsgAction:
err = cmdme.Execute(buf, dc)
case MsgServer:
err = announcement.Execute(buf, dc)
case MsgError:
err = errormsg.Execute(buf, dc)
case MsgNotice:
err = notice.Execute(buf, dc)
case MsgCommandResponse:
err = command.Execute(buf, dc)
case MsgCommandError:
err = commanderror.Execute(buf, dc)
default:
switch dc.Level {
case CmdlMod:
err = cmdlMod.Execute(buf, dc)
case CmdlAdmin:
err = cmdlAdmin.Execute(buf, dc)
default:
err = defaultMsg.Execute(buf, dc)
}
}
if err != nil {
LogErrorf("Could not convert data message to html: %v\n", err)
return fmt.Sprintf(htmlConversionErrSpan, "message")
}
return buf.String()
}
func NewChatMessage(name, color, msg string, lvl CommandLevel, msgtype MessageType) ChatData {
return ChatData{
Type: DTChat,
Data: DataMessage{
From: name,
Color: color,
Message: msg,
Type: msgtype,
Level: lvl,
},
}
}
type DataCommand struct {
Command CommandType
Arguments []string
}
func (de DataCommand) HTML() string {
switch de.Command {
case CmdPurgeChat:
return `<span class="notice">Chat has been purged by a moderator.</span>`
default:
return ""
}
}
func NewChatCommand(command CommandType, args []string) ChatData {
return ChatData{
Type: DTCommand,
Data: DataCommand{
Command: command,
Arguments: args,
},
}
}
type DataEvent struct {
Event EventType
User string
Color string
Users []string
}
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>`))
)
func (de DataEvent) HTML() string {
var err error
buf := &bytes.Buffer{}
switch de.Event {
case EvKick:
err = evKick.Execute(buf, de)
case EvLeave:
err = evLeave.Execute(buf, de)
case EvBan:
err = evBan.Execute(buf, de)
case EvJoin:
err = evJoin.Execute(buf, de)
case EvNameChange:
de.Users = strings.Split(de.User, ":")
if len(de.Users) < 2 {
err = evNameChangeWC.Execute(buf, ParseEmotes("Jebaited"))
} else {
err = evNameChange.Execute(buf, de)
}
case EvNameChangeForced:
de.Users = strings.Split(de.User, ":")
if len(de.Users) < 2 {
err = evNameChangeForcedWC.Execute(buf, ParseEmotes("Jebaited"))
} else {
err = evNameChangeForced.Execute(buf, de)
}
}
if err != nil {
LogErrorf("Could not convert event message to html: %v\n", err)
return fmt.Sprintf(htmlConversionErrSpan, "event")
}
return buf.String()
}
func NewChatEvent(event EventType, name, color string) ChatData {
return ChatData{
Type: DTEvent,
Data: DataEvent{
Event: event,
User: name,
Color: color,
},
}
}
// 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 ""
}
func NewChatHiddenMessage(clientType ClientDataType, data interface{}) ChatData {
return ChatData{
Type: DTHidden,
Data: HiddenMessage{
Type: clientType,
Data: data,
},
}
}
func DecodeData(rawjson string) (ChatDataJSON, error) {
var data ChatDataJSON
err := json.Unmarshal([]byte(rawjson), &data)
return data, err
}
type JoinData struct {
Name string
Color string
}