Mirror of github.com/gissleh/irc
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
2.0 KiB

package irc
import (
"errors"
"strings"
"time"
)
var unescapeTags = strings.NewReplacer("\\\\", "\\", "\\:", ";", "\\s", " ", "\\r", "\r", "\\n", "\n")
// ParsePacket parses and irc line and returns an event that's either of kind `packet`, `ctcp` or `ctcpreply`
func ParsePacket(line string) (Event, error) {
event := NewEvent("packet", "")
event.Time = time.Now()
if len(line) == 0 {
return event, errors.New("irc: empty line")
}
// Parse tags
if line[0] == '@' {
split := strings.SplitN(line, " ", 2)
if len(split) < 2 {
return event, errors.New("irc: incomplete packet")
}
tagTokens := strings.Split(split[0][1:], ";")
for _, token := range tagTokens {
kv := strings.SplitN(token, "=", 2)
if len(kv) == 2 {
event.Tags[kv[0]] = unescapeTags.Replace(kv[1])
} else {
event.Tags[kv[0]] = ""
}
}
line = split[1]
}
// Parse prefix
if line[0] == ':' {
split := strings.SplitN(line, " ", 2)
if len(split) < 2 {
return event, errors.New("ParsePacket: incomplete packet")
}
prefixTokens := strings.Split(split[0][1:], "!")
event.Nick = prefixTokens[0]
if len(prefixTokens) > 1 {
userhost := strings.Split(prefixTokens[1], "@")
if len(userhost) < 2 {
return event, errors.New("ParsePacket: invalid user@host format")
}
event.User = userhost[0]
event.Host = userhost[1]
}
line = split[1]
}
// Parse body
split := strings.Split(line, " :")
tokens := strings.Split(split[0], " ")
if len(split) == 2 {
event.Text = split[1]
}
event.verb = tokens[0]
event.Args = tokens[1:]
// Parse CTCP
if (event.verb == "PRIVMSG" || event.verb == "NOTICE") && strings.HasPrefix(event.Text, "\x01") {
verbtext := strings.SplitN(strings.Replace(event.Text, "\x01", "", 2), " ", 2)
event.verb = verbtext[0]
if len(verbtext) == 2 {
event.Text = verbtext[1]
} else {
event.Text = ""
}
if event.verb == "PRIVMSG" {
event.kind = "ctcp"
} else {
event.kind = "ctcp-reply"
}
}
event.name = event.kind + "." + strings.ToLower(event.verb)
return event, nil
}