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,258 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnyxCord
4
+ # An Embed object that is contained in a message
5
+ # A freshly generated embed object will not appear in a message object
6
+ # unless grabbed from its ID in a channel.
7
+ class Embed
8
+ # @return [String] the URL this embed object is based on.
9
+ attr_reader :url
10
+
11
+ # @return [String, nil] the title of the embed object. `nil` if there is not a title
12
+ attr_reader :title
13
+
14
+ # @return [String, nil] the description of the embed object. `nil` if there is not a description
15
+ attr_reader :description
16
+
17
+ # @return [Symbol] the type of the embed object. Possible types are:
18
+ #
19
+ # * `:link`
20
+ # * `:video`
21
+ # * `:image`
22
+ attr_reader :type
23
+
24
+ # @return [Time, nil] the timestamp of the embed object. `nil` if there is not a timestamp
25
+ attr_reader :timestamp
26
+
27
+ # @return [String, nil] the color of the embed object. `nil` if there is not a color
28
+ attr_reader :color
29
+ alias_method :colour, :color
30
+
31
+ # @return [EmbedFooter, nil] the footer of the embed object. `nil` if there is not a footer
32
+ attr_reader :footer
33
+
34
+ # @return [EmbedProvider, nil] the provider of the embed object. `nil` if there is not a provider
35
+ attr_reader :provider
36
+
37
+ # @return [EmbedImage, nil] the image of the embed object. `nil` if there is not an image
38
+ attr_reader :image
39
+
40
+ # @return [EmbedThumbnail, nil] the thumbnail of the embed object. `nil` if there is not a thumbnail
41
+ attr_reader :thumbnail
42
+
43
+ # @return [EmbedVideo, nil] the video of the embed object. `nil` if there is not a video
44
+ attr_reader :video
45
+
46
+ # @return [EmbedAuthor, nil] the author of the embed object. `nil` if there is not an author
47
+ attr_reader :author
48
+
49
+ # @return [Array<EmbedField>, nil] the fields of the embed object. `nil` if there are no fields
50
+ attr_reader :fields
51
+
52
+ # @!visibility private
53
+ def initialize(data, message)
54
+ @message = message
55
+
56
+ @url = data['url']
57
+ @title = data['title']
58
+ @type = data['type'].to_sym
59
+ @description = data['description']
60
+ @timestamp = data['timestamp'].nil? ? nil : Time.parse(data['timestamp'])
61
+ @color = data['color']
62
+ @footer = data['footer'].nil? ? nil : EmbedFooter.new(data['footer'], self)
63
+ @image = data['image'].nil? ? nil : EmbedImage.new(data['image'], self)
64
+ @video = data['video'].nil? ? nil : EmbedVideo.new(data['video'], self)
65
+ @provider = data['provider'].nil? ? nil : EmbedProvider.new(data['provider'], self)
66
+ @thumbnail = data['thumbnail'].nil? ? nil : EmbedThumbnail.new(data['thumbnail'], self)
67
+ @author = data['author'].nil? ? nil : EmbedAuthor.new(data['author'], self)
68
+ @fields = data['fields'].nil? ? nil : data['fields'].map { |field| EmbedField.new(field, self) }
69
+ end
70
+
71
+ # @return [Message, nil] the message this embed object is contained in.
72
+ def message
73
+ @message unless @message.is_a?(Snapshot)
74
+ end
75
+
76
+ # @return [Snapshot, nil] the message snapshot this embed object is contained in.
77
+ def snapshot
78
+ @message unless @message.is_a?(Message)
79
+ end
80
+ end
81
+
82
+ # An Embed footer for the embed object.
83
+ class EmbedFooter
84
+ # @return [Embed] the embed object this is based on.
85
+ attr_reader :embed
86
+
87
+ # @return [String] the footer text.
88
+ attr_reader :text
89
+
90
+ # @return [String] the URL of the footer icon.
91
+ attr_reader :icon_url
92
+
93
+ # @return [String] the proxied URL of the footer icon.
94
+ attr_reader :proxy_icon_url
95
+
96
+ # @!visibility private
97
+ def initialize(data, embed)
98
+ @embed = embed
99
+
100
+ @text = data['text']
101
+ @icon_url = data['icon_url']
102
+ @proxy_icon_url = data['proxy_icon_url']
103
+ end
104
+ end
105
+
106
+ # An Embed image for the embed object.
107
+ class EmbedImage
108
+ # @return [Embed] the embed object this is based on.
109
+ attr_reader :embed
110
+
111
+ # @return [String] the source URL of the image.
112
+ attr_reader :url
113
+
114
+ # @return [String] the proxy URL of the image.
115
+ attr_reader :proxy_url
116
+
117
+ # @return [Integer] the width of the image, in pixels.
118
+ attr_reader :width
119
+
120
+ # @return [Integer] the height of the image, in pixels.
121
+ attr_reader :height
122
+
123
+ # @!visibility private
124
+ def initialize(data, embed)
125
+ @embed = embed
126
+
127
+ @url = data['url']
128
+ @proxy_url = data['proxy_url']
129
+ @width = data['width']
130
+ @height = data['height']
131
+ end
132
+ end
133
+
134
+ # An Embed video for the embed object
135
+ class EmbedVideo
136
+ # @return [Embed] the embed object this is based on.
137
+ attr_reader :embed
138
+
139
+ # @return [String] the source URL of the video.
140
+ attr_reader :url
141
+
142
+ # @return [Integer] the width of the video, in pixels.
143
+ attr_reader :width
144
+
145
+ # @return [Integer] the height of the video, in pixels.
146
+ attr_reader :height
147
+
148
+ # @!visibility private
149
+ def initialize(data, embed)
150
+ @embed = embed
151
+
152
+ @url = data['url']
153
+ @width = data['width']
154
+ @height = data['height']
155
+ end
156
+ end
157
+
158
+ # An Embed thumbnail for the embed object
159
+ class EmbedThumbnail
160
+ # @return [Embed] the embed object this is based on.
161
+ attr_reader :embed
162
+
163
+ # @return [String] the CDN URL this thumbnail can be downloaded at.
164
+ attr_reader :url
165
+
166
+ # @return [String] the thumbnail's proxy URL - I'm not sure what exactly this does, but I think it has something to
167
+ # do with CDNs.
168
+ attr_reader :proxy_url
169
+
170
+ # @return [Integer] the width of this thumbnail file, in pixels.
171
+ attr_reader :width
172
+
173
+ # @return [Integer] the height of this thumbnail file, in pixels.
174
+ attr_reader :height
175
+
176
+ # @!visibility private
177
+ def initialize(data, embed)
178
+ @embed = embed
179
+
180
+ @url = data['url']
181
+ @proxy_url = data['proxy_url']
182
+ @width = data['width']
183
+ @height = data['height']
184
+ end
185
+ end
186
+
187
+ # An Embed provider for the embed object
188
+ class EmbedProvider
189
+ # @return [Embed] the embed object this is based on.
190
+ attr_reader :embed
191
+
192
+ # @return [String] the provider's name.
193
+ attr_reader :name
194
+
195
+ # @return [String, nil] the URL of the provider, or `nil` if there is no URL.
196
+ attr_reader :url
197
+
198
+ # @!visibility private
199
+ def initialize(data, embed)
200
+ @embed = embed
201
+
202
+ @name = data['name']
203
+ @url = data['url']
204
+ end
205
+ end
206
+
207
+ # An Embed author for the embed object
208
+ class EmbedAuthor
209
+ # @return [Embed] the embed object this is based on.
210
+ attr_reader :embed
211
+
212
+ # @return [String] the author's name.
213
+ attr_reader :name
214
+
215
+ # @return [String, nil] the URL of the author's website, or `nil` if there is no URL.
216
+ attr_reader :url
217
+
218
+ # @return [String, nil] the icon of the author, or `nil` if there is no icon.
219
+ attr_reader :icon_url
220
+
221
+ # @return [String, nil] the Discord proxy URL, or `nil` if there is no `icon_url`.
222
+ attr_reader :proxy_icon_url
223
+
224
+ # @!visibility private
225
+ def initialize(data, embed)
226
+ @embed = embed
227
+
228
+ @name = data['name']
229
+ @url = data['url']
230
+ @icon_url = data['icon_url']
231
+ @proxy_icon_url = data['proxy_icon_url']
232
+ end
233
+ end
234
+
235
+ # An Embed field for the embed object
236
+ class EmbedField
237
+ # @return [Embed] the embed object this is based on.
238
+ attr_reader :embed
239
+
240
+ # @return [String] the field's name.
241
+ attr_reader :name
242
+
243
+ # @return [String] the field's value.
244
+ attr_reader :value
245
+
246
+ # @return [true, false] whether this field is inline.
247
+ attr_reader :inline
248
+
249
+ # @!visibility private
250
+ def initialize(data, embed)
251
+ @embed = embed
252
+
253
+ @name = data['name']
254
+ @value = data['value']
255
+ @inline = data['inline']
256
+ end
257
+ end
258
+ end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnyxCord
4
+ # Server emoji
5
+ class Emoji
6
+ include IDObject
7
+
8
+ # @return [String] the emoji name
9
+ attr_reader :name
10
+
11
+ # @return [Server, nil] the server of this emoji
12
+ attr_reader :server
13
+
14
+ # @return [Array<Role>, nil] roles this emoji is active for, or nil if the emoji's server is unknown
15
+ attr_reader :roles
16
+
17
+ # @return [User, nil] the user who uploaded this emoji, or nil if the emoji's server is unknown
18
+ attr_reader :creator
19
+
20
+ # @return [Boolean, nil] if the emoji requires colons to be used, or nil if the emoji's server is unknown
21
+ attr_reader :requires_colons
22
+ alias_method :requires_colons?, :requires_colons
23
+
24
+ # @return [Boolean, nil] whether this emoji is managed by an integration, or nil if the emoji's server is unknown
25
+ attr_reader :managed
26
+ alias_method :managed?, :managed
27
+
28
+ # @return [Boolean, nil] if this emoji is currently usable, or nil if the emoji's server is unknown
29
+ attr_reader :available
30
+ alias_method :available?, :available
31
+
32
+ # @return [true, false] if the emoji is animated
33
+ attr_reader :animated
34
+ alias_method :animated?, :animated
35
+
36
+ # @!visibility private
37
+ def initialize(data, bot, server = nil)
38
+ @bot = bot
39
+ @roles = nil
40
+
41
+ @name = data['name']
42
+ @server = server
43
+ @id = data['id']&.to_i
44
+ @animated = data['animated'] || false
45
+ @managed = data['managed']
46
+ @available = data['available']
47
+ @requires_colons = data['require_colons']
48
+ @creator = data['user'] ? bot.ensure_user(data['user']) : nil
49
+
50
+ process_roles(data['roles']) if server
51
+ end
52
+
53
+ # ID or name based comparison
54
+ def ==(other)
55
+ return false unless other.is_a? Emoji
56
+ return OnyxCord.id_compare?(@id, other) if @id
57
+
58
+ name == other.name
59
+ end
60
+
61
+ alias_method :eql?, :==
62
+
63
+ # @return [String] the layout to mention it (or have it used) in a message
64
+ def mention
65
+ return name if id.nil?
66
+
67
+ "<#{'a' if animated}:#{name}:#{id}>"
68
+ end
69
+
70
+ alias_method :use, :mention
71
+ alias_method :to_s, :mention
72
+
73
+ # @return [String] the layout to use this emoji in a reaction
74
+ def to_reaction
75
+ return name if id.nil?
76
+
77
+ "#{name}:#{id}"
78
+ end
79
+
80
+ # @return [String] the icon URL of the emoji
81
+ def icon_url
82
+ API.emoji_icon_url(id)
83
+ end
84
+
85
+ # The inspect method is overwritten to give more useful output
86
+ def inspect
87
+ "<Emoji name=#{name.inspect} id=#{id.inspect} animated=#{animated}>"
88
+ end
89
+
90
+ # Converts this Emoji into a hash that can be sent back to Discord in other endpoints.
91
+ # @return [Hash] A hash representation of this emoji.
92
+ def to_h
93
+ id.nil? ? { name: name } : { id: id }
94
+ end
95
+
96
+ # @!visibility private
97
+ def process_roles(roles)
98
+ @roles = []
99
+ return unless roles
100
+
101
+ roles.each do |role_id|
102
+ role = server.role(role_id)
103
+ @roles << role
104
+ end
105
+ end
106
+
107
+ # @!visibility private
108
+ def self.build_emoji_hash(emoji, prefix: true)
109
+ data = { id: nil, name: nil }
110
+
111
+ case emoji
112
+ when Emoji, Reaction
113
+ emoji.id ? data[:id] = emoji.id : data[:name] = emoji.name
114
+ when Integer, String
115
+ emoji.to_i.zero? ? data[:name] = emoji : data[:id] = emoji
116
+ else
117
+ raise TypeError, "Invalid emoji type: #{emoji.class}" unless emoji.nil?
118
+ end
119
+
120
+ prefix ? data.transform_keys!({ id: :emoji_id, name: :emoji_name }) : data
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnyxCord
4
+ # Default installation parameters for an application.
5
+ class InstallParams
6
+ # @return [Array<String>] the default scopes to add an application to a server with.
7
+ attr_reader :scopes
8
+
9
+ # @return [Permissions, nil] the default permissions to add an application to a server with.
10
+ attr_reader :permissions
11
+
12
+ # @!visibility private
13
+ def initialize(data, bot)
14
+ @bot = bot
15
+ @scopes = data['scopes'] || []
16
+ @permissions = data['permissions'] ? Permissions.new(data['permissions']) : nil
17
+ end
18
+
19
+ # @!visibility private
20
+ def to_h
21
+ { scopes: @scopes.any? ? @scopes : nil, permissions: @permissions&.bits&.to_s }.compact
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnyxCord
4
+ # Integration Account
5
+ class IntegrationAccount
6
+ include IDObject
7
+
8
+ # @return [String] this account's name.
9
+ attr_reader :name
10
+
11
+ # @!visibility private
12
+ def initialize(data)
13
+ @id = data['id'].to_i
14
+ @name = data['name']
15
+ end
16
+ end
17
+
18
+ # Bot/OAuth2 application for discord integrations
19
+ class IntegrationApplication
20
+ include IDObject
21
+
22
+ # @return [String] the name of the application.
23
+ attr_reader :name
24
+
25
+ # @return [String, nil] the icon hash of the application.
26
+ attr_reader :icon
27
+
28
+ # @return [String] the description of the application.
29
+ attr_reader :description
30
+
31
+ # @return [User, nil] the bot associated with this application.
32
+ attr_reader :bot
33
+
34
+ # @!visibility private
35
+ def initialize(data, bot)
36
+ @id = data['id'].to_i
37
+ @name = data['name']
38
+ @icon = data['icon']
39
+ @description = data['description']
40
+ @bot = bot.ensure_user(data['bot']) if data['bot']
41
+ end
42
+ end
43
+
44
+ # Server integration
45
+ class Integration
46
+ include IDObject
47
+
48
+ # Map of expire behaviors.
49
+ EXPIRE_BEHAVIORS = {
50
+ remove: 0,
51
+ kick: 1
52
+ }.freeze
53
+
54
+ # @return [String] the integration name
55
+ attr_reader :name
56
+
57
+ # @return [Server] the server the integration is linked to
58
+ attr_reader :server
59
+
60
+ # @return [User, nil] the user who added the integration to the server. This will be `nil`
61
+ # for very old integrations, or if the integration was sent via a Gateway event.
62
+ attr_reader :user
63
+
64
+ # @return [Integer, nil] the ID of the role that this integration uses for "subscribers"
65
+ attr_reader :role_id
66
+
67
+ # @return [true, false] whether or not emoticons are enabled
68
+ attr_reader :emoticon
69
+ alias_method :emoticon?, :emoticon
70
+ alias_method :emoticons?, :emoticon
71
+
72
+ # @return [String] the integration type (YouTube, Twitch, Discord, etc.)
73
+ attr_reader :type
74
+
75
+ # @return [true, false] whether the integration is enabled
76
+ attr_reader :enabled
77
+ alias_method :enabled?, :enabled
78
+
79
+ # @return [true, false] whether or not the integration is syncing
80
+ attr_reader :syncing
81
+ alias_method :syncing?, :syncing
82
+
83
+ # @return [IntegrationAccount] the integration account information
84
+ attr_reader :account
85
+
86
+ # @return [Time, nil] the time the integration was last synced at
87
+ attr_reader :synced_at
88
+
89
+ # @return [Symbol, nil] the behaviour of expiring subscribers. When this is `:remove`, the
90
+ # associated role will be removed from the user. When this is `:kick`, the user will be
91
+ # kicked out of the server
92
+ attr_reader :expire_behaviour
93
+ alias_method :expire_behavior, :expire_behaviour
94
+
95
+ # @return [Integer] the grace period before subscribers expire (in days)
96
+ attr_reader :expire_grace_period
97
+
98
+ # @return [Integer, nil] how many subscribers this integration has.
99
+ attr_reader :subscriber_count
100
+
101
+ # @return [true, false] whether or not this integration been revoked.
102
+ attr_reader :revoked
103
+ alias_method :revoked?, :revoked
104
+
105
+ # @return [IntegrationApplication, nil] the application for the integration.
106
+ attr_reader :application
107
+
108
+ # @return [Array<String>] the oauth2 scopes the application has been authorized for
109
+ attr_reader :scopes
110
+
111
+ # @!visibility private
112
+ def initialize(data, bot, server)
113
+ @bot = bot
114
+ @server = server
115
+ @id = data['id'].to_i
116
+ @name = data['name']
117
+ @enabled = data['enabled']
118
+ @syncing = data['syncing'] || false
119
+ @type = data['type']
120
+ @account = IntegrationAccount.new(data['account'])
121
+ @synced_at = Time.parse(data['synced_at']) if data['synced_at']
122
+ @expire_behaviour = EXPIRE_BEHAVIORS.key(data['expire_behavior']) if data['expire_behavior']
123
+ @expire_grace_period = data['expire_grace_period'] || 0
124
+ @user = @bot.ensure_user(data['user']) if data['user']
125
+ @role_id = data['role_id']&.to_i
126
+ @emoticon = data['enable_emoticons'] || false
127
+ @subscriber_count = data['subscriber_count']&.to_i
128
+ @revoked = data['revoked'] || false
129
+ @application = IntegrationApplication.new(data['application'], bot) if data['application']
130
+ @scopes = data['scopes'] || []
131
+ end
132
+
133
+ # Get the role that this integration uses for subscribers.
134
+ # @return [Role, nil] The role that this integration uses for subscribers.
135
+ def subscriber_role
136
+ @server.role(@role_id) if @role_id
137
+ end
138
+
139
+ # The inspect method is overwritten to give more useful output.
140
+ def inspect
141
+ "<Integration name=\"#{@name}\" id=#{@id} type=\"#{@type}\" enabled=#{@enabled}>"
142
+ end
143
+ end
144
+ end