|
|
package irc
import ( "errors" "strings" "time" )
var unescapeTags = strings.NewReplacer("\\\\", "\\", "\\:", ";", "\\s", " ", "\\r", "\r", "\\n", "\n")
// ParsePacket parses an 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.SplitN(line, " :", 2) 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)
if event.verb == "PRIVMSG" { event.kind = "ctcp" } else { event.kind = "ctcp-reply" }
event.verb = verbtext[0] if len(verbtext) == 2 { event.Text = verbtext[1] } else { event.Text = "" } }
event.name = event.kind + "." + strings.ToLower(event.verb) return event, nil }
|