選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

isupport.go 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Copyright (c) 2016 Daniel Oaks <daniel@danieloaks.net>
  2. // released under the MIT license
  3. package irc
  4. import "fmt"
  5. const isupportSupportedString = "are supported by this server"
  6. // ISupportList holds a list of ISUPPORT tokens
  7. type ISupportList struct {
  8. Tokens map[string]*string
  9. CachedReply [][]string
  10. }
  11. // NewISupportList returns a new ISupportList
  12. func NewISupportList() *ISupportList {
  13. var il ISupportList
  14. il.Tokens = make(map[string]*string)
  15. il.CachedReply = make([][]string, 0)
  16. return &il
  17. }
  18. // Add adds an RPL_ISUPPORT token to our internal list
  19. func (il *ISupportList) Add(name string, value string) {
  20. il.Tokens[name] = &value
  21. }
  22. // AddNoValue adds an RPL_ISUPPORT token that does not have a value
  23. func (il *ISupportList) AddNoValue(name string) {
  24. il.Tokens[name] = nil
  25. }
  26. // getTokenString gets the appropriate string for a token+value.
  27. func getTokenString(name string, value *string) string {
  28. if value == nil {
  29. return name
  30. }
  31. return fmt.Sprintf("%s=%s", name, *value)
  32. }
  33. // GetDifference returns the difference between two token lists.
  34. func (il *ISupportList) GetDifference(newil *ISupportList) [][]string {
  35. replies := make([][]string, 0)
  36. var length int // Length of the current cache
  37. var cache []string // Token list cache
  38. // append removed tokens
  39. for name := range il.Tokens {
  40. _, exists := newil.Tokens[name]
  41. if exists {
  42. continue
  43. }
  44. token := fmt.Sprintf("-%s", name)
  45. if len(token)+length <= maxLastArgLength {
  46. // account for the space separating tokens
  47. if len(cache) > 0 {
  48. length++
  49. }
  50. cache = append(cache, token)
  51. length += len(token)
  52. }
  53. if len(cache) == 13 || len(token)+length >= maxLastArgLength {
  54. cache = append(cache, isupportSupportedString)
  55. replies = append(replies, cache)
  56. cache = make([]string, 0)
  57. length = 0
  58. }
  59. }
  60. // append added tokens
  61. for name, value := range newil.Tokens {
  62. newval, exists := il.Tokens[name]
  63. if exists && *value == *newval {
  64. continue
  65. }
  66. token := getTokenString(name, value)
  67. if len(token)+length <= maxLastArgLength {
  68. // account for the space separating tokens
  69. if len(cache) > 0 {
  70. length++
  71. }
  72. cache = append(cache, token)
  73. length += len(token)
  74. }
  75. if len(cache) == 13 || len(token)+length >= maxLastArgLength {
  76. cache = append(cache, isupportSupportedString)
  77. replies = append(replies, cache)
  78. cache = make([]string, 0)
  79. length = 0
  80. }
  81. }
  82. if len(cache) > 0 {
  83. cache = append(cache, isupportSupportedString)
  84. replies = append(replies, cache)
  85. }
  86. return replies
  87. }
  88. // RegenerateCachedReply regenerates the cached RPL_ISUPPORT reply
  89. func (il *ISupportList) RegenerateCachedReply() {
  90. il.CachedReply = make([][]string, 0)
  91. var length int // Length of the current cache
  92. var cache []string // Token list cache
  93. for name, value := range il.Tokens {
  94. token := getTokenString(name, value)
  95. if len(token)+length <= maxLastArgLength {
  96. // account for the space separating tokens
  97. if len(cache) > 0 {
  98. length++
  99. }
  100. cache = append(cache, token)
  101. length += len(token)
  102. }
  103. if len(cache) == 13 || len(token)+length >= maxLastArgLength {
  104. cache = append(cache, isupportSupportedString)
  105. il.CachedReply = append(il.CachedReply, cache)
  106. cache = make([]string, 0)
  107. length = 0
  108. }
  109. }
  110. if len(cache) > 0 {
  111. cache = append(cache, isupportSupportedString)
  112. il.CachedReply = append(il.CachedReply, cache)
  113. }
  114. }
  115. // RplISupport outputs our ISUPPORT lines to the client. This is used on connection and in VERSION responses.
  116. func (client *Client) RplISupport() {
  117. for _, tokenline := range client.server.isupport.CachedReply {
  118. // ugly trickery ahead
  119. client.Send(nil, client.server.name, RPL_ISUPPORT, append([]string{client.nick}, tokenline...)...)
  120. }
  121. }