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.

216 lines
4.9 KiB

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