diff --git a/client/line.go b/client/line.go index 1f523d0..89459ef 100644 --- a/client/line.go +++ b/client/line.go @@ -105,6 +105,9 @@ func (line *Line) Public() bool { // CTCP command separated from any subsequent text. Then, CTCP ACTIONs are // rewritten such that Line.Cmd == ACTION. Other CTCP messages have Cmd // set to CTCP or CTCPREPLY, and the CTCP command prepended to line.Args. +// +// ParseLine also parses IRCv3 tags, if received. If a line does not have +// the tags section, Line.Tags will be nil. func ParseLine(s string) *Line { line := &Line{Raw: s} @@ -117,19 +120,17 @@ func ParseLine(s string) *Line { return nil } - // all tags are escaped, so splitting on ; is right by design + // ; is represented as \: in a tag, so it's safe to split on ; for _, tag := range strings.Split(rawTags, ";") { if tag == "" { - return nil + continue } - pair := strings.Split(tagsReplacer.Replace(tag), "=") + pair := strings.SplitN(tagsReplacer.Replace(tag), "=", 2) if len(pair) < 2 { line.Tags[tag] = "" - } else if len(pair) == 2 { - line.Tags[pair[0]] = pair[1] } else { - return nil + line.Tags[pair[0]] = pair[1] } } } diff --git a/client/line_test.go b/client/line_test.go index b041639..82132d1 100644 --- a/client/line_test.go +++ b/client/line_test.go @@ -137,8 +137,32 @@ func TestLineTags(t *testing.T) { Args: []string{"me", "Hello"}, }, }, - {"@a=a; :nick!ident@host.com PRIVMSG me :Hello", nil}, // Bad inputs - {"@a=a=a :nick!ident@host.com PRIVMSG me :Hello", nil}, + { // Skip empty tag + "@a=a; :nick!ident@host.com PRIVMSG me :Hello", + &Line{ + Tags: map[string]string{"a": "a"}, + Nick: "nick", + Ident: "ident", + Host: "host.com", + Src: "nick!ident@host.com", + Cmd: PRIVMSG, + Raw: "@a=a; :nick!ident@host.com PRIVMSG me :Hello", + Args: []string{"me", "Hello"}, + }, + }, + { // = in tag + "@a=a=a; :nick!ident@host.com PRIVMSG me :Hello", + &Line{ + Tags: map[string]string{"a": "a=a"}, + Nick: "nick", + Ident: "ident", + Host: "host.com", + Src: "nick!ident@host.com", + Cmd: PRIVMSG, + Raw: "@a=a=a; :nick!ident@host.com PRIVMSG me :Hello", + Args: []string{"me", "Hello"}, + }, + }, } for i, test := range tests {