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

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. package irc
  2. import (
  3. "errors"
  4. "strings"
  5. "time"
  6. )
  7. var unescapeTags = strings.NewReplacer("\\\\", "\\", "\\:", ";", "\\s", " ", "\\r", "\r", "\\n", "\n")
  8. // ParsePacket parses an irc line and returns an event that's either of kind `packet`, `ctcp` or `ctcpreply`
  9. func ParsePacket(line string) (Event, error) {
  10. event := NewEvent("packet", "")
  11. event.Time = time.Now()
  12. if len(line) == 0 {
  13. return event, errors.New("irc: empty line")
  14. }
  15. // Parse tags
  16. if line[0] == '@' {
  17. split := strings.SplitN(line, " ", 2)
  18. if len(split) < 2 {
  19. return event, errors.New("irc: incomplete packet")
  20. }
  21. tagTokens := strings.Split(split[0][1:], ";")
  22. for _, token := range tagTokens {
  23. kv := strings.SplitN(token, "=", 2)
  24. if len(kv) == 2 {
  25. event.Tags[kv[0]] = unescapeTags.Replace(kv[1])
  26. } else {
  27. event.Tags[kv[0]] = ""
  28. }
  29. }
  30. line = split[1]
  31. }
  32. // Parse prefix
  33. if line[0] == ':' {
  34. split := strings.SplitN(line, " ", 2)
  35. if len(split) < 2 {
  36. return event, errors.New("ParsePacket: incomplete packet")
  37. }
  38. prefixTokens := strings.Split(split[0][1:], "!")
  39. event.Nick = prefixTokens[0]
  40. if len(prefixTokens) > 1 {
  41. userhost := strings.Split(prefixTokens[1], "@")
  42. if len(userhost) < 2 {
  43. return event, errors.New("ParsePacket: invalid user@host format")
  44. }
  45. event.User = userhost[0]
  46. event.Host = userhost[1]
  47. }
  48. line = split[1]
  49. }
  50. // Parse body
  51. split := strings.SplitN(line, " :", 2)
  52. tokens := strings.Split(split[0], " ")
  53. if len(split) == 2 {
  54. event.Text = split[1]
  55. }
  56. event.verb = tokens[0]
  57. event.Args = tokens[1:]
  58. // Parse CTCP
  59. if (event.verb == "PRIVMSG" || event.verb == "NOTICE") && strings.HasPrefix(event.Text, "\x01") {
  60. verbtext := strings.SplitN(strings.Replace(event.Text, "\x01", "", 2), " ", 2)
  61. if event.verb == "PRIVMSG" {
  62. event.kind = "ctcp"
  63. } else {
  64. event.kind = "ctcp-reply"
  65. }
  66. event.verb = verbtext[0]
  67. if len(verbtext) == 2 {
  68. event.Text = verbtext[1]
  69. } else {
  70. event.Text = ""
  71. }
  72. }
  73. event.name = event.kind + "." + strings.ToLower(event.verb)
  74. return event, nil
  75. }