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.

94 lines
1.9 KiB

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