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,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnyxCord
4
+ # An attachment to a message
5
+ class Attachment
6
+ include IDObject
7
+
8
+ # @return [String] the CDN URL this attachment can be downloaded at.
9
+ attr_reader :url
10
+
11
+ # @return [String] the attachment's proxy URL - I'm not sure what exactly this does, but I think it has something to
12
+ # do with CDNs.
13
+ attr_reader :proxy_url
14
+
15
+ # @return [String] the attachment's filename.
16
+ attr_reader :filename
17
+
18
+ # @return [Integer] the attachment's file size in bytes.
19
+ attr_reader :size
20
+
21
+ # @return [Integer, nil] the width of an image file, in pixels, or `nil` if the file is not an image.
22
+ attr_reader :width
23
+
24
+ # @return [Integer, nil] the height of an image file, in pixels, or `nil` if the file is not an image.
25
+ attr_reader :height
26
+
27
+ # @return [String, nil] the attachment's description.
28
+ attr_reader :description
29
+
30
+ # @return [String, nil] the attachment's media type.
31
+ attr_reader :content_type
32
+
33
+ # @return [true, false] whether this attachment is ephemeral.
34
+ attr_reader :ephemeral
35
+ alias_method :ephemeral?, :ephemeral
36
+
37
+ # @return [Float, nil] the duration of the voice message in seconds.
38
+ attr_reader :duration_seconds
39
+
40
+ # @return [String, nil] the base64 encoded bytearray representing a sampled waveform for a voice message.
41
+ attr_reader :waveform
42
+
43
+ # @return [Integer] the flags set on this attachment combined as a bitfield.
44
+ attr_reader :flags
45
+
46
+ # @!visibility private
47
+ def initialize(data, message, bot)
48
+ @bot = bot
49
+ @message = message
50
+
51
+ @id = data['id'].to_i
52
+ @url = data['url']
53
+ @proxy_url = data['proxy_url']
54
+ @filename = data['filename']
55
+
56
+ @size = data['size']
57
+
58
+ @width = data['width']
59
+ @height = data['height']
60
+
61
+ @description = data['description']
62
+ @content_type = data['content_type']
63
+
64
+ @ephemeral = data['ephemeral']
65
+
66
+ @duration_seconds = data['duration_secs']&.to_f
67
+ @waveform = data['waveform']
68
+ @flags = data['flags'] || 0
69
+ end
70
+
71
+ # @return [true, false] whether this file is an image file.
72
+ def image?
73
+ !(@width.nil? || @height.nil?)
74
+ end
75
+
76
+ # @return [true, false] whether this file is tagged as a spoiler.
77
+ def spoiler?
78
+ @filename.start_with? 'SPOILER_'
79
+ end
80
+
81
+ # @return [Message, nil] the message this attachment object belongs to.
82
+ def message
83
+ @message unless @message.is_a?(Snapshot)
84
+ end
85
+
86
+ # @return [Snapshot, nil] the message snapshot this attachment object belongs to.
87
+ def snapshot
88
+ @message unless @message.is_a?(Message)
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,438 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnyxCord
4
+ # A server's audit logs
5
+ class AuditLogs
6
+ # The numbers associated with the type of action.
7
+ ACTIONS = {
8
+ 1 => :server_update,
9
+ 10 => :channel_create,
10
+ 11 => :channel_update,
11
+ 12 => :channel_delete,
12
+ 13 => :channel_overwrite_create,
13
+ 14 => :channel_overwrite_update,
14
+ 15 => :channel_overwrite_delete,
15
+ 20 => :member_kick,
16
+ 21 => :member_prune,
17
+ 22 => :member_ban_add,
18
+ 23 => :member_ban_remove,
19
+ 24 => :member_update,
20
+ 25 => :member_role_update,
21
+ 26 => :member_move,
22
+ 27 => :member_disconnect,
23
+ 28 => :bot_add,
24
+ 30 => :role_create,
25
+ 31 => :role_update,
26
+ 32 => :role_delete,
27
+ 40 => :invite_create,
28
+ 41 => :invite_update,
29
+ 42 => :invite_delete,
30
+ 50 => :webhook_create,
31
+ 51 => :webhook_update,
32
+ 52 => :webhook_delete,
33
+ 60 => :emoji_create,
34
+ 61 => :emoji_update,
35
+ 62 => :emoji_delete,
36
+ # 70
37
+ # 71
38
+ 72 => :message_delete,
39
+ 73 => :message_bulk_delete,
40
+ 74 => :message_pin,
41
+ 75 => :message_unpin,
42
+ 80 => :integration_create,
43
+ 81 => :integration_update,
44
+ 82 => :integration_delete,
45
+ 83 => :stage_instance_create,
46
+ 84 => :stage_instance_update,
47
+ 85 => :stage_instance_delete,
48
+ 90 => :sticker_create,
49
+ 91 => :sticker_update,
50
+ 92 => :sticker_delete,
51
+ 100 => :scheduled_event_create,
52
+ 101 => :scheduled_event_update,
53
+ 102 => :scheduled_event_delete,
54
+ 110 => :thread_create,
55
+ 111 => :thread_update,
56
+ 112 => :thread_delete,
57
+ 121 => :application_command_permission_update,
58
+ 130 => :soundboard_sound_create,
59
+ 131 => :soundboard_sound_update,
60
+ 132 => :soundboard_sound_delete,
61
+ 140 => :auto_moderation_rule_create,
62
+ 141 => :auto_moderation_rule_update,
63
+ 142 => :auto_moderation_rule_delete,
64
+ 143 => :auto_moderation_block_message,
65
+ 144 => :auto_moderation_flag_to_channel,
66
+ 145 => :auto_moderation_user_communication_disabled,
67
+ 146 => :auto_moderation_quarantine_user,
68
+ 150 => :creator_monetization_request_created,
69
+ 151 => :creator_monetization_terms_accepted,
70
+ 163 => :onboarding_prompt_create,
71
+ 164 => :onboarding_prompt_update,
72
+ 165 => :onboarding_prompt_delete,
73
+ 166 => :onboarding_create,
74
+ 167 => :onboarding_update,
75
+ 190 => :home_settings_create,
76
+ 191 => :home_settings_update
77
+ }.freeze
78
+
79
+ # @!visibility private
80
+ CREATE_ACTIONS = %i[
81
+ channel_create channel_overwrite_create member_ban_add role_create
82
+ invite_create webhook_create emoji_create integration_create
83
+ stage_instance_create sticker_create scheduled_event_create thread_create
84
+ soundboard_sound_create auto_moderation_rule_create onboarding_prompt_create
85
+ onboarding_create home_settings_create creator_monetization_request_created
86
+ message_pin auto_moderation_flag_to_channel
87
+ ].freeze
88
+
89
+ # @!visibility private
90
+ DELETE_ACTIONS = %i[
91
+ channel_delete channel_overwrite_delete member_kick member_prune
92
+ member_ban_remove role_delete invite_delete webhook_delete
93
+ emoji_delete message_delete message_bulk_delete integration_delete
94
+ stage_instance_delete sticker_delete scheduled_event_delete
95
+ thread_delete soundboard_sound_delete auto_moderation_rule_delete
96
+ onboarding_prompt_delete message_unpin auto_moderation_block_message
97
+ ].freeze
98
+
99
+ # @!visibility private
100
+ UPDATE_ACTIONS = %i[
101
+ server_update channel_update channel_overwrite_update member_update
102
+ member_role_update role_update invite_update webhook_update
103
+ emoji_update integration_update stage_instance_update sticker_update
104
+ scheduled_event_update thread_update application_command_permission_update
105
+ soundboard_sound_update auto_moderation_rule_update onboarding_prompt_update
106
+ onboarding_update home_settings_update creator_monetization_terms_accepted
107
+ auto_moderation_user_communication_disabled auto_moderation_quarantine_user
108
+ ].freeze
109
+
110
+ # @return [Hash<String => User>] the users included in the audit logs.
111
+ attr_reader :users
112
+
113
+ # @return [Hash<String => Webhook>] the webhooks included in the audit logs.
114
+ attr_reader :webhooks
115
+
116
+ # @return [Array<Entry>] the entries listed in the audit logs.
117
+ attr_reader :entries
118
+
119
+ # @!visibility private
120
+ def initialize(server, bot, data)
121
+ @bot = bot
122
+ @server = server
123
+ @users = {}
124
+ @webhooks = {}
125
+ @entries = data['audit_log_entries'].map { |entry| Entry.new(self, @server, @bot, entry) }
126
+
127
+ process_users(data['users'])
128
+ process_webhooks(data['webhooks'])
129
+ end
130
+
131
+ # An entry in a server's audit logs.
132
+ class Entry
133
+ include IDObject
134
+
135
+ # @return [Symbol] the action that was performed.
136
+ attr_reader :action
137
+
138
+ # @return [Symbol] the type action that was performed. (:create, :delete, :update, :unknown)
139
+ attr_reader :action_type
140
+
141
+ # @return [Symbol] the type of target being performed on. (:server, :channel, :user, :role, :invite, :webhook, :emoji, :unknown)
142
+ attr_reader :target_type
143
+
144
+ # @return [Integer, nil] the amount of messages deleted. Only present if the action is `:message_delete`.
145
+ attr_reader :count
146
+ alias_method :amount, :count
147
+
148
+ # @return [Integer, nil] the amount of days the members were inactive for. Only present if the action is `:member_prune`.
149
+ attr_reader :days
150
+
151
+ # @return [Integer, nil] the amount of members removed. Only present if the action is `:member_prune`.
152
+ attr_reader :members_removed
153
+
154
+ # @return [Integer, nil] the ID of the message that was pinned or unpinned.
155
+ attr_reader :message_id
156
+
157
+ # @return [String, nil] the type of the integration that updated the member's roles, or kicked the member.
158
+ attr_reader :integration_type
159
+
160
+ # @return [Integer, nil] the ID of the application whose application command permissions were updated.
161
+ attr_reader :application_id
162
+
163
+ # @return [String, nil] the name of the auto moderation rule that was triggered.
164
+ attr_reader :automod_rule_name
165
+
166
+ # @return [Integer, nil] the trigger type of the auto moderation rules that was triggered.
167
+ attr_reader :automod_rule_trigger_type
168
+
169
+ # @return [String, nil] the name of the role associated with the permission overwrite.
170
+ attr_reader :overwrite_role_name
171
+
172
+ # @return [Integer, nil] the ID of the permission overwrite.
173
+ attr_reader :overwrite_id
174
+
175
+ # @return [Symbol, nil] the type of the permission overwrite.
176
+ attr_reader :overwrite_type
177
+
178
+ # @return [String, nil] the reason for this action occurring.
179
+ attr_reader :reason
180
+
181
+ # @return [Hash<String => Change>, RoleChange, nil] the changes from this log, listing the key as the key changed. Will be a RoleChange object if the action is `:member_role_update`. Will be nil if the action is either `:message_delete` or `:member_prune`.
182
+ attr_reader :changes
183
+
184
+ # @!visibility private
185
+ def initialize(logs, server, bot, data)
186
+ @bot = bot
187
+ @id = data['id'].to_i
188
+ @logs = logs
189
+ @server = server
190
+ @data = data
191
+ @action = ACTIONS[data['action_type']]
192
+ @reason = data['reason']
193
+ @action_type = AuditLogs.action_type_for(data['action_type'])
194
+ @target_type = AuditLogs.target_type_for(data['action_type'])
195
+
196
+ # Sets the 'changes' variable to a empty hash if there are no special actions.
197
+ @changes = {} unless @action == :message_delete || @action == :member_prune || @action == :member_role_update
198
+
199
+ # Sets the 'changes' variable to a RoleChange class if there's a role update.
200
+ @changes = RoleChange.new(data['changes'][0], @server) if @action == :member_role_update
201
+
202
+ process_changes(data['changes']) unless @action == :member_role_update
203
+ return unless (options = data['options'])
204
+
205
+ # https://docs.discord.com/developers/resources/audit-log#audit-log-entry-object-optional-audit-entry-info
206
+ @count = options['count']&.to_i
207
+ @channel_id = options['channel_id']&.to_i
208
+ @days = options['delete_member_days']&.to_i
209
+ @members_removed = options['members_removed']&.to_i
210
+ @message_id = options['message_id']&.to_i
211
+ @integration_type = options['integration_type']
212
+ @application_id = options['application_id']&.to_i
213
+ @automod_rule_name = options['auto_moderation_rule_name']
214
+ @automod_rule_trigger_type = options['auto_moderation_rule_trigger_type']
215
+ @overwrite_role_name = options['role_name']
216
+ @overwrite_id = options['id']&.to_i
217
+ @overwrite_type = Overwrite::TYPES.key(options['type']) if options['type']
218
+ end
219
+
220
+ # @return [Server, Channel, Member, User, Role, Invite, Webhook, Emoji, nil] the target being performed on.
221
+ def target
222
+ @target ||= process_target(@data['target_id'], @target_type)
223
+ end
224
+
225
+ # @return [Member, User] the user that authored this action. Can be a User object if the user no longer exists in the server.
226
+ def user
227
+ @user ||= @server.member(@data['user_id'].to_i) || @bot.user(@data['user_id'].to_i) || @logs&.user(@data['user_id'].to_i)
228
+ end
229
+
230
+ alias_method :author, :user
231
+
232
+ # @return [Channel, nil] the channel associated with the audit log event.
233
+ def channel
234
+ return nil unless @channel_id
235
+
236
+ @channel ||= @bot.channel(@channel_id)
237
+ end
238
+
239
+ # @return [Message, nil] the message that was pinned or un-pinned.
240
+ def message
241
+ channel.load_message(@message_id) if @message_id
242
+ end
243
+
244
+ # @!visibility private
245
+ def process_target(id, type)
246
+ id = id.resolve_id unless id.nil?
247
+ case type
248
+ when :server then @server # Since it won't be anything else
249
+ when :channel then @bot.channel(id, @server)
250
+ when :user, :message then @server.member(id) || @bot.user(id) || @logs&.user(id)
251
+ when :role then @server.role(id)
252
+ when :invite then @bot.invite(@data['changes'].find { |change| change['key'] == 'code' }.values.delete_if { |v| v == 'code' }.first)
253
+ when :webhook then @server.webhooks.find { |webhook| webhook.id == id } || @logs&.webhook(id)
254
+ when :emoji then @server.emoji[id]
255
+ when :integration then @server.integrations.find { |integration| integration.id == id }
256
+ end
257
+ end
258
+
259
+ # The inspect method is overwritten to give more useful output
260
+ def inspect
261
+ "<AuditLogs::Entry id=#{@id} key=#{@key} action=#{@action} reason=#{@reason} action_type=#{@action_type} target_type=#{@target_type} count=#{@count} days=#{@days} members_removed=#{@members_removed}>"
262
+ end
263
+
264
+ # Process action changes
265
+ # @note For internal use only
266
+ # @!visibility private
267
+ def process_changes(changes)
268
+ return unless changes
269
+
270
+ changes.each do |element|
271
+ change = Change.new(element, @server, @bot, self)
272
+ @changes[change.key] = change
273
+ end
274
+ end
275
+ end
276
+
277
+ # A change in a audit log entry.
278
+ class Change
279
+ # @return [String] the key that was changed.
280
+ # @note You should check with the Discord API Documentation on what key gives out what value.
281
+ attr_reader :key
282
+
283
+ # @return [String, Integer, true, false, Permissions, Overwrite, nil] the value that was changed from.
284
+ attr_reader :old
285
+ alias_method :old_value, :old
286
+
287
+ # @return [String, Integer, true, false, Permissions, Overwrite, nil] the value that was changed to.
288
+ attr_reader :new
289
+ alias_method :new_value, :new
290
+
291
+ # @!visibility private
292
+ def initialize(data, server, bot, logs)
293
+ @key = data['key']
294
+ @old = data['old_value']
295
+ @new = data['new_value']
296
+ @server = server
297
+ @bot = bot
298
+ @logs = logs
299
+
300
+ @old = Permissions.new(@old) if @old && @key == 'permissions'
301
+ @new = Permissions.new(@new) if @new && @key == 'permissions'
302
+
303
+ @old = @old.map { |o| Overwrite.new(o['id'], type: o['type'], allow: o['allow'], deny: o['deny']) } if @old && @key == 'permission_overwrites'
304
+ @new = @new.map { |o| Overwrite.new(o['id'], type: o['type'], allow: o['allow'], deny: o['deny']) } if @new && @key == 'permission_overwrites'
305
+ end
306
+
307
+ # @return [Channel, nil] the channel that was previously used in the server widget. Only present if the key for this change is `widget_channel_id`.
308
+ def old_widget_channel
309
+ @bot.channel(@old, @server) if @old && @key == 'widget_channel_id'
310
+ end
311
+
312
+ # @return [Channel, nil] the channel that is used in the server widget prior to this change. Only present if the key for this change is `widget_channel_id`.
313
+ def new_widget_channel
314
+ @bot.channel(@new, @server) if @new && @key == 'widget_channel_id'
315
+ end
316
+
317
+ # @return [Channel, nil] the channel that was previously used in the server as an AFK channel. Only present if the key for this change is `afk_channel_id`.
318
+ def old_afk_channel
319
+ @bot.channel(@old, @server) if @old && @key == 'afk_channel_id'
320
+ end
321
+
322
+ # @return [Channel, nil] the channel that is used in the server as an AFK channel prior to this change. Only present if the key for this change is `afk_channel_id`.
323
+ def new_afk_channel
324
+ @bot.channel(@new, @server) if @new && @key == 'afk_channel_id'
325
+ end
326
+
327
+ # @return [Member, User, nil] the member that used to be the owner of the server. Only present if the for key for this change is `owner_id`.
328
+ def old_owner
329
+ @server.member(@old) || @bot.user(@old) || @logs&.user(@old) if @old && @key == 'owner_id'
330
+ end
331
+
332
+ # @return [Member, User, nil] the member that is now the owner of the server prior to this change. Only present if the key for this change is `owner_id`.
333
+ def new_owner
334
+ @server.member(@new) || @bot.user(@new) || @logs&.user(@new) if @new && @key == 'owner_id'
335
+ end
336
+ end
337
+
338
+ # A change that includes roles.
339
+ class RoleChange
340
+ # @return [Symbol] what type of change this is: (:add, :remove)
341
+ attr_reader :type
342
+
343
+ # @!visibility private
344
+ def initialize(data, server)
345
+ @type = data['key'].delete('$').to_sym
346
+ @role_id = data['new_value'][0]['id'].to_i
347
+ @server = server
348
+ end
349
+
350
+ # @return [Role] the role being used.
351
+ def role
352
+ @role ||= @server.role(@role_id)
353
+ end
354
+ end
355
+
356
+ # @return [Entry] the latest entry in the audit logs.
357
+ def latest
358
+ @entries.first
359
+ end
360
+ alias_method :first, :latest
361
+
362
+ # Gets a user in the audit logs data based on user ID
363
+ # @note This only uses data given by the audit logs request
364
+ # @param id [String, Integer] The user ID to look for
365
+ def user(id)
366
+ @users[id.resolve_id]
367
+ end
368
+
369
+ # Gets a webhook in the audit logs data based on webhook ID
370
+ # @note This only uses data given by the audit logs request
371
+ # @param id [String, Integer] The webhook ID to look for
372
+ def webhook(id)
373
+ @webhooks[id.resolve_id]
374
+ end
375
+
376
+ # Process user objects given by the request
377
+ # @note For internal use only
378
+ # @!visibility private
379
+ def process_users(users)
380
+ users.each do |element|
381
+ user = @bot.ensure_user(element)
382
+ @users[user.id] = user
383
+ end
384
+ end
385
+
386
+ # Process webhook objects given by the request
387
+ # @note For internal use only
388
+ # @!visibility private
389
+ def process_webhooks(webhooks)
390
+ webhooks.each do |element|
391
+ webhook = Webhook.new(element, @bot)
392
+ @webhooks[webhook.id] = webhook
393
+ end
394
+ end
395
+
396
+ # Find the type of target by it's action number
397
+ # @note For internal use only
398
+ # @!visibility private
399
+ def self.target_type_for(action)
400
+ case action
401
+ when 1 then :server
402
+ when 10..15 then :channel
403
+ when 20..28 then :user
404
+ when 30..32 then :role
405
+ when 40..42 then :invite
406
+ when 50..52 then :webhook
407
+ when 60..62 then :emoji
408
+ when 72..75 then :message
409
+ when 80..82 then :integration
410
+ when 83..85 then :stage_instance
411
+ when 90..92 then :sticker
412
+ when 100..102 then :scheduled_event
413
+ when 110..112 then :thread
414
+ when 121 then :application_command
415
+ when 130..132 then :soundboard_sound
416
+ when 140..146 then :auto_moderation
417
+ when 150..151 then :creator_monetization
418
+ when 163..165 then :onboarding_prompt
419
+ when 166..167 then :onboarding
420
+ when 190..191 then :home_settings
421
+
422
+ else :unknown
423
+ end
424
+ end
425
+
426
+ # Find the type of action by its action number
427
+ # @note For internal use only
428
+ # @!visibility private
429
+ def self.action_type_for(action)
430
+ action = ACTIONS[action]
431
+ return :create if CREATE_ACTIONS.include?(action)
432
+ return :delete if DELETE_ACTIONS.include?(action)
433
+ return :update if UPDATE_ACTIONS.include?(action)
434
+
435
+ :unknown
436
+ end
437
+ end
438
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnyxCord
4
+ # A decoration displayed on a user's avatar.
5
+ class AvatarDecoration
6
+ # @return [Integer] ID of the avatar decoration's SKU.
7
+ attr_reader :sku_id
8
+
9
+ # @return [String] ID that can be used to generate an avatar decoration URL.
10
+ # @see #url
11
+ attr_reader :decoration_id
12
+
13
+ # @!visibility private
14
+ def initialize(data, bot)
15
+ @bot = bot
16
+ @sku_id = data['sku_id']&.to_i
17
+ @decoration_id = data['asset']
18
+ end
19
+
20
+ # Utility method to get an avatar decoration URL.
21
+ # @return [String] the URL to the avatar decoration.
22
+ def url
23
+ API.avatar_decoration_url(@decoration_id)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnyxCord
4
+ # A call in a private channel.
5
+ class Call
6
+ # @return [Time, nil] the time at when the call ended.
7
+ attr_reader :ended_at
8
+
9
+ # @!visibility private
10
+ def initialize(data, bot)
11
+ @bot = bot
12
+ @participant_ids = data['participants'] || []
13
+ @ended_at = Time.iso8601(data['ended_timestamp']) if data['ended_timestamp']
14
+ end
15
+
16
+ # Get the users that participated in this call.
17
+ # @return [Array<User>] the participants of this call.
18
+ def participants
19
+ @participants ||= @participant_ids.map { |participant| @bot.user(participant) }
20
+ end
21
+ end
22
+ end