rubycord 1.0.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 (88) hide show
  1. checksums.yaml +7 -0
  2. data/lib/rubycord/allowed_mentions.rb +34 -0
  3. data/lib/rubycord/api/application.rb +200 -0
  4. data/lib/rubycord/api/channel.rb +597 -0
  5. data/lib/rubycord/api/interaction.rb +52 -0
  6. data/lib/rubycord/api/invite.rb +42 -0
  7. data/lib/rubycord/api/server.rb +557 -0
  8. data/lib/rubycord/api/user.rb +153 -0
  9. data/lib/rubycord/api/webhook.rb +138 -0
  10. data/lib/rubycord/api.rb +356 -0
  11. data/lib/rubycord/await.rb +49 -0
  12. data/lib/rubycord/bot.rb +1757 -0
  13. data/lib/rubycord/cache.rb +259 -0
  14. data/lib/rubycord/colour_rgb.rb +41 -0
  15. data/lib/rubycord/commands/command_bot.rb +519 -0
  16. data/lib/rubycord/commands/container.rb +110 -0
  17. data/lib/rubycord/commands/events.rb +9 -0
  18. data/lib/rubycord/commands/parser.rb +325 -0
  19. data/lib/rubycord/commands/rate_limiter.rb +142 -0
  20. data/lib/rubycord/container.rb +753 -0
  21. data/lib/rubycord/data/activity.rb +269 -0
  22. data/lib/rubycord/data/application.rb +48 -0
  23. data/lib/rubycord/data/attachment.rb +109 -0
  24. data/lib/rubycord/data/audit_logs.rb +343 -0
  25. data/lib/rubycord/data/channel.rb +996 -0
  26. data/lib/rubycord/data/component.rb +227 -0
  27. data/lib/rubycord/data/embed.rb +249 -0
  28. data/lib/rubycord/data/emoji.rb +80 -0
  29. data/lib/rubycord/data/integration.rb +120 -0
  30. data/lib/rubycord/data/interaction.rb +798 -0
  31. data/lib/rubycord/data/invite.rb +135 -0
  32. data/lib/rubycord/data/member.rb +370 -0
  33. data/lib/rubycord/data/message.rb +412 -0
  34. data/lib/rubycord/data/overwrite.rb +106 -0
  35. data/lib/rubycord/data/profile.rb +89 -0
  36. data/lib/rubycord/data/reaction.rb +31 -0
  37. data/lib/rubycord/data/recipient.rb +32 -0
  38. data/lib/rubycord/data/role.rb +246 -0
  39. data/lib/rubycord/data/server.rb +1002 -0
  40. data/lib/rubycord/data/user.rb +261 -0
  41. data/lib/rubycord/data/voice_region.rb +43 -0
  42. data/lib/rubycord/data/voice_state.rb +39 -0
  43. data/lib/rubycord/data/webhook.rb +232 -0
  44. data/lib/rubycord/data.rb +40 -0
  45. data/lib/rubycord/errors.rb +737 -0
  46. data/lib/rubycord/events/await.rb +46 -0
  47. data/lib/rubycord/events/bans.rb +58 -0
  48. data/lib/rubycord/events/channels.rb +186 -0
  49. data/lib/rubycord/events/generic.rb +126 -0
  50. data/lib/rubycord/events/guilds.rb +191 -0
  51. data/lib/rubycord/events/interactions.rb +480 -0
  52. data/lib/rubycord/events/invites.rb +123 -0
  53. data/lib/rubycord/events/lifetime.rb +29 -0
  54. data/lib/rubycord/events/members.rb +91 -0
  55. data/lib/rubycord/events/message.rb +337 -0
  56. data/lib/rubycord/events/presence.rb +127 -0
  57. data/lib/rubycord/events/raw.rb +45 -0
  58. data/lib/rubycord/events/reactions.rb +156 -0
  59. data/lib/rubycord/events/roles.rb +86 -0
  60. data/lib/rubycord/events/threads.rb +94 -0
  61. data/lib/rubycord/events/typing.rb +70 -0
  62. data/lib/rubycord/events/voice_server_update.rb +45 -0
  63. data/lib/rubycord/events/voice_state_update.rb +103 -0
  64. data/lib/rubycord/events/webhooks.rb +62 -0
  65. data/lib/rubycord/gateway.rb +867 -0
  66. data/lib/rubycord/id_object.rb +37 -0
  67. data/lib/rubycord/light/data.rb +60 -0
  68. data/lib/rubycord/light/integrations.rb +71 -0
  69. data/lib/rubycord/light/light_bot.rb +56 -0
  70. data/lib/rubycord/light.rb +6 -0
  71. data/lib/rubycord/logger.rb +118 -0
  72. data/lib/rubycord/paginator.rb +55 -0
  73. data/lib/rubycord/permissions.rb +251 -0
  74. data/lib/rubycord/version.rb +5 -0
  75. data/lib/rubycord/voice/encoder.rb +113 -0
  76. data/lib/rubycord/voice/network.rb +366 -0
  77. data/lib/rubycord/voice/sodium.rb +96 -0
  78. data/lib/rubycord/voice/voice_bot.rb +408 -0
  79. data/lib/rubycord/webhooks/builder.rb +100 -0
  80. data/lib/rubycord/webhooks/client.rb +132 -0
  81. data/lib/rubycord/webhooks/embeds.rb +248 -0
  82. data/lib/rubycord/webhooks/modal.rb +78 -0
  83. data/lib/rubycord/webhooks/version.rb +7 -0
  84. data/lib/rubycord/webhooks/view.rb +192 -0
  85. data/lib/rubycord/webhooks.rb +12 -0
  86. data/lib/rubycord/websocket.rb +70 -0
  87. data/lib/rubycord.rb +140 -0
  88. metadata +231 -0
@@ -0,0 +1,227 @@
1
+ module Rubycord
2
+ # Components are interactable interfaces that can be attached to messages.
3
+ module Components
4
+ # @deprecated This alias will be removed in future releases.
5
+ class View < Webhooks::View
6
+ end
7
+
8
+ # @!visibility private
9
+ def self.from_data(data, bot)
10
+ case data["type"]
11
+ when Webhooks::View::COMPONENT_TYPES[:action_row]
12
+ ActionRow.new(data, bot)
13
+ when Webhooks::View::COMPONENT_TYPES[:button]
14
+ Button.new(data, bot)
15
+ when Webhooks::View::COMPONENT_TYPES[:string_select]
16
+ SelectMenu.new(data, bot)
17
+ when Webhooks::Modal::COMPONENT_TYPES[:text_input]
18
+ TextInput.new(data, bot)
19
+ end
20
+ end
21
+
22
+ # Represents a row of components
23
+ class ActionRow
24
+ include Enumerable
25
+
26
+ # @return [Array<Button>]
27
+ attr_reader :components
28
+
29
+ # @!visibility private
30
+ def initialize(data, bot)
31
+ @bot = bot
32
+ @components = data["components"].map { |component_data| Components.from_data(component_data, @bot) }
33
+ end
34
+
35
+ # Iterate over each component in the row.
36
+ def each(&)
37
+ @components.each(&)
38
+ end
39
+
40
+ # Get all buttons in this row
41
+ # @return [Array<Button>]
42
+ def buttons
43
+ select { |component| component.is_a? Button }
44
+ end
45
+
46
+ # Get all buttons in this row
47
+ # @return [Array<Button>]
48
+ def text_inputs
49
+ select { |component| component.is_a? TextInput }
50
+ end
51
+
52
+ # @!visibility private
53
+ def to_a
54
+ @components
55
+ end
56
+ end
57
+
58
+ # An interactable button component.
59
+ class Button
60
+ # @return [String]
61
+ attr_reader :label
62
+
63
+ # @return [Integer]
64
+ attr_reader :style
65
+
66
+ # @return [String]
67
+ attr_reader :custom_id
68
+
69
+ # @return [true, false]
70
+ attr_reader :disabled
71
+
72
+ # @return [String, nil]
73
+ attr_reader :url
74
+
75
+ # @return [Emoji, nil]
76
+ attr_reader :emoji
77
+
78
+ # @!visibility private
79
+ def initialize(data, bot)
80
+ @bot = bot
81
+
82
+ @label = data["label"]
83
+ @style = data["style"]
84
+ @custom_id = data["custom_id"]
85
+ @disabled = data["disabled"]
86
+ @url = data["url"]
87
+ @emoji = Emoji.new(data["emoji"], @bot) if data["emoji"]
88
+ end
89
+
90
+ # @method primary?
91
+ # @return [true, false]
92
+ # @method secondary?
93
+ # @return [true, false]
94
+ # @method success?
95
+ # @return [true, false]
96
+ # @method danger?
97
+ # @return [true, false]
98
+ # @method link?
99
+ # @return [true, false]
100
+ Webhooks::View::BUTTON_STYLES.each do |name, value|
101
+ define_method(:"#{name}?") do
102
+ @style == value
103
+ end
104
+ end
105
+
106
+ # Await a button click
107
+ def await_click(key, **attributes, &)
108
+ @bot.add_await(key, Rubycord::Events::ButtonEvent, {custom_id: @custom_id}.merge(attributes), &)
109
+ end
110
+
111
+ # Await a button click, blocking.
112
+ def await_click!(**attributes, &)
113
+ @bot.add_await!(Rubycord::Events::ButtonEvent, {custom_id: @custom_id}.merge(attributes), &)
114
+ end
115
+ end
116
+
117
+ # An interactable select menu component.
118
+ class SelectMenu
119
+ # A select menu option.
120
+ class Option
121
+ # @return [String]
122
+ attr_reader :label
123
+
124
+ # @return [String]
125
+ attr_reader :value
126
+
127
+ # @return [String, nil]
128
+ attr_reader :description
129
+
130
+ # @return [Emoji, nil]
131
+ attr_reader :emoji
132
+
133
+ # @!visibility hidden
134
+ def initialize(data)
135
+ @label = data["label"]
136
+ @value = data["value"]
137
+ @description = data["description"]
138
+ @emoji = Emoji.new(data["emoji"], @bot) if data["emoji"]
139
+ end
140
+ end
141
+
142
+ # @return [String]
143
+ attr_reader :custom_id
144
+
145
+ # @return [Integer, nil]
146
+ attr_reader :max_values
147
+
148
+ # @return [Integer, nil]
149
+ attr_reader :min_values
150
+
151
+ # @return [String, nil]
152
+ attr_reader :placeholder
153
+
154
+ # @return [Array<Option>]
155
+ attr_reader :options
156
+
157
+ # @!visibility private
158
+ def initialize(data, bot)
159
+ @bot = bot
160
+
161
+ @max_values = data["max_values"]
162
+ @min_values = data["min_values"]
163
+ @placeholder = data["placeholder"]
164
+ @custom_id = data["custom_id"]
165
+ @emoji = Emoji.new(data["emoji"], @bot) if data["emoji"]
166
+ @options = data["options"].map { |opt| Option.new(opt) }
167
+ end
168
+ end
169
+
170
+ # Text input component for use in modals. Can be either a line (`short`), or a multi line (`paragraph`) block.
171
+ class TextInput
172
+ # Single line text input
173
+ SHORT = 1
174
+ # Multi-line text input
175
+ PARAGRAPH = 2
176
+
177
+ # @return [String]
178
+ attr_reader :custom_id
179
+
180
+ # @return [Symbol]
181
+ attr_reader :style
182
+
183
+ # @return [String]
184
+ attr_reader :label
185
+
186
+ # @return [Integer, nil]
187
+ attr_reader :min_length
188
+
189
+ # @return [Integer, nil]
190
+ attr_reader :max_length
191
+
192
+ # @return [true, false]
193
+ attr_reader :required
194
+
195
+ # @return [String, nil]
196
+ attr_reader :value
197
+
198
+ # @return [String, nil]
199
+ attr_reader :placeholder
200
+
201
+ # @!visibility private
202
+ def initialize(data, bot)
203
+ @bot = bot
204
+ @style = (data["style"] == SHORT) ? :short : :paragraph
205
+ @label = data["label"]
206
+ @min_length = data["min_length"]
207
+ @max_length = data["max_length"]
208
+ @required = data["required"]
209
+ @value = data["value"]
210
+ @placeholder = data["placeholder"]
211
+ @custom_id = data["custom_id"]
212
+ end
213
+
214
+ def short?
215
+ @style == :short
216
+ end
217
+
218
+ def paragraph?
219
+ @style == :paragraph
220
+ end
221
+
222
+ def required?
223
+ @required
224
+ end
225
+ end
226
+ end
227
+ end
@@ -0,0 +1,249 @@
1
+ module Rubycord
2
+ # An Embed object that is contained in a message
3
+ # A freshly generated embed object will not appear in a message object
4
+ # unless grabbed from its ID in a channel.
5
+ class Embed
6
+ # @return [Message] the message this embed object is contained in.
7
+ attr_reader :message
8
+
9
+ # @return [String] the URL this embed object is based on.
10
+ attr_reader :url
11
+
12
+ # @return [String, nil] the title of the embed object. `nil` if there is not a title
13
+ attr_reader :title
14
+
15
+ # @return [String, nil] the description of the embed object. `nil` if there is not a description
16
+ attr_reader :description
17
+
18
+ # @return [Symbol] the type of the embed object. Possible types are:
19
+ #
20
+ # * `:link`
21
+ # * `:video`
22
+ # * `:image`
23
+ attr_reader :type
24
+
25
+ # @return [Time, nil] the timestamp of the embed object. `nil` if there is not a timestamp
26
+ attr_reader :timestamp
27
+
28
+ # @return [String, nil] the color of the embed object. `nil` if there is not a color
29
+ attr_reader :color
30
+ alias_method :colour, :color
31
+
32
+ # @return [EmbedFooter, nil] the footer of the embed object. `nil` if there is not a footer
33
+ attr_reader :footer
34
+
35
+ # @return [EmbedProvider, nil] the provider of the embed object. `nil` if there is not a provider
36
+ attr_reader :provider
37
+
38
+ # @return [EmbedImage, nil] the image of the embed object. `nil` if there is not an image
39
+ attr_reader :image
40
+
41
+ # @return [EmbedThumbnail, nil] the thumbnail of the embed object. `nil` if there is not a thumbnail
42
+ attr_reader :thumbnail
43
+
44
+ # @return [EmbedVideo, nil] the video of the embed object. `nil` if there is not a video
45
+ attr_reader :video
46
+
47
+ # @return [EmbedAuthor, nil] the author of the embed object. `nil` if there is not an author
48
+ attr_reader :author
49
+
50
+ # @return [Array<EmbedField>, nil] the fields of the embed object. `nil` if there are no fields
51
+ attr_reader :fields
52
+
53
+ # @!visibility private
54
+ def initialize(data, message)
55
+ @message = message
56
+
57
+ @url = data["url"]
58
+ @title = data["title"]
59
+ @type = data["type"].to_sym
60
+ @description = data["description"]
61
+ @timestamp = data["timestamp"].nil? ? nil : Time.parse(data["timestamp"])
62
+ @color = data["color"]
63
+ @footer = data["footer"].nil? ? nil : EmbedFooter.new(data["footer"], self)
64
+ @image = data["image"].nil? ? nil : EmbedImage.new(data["image"], self)
65
+ @video = data["video"].nil? ? nil : EmbedVideo.new(data["video"], self)
66
+ @provider = data["provider"].nil? ? nil : EmbedProvider.new(data["provider"], self)
67
+ @thumbnail = data["thumbnail"].nil? ? nil : EmbedThumbnail.new(data["thumbnail"], self)
68
+ @author = data["author"].nil? ? nil : EmbedAuthor.new(data["author"], self)
69
+ @fields = data["fields"]&.map { |field| EmbedField.new(field, self) }
70
+ end
71
+ end
72
+
73
+ # An Embed footer for the embed object.
74
+ class EmbedFooter
75
+ # @return [Embed] the embed object this is based on.
76
+ attr_reader :embed
77
+
78
+ # @return [String] the footer text.
79
+ attr_reader :text
80
+
81
+ # @return [String] the URL of the footer icon.
82
+ attr_reader :icon_url
83
+
84
+ # @return [String] the proxied URL of the footer icon.
85
+ attr_reader :proxy_icon_url
86
+
87
+ # @!visibility private
88
+ def initialize(data, embed)
89
+ @embed = embed
90
+
91
+ @text = data["text"]
92
+ @icon_url = data["icon_url"]
93
+ @proxy_icon_url = data["proxy_icon_url"]
94
+ end
95
+ end
96
+
97
+ # An Embed image for the embed object.
98
+ class EmbedImage
99
+ # @return [Embed] the embed object this is based on.
100
+ attr_reader :embed
101
+
102
+ # @return [String] the source URL of the image.
103
+ attr_reader :url
104
+
105
+ # @return [String] the proxy URL of the image.
106
+ attr_reader :proxy_url
107
+
108
+ # @return [Integer] the width of the image, in pixels.
109
+ attr_reader :width
110
+
111
+ # @return [Integer] the height of the image, in pixels.
112
+ attr_reader :height
113
+
114
+ # @!visibility private
115
+ def initialize(data, embed)
116
+ @embed = embed
117
+
118
+ @url = data["url"]
119
+ @proxy_url = data["proxy_url"]
120
+ @width = data["width"]
121
+ @height = data["height"]
122
+ end
123
+ end
124
+
125
+ # An Embed video for the embed object
126
+ class EmbedVideo
127
+ # @return [Embed] the embed object this is based on.
128
+ attr_reader :embed
129
+
130
+ # @return [String] the source URL of the video.
131
+ attr_reader :url
132
+
133
+ # @return [Integer] the width of the video, in pixels.
134
+ attr_reader :width
135
+
136
+ # @return [Integer] the height of the video, in pixels.
137
+ attr_reader :height
138
+
139
+ # @!visibility private
140
+ def initialize(data, embed)
141
+ @embed = embed
142
+
143
+ @url = data["url"]
144
+ @width = data["width"]
145
+ @height = data["height"]
146
+ end
147
+ end
148
+
149
+ # An Embed thumbnail for the embed object
150
+ class EmbedThumbnail
151
+ # @return [Embed] the embed object this is based on.
152
+ attr_reader :embed
153
+
154
+ # @return [String] the CDN URL this thumbnail can be downloaded at.
155
+ attr_reader :url
156
+
157
+ # @return [String] the thumbnail's proxy URL - I'm not sure what exactly this does, but I think it has something to
158
+ # do with CDNs.
159
+ attr_reader :proxy_url
160
+
161
+ # @return [Integer] the width of this thumbnail file, in pixels.
162
+ attr_reader :width
163
+
164
+ # @return [Integer] the height of this thumbnail file, in pixels.
165
+ attr_reader :height
166
+
167
+ # @!visibility private
168
+ def initialize(data, embed)
169
+ @embed = embed
170
+
171
+ @url = data["url"]
172
+ @proxy_url = data["proxy_url"]
173
+ @width = data["width"]
174
+ @height = data["height"]
175
+ end
176
+ end
177
+
178
+ # An Embed provider for the embed object
179
+ class EmbedProvider
180
+ # @return [Embed] the embed object this is based on.
181
+ attr_reader :embed
182
+
183
+ # @return [String] the provider's name.
184
+ attr_reader :name
185
+
186
+ # @return [String, nil] the URL of the provider, or `nil` if there is no URL.
187
+ attr_reader :url
188
+
189
+ # @!visibility private
190
+ def initialize(data, embed)
191
+ @embed = embed
192
+
193
+ @name = data["name"]
194
+ @url = data["url"]
195
+ end
196
+ end
197
+
198
+ # An Embed author for the embed object
199
+ class EmbedAuthor
200
+ # @return [Embed] the embed object this is based on.
201
+ attr_reader :embed
202
+
203
+ # @return [String] the author's name.
204
+ attr_reader :name
205
+
206
+ # @return [String, nil] the URL of the author's website, or `nil` if there is no URL.
207
+ attr_reader :url
208
+
209
+ # @return [String, nil] the icon of the author, or `nil` if there is no icon.
210
+ attr_reader :icon_url
211
+
212
+ # @return [String, nil] the Discord proxy URL, or `nil` if there is no `icon_url`.
213
+ attr_reader :proxy_icon_url
214
+
215
+ # @!visibility private
216
+ def initialize(data, embed)
217
+ @embed = embed
218
+
219
+ @name = data["name"]
220
+ @url = data["url"]
221
+ @icon_url = data["icon_url"]
222
+ @proxy_icon_url = data["proxy_icon_url"]
223
+ end
224
+ end
225
+
226
+ # An Embed field for the embed object
227
+ class EmbedField
228
+ # @return [Embed] the embed object this is based on.
229
+ attr_reader :embed
230
+
231
+ # @return [String] the field's name.
232
+ attr_reader :name
233
+
234
+ # @return [String] the field's value.
235
+ attr_reader :value
236
+
237
+ # @return [true, false] whether this field is inline.
238
+ attr_reader :inline
239
+
240
+ # @!visibility private
241
+ def initialize(data, embed)
242
+ @embed = embed
243
+
244
+ @name = data["name"]
245
+ @value = data["value"]
246
+ @inline = data["inline"]
247
+ end
248
+ end
249
+ end
@@ -0,0 +1,80 @@
1
+ module Rubycord
2
+ # Server emoji
3
+ class Emoji
4
+ include IDObject
5
+
6
+ # @return [String] the emoji name
7
+ attr_reader :name
8
+
9
+ # @return [Server, nil] the server of this emoji
10
+ attr_reader :server
11
+
12
+ # @return [Array<Role>, nil] roles this emoji is active for, or nil if the emoji's server is unknown
13
+ attr_reader :roles
14
+
15
+ # @return [true, false] if the emoji is animated
16
+ attr_reader :animated
17
+ alias_method :animated?, :animated
18
+
19
+ # @!visibility private
20
+ def initialize(data, bot, server = nil)
21
+ @bot = bot
22
+ @roles = nil
23
+
24
+ @name = data["name"]
25
+ @server = server
26
+ @id = data["id"]&.to_i
27
+ @animated = data["animated"]
28
+
29
+ process_roles(data["roles"]) if server
30
+ end
31
+
32
+ # ID or name based comparison
33
+ def ==(other)
34
+ return false unless other.is_a? Emoji
35
+ return Rubycord.id_compare(@id, other) if @id
36
+
37
+ name == other.name
38
+ end
39
+
40
+ alias_method :eql?, :==
41
+
42
+ # @return [String] the layout to mention it (or have it used) in a message
43
+ def mention
44
+ return name if id.nil?
45
+
46
+ "<#{"a" if animated}:#{name}:#{id}>"
47
+ end
48
+
49
+ alias_method :use, :mention
50
+ alias_method :to_s, :mention
51
+
52
+ # @return [String] the layout to use this emoji in a reaction
53
+ def to_reaction
54
+ return name if id.nil?
55
+
56
+ "#{name}:#{id}"
57
+ end
58
+
59
+ # @return [String] the icon URL of the emoji
60
+ def icon_url
61
+ API.emoji_icon_url(id)
62
+ end
63
+
64
+ # The inspect method is overwritten to give more useful output
65
+ def inspect
66
+ "<Emoji name=#{name} id=#{id} animated=#{animated}>"
67
+ end
68
+
69
+ # @!visibility private
70
+ def process_roles(roles)
71
+ @roles = []
72
+ return unless roles
73
+
74
+ roles.each do |role_id|
75
+ role = server.role(role_id)
76
+ @roles << role
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,120 @@
1
+ module Rubycord
2
+ # Integration Account
3
+ class IntegrationAccount
4
+ # @return [String] this account's name.
5
+ attr_reader :name
6
+
7
+ # @return [Integer] this account's ID.
8
+ attr_reader :id
9
+
10
+ def initialize(data)
11
+ @name = data["name"]
12
+ @id = data["id"].to_i
13
+ end
14
+ end
15
+
16
+ # Bot/OAuth2 application for discord integrations
17
+ class IntegrationApplication
18
+ # @return [Integer] the ID of the application.
19
+ attr_reader :id
20
+
21
+ # @return [String] the name of the application.
22
+ attr_reader :name
23
+
24
+ # @return [String, nil] the icon hash of the application.
25
+ attr_reader :icon
26
+
27
+ # @return [String] the description of the application.
28
+ attr_reader :description
29
+
30
+ # @return [String] the summary of the application.
31
+ attr_reader :summary
32
+
33
+ # @return [User, nil] the bot associated with this application.
34
+ attr_reader :bot
35
+
36
+ def initialize(data, bot)
37
+ @id = data["id"].to_i
38
+ @name = data["name"]
39
+ @icon = data["icon"]
40
+ @description = data["description"]
41
+ @summary = data["summary"]
42
+ @bot = Rubycord::User.new(data["user"], bot) if data["user"]
43
+ end
44
+ end
45
+
46
+ # Server integration
47
+ class Integration
48
+ include IDObject
49
+
50
+ # @return [String] the integration name
51
+ attr_reader :name
52
+
53
+ # @return [Server] the server the integration is linked to
54
+ attr_reader :server
55
+
56
+ # @return [User] the user the integration is linked to
57
+ attr_reader :user
58
+
59
+ # @return [Integer, nil] the role that this integration uses for "subscribers"
60
+ attr_reader :role_id
61
+
62
+ # @return [true, false] whether emoticons are enabled
63
+ attr_reader :emoticon
64
+ alias_method :emoticon?, :emoticon
65
+
66
+ # @return [String] the integration type (YouTube, Twitch, etc.)
67
+ attr_reader :type
68
+
69
+ # @return [true, false] whether the integration is enabled
70
+ attr_reader :enabled
71
+
72
+ # @return [true, false] whether the integration is syncing
73
+ attr_reader :syncing
74
+
75
+ # @return [IntegrationAccount] the integration account information
76
+ attr_reader :account
77
+
78
+ # @return [Time] the time the integration was synced at
79
+ attr_reader :synced_at
80
+
81
+ # @return [Symbol] the behaviour of expiring subscribers (:remove = Remove User from role; :kick = Kick User from server)
82
+ attr_reader :expire_behaviour
83
+ alias_method :expire_behavior, :expire_behaviour
84
+
85
+ # @return [Integer] the grace period before subscribers expire (in days)
86
+ attr_reader :expire_grace_period
87
+
88
+ # @return [Integer, nil] how many subscribers this integration has.
89
+ attr_reader :subscriber_count
90
+
91
+ # @return [true, false] has this integration been revoked.
92
+ attr_reader :revoked
93
+
94
+ def initialize(data, bot, server)
95
+ @bot = bot
96
+
97
+ @name = data["name"]
98
+ @server = server
99
+ @id = data["id"].to_i
100
+ @enabled = data["enabled"]
101
+ @syncing = data["syncing"]
102
+ @type = data["type"]
103
+ @account = IntegrationAccount.new(data["account"])
104
+ @synced_at = Time.parse(data["synced_at"])
105
+ @expire_behaviour = %i[remove kick][data["expire_behavior"]]
106
+ @expire_grace_period = data["expire_grace_period"]
107
+ @user = @bot.ensure_user(data["user"])
108
+ @role_id = data["role_id"]&.to_i
109
+ @emoticon = data["enable_emoticons"]
110
+ @subscriber_count = data["subscriber_count"]&.to_i
111
+ @revoked = data["revoked"]
112
+ @application = IntegrationApplication.new(data["application"], bot) if data["application"]
113
+ end
114
+
115
+ # The inspect method is overwritten to give more useful output
116
+ def inspect
117
+ "<Integration name=#{@name} id=#{@id} type=#{@type} enabled=#{@enabled}>"
118
+ end
119
+ end
120
+ end