Add support for parsing IRCv3 tags in received messages
This commit is contained in:
parent
1b0acb5f2f
commit
e1d00ae799
31
irc.go
31
irc.go
@ -87,6 +87,17 @@ func (irc *Connection) readLoop() {
|
||||
}
|
||||
}
|
||||
|
||||
// Unescape tag values as defined in the IRCv3.2 message tags spec
|
||||
// http://ircv3.net/specs/core/message-tags-3.2.html
|
||||
func unescapeTagValue(value string) string {
|
||||
value = strings.Replace(value, "\\:", ";", -1)
|
||||
value = strings.Replace(value, "\\s", " ", -1)
|
||||
value = strings.Replace(value, "\\\\", "\\", -1)
|
||||
value = strings.Replace(value, "\\r", "\r", -1)
|
||||
value = strings.Replace(value, "\\n", "\n", -1)
|
||||
return value
|
||||
}
|
||||
|
||||
//Parse raw irc messages
|
||||
func parseToEvent(msg string) (*Event, error) {
|
||||
msg = strings.TrimSuffix(msg, "\n") //Remove \r\n
|
||||
@ -95,6 +106,26 @@ func parseToEvent(msg string) (*Event, error) {
|
||||
if len(msg) < 5 {
|
||||
return nil, errors.New("Malformed msg from server")
|
||||
}
|
||||
|
||||
if msg[0] == '@' {
|
||||
// IRCv3 Message Tags
|
||||
if i := strings.Index(msg, " "); i > -1 {
|
||||
event.Tags = make(map[string]string)
|
||||
tags := strings.Split(msg[1:i], ";")
|
||||
for _, data := range tags {
|
||||
parts := strings.SplitN(data, "=", 2)
|
||||
if len(parts) == 1 {
|
||||
event.Tags[parts[0]] = ""
|
||||
} else {
|
||||
event.Tags[parts[0]] = unescapeTagValue(parts[1])
|
||||
}
|
||||
}
|
||||
msg = msg[i+1 : len(msg)]
|
||||
} else {
|
||||
return nil, errors.New("Malformed msg from server")
|
||||
}
|
||||
}
|
||||
|
||||
if msg[0] == ':' {
|
||||
if i := strings.Index(msg, " "); i > -1 {
|
||||
event.Source = msg[1:i]
|
||||
|
47
irc_parse_test.go
Normal file
47
irc_parse_test.go
Normal file
@ -0,0 +1,47 @@
|
||||
package irc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func checkResult(t *testing.T, event *Event) {
|
||||
if event.Nick != "nick" {
|
||||
t.Fatal("Parse failed: nick")
|
||||
}
|
||||
if event.User != "~user" {
|
||||
t.Fatal("Parse failed: user")
|
||||
}
|
||||
if event.Code != "PRIVMSG" {
|
||||
t.Fatal("Parse failed: code")
|
||||
}
|
||||
if event.Arguments[0] != "#channel" {
|
||||
t.Fatal("Parse failed: channel")
|
||||
}
|
||||
if event.Arguments[1] != "message text" {
|
||||
t.Fatal("Parse failed: message")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
event, err := parseToEvent(":nick!~user@host PRIVMSG #channel :message text")
|
||||
if err != nil {
|
||||
t.Fatal("Parse PRIVMSG failed")
|
||||
}
|
||||
checkResult(t, event)
|
||||
}
|
||||
|
||||
func TestParseTags(t *testing.T) {
|
||||
event, err := parseToEvent("@tag;+tag2=raw+:=,escaped\\:\\s\\\\ :nick!~user@host PRIVMSG #channel :message text")
|
||||
if err != nil {
|
||||
t.Fatal("Parse PRIVMSG with tags failed")
|
||||
}
|
||||
checkResult(t, event)
|
||||
fmt.Printf("%s", event.Tags)
|
||||
if _, ok := event.Tags["tag"]; !ok {
|
||||
t.Fatal("Parsing value-less tag failed")
|
||||
}
|
||||
if event.Tags["+tag2"] != "raw+:=,escaped; \\" {
|
||||
t.Fatal("Parsing tag failed")
|
||||
}
|
||||
}
|
@ -59,6 +59,7 @@ type Event struct {
|
||||
Source string //<host>
|
||||
User string //<usr>
|
||||
Arguments []string
|
||||
Tags map[string]string
|
||||
Connection *Connection
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user