onyxcord 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. checksums.yaml +7 -0
  2. data/.devcontainer/Dockerfile +13 -0
  3. data/.devcontainer/devcontainer.json +29 -0
  4. data/.devcontainer/postcreate.sh +4 -0
  5. data/.github/CONTRIBUTING.md +13 -0
  6. data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  7. data/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
  8. data/.github/pull_request_template.md +37 -0
  9. data/.github/workflows/ci.yml +78 -0
  10. data/.github/workflows/codeql.yml +65 -0
  11. data/.github/workflows/deploy.yml +54 -0
  12. data/.github/workflows/release.yml +51 -0
  13. data/.gitignore +16 -0
  14. data/.markdownlint.json +4 -0
  15. data/.overcommit.yml +7 -0
  16. data/.rspec +2 -0
  17. data/.rubocop.yml +129 -0
  18. data/.yardopts +1 -0
  19. data/CHANGELOG.md +0 -0
  20. data/Gemfile +7 -0
  21. data/LICENSE.txt +21 -0
  22. data/README.md +305 -0
  23. data/Rakefile +17 -0
  24. data/bin/console +15 -0
  25. data/bin/setup +7 -0
  26. data/lib/onyxcord/allowed_mentions.rb +43 -0
  27. data/lib/onyxcord/api/application.rb +316 -0
  28. data/lib/onyxcord/api/channel.rb +700 -0
  29. data/lib/onyxcord/api/interaction.rb +67 -0
  30. data/lib/onyxcord/api/invite.rb +44 -0
  31. data/lib/onyxcord/api/server.rb +775 -0
  32. data/lib/onyxcord/api/user.rb +158 -0
  33. data/lib/onyxcord/api/webhook.rb +163 -0
  34. data/lib/onyxcord/api.rb +335 -0
  35. data/lib/onyxcord/await.rb +51 -0
  36. data/lib/onyxcord/bot.rb +1971 -0
  37. data/lib/onyxcord/cache.rb +326 -0
  38. data/lib/onyxcord/colour_rgb.rb +43 -0
  39. data/lib/onyxcord/commands/command_bot.rb +511 -0
  40. data/lib/onyxcord/commands/container.rb +112 -0
  41. data/lib/onyxcord/commands/events.rb +11 -0
  42. data/lib/onyxcord/commands/parser.rb +327 -0
  43. data/lib/onyxcord/commands/rate_limiter.rb +144 -0
  44. data/lib/onyxcord/configuration.rb +125 -0
  45. data/lib/onyxcord/container.rb +988 -0
  46. data/lib/onyxcord/data/activity.rb +271 -0
  47. data/lib/onyxcord/data/application.rb +341 -0
  48. data/lib/onyxcord/data/attachment.rb +91 -0
  49. data/lib/onyxcord/data/audit_logs.rb +438 -0
  50. data/lib/onyxcord/data/avatar_decoration.rb +26 -0
  51. data/lib/onyxcord/data/call.rb +22 -0
  52. data/lib/onyxcord/data/channel.rb +1355 -0
  53. data/lib/onyxcord/data/channel_tag.rb +69 -0
  54. data/lib/onyxcord/data/collectibles.rb +47 -0
  55. data/lib/onyxcord/data/component.rb +583 -0
  56. data/lib/onyxcord/data/embed.rb +258 -0
  57. data/lib/onyxcord/data/emoji.rb +123 -0
  58. data/lib/onyxcord/data/install_params.rb +24 -0
  59. data/lib/onyxcord/data/integration.rb +144 -0
  60. data/lib/onyxcord/data/interaction.rb +1141 -0
  61. data/lib/onyxcord/data/invite.rb +137 -0
  62. data/lib/onyxcord/data/member.rb +528 -0
  63. data/lib/onyxcord/data/message.rb +612 -0
  64. data/lib/onyxcord/data/message_activity.rb +41 -0
  65. data/lib/onyxcord/data/overwrite.rb +109 -0
  66. data/lib/onyxcord/data/poll.rb +365 -0
  67. data/lib/onyxcord/data/primary_server.rb +60 -0
  68. data/lib/onyxcord/data/profile.rb +79 -0
  69. data/lib/onyxcord/data/reaction.rb +64 -0
  70. data/lib/onyxcord/data/recipient.rb +34 -0
  71. data/lib/onyxcord/data/role.rb +449 -0
  72. data/lib/onyxcord/data/role_connection_data.rb +69 -0
  73. data/lib/onyxcord/data/role_subscription.rb +41 -0
  74. data/lib/onyxcord/data/scheduled_event.rb +513 -0
  75. data/lib/onyxcord/data/server.rb +1614 -0
  76. data/lib/onyxcord/data/server_preview.rb +68 -0
  77. data/lib/onyxcord/data/snapshot.rb +112 -0
  78. data/lib/onyxcord/data/team.rb +98 -0
  79. data/lib/onyxcord/data/timestamp.rb +69 -0
  80. data/lib/onyxcord/data/user.rb +324 -0
  81. data/lib/onyxcord/data/voice_region.rb +46 -0
  82. data/lib/onyxcord/data/voice_state.rb +41 -0
  83. data/lib/onyxcord/data/webhook.rb +238 -0
  84. data/lib/onyxcord/data.rb +57 -0
  85. data/lib/onyxcord/errors.rb +246 -0
  86. data/lib/onyxcord/event_executor.rb +80 -0
  87. data/lib/onyxcord/events/await.rb +48 -0
  88. data/lib/onyxcord/events/bans.rb +60 -0
  89. data/lib/onyxcord/events/channels.rb +225 -0
  90. data/lib/onyxcord/events/generic.rb +129 -0
  91. data/lib/onyxcord/events/guilds.rb +269 -0
  92. data/lib/onyxcord/events/integrations.rb +100 -0
  93. data/lib/onyxcord/events/interactions.rb +624 -0
  94. data/lib/onyxcord/events/invites.rb +127 -0
  95. data/lib/onyxcord/events/lifetime.rb +31 -0
  96. data/lib/onyxcord/events/members.rb +110 -0
  97. data/lib/onyxcord/events/message.rb +399 -0
  98. data/lib/onyxcord/events/polls.rb +118 -0
  99. data/lib/onyxcord/events/presence.rb +131 -0
  100. data/lib/onyxcord/events/raw.rb +74 -0
  101. data/lib/onyxcord/events/reactions.rb +218 -0
  102. data/lib/onyxcord/events/roles.rb +87 -0
  103. data/lib/onyxcord/events/scheduled_events.rb +171 -0
  104. data/lib/onyxcord/events/threads.rb +100 -0
  105. data/lib/onyxcord/events/typing.rb +73 -0
  106. data/lib/onyxcord/events/voice_server_update.rb +48 -0
  107. data/lib/onyxcord/events/voice_state_update.rb +106 -0
  108. data/lib/onyxcord/events/webhooks.rb +65 -0
  109. data/lib/onyxcord/gateway.rb +890 -0
  110. data/lib/onyxcord/id_object.rb +39 -0
  111. data/lib/onyxcord/light/data.rb +62 -0
  112. data/lib/onyxcord/light/integrations.rb +73 -0
  113. data/lib/onyxcord/light/light_bot.rb +58 -0
  114. data/lib/onyxcord/light.rb +8 -0
  115. data/lib/onyxcord/logger.rb +120 -0
  116. data/lib/onyxcord/message_components.rb +70 -0
  117. data/lib/onyxcord/paginator.rb +60 -0
  118. data/lib/onyxcord/permissions.rb +255 -0
  119. data/lib/onyxcord/rate_limiter/gateway.rb +42 -0
  120. data/lib/onyxcord/rate_limiter/rest.rb +89 -0
  121. data/lib/onyxcord/version.rb +7 -0
  122. data/lib/onyxcord/voice/encoder.rb +115 -0
  123. data/lib/onyxcord/voice/network.rb +380 -0
  124. data/lib/onyxcord/voice/opcodes.rb +29 -0
  125. data/lib/onyxcord/voice/sodium.rb +157 -0
  126. data/lib/onyxcord/voice/timer.rb +19 -0
  127. data/lib/onyxcord/voice/voice_bot.rb +386 -0
  128. data/lib/onyxcord/webhooks.rb +14 -0
  129. data/lib/onyxcord/websocket.rb +62 -0
  130. data/lib/onyxcord.rb +180 -0
  131. data/onyxcord-webhooks.gemspec +30 -0
  132. data/onyxcord.gemspec +50 -0
  133. metadata +421 -0
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnyxCord
4
+ # Event execution strategies used by bot dispatch.
5
+ module EventExecutor
6
+ STOP = Object.new.freeze
7
+
8
+ # Deterministic executor useful for tests, benchmarks, and tiny bots.
9
+ class Inline
10
+ def post
11
+ yield
12
+ end
13
+
14
+ def shutdown; end
15
+
16
+ def threads
17
+ []
18
+ end
19
+ end
20
+
21
+ # Fixed-size worker pool for event handlers.
22
+ class Pool
23
+ attr_reader :threads
24
+
25
+ def initialize(size:)
26
+ raise ArgumentError, 'Pool size must be greater than zero' unless size.positive?
27
+
28
+ @queue = Queue.new
29
+ @closed = false
30
+ @threads = Array.new(size) do |index|
31
+ Thread.new do
32
+ Thread.current[:onyxcord_name] = "event-worker-#{index + 1}"
33
+ worker_loop
34
+ end
35
+ end
36
+ end
37
+
38
+ def post(&block)
39
+ raise ArgumentError, 'EventExecutor::Pool#post requires a block' unless block
40
+ raise 'Event executor has been shut down' if @closed
41
+
42
+ @queue << block
43
+ end
44
+
45
+ def shutdown
46
+ return if @closed
47
+
48
+ @closed = true
49
+ @threads.length.times { @queue << STOP }
50
+ @threads.each { |thread| thread.join unless thread == Thread.current }
51
+ end
52
+
53
+ private
54
+
55
+ def worker_loop
56
+ loop do
57
+ job = @queue.pop
58
+ break if job.equal?(STOP)
59
+
60
+ job.call
61
+ rescue StandardError => e
62
+ OnyxCord::LOGGER.log_exception(e) if defined?(OnyxCord::LOGGER)
63
+ end
64
+ end
65
+ end
66
+
67
+ module_function
68
+
69
+ def build(type, workers:)
70
+ case type
71
+ when :inline
72
+ Inline.new
73
+ when :pool
74
+ Pool.new(size: workers)
75
+ else
76
+ raise ArgumentError, "Unknown event executor: #{type.inspect}"
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'onyxcord/events/generic'
4
+ require 'onyxcord/await'
5
+
6
+ module OnyxCord::Events
7
+ # @see Bot#await
8
+ class AwaitEvent < Event
9
+ # The await that was triggered.
10
+ # @return [Await] The await
11
+ attr_reader :await
12
+
13
+ # The event that triggered the await.
14
+ # @return [Event] The event
15
+ attr_reader :event
16
+
17
+ # @!attribute [r] key
18
+ # @return [Symbol] the await's key.
19
+ # @see Await#key
20
+ # @!attribute [r] type
21
+ # @return [Class] the await's event class.
22
+ # @see Await#type
23
+ # @!attribute [r] attributes
24
+ # @return [Hash] a hash of attributes defined on the await.
25
+ # @see Await#attributes
26
+ delegate :key, :type, :attributes, to: :await
27
+
28
+ # @!visibility private
29
+ def initialize(await, event, bot)
30
+ @await = await
31
+ @event = event
32
+ @bot = bot
33
+ end
34
+ end
35
+
36
+ # Event handler for {AwaitEvent}
37
+ class AwaitEventHandler < EventHandler
38
+ def matches?(event)
39
+ # Check for the proper event type
40
+ return false unless event.is_a? AwaitEvent
41
+
42
+ [
43
+ matches_all(@attributes[:key], event.key) { |a, e| a == e },
44
+ matches_all(@attributes[:type], event.type) { |a, e| a == e }
45
+ ].reduce(true, &:&)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'onyxcord/events/generic'
4
+
5
+ module OnyxCord::Events
6
+ # Raised when a user is banned
7
+ class UserBanEvent < Event
8
+ # @return [User] the user that was banned
9
+ attr_reader :user
10
+
11
+ # @return [Server] the server from which the user was banned
12
+ attr_reader :server
13
+
14
+ # @!visibility private
15
+ def initialize(data, bot)
16
+ @user = bot.user(data['user']['id'].to_i)
17
+ @server = bot.server(data['guild_id'].to_i)
18
+ @bot = bot
19
+ end
20
+ end
21
+
22
+ # Event handler for {UserBanEvent}
23
+ class UserBanEventHandler < EventHandler
24
+ def matches?(event)
25
+ # Check for the proper event type
26
+ return false unless event.is_a? UserBanEvent
27
+
28
+ [
29
+ matches_all(@attributes[:user], event.user) do |a, e|
30
+ case a
31
+ when String
32
+ a == e.name
33
+ when Integer
34
+ a == e.id
35
+ when :bot
36
+ e.current_bot?
37
+ else
38
+ a == e
39
+ end
40
+ end,
41
+ matches_all(@attributes[:server], event.server) do |a, e|
42
+ a == case a
43
+ when String
44
+ e.name
45
+ when Integer
46
+ e.id
47
+ else
48
+ e
49
+ end
50
+ end
51
+ ].reduce(true, &:&)
52
+ end
53
+ end
54
+
55
+ # Raised when a user is unbanned from a server
56
+ class UserUnbanEvent < UserBanEvent; end
57
+
58
+ # Event handler for {UserUnbanEvent}
59
+ class UserUnbanEventHandler < UserBanEventHandler; end
60
+ end
@@ -0,0 +1,225 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'onyxcord/events/generic'
4
+ require 'onyxcord/data'
5
+
6
+ module OnyxCord::Events
7
+ # Raised when a channel is created
8
+ class ChannelCreateEvent < Event
9
+ # @return [Channel] the channel in question.
10
+ attr_reader :channel
11
+
12
+ # @!attribute [r] type
13
+ # @return [Integer] the channel's type (0: text, 1: private, 2: voice, 3: group).
14
+ # @see Channel#type
15
+ # @!attribute [r] topic
16
+ # @return [String] the channel's topic.
17
+ # @see Channel#topic
18
+ # @!attribute [r] position
19
+ # @return [Integer] the position of the channel in the channels list.
20
+ # @see Channel#position
21
+ # @!attribute [r] name
22
+ # @return [String] the channel's name
23
+ # @see Channel#name
24
+ # @!attribute [r] id
25
+ # @return [Integer] the channel's unique ID.
26
+ # @see Channel#id
27
+ # @!attribute [r] server
28
+ # @return [Server] the server the channel belongs to.
29
+ # @see Channel#server
30
+ delegate :name, :server, :type, :owner_id, :recipients, :topic, :user_limit, :position, :permission_overwrites, to: :channel
31
+
32
+ # @!visibility private
33
+ def initialize(data, bot)
34
+ @bot = bot
35
+ @channel = data.is_a?(OnyxCord::Channel) ? data : bot.channel(data['id'].to_i)
36
+ end
37
+ end
38
+
39
+ # Event handler for ChannelCreateEvent
40
+ class ChannelCreateEventHandler < EventHandler
41
+ def matches?(event)
42
+ # Check for the proper event type
43
+ return false unless event.is_a? ChannelCreateEvent
44
+
45
+ [
46
+ matches_all(@attributes[:type], event.type) do |a, e|
47
+ a == if a.is_a? String
48
+ e.name
49
+ else
50
+ e
51
+ end
52
+ end,
53
+ matches_all(@attributes[:name], event.name) do |a, e|
54
+ a == if a.is_a? String
55
+ e.to_s
56
+ else
57
+ e
58
+ end
59
+ end
60
+ ].reduce(true, &:&)
61
+ end
62
+ end
63
+
64
+ # Raised when a channel is deleted
65
+ class ChannelDeleteEvent < Event
66
+ # @return [Integer] the channel's type (0: text, 1: private, 2: voice, 3: group).
67
+ attr_reader :type
68
+
69
+ # @return [String] the channel's topic
70
+ attr_reader :topic
71
+
72
+ # @return [Integer] the position of the channel on the list
73
+ attr_reader :position
74
+
75
+ # @return [String] the channel's name
76
+ attr_reader :name
77
+
78
+ # @return [Integer] the channel's ID
79
+ attr_reader :id
80
+
81
+ # @return [Server] the channel's server
82
+ attr_reader :server
83
+
84
+ # @return [Integer, nil] the channel's owner ID if this is a group channel
85
+ attr_reader :owner_id
86
+
87
+ # @!visibility private
88
+ def initialize(data, bot)
89
+ @bot = bot
90
+
91
+ @type = data['type']
92
+ @topic = data['topic']
93
+ @position = data['position']
94
+ @name = data['name']
95
+ @is_private = data['is_private']
96
+ @id = data['id'].to_i
97
+ @server = bot.server(data['guild_id'].to_i) if data['guild_id']
98
+ @owner_id = bot.user(data['owner_id']) if @type == 3
99
+ end
100
+ end
101
+
102
+ # Event handler for ChannelDeleteEvent
103
+ class ChannelDeleteEventHandler < EventHandler
104
+ def matches?(event)
105
+ # Check for the proper event type
106
+ return false unless event.is_a? ChannelDeleteEvent
107
+
108
+ [
109
+ matches_all(@attributes[:type], event.type) do |a, e|
110
+ a == if a.is_a? String
111
+ e.name
112
+ else
113
+ e
114
+ end
115
+ end,
116
+ matches_all(@attributes[:name], event.name) do |a, e|
117
+ a == if a.is_a? String
118
+ e.to_s
119
+ else
120
+ e
121
+ end
122
+ end
123
+ ].reduce(true, &:&)
124
+ end
125
+ end
126
+
127
+ # Generic subclass for recipient events (add/remove)
128
+ class ChannelRecipientEvent < Event
129
+ # @return [Channel] the channel in question.
130
+ attr_reader :channel
131
+
132
+ delegate :name, :server, :type, :owner_id, :recipients, :topic, :user_limit, :position, :permission_overwrites, to: :channel
133
+
134
+ # @return [Recipient] the recipient that was added/removed from the group
135
+ attr_reader :recipient
136
+
137
+ delegate :id, to: :recipient
138
+
139
+ # @!visibility private
140
+ def initialize(data, bot)
141
+ @bot = bot
142
+
143
+ @channel = bot.channel(data['channel_id'].to_i)
144
+ recipient = data['user']
145
+ recipient_user = bot.ensure_user(recipient)
146
+ @recipient = OnyxCord::Recipient.new(recipient_user, @channel, bot)
147
+ end
148
+ end
149
+
150
+ # Generic event handler for channel recipient events
151
+ class ChannelRecipientEventHandler < EventHandler
152
+ def matches?(event)
153
+ # Check for the proper event type
154
+ return false unless event.is_a? ChannelRecipientEvent
155
+
156
+ [
157
+ matches_all(@attributes[:owner_id], event.owner_id) do |a, e|
158
+ a.resolve_id == e.resolve_id
159
+ end,
160
+ matches_all(@attributes[:id], event.id) do |a, e|
161
+ a.resolve_id == e.resolve_id
162
+ end,
163
+ matches_all(@attributes[:name], event.name) do |a, e|
164
+ a == if a.is_a? String
165
+ e.to_s
166
+ else
167
+ e
168
+ end
169
+ end
170
+ ]
171
+ end
172
+ end
173
+
174
+ # Raised when a message is pinned or unpinned.
175
+ class ChannelPinsUpdateEvent < Event
176
+ # @return [Time, nil] Time at which the most recent pinned message was pinned.
177
+ attr_reader :last_pin_timestamp
178
+
179
+ # @return [Channel] The channel this event originates from.
180
+ attr_reader :channel
181
+
182
+ # @return [Server, nil] The server this event originates from.
183
+ attr_reader :server
184
+
185
+ # @!visibility private
186
+ def initialize(data, bot)
187
+ @bot = bot
188
+
189
+ @server = bot.server(data['guild_id']) if data['guild_id']
190
+ @channel = bot.channel(data['channel_id'])
191
+ @last_pin_timestamp = Time.iso8601(data['last_pin_timestamp']) if data['last_pin_timestamp']
192
+ end
193
+ end
194
+
195
+ # Event handler for ChannelPinsUpdateEvent.
196
+ class ChannelPinsUpdateEventHandler < EventHandler
197
+ def matches?(event)
198
+ # Check for the proper event type.
199
+ return false unless event.is_a? ChannelPinsUpdateEvent
200
+
201
+ [
202
+ matches_all(@attributes[:server], event.server) { |a, e| a.resolve_id == e&.id },
203
+ matches_all(@attributes[:channel], event.channel) { |a, e| a.resolve_id == e.id }
204
+ ].reduce(true, &:&)
205
+ end
206
+ end
207
+
208
+ # Raised when a user is added to a private channel
209
+ class ChannelRecipientAddEvent < ChannelRecipientEvent; end
210
+
211
+ # Event handler for ChannelRecipientAddEvent
212
+ class ChannelRecipientAddEventHandler < ChannelRecipientEventHandler; end
213
+
214
+ # Raised when a recipient that isn't the bot leaves or is kicked from a group channel
215
+ class ChannelRecipientRemoveEvent < ChannelRecipientEvent; end
216
+
217
+ # Event handler for ChannelRecipientRemoveEvent
218
+ class ChannelRecipientRemoveEventHandler < ChannelRecipientEventHandler; end
219
+
220
+ # Raised when a channel is updated (e.g. topic changes)
221
+ class ChannelUpdateEvent < ChannelCreateEvent; end
222
+
223
+ # Event handler for ChannelUpdateEvent
224
+ class ChannelUpdateEventHandler < ChannelCreateEventHandler; end
225
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Events used by onyxcord
4
+ module OnyxCord::Events
5
+ # A negated object, used to not match something in event parameters.
6
+ # @see OnyxCord::Events.matches_all
7
+ class Negated
8
+ attr_reader :object
9
+
10
+ # @!visibility private
11
+ def initialize(object)
12
+ @object = object
13
+ end
14
+ end
15
+
16
+ # Attempts to match possible formats of event attributes to a set comparison value, using a comparison block.
17
+ # It allows five kinds of attribute formats:
18
+ # 0. nil -> always returns true
19
+ # 1. A single attribute, not negated
20
+ # 2. A single attribute, negated
21
+ # 3. An array of attributes, not negated
22
+ # 4. An array of attributes, not negated
23
+ # Note that it doesn't allow an array of negated attributes. For info on negation stuff, see {::#not!}
24
+ # @param attributes [Object, Array<Object>, Negated<Object>, Negated<Array<Object>>, nil] One or more attributes to
25
+ # compare to the to_check value.
26
+ # @param to_check [Object] What to compare the attributes to.
27
+ # @yield [a, e] The block will be called when a comparison happens.
28
+ # @yieldparam [Object] a The attribute to compare to the value to check. Will always be a single not-negated object,
29
+ # all the negation and array handling is done by the method
30
+ # @yieldparam [Object] e The value to compare the attribute to. Will always be the value passed to the function as
31
+ # to_check.
32
+ # @yieldreturn [true, false] Whether or not the attribute a matches the given comparison value e.
33
+ # @return [true, false] whether the attributes match the comparison value in at least one way.
34
+ def self.matches_all(attributes, to_check, &block)
35
+ # "Zeroth" case: attributes is nil
36
+ return true if attributes.nil?
37
+
38
+ # First case: there's a single negated attribute
39
+ if attributes.is_a? Negated
40
+ # The contained object might also be an array, so recursively call matches_all (and negate the result)
41
+ return !matches_all(attributes.object, to_check, &block)
42
+ end
43
+
44
+ # Second case: there's a single, not-negated attribute
45
+ return yield(attributes, to_check) unless attributes.is_a? Array
46
+
47
+ # Third case: it's an array of attributes
48
+ attributes.reduce(false) do |result, element|
49
+ result || yield(element, to_check)
50
+ end
51
+ end
52
+
53
+ # Generic event class that can be extended
54
+ class Event
55
+ # @return [Bot] the bot used to initialize this event.
56
+ attr_reader :bot
57
+
58
+ class << self
59
+ protected
60
+
61
+ # Delegates a list of methods to a particular object. This is essentially a reimplementation of ActiveSupport's
62
+ # `#delegate`, but without the overhead provided by the rest. Used in subclasses of `Event` to delegate properties
63
+ # on events to properties on data objects.
64
+ # @param methods [Array<Symbol>] The methods to delegate.
65
+ # @param hash [Hash<Symbol => Symbol>] A hash with one `:to` key and the value the method to be delegated to.
66
+ def delegate(*methods, hash)
67
+ methods.each do |e|
68
+ define_method(e) do
69
+ object = __send__(hash[:to])
70
+ object.__send__(e)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ # Generic event handler that can be extended
78
+ class EventHandler
79
+ # @!visibility private
80
+ def initialize(attributes, block)
81
+ @attributes = attributes
82
+ @block = block
83
+ end
84
+
85
+ # Whether or not this event handler matches the given event with its attributes.
86
+ # @raise [RuntimeError] if this method is called - overwrite it in your event handler!
87
+ def matches?(_)
88
+ raise 'Attempted to call matches?() from a generic EventHandler'
89
+ end
90
+
91
+ # Checks whether this handler matches the given event, and then calls it.
92
+ # @param event [Object] The event object to match and call the handler with
93
+ def match(event)
94
+ call(event) if matches? event
95
+ end
96
+
97
+ # Calls this handler
98
+ # @param event [Object] The event object to call this handler with
99
+ def call(event)
100
+ @block.call(event)
101
+ end
102
+
103
+ # to be overwritten by extending event handlers
104
+ def after_call(event); end
105
+
106
+ # @see OnyxCord::Events::matches_all
107
+ def matches_all(attributes, to_check, &block)
108
+ OnyxCord::Events.matches_all(attributes, to_check, &block)
109
+ end
110
+ end
111
+
112
+ # Event handler that matches all events. Only useful for making an event that has no attributes, such as {ReadyEvent}.
113
+ class TrueEventHandler < EventHandler
114
+ # Always returns true.
115
+ # @return [true]
116
+ def matches?(_)
117
+ true
118
+ end
119
+ end
120
+ end
121
+
122
+ # Utility function that creates a negated object for {OnyxCord::Events.matches_all}
123
+ # @param [Object] object The object to negate
124
+ # @see OnyxCord::Events::Negated
125
+ # @see OnyxCord::Events.matches_all
126
+ # @return [Negated<Object>] the object, negated, as an attribute to pass to matches_all
127
+ def not!(object)
128
+ OnyxCord::Events::Negated.new(object)
129
+ end