|
@@ -61,10 +61,10 @@ var (
|
61
|
61
|
ErrorBadParam = errors.New("Cannot have an empty param, a param with spaces, or a param that starts with ':' before the last parameter")
|
62
|
62
|
)
|
63
|
63
|
|
64
|
|
-// IRCMessage represents an IRC message, as defined by the RFCs and as
|
|
64
|
+// Message represents an IRC message, as defined by the RFCs and as
|
65
|
65
|
// extended by the IRCv3 Message Tags specification with the introduction
|
66
|
66
|
// of message tags.
|
67
|
|
-type IRCMessage struct {
|
|
67
|
+type Message struct {
|
68
|
68
|
Prefix string
|
69
|
69
|
Command string
|
70
|
70
|
Params []string
|
|
@@ -77,12 +77,12 @@ type IRCMessage struct {
|
77
|
77
|
// will be encoded as a "trailing parameter" (preceded by a colon). This is
|
78
|
78
|
// almost never necessary and should not be used except when having to interact
|
79
|
79
|
// with broken implementations that don't correctly interpret IRC messages.
|
80
|
|
-func (msg *IRCMessage) ForceTrailing() {
|
|
80
|
+func (msg *Message) ForceTrailing() {
|
81
|
81
|
msg.forceTrailing = true
|
82
|
82
|
}
|
83
|
83
|
|
84
|
84
|
// GetTag returns whether a tag is present, and if so, what its value is.
|
85
|
|
-func (msg *IRCMessage) GetTag(tagName string) (present bool, value string) {
|
|
85
|
+func (msg *Message) GetTag(tagName string) (present bool, value string) {
|
86
|
86
|
if len(tagName) == 0 {
|
87
|
87
|
return
|
88
|
88
|
} else if tagName[0] == '+' {
|
|
@@ -95,13 +95,13 @@ func (msg *IRCMessage) GetTag(tagName string) (present bool, value string) {
|
95
|
95
|
}
|
96
|
96
|
|
97
|
97
|
// HasTag returns whether a tag is present.
|
98
|
|
-func (msg *IRCMessage) HasTag(tagName string) (present bool) {
|
|
98
|
+func (msg *Message) HasTag(tagName string) (present bool) {
|
99
|
99
|
present, _ = msg.GetTag(tagName)
|
100
|
100
|
return
|
101
|
101
|
}
|
102
|
102
|
|
103
|
103
|
// SetTag sets a tag.
|
104
|
|
-func (msg *IRCMessage) SetTag(tagName, tagValue string) {
|
|
104
|
+func (msg *Message) SetTag(tagName, tagValue string) {
|
105
|
105
|
if len(tagName) == 0 {
|
106
|
106
|
return
|
107
|
107
|
} else if tagName[0] == '+' {
|
|
@@ -118,7 +118,7 @@ func (msg *IRCMessage) SetTag(tagName, tagValue string) {
|
118
|
118
|
}
|
119
|
119
|
|
120
|
120
|
// DeleteTag deletes a tag.
|
121
|
|
-func (msg *IRCMessage) DeleteTag(tagName string) {
|
|
121
|
+func (msg *Message) DeleteTag(tagName string) {
|
122
|
122
|
if len(tagName) == 0 {
|
123
|
123
|
return
|
124
|
124
|
} else if tagName[0] == '+' {
|
|
@@ -129,14 +129,14 @@ func (msg *IRCMessage) DeleteTag(tagName string) {
|
129
|
129
|
}
|
130
|
130
|
|
131
|
131
|
// UpdateTags is a convenience to set multiple tags at once.
|
132
|
|
-func (msg *IRCMessage) UpdateTags(tags map[string]string) {
|
|
132
|
+func (msg *Message) UpdateTags(tags map[string]string) {
|
133
|
133
|
for name, value := range tags {
|
134
|
134
|
msg.SetTag(name, value)
|
135
|
135
|
}
|
136
|
136
|
}
|
137
|
137
|
|
138
|
138
|
// AllTags returns all tags as a single map.
|
139
|
|
-func (msg *IRCMessage) AllTags() (result map[string]string) {
|
|
139
|
+func (msg *Message) AllTags() (result map[string]string) {
|
140
|
140
|
result = make(map[string]string, len(msg.tags)+len(msg.clientOnlyTags))
|
141
|
141
|
for name, value := range msg.tags {
|
142
|
142
|
result[name] = value
|
|
@@ -148,23 +148,23 @@ func (msg *IRCMessage) AllTags() (result map[string]string) {
|
148
|
148
|
}
|
149
|
149
|
|
150
|
150
|
// ClientOnlyTags returns the client-only tags (the tags with the + prefix).
|
151
|
|
-// The returned map may be internal storage of the IRCMessage object and
|
|
151
|
+// The returned map may be internal storage of the Message object and
|
152
|
152
|
// should not be modified.
|
153
|
|
-func (msg *IRCMessage) ClientOnlyTags() map[string]string {
|
|
153
|
+func (msg *Message) ClientOnlyTags() map[string]string {
|
154
|
154
|
return msg.clientOnlyTags
|
155
|
155
|
}
|
156
|
156
|
|
157
|
157
|
// ParseLine creates and returns a message from the given IRC line.
|
158
|
|
-func ParseLine(line string) (ircmsg IRCMessage, err error) {
|
|
158
|
+func ParseLine(line string) (ircmsg Message, err error) {
|
159
|
159
|
return parseLine(line, 0, 0)
|
160
|
160
|
}
|
161
|
161
|
|
162
|
|
-// ParseLineStrict creates and returns an IRCMessage from the given IRC line,
|
|
162
|
+// ParseLineStrict creates and returns an Message from the given IRC line,
|
163
|
163
|
// taking the maximum length into account and truncating the message as appropriate.
|
164
|
164
|
// If fromClient is true, it enforces the client limit on tag data length (4094 bytes),
|
165
|
165
|
// allowing the server to return ERR_INPUTTOOLONG as appropriate. If truncateLen is
|
166
|
166
|
// nonzero, it is the length at which the non-tag portion of the message is truncated.
|
167
|
|
-func ParseLineStrict(line string, fromClient bool, truncateLen int) (ircmsg IRCMessage, err error) {
|
|
167
|
+func ParseLineStrict(line string, fromClient bool, truncateLen int) (ircmsg Message, err error) {
|
168
|
168
|
maxTagDataLength := MaxlenTagData
|
169
|
169
|
if fromClient {
|
170
|
170
|
maxTagDataLength = MaxlenClientTagData
|
|
@@ -180,7 +180,7 @@ func trimInitialSpaces(str string) string {
|
180
|
180
|
return str[i:]
|
181
|
181
|
}
|
182
|
182
|
|
183
|
|
-func parseLine(line string, maxTagDataLength int, truncateLen int) (ircmsg IRCMessage, err error) {
|
|
183
|
+func parseLine(line string, maxTagDataLength int, truncateLen int) (ircmsg Message, err error) {
|
184
|
184
|
// remove either \n or \r\n from the end of the line:
|
185
|
185
|
line = strings.TrimSuffix(line, "\n")
|
186
|
186
|
line = strings.TrimSuffix(line, "\r")
|
|
@@ -279,7 +279,7 @@ func parseLine(line string, maxTagDataLength int, truncateLen int) (ircmsg IRCMe
|
279
|
279
|
}
|
280
|
280
|
|
281
|
281
|
// helper to parse tags
|
282
|
|
-func (ircmsg *IRCMessage) parseTags(tags string) (err error) {
|
|
282
|
+func (ircmsg *Message) parseTags(tags string) (err error) {
|
283
|
283
|
for 0 < len(tags) {
|
284
|
284
|
tagEnd := strings.IndexByte(tags, ';')
|
285
|
285
|
endPos := tagEnd
|
|
@@ -311,8 +311,8 @@ func (ircmsg *IRCMessage) parseTags(tags string) (err error) {
|
311
|
311
|
return nil
|
312
|
312
|
}
|
313
|
313
|
|
314
|
|
-// MakeMessage provides a simple way to create a new IRCMessage.
|
315
|
|
-func MakeMessage(tags map[string]string, prefix string, command string, params ...string) (ircmsg IRCMessage) {
|
|
314
|
+// MakeMessage provides a simple way to create a new Message.
|
|
315
|
+func MakeMessage(tags map[string]string, prefix string, command string, params ...string) (ircmsg Message) {
|
316
|
316
|
ircmsg.Prefix = prefix
|
317
|
317
|
ircmsg.Command = command
|
318
|
318
|
ircmsg.Params = params
|
|
@@ -320,8 +320,8 @@ func MakeMessage(tags map[string]string, prefix string, command string, params .
|
320
|
320
|
return ircmsg
|
321
|
321
|
}
|
322
|
322
|
|
323
|
|
-// Line returns a sendable line created from an IRCMessage.
|
324
|
|
-func (ircmsg *IRCMessage) Line() (result string, err error) {
|
|
323
|
+// Line returns a sendable line created from an Message.
|
|
324
|
+func (ircmsg *Message) Line() (result string, err error) {
|
325
|
325
|
bytes, err := ircmsg.line(0, 0, 0, 0)
|
326
|
326
|
if err == nil {
|
327
|
327
|
result = string(bytes)
|
|
@@ -329,17 +329,17 @@ func (ircmsg *IRCMessage) Line() (result string, err error) {
|
329
|
329
|
return
|
330
|
330
|
}
|
331
|
331
|
|
332
|
|
-// LineBytes returns a sendable line created from an IRCMessage.
|
333
|
|
-func (ircmsg *IRCMessage) LineBytes() (result []byte, err error) {
|
|
332
|
+// LineBytes returns a sendable line created from an Message.
|
|
333
|
+func (ircmsg *Message) LineBytes() (result []byte, err error) {
|
334
|
334
|
result, err = ircmsg.line(0, 0, 0, 0)
|
335
|
335
|
return
|
336
|
336
|
}
|
337
|
337
|
|
338
|
|
-// LineBytesStrict returns a sendable line, as a []byte, created from an IRCMessage.
|
|
338
|
+// LineBytesStrict returns a sendable line, as a []byte, created from an Message.
|
339
|
339
|
// fromClient controls whether the server-side or client-side tag length limit
|
340
|
340
|
// is enforced. If truncateLen is nonzero, it is the length at which the
|
341
|
341
|
// non-tag portion of the message is truncated.
|
342
|
|
-func (ircmsg *IRCMessage) LineBytesStrict(fromClient bool, truncateLen int) ([]byte, error) {
|
|
342
|
+func (ircmsg *Message) LineBytesStrict(fromClient bool, truncateLen int) ([]byte, error) {
|
343
|
343
|
var tagLimit, clientOnlyTagDataLimit, serverAddedTagDataLimit int
|
344
|
344
|
if fromClient {
|
345
|
345
|
// enforce client max tags:
|
|
@@ -359,8 +359,8 @@ func paramRequiresTrailing(param string) bool {
|
359
|
359
|
return len(param) == 0 || strings.IndexByte(param, ' ') != -1 || param[0] == ':'
|
360
|
360
|
}
|
361
|
361
|
|
362
|
|
-// line returns a sendable line created from an IRCMessage.
|
363
|
|
-func (ircmsg *IRCMessage) line(tagLimit, clientOnlyTagDataLimit, serverAddedTagDataLimit, truncateLen int) (result []byte, err error) {
|
|
362
|
+// line returns a sendable line created from an Message.
|
|
363
|
+func (ircmsg *Message) line(tagLimit, clientOnlyTagDataLimit, serverAddedTagDataLimit, truncateLen int) (result []byte, err error) {
|
364
|
364
|
if len(ircmsg.Command) == 0 {
|
365
|
365
|
return nil, ErrorCommandMissing
|
366
|
366
|
}
|