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.

245 lines
5.7 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. package irc
  2. import (
  3. "context"
  4. "encoding/json"
  5. "time"
  6. )
  7. // An Event is any thing that passes through the irc client's event loop. It's not thread safe, because it's processed
  8. // in sequence and should not be used off the goroutine that processed it.
  9. type Event struct {
  10. kind string
  11. verb string
  12. name string
  13. Time time.Time
  14. Nick string
  15. User string
  16. Host string
  17. Args []string
  18. Text string
  19. Tags map[string]string
  20. RenderTags map[string]string
  21. ctx context.Context
  22. cancel context.CancelFunc
  23. preventedDefault bool
  24. hidden bool
  25. targets []Target
  26. }
  27. // NewEvent makes a new event with Kind, Verb, Time set and Args and Tags initialized.
  28. func NewEvent(kind, verb string) Event {
  29. return Event{
  30. kind: kind,
  31. verb: verb,
  32. name: kind + "." + verb,
  33. Time: time.Now(),
  34. Args: make([]string, 0, 4),
  35. Tags: make(map[string]string),
  36. RenderTags: make(map[string]string),
  37. }
  38. }
  39. // Kind gets the event's kind
  40. func (event *Event) Kind() string {
  41. return event.kind
  42. }
  43. // Verb gets the event's verb
  44. func (event *Event) Verb() string {
  45. return event.verb
  46. }
  47. // Name gets the event name, which is Kind and Verb separated by a dot.
  48. func (event *Event) Name() string {
  49. return event.name
  50. }
  51. // IsEither returns true if the event has the kind and one of the verbs.
  52. func (event *Event) IsEither(kind string, verbs ...string) bool {
  53. if event.kind != kind {
  54. return false
  55. }
  56. for i := range verbs {
  57. if event.verb == verbs[i] {
  58. return true
  59. }
  60. }
  61. return false
  62. }
  63. // Context gets the event's context if it's part of the loop, or `context.Background` otherwise. client.Emit
  64. // will set this context on its copy and return it.
  65. func (event *Event) Context() context.Context {
  66. if event.ctx == nil {
  67. return context.Background()
  68. }
  69. return event.ctx
  70. }
  71. // PreventDefault stops propagation of the event. The context will be killed once
  72. // the current event handler returns.
  73. //
  74. // A use case for this is to prevent the default input handler from firing
  75. // on an already processed input event.
  76. func (event *Event) PreventDefault() {
  77. event.preventedDefault = true
  78. }
  79. // Hide will not stop propagation, but it will allow output handlers to know not to
  80. // render it.
  81. func (event *Event) Hide() {
  82. event.hidden = true
  83. }
  84. // Hidden returns true if Hide has been called.
  85. func (event *Event) Hidden() bool {
  86. return event.hidden
  87. }
  88. // Arg gets the argument by index, counting the trailing as the last argument. The rationale
  89. // behind it is that some servers may use it for the last argument in JOINs and such.
  90. func (event *Event) Arg(index int) string {
  91. if index < 0 || index > len(event.Args) {
  92. return ""
  93. }
  94. if index == len(event.Args) {
  95. return event.Text
  96. }
  97. return event.Args[index]
  98. }
  99. // Target finds the first target with one of the kinds specified. If none
  100. // are specified, the first target will be returned. If more than one
  101. // is provided, the first kinds are prioritized.
  102. func (event *Event) Target(kinds ...string) Target {
  103. if len(event.targets) == 0 {
  104. return nil
  105. }
  106. if len(kinds) == 0 || kinds[0] == "" {
  107. return event.targets[0]
  108. }
  109. for _, kind := range kinds {
  110. for _, target := range event.targets {
  111. if target.Kind() == kind {
  112. return target
  113. }
  114. }
  115. }
  116. return nil
  117. }
  118. // ChannelTarget gets the first channel target.
  119. func (event *Event) ChannelTarget() *Channel {
  120. target := event.Target("channel")
  121. if target == nil {
  122. return nil
  123. }
  124. return target.(*Channel)
  125. }
  126. // QueryTarget gets the first query target.
  127. func (event *Event) QueryTarget() *Query {
  128. target := event.Target("query")
  129. if target == nil {
  130. return nil
  131. }
  132. return target.(*Query)
  133. }
  134. // StatusTarget gets the first status target.
  135. func (event *Event) StatusTarget() *Status {
  136. target := event.Target("status")
  137. if target == nil {
  138. return nil
  139. }
  140. return target.(*Status)
  141. }
  142. func (event *Event) TargetIDs() []string {
  143. ids := make([]string, len(event.targets))
  144. for _, target := range event.targets {
  145. ids = append(ids, target.ID())
  146. }
  147. return ids
  148. }
  149. // MarshalJSON makes a JSON object from the event.
  150. func (event *Event) MarshalJSON() ([]byte, error) {
  151. data := eventJSONData{
  152. Name: event.Name(),
  153. Kind: event.kind,
  154. Verb: event.verb,
  155. Time: event.Time,
  156. Nick: event.Nick,
  157. User: event.User,
  158. Host: event.Host,
  159. Args: event.Args,
  160. Text: event.Text,
  161. Tags: event.Tags,
  162. RenderTags: event.RenderTags,
  163. }
  164. data.Targets = make([]string, 0, len(event.targets))
  165. for _, target := range event.targets {
  166. data.Targets = append(data.Targets, target.ID())
  167. }
  168. return json.Marshal(data)
  169. }
  170. func (event *Event) Copy() *Event {
  171. eventCopy := *event
  172. if len(event.Args) > 0 {
  173. eventCopy.Args = append(event.Args[:0:0], event.Args...)
  174. }
  175. if len(event.Tags) > 0 {
  176. eventCopy.Tags = make(map[string]string, len(event.Tags))
  177. for key, value := range event.Tags {
  178. eventCopy.Tags[key] = value
  179. }
  180. }
  181. if len(event.RenderTags) > 0 {
  182. eventCopy.RenderTags = make(map[string]string, len(event.RenderTags))
  183. for key, value := range event.RenderTags {
  184. eventCopy.RenderTags[key] = value
  185. }
  186. }
  187. if len(event.targets) > 0 {
  188. eventCopy.targets = append(event.targets[:0:0], event.targets...)
  189. }
  190. return &eventCopy
  191. }
  192. type eventJSONData struct {
  193. Name string `json:"name"`
  194. Kind string `json:"kind"`
  195. Verb string `json:"verb"`
  196. Time time.Time `json:"time"`
  197. Nick string `json:"nick"`
  198. User string `json:"user"`
  199. Host string `json:"host"`
  200. Args []string `json:"args"`
  201. Text string `json:"text"`
  202. Tags map[string]string `json:"tags"`
  203. Targets []string `json:"targets"`
  204. RenderTags map[string]string `json:"renderTags"`
  205. }