您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

metadata.go 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // Copyright (c) 2018 Daniel Oaks <daniel@danieloaks.net>
  2. // released under the MIT license
  3. package irc
  4. import (
  5. "sync"
  6. "github.com/goshuirc/irc-go/ircmsg"
  7. )
  8. var (
  9. //TODO(dan): temporary hardcoded limits, make these configurable instead.
  10. metadataKeysLimit = 20
  11. metadataSubsLimit = 20
  12. )
  13. // MetadataKeysLimit returns how many metadata keys can be set on each client/channel.
  14. //TODO(dan): have this be configurable in the config file instead.
  15. func (server *Server) MetadataKeysLimit() int {
  16. return metadataKeysLimit
  17. }
  18. // MetadataSubsLimit returns how many metadata keys can be subscribed to.
  19. //TODO(dan): have this be configurable in the config file instead.
  20. func (server *Server) MetadataSubsLimit() int {
  21. return metadataSubsLimit
  22. }
  23. // MetadataManager manages metadata for a client or channel.
  24. type MetadataManager struct {
  25. sync.RWMutex
  26. // keyvals holds our values internally.
  27. keyvals map[string]string
  28. }
  29. // NewMetadataManager returns a new MetadataManager.
  30. func NewMetadataManager() *MetadataManager {
  31. var mm MetadataManager
  32. mm.keyvals = make(map[string]string)
  33. return &mm
  34. }
  35. // Clear deletes all keys, returning a list of the deleted keys.
  36. func (mm *MetadataManager) Clear() []string {
  37. var keys []string
  38. mm.Lock()
  39. defer mm.Unlock()
  40. for key := range mm.keyvals {
  41. keys = append(keys, key)
  42. delete(mm.keyvals, key)
  43. }
  44. return keys
  45. }
  46. // List returns all keys and values.
  47. func (mm *MetadataManager) List() map[string]string {
  48. data := make(map[string]string)
  49. mm.RLock()
  50. defer mm.RUnlock()
  51. for key, value := range mm.keyvals {
  52. data[key] = value
  53. }
  54. return data
  55. }
  56. // Get returns the value of a single key.
  57. func (mm *MetadataManager) Get(key string) (string, bool) {
  58. mm.RLock()
  59. defer mm.RUnlock()
  60. value, exists := mm.keyvals[key]
  61. return value, exists
  62. }
  63. // Set sets the value of the given key. A limit of -1 means ignore any limits.
  64. func (mm *MetadataManager) Set(key, value string, limit int) error {
  65. mm.Lock()
  66. defer mm.Unlock()
  67. _, currentlyExists := mm.keyvals[key]
  68. if limit != -1 && !currentlyExists && limit < len(mm.keyvals)+1 {
  69. return errTooManyKeys
  70. }
  71. mm.keyvals[key] = value
  72. return nil
  73. }
  74. // Delete removes the given key.
  75. func (mm *MetadataManager) Delete(key string) {
  76. mm.Lock()
  77. defer mm.Unlock()
  78. delete(mm.keyvals, key)
  79. }
  80. // MetadataSubsManager manages metadata key subscriptions.
  81. type MetadataSubsManager struct {
  82. sync.RWMutex
  83. // watchedKeys holds our list of watched (sub'd) keys.
  84. watchedKeys map[string]bool
  85. }
  86. // NewMetadataSubsManager returns a new MetadataSubsManager.
  87. func NewMetadataSubsManager() *MetadataSubsManager {
  88. var msm MetadataSubsManager
  89. msm.watchedKeys = make(map[string]bool)
  90. return &msm
  91. }
  92. // Sub subscribes to the given keys.
  93. func (msm *MetadataSubsManager) Sub(key ...string) {
  94. msm.Lock()
  95. defer msm.Unlock()
  96. for _, k := range key {
  97. msm.watchedKeys[k] = true
  98. }
  99. }
  100. // Unsub ubsubscribes from the given keys.
  101. func (msm *MetadataSubsManager) Unsub(key ...string) {
  102. msm.Lock()
  103. defer msm.Unlock()
  104. for _, k := range key {
  105. delete(msm.watchedKeys, k)
  106. }
  107. }
  108. // List returns a list of the currently-subbed keys.
  109. func (msm *MetadataSubsManager) List() []string {
  110. var keys []string
  111. msm.RLock()
  112. defer msm.RUnlock()
  113. for k := range msm.watchedKeys {
  114. keys = append(keys, k)
  115. }
  116. return keys
  117. }
  118. var (
  119. metadataValidChars = map[rune]bool{
  120. 'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true,
  121. 'h': true, 'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'o': true,
  122. 'p': true, 'q': true, 'r': true, 's': true, 't': true, 'u': true, 'v': true,
  123. 'w': true, 'x': true, 'y': true, 'z': true, '0': true, '1': true, '2': true,
  124. '3': true, '4': true, '5': true, '6': true, '7': true, '8': true, '9': true,
  125. '_': true, '-': true, '.': true, ':': true,
  126. }
  127. )
  128. // metadataKeyValid returns true if the given key is valid.
  129. func metadataKeyValid(key string) bool {
  130. // key length
  131. if len(key) < 1 {
  132. return false
  133. }
  134. // invalid first character for a key
  135. if key[0] == ':' {
  136. return false
  137. }
  138. // name characters
  139. for _, cha := range []rune(key) {
  140. if metadataValidChars[rune(cha)] == false {
  141. return false
  142. }
  143. }
  144. return true
  145. }
  146. var (
  147. metadataSubcommands = map[string]func(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool{
  148. "clear": metadataClearHandler,
  149. "get": metadataGetHandler,
  150. "list": metadataListHandler,
  151. "set": metadataSetHandler,
  152. "sub": metadataSubHandler,
  153. "subs": metadataSubsHandler,
  154. "sync": metadataSyncHandler,
  155. "unsub": metadataUnsubHandler,
  156. }
  157. )