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.

145 lines
3.1 KiB

6 years ago
6 years ago
6 years ago
  1. package irc
  2. import (
  3. "strings"
  4. "git.aiterp.net/gisle/irc/list"
  5. )
  6. // A Channel is a target that manages the userlist
  7. type Channel struct {
  8. name string
  9. userlist *list.List
  10. parted bool
  11. }
  12. // Kind returns "channel"
  13. func (channel *Channel) Kind() string {
  14. return "channel"
  15. }
  16. // Name gets the channel name
  17. func (channel *Channel) Name() string {
  18. return channel.name
  19. }
  20. // UserList gets the channel userlist
  21. func (channel *Channel) UserList() list.Immutable {
  22. return channel.userlist.Immutable()
  23. }
  24. // Parted returnes whether the channel has been parted
  25. func (channel *Channel) Parted() bool {
  26. return channel.parted
  27. }
  28. // Handle handles messages routed to this channel by the client's event loop
  29. func (channel *Channel) Handle(event *Event, client *Client) {
  30. switch event.Name() {
  31. case "packet.join":
  32. {
  33. // Support extended-join
  34. account := ""
  35. if accountArg := event.Arg(1); accountArg != "" && accountArg != "*" {
  36. account = accountArg
  37. }
  38. channel.userlist.Insert(list.User{
  39. Nick: event.Nick,
  40. User: event.User,
  41. Host: event.Host,
  42. Account: account,
  43. })
  44. }
  45. case "packet.part", "packet.quit":
  46. {
  47. // Close the target if the client has left
  48. if event.Nick == client.Nick() && event.Name() == "packet.part" {
  49. channel.parted = true
  50. client.RemoveTarget(channel)
  51. }
  52. channel.userlist.Remove(event.Nick)
  53. }
  54. case "packet.nick":
  55. {
  56. channel.userlist.Rename(event.Nick, event.Arg(0))
  57. }
  58. case "packet.account":
  59. {
  60. newAccount := event.Arg(0)
  61. if newAccount != "*" && newAccount != "" {
  62. channel.userlist.Patch(event.Nick, list.UserPatch{Account: newAccount})
  63. } else {
  64. channel.userlist.Patch(event.Nick, list.UserPatch{ClearAccount: true})
  65. }
  66. }
  67. case "packet.away":
  68. {
  69. if event.Text != "" {
  70. channel.userlist.Patch(event.Nick, list.UserPatch{Away: event.Text})
  71. } else {
  72. channel.userlist.Patch(event.Nick, list.UserPatch{ClearAway: true})
  73. }
  74. }
  75. case "packet.chghost":
  76. {
  77. newUser := event.Arg(0)
  78. newHost := event.Arg(1)
  79. channel.userlist.Patch(event.Nick, list.UserPatch{User: newUser, Host: newHost})
  80. }
  81. case "packet.353": // NAMES
  82. {
  83. channel.userlist.SetAutoSort(false)
  84. tokens := strings.Split(event.Text, " ")
  85. for _, token := range tokens {
  86. channel.userlist.InsertFromNamesToken(token)
  87. }
  88. }
  89. case "packet.366": // End of NAMES
  90. {
  91. channel.userlist.SetAutoSort(true)
  92. }
  93. case "packet.mode":
  94. {
  95. isupport := client.ISupport()
  96. plus := false
  97. argIndex := 2
  98. for _, ch := range event.Arg(1) {
  99. if ch == '+' {
  100. plus = true
  101. continue
  102. }
  103. if ch == '-' {
  104. plus = false
  105. continue
  106. }
  107. arg := ""
  108. if isupport.ModeTakesArgument(ch, plus) {
  109. arg = event.Arg(argIndex)
  110. argIndex++
  111. }
  112. if isupport.IsPermissionMode(ch) {
  113. if plus {
  114. channel.userlist.AddMode(arg, ch)
  115. } else {
  116. channel.userlist.RemoveMode(arg, ch)
  117. }
  118. } else {
  119. // TODO: track non-permission modes
  120. }
  121. }
  122. }
  123. case "packet.privmsg", "ctcp.action":
  124. {
  125. if accountTag, ok := event.Tags["account"]; ok && accountTag != "" {
  126. channel.userlist.Patch(event.Nick, list.UserPatch{Account: accountTag})
  127. }
  128. }
  129. }
  130. }