rubycord 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,248 @@
1
+ module Rubycord::Webhooks
2
+ # An embed is a multipart-style attachment to a webhook message that can have a variety of different purposes and
3
+ # appearances.
4
+ class Embed
5
+ def initialize(title: nil, description: nil, url: nil, timestamp: nil, colour: nil, color: nil, footer: nil,
6
+ image: nil, thumbnail: nil, video: nil, provider: nil, author: nil, fields: [])
7
+ @title = title
8
+ @description = description
9
+ @url = url
10
+ @timestamp = timestamp
11
+ self.colour = colour || color
12
+ @footer = footer
13
+ @image = image
14
+ @thumbnail = thumbnail
15
+ @video = video
16
+ @provider = provider
17
+ @author = author
18
+ @fields = fields
19
+ end
20
+
21
+ # @return [String, nil] title of the embed that will be displayed above everything else.
22
+ attr_accessor :title
23
+
24
+ # @return [String, nil] description for this embed
25
+ attr_accessor :description
26
+
27
+ # @return [String, nil] URL the title should point to
28
+ attr_accessor :url
29
+
30
+ # @return [Time, nil] timestamp for this embed. Will be displayed just below the title.
31
+ attr_accessor :timestamp
32
+
33
+ # @return [Integer, nil] the colour of the bar to the side, in decimal form
34
+ attr_reader :colour
35
+ alias_method :color, :colour
36
+
37
+ # Sets the colour of the bar to the side of the embed to something new.
38
+ # @param value [String, Integer, {Integer, Integer, Integer}, #to_i, nil] The colour in decimal, hexadecimal, R/G/B decimal, or nil to clear the embeds colour
39
+ # form.
40
+ def colour=(value)
41
+ if value.nil?
42
+ @colour = nil
43
+ elsif value.is_a? Integer
44
+ raise ArgumentError, "Embed colour must be 24-bit!" if value >= 16_777_216
45
+
46
+ @colour = value
47
+ elsif value.is_a? String
48
+ self.colour = value.delete("#").to_i(16)
49
+ elsif value.is_a? Array
50
+ raise ArgumentError, "Colour tuple must have three values!" if value.length != 3
51
+
52
+ self.colour = (value[0] << 16) | (value[1] << 8) | value[2]
53
+ else
54
+ self.colour = value.to_i
55
+ end
56
+ end
57
+
58
+ alias_method :color=, :colour=
59
+
60
+ # @example Add a footer to an embed
61
+ # embed.footer = Rubycord::Webhooks::EmbedFooter.new(text: 'Hello', icon_url: 'https://i.imgur.com/j69wMDu.jpg')
62
+ # @return [EmbedFooter, nil] footer for this embed
63
+ attr_accessor :footer
64
+
65
+ # @see EmbedImage
66
+ # @example Add a image to an embed
67
+ # embed.image = Rubycord::Webhooks::EmbedImage.new(url: 'https://i.imgur.com/PcMltU7.jpg')
68
+ # @return [EmbedImage, nil] image for this embed
69
+ attr_accessor :image
70
+
71
+ # @see EmbedThumbnail
72
+ # @example Add a thumbnail to an embed
73
+ # embed.thumbnail = Rubycord::Webhooks::EmbedThumbnail.new(url: 'https://i.imgur.com/xTG3a1I.jpg')
74
+ # @return [EmbedThumbnail, nil] thumbnail for this embed
75
+ attr_accessor :thumbnail
76
+
77
+ # @see EmbedAuthor
78
+ # @example Add a author to an embed
79
+ # embed.author = Rubycord::Webhooks::EmbedAuthor.new(name: 'meew0', url: 'https://github.com/meew0', icon_url: 'https://avatars2.githubusercontent.com/u/3662915?v=3&s=466')
80
+ # @return [EmbedAuthor, nil] author for this embed
81
+ attr_accessor :author
82
+
83
+ # Add a field object to this embed.
84
+ # @param field [EmbedField] The field to add.
85
+ def <<(field)
86
+ @fields << field
87
+ end
88
+
89
+ # Convenience method to add a field to the embed without having to create one manually.
90
+ # @see EmbedField
91
+ # @example Add a field to an embed, conveniently
92
+ # embed.add_field(name: 'A field', value: "The field's content")
93
+ # @param name [String] The field's name
94
+ # @param value [String] The field's value
95
+ # @param inline [true, false] Whether the field should be inline
96
+ def add_field(name: nil, value: nil, inline: nil)
97
+ self << EmbedField.new(name: name, value: value, inline: inline)
98
+ end
99
+
100
+ # @return [Array<EmbedField>] the fields attached to this embed.
101
+ attr_accessor :fields
102
+
103
+ # @return [Hash] a hash representation of this embed, to be converted to JSON.
104
+ def to_hash
105
+ {
106
+ title: @title,
107
+ description: @description,
108
+ url: @url,
109
+ timestamp: @timestamp&.utc&.iso8601,
110
+ color: @colour,
111
+ footer: @footer&.to_hash,
112
+ image: @image&.to_hash,
113
+ thumbnail: @thumbnail&.to_hash,
114
+ video: @video&.to_hash,
115
+ provider: @provider&.to_hash,
116
+ author: @author&.to_hash,
117
+ fields: @fields.map(&:to_hash)
118
+ }
119
+ end
120
+ end
121
+
122
+ # An embed's footer will be displayed at the very bottom of an embed, together with the timestamp. An icon URL can be
123
+ # set together with some text to be displayed.
124
+ class EmbedFooter
125
+ # @return [String, nil] text to be displayed in the footer
126
+ attr_accessor :text
127
+
128
+ # @return [String, nil] URL to an icon to be showed alongside the text
129
+ attr_accessor :icon_url
130
+
131
+ # Creates a new footer object.
132
+ # @param text [String, nil] The text to be displayed in the footer.
133
+ # @param icon_url [String, nil] The URL to an icon to be showed alongside the text.
134
+ def initialize(text: nil, icon_url: nil)
135
+ @text = text
136
+ @icon_url = icon_url
137
+ end
138
+
139
+ # @return [Hash] a hash representation of this embed footer, to be converted to JSON.
140
+ def to_hash
141
+ {
142
+ text: @text,
143
+ icon_url: @icon_url
144
+ }
145
+ end
146
+ end
147
+
148
+ # An embed's image will be displayed at the bottom, in large format. It will replace a footer icon URL if one is set.
149
+ class EmbedImage
150
+ # @return [String, nil] URL of the image
151
+ attr_accessor :url
152
+
153
+ # Creates a new image object.
154
+ # @param url [String, nil] The URL of the image.
155
+ def initialize(url: nil)
156
+ @url = url
157
+ end
158
+
159
+ # @return [Hash] a hash representation of this embed image, to be converted to JSON.
160
+ def to_hash
161
+ {
162
+ url: @url
163
+ }
164
+ end
165
+ end
166
+
167
+ # An embed's thumbnail will be displayed at the right of the message, next to the description and fields. When clicked
168
+ # it will point to the embed URL.
169
+ class EmbedThumbnail
170
+ # @return [String, nil] URL of the thumbnail
171
+ attr_accessor :url
172
+
173
+ # Creates a new thumbnail object.
174
+ # @param url [String, nil] The URL of the thumbnail.
175
+ def initialize(url: nil)
176
+ @url = url
177
+ end
178
+
179
+ # @return [Hash] a hash representation of this embed thumbnail, to be converted to JSON.
180
+ def to_hash
181
+ {
182
+ url: @url
183
+ }
184
+ end
185
+ end
186
+
187
+ # An embed's author will be shown at the top to indicate who "authored" the particular event the webhook was sent for.
188
+ class EmbedAuthor
189
+ # @return [String, nil] name of the author
190
+ attr_accessor :name
191
+
192
+ # @return [String, nil] URL the name should link to
193
+ attr_accessor :url
194
+
195
+ # @return [String, nil] URL of the icon to be displayed next to the author
196
+ attr_accessor :icon_url
197
+
198
+ # Creates a new author object.
199
+ # @param name [String, nil] The name of the author.
200
+ # @param url [String, nil] The URL the name should link to.
201
+ # @param icon_url [String, nil] The URL of the icon to be displayed next to the author.
202
+ def initialize(name: nil, url: nil, icon_url: nil)
203
+ @name = name
204
+ @url = url
205
+ @icon_url = icon_url
206
+ end
207
+
208
+ # @return [Hash] a hash representation of this embed author, to be converted to JSON.
209
+ def to_hash
210
+ {
211
+ name: @name,
212
+ url: @url,
213
+ icon_url: @icon_url
214
+ }
215
+ end
216
+ end
217
+
218
+ # A field is a small block of text with a header that can be relatively freely layouted with other fields.
219
+ class EmbedField
220
+ # @return [String, nil] name of the field, displayed in bold at the top of the field.
221
+ attr_accessor :name
222
+
223
+ # @return [String, nil] value of the field, displayed in normal text below the name.
224
+ attr_accessor :value
225
+
226
+ # @return [true, false] whether the field should be displayed inline with other fields.
227
+ attr_accessor :inline
228
+
229
+ # Creates a new field object.
230
+ # @param name [String, nil] The name of the field, displayed in bold at the top of the field.
231
+ # @param value [String, nil] The value of the field, displayed in normal text below the name.
232
+ # @param inline [true, false] Whether the field should be displayed inline with other fields.
233
+ def initialize(name: nil, value: nil, inline: false)
234
+ @name = name
235
+ @value = value
236
+ @inline = inline
237
+ end
238
+
239
+ # @return [Hash] a hash representation of this embed field, to be converted to JSON.
240
+ def to_hash
241
+ {
242
+ name: @name,
243
+ value: @value,
244
+ inline: @inline
245
+ }
246
+ end
247
+ end
248
+ end
@@ -0,0 +1,78 @@
1
+ # Modal component builder.
2
+ class Rubycord::Webhooks::Modal
3
+ # A mapping of names to types of components usable in a modal.
4
+ COMPONENT_TYPES = {
5
+ action_row: 1,
6
+ text_input: 4
7
+ }.freeze
8
+
9
+ # This builder is used when constructing an ActionRow. All current components must be within an action row, but this can
10
+ # change in the future. A message can have 5 action rows, each action row can hold a weight of 5. Buttons have a weight of 1,
11
+ # and dropdowns have a weight of 5.
12
+ class RowBuilder
13
+ # A mapping of short names to types of input styles. `short` is a single line where `paragraph` is a block.
14
+ TEXT_INPUT_STYLES = {
15
+ short: 1,
16
+ paragraph: 2
17
+ }.freeze
18
+
19
+ # @!visibility private
20
+ def initialize
21
+ @components = []
22
+ end
23
+
24
+ # Add a text input to this action row.
25
+ # @param style [Symbol, Integer] The text input's style type. See {TEXT_INPUT_STYLES}
26
+ # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions.
27
+ # There is a limit of 100 characters to each custom_id.
28
+ # @param label [String, nil] The text label for the field.
29
+ # @param min_length [Integer, nil] The minimum input length for a text input, min 0, max 4000.
30
+ # @param max_length [Integer, nil] The maximum input length for a text input, min 1, max 4000.
31
+ # @param required [true, false, nil] Whether this component is required to be filled, default true.
32
+ # @param value [String, nil] A pre-filled value for this component, max 4000 characters.
33
+ # @param placeholder [String, nil] Custom placeholder text if the input is empty, max 100 characters
34
+ def text_input(style:, custom_id:, label: nil, min_length: nil, max_length: nil, required: nil, value: nil, placeholder: nil)
35
+ style = TEXT_INPUT_STYLES[style] || style
36
+
37
+ @components << {
38
+ style: style,
39
+ custom_id: custom_id,
40
+ type: COMPONENT_TYPES[:text_input],
41
+ label: label,
42
+ min_length: min_length,
43
+ max_length: max_length,
44
+ required: required,
45
+ value: value,
46
+ placeholder: placeholder
47
+ }
48
+ end
49
+
50
+ # @!visibility private
51
+ def to_h
52
+ {type: COMPONENT_TYPES[:action_row], components: @components}
53
+ end
54
+ end
55
+
56
+ attr_reader :rows
57
+
58
+ def initialize
59
+ @rows = []
60
+
61
+ yield self if block_given?
62
+ end
63
+
64
+ # Add a new ActionRow to the view
65
+ # @yieldparam [RowBuilder]
66
+ def row
67
+ new_row = RowBuilder.new
68
+
69
+ yield new_row
70
+
71
+ @rows << new_row
72
+ end
73
+
74
+ # @!visibility private
75
+ def to_a
76
+ @rows.map(&:to_h)
77
+ end
78
+ end
@@ -0,0 +1,7 @@
1
+ # Webhook support for rubycord
2
+ module Rubycord
3
+ module Webhooks
4
+ # The current version of rubycord-webhooks.
5
+ VERSION = "1.0.0" unless const_defined?(:VERSION)
6
+ end
7
+ end
@@ -0,0 +1,192 @@
1
+ # A reusable view representing a component collection, with builder methods.
2
+ class Rubycord::Webhooks::View
3
+ # Possible button style names and values.
4
+ BUTTON_STYLES = {
5
+ primary: 1,
6
+ secondary: 2,
7
+ success: 3,
8
+ danger: 4,
9
+ link: 5
10
+ }.freeze
11
+
12
+ # Component types.
13
+ # @see https://discord.com/developers/docs/interactions/message-components#component-types
14
+ COMPONENT_TYPES = {
15
+ action_row: 1,
16
+ button: 2,
17
+ string_select: 3,
18
+ # text_input: 4, # (defined in modal.rb)
19
+ user_select: 5,
20
+ role_select: 6,
21
+ mentionable_select: 7,
22
+ channel_select: 8
23
+ }.freeze
24
+
25
+ # This builder is used when constructing an ActionRow. All current components must be within an action row, but this can
26
+ # change in the future. A message can have 5 action rows, each action row can hold a weight of 5. Buttons have a weight of 1,
27
+ # and dropdowns have a weight of 5.
28
+ class RowBuilder
29
+ # @!visibility private
30
+ def initialize
31
+ @components = []
32
+ end
33
+
34
+ # Add a button to this action row.
35
+ # @param style [Symbol, Integer] The button's style type. See {BUTTON_STYLES}
36
+ # @param label [String, nil] The text label for the button. Either a label or emoji must be provided.
37
+ # @param emoji [#to_h, String, Integer] An emoji ID, or unicode emoji to attach to the button. Can also be a object
38
+ # that responds to `#to_h` which returns a hash in the format of `{ id: Integer, name: string }`.
39
+ # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions.
40
+ # There is a limit of 100 characters to each custom_id.
41
+ # @param disabled [true, false] Whether this button is disabled and shown as greyed out.
42
+ # @param url [String, nil] The URL, when using a link style button.
43
+ def button(style:, label: nil, emoji: nil, custom_id: nil, disabled: nil, url: nil)
44
+ style = BUTTON_STYLES[style] || style
45
+
46
+ emoji = case emoji
47
+ when Integer, String
48
+ emoji.to_i.positive? ? {id: emoji} : {name: emoji}
49
+ else
50
+ emoji&.to_h
51
+ end
52
+
53
+ @components << {type: COMPONENT_TYPES[:button], label: label, emoji: emoji, style: style, custom_id: custom_id, disabled: disabled, url: url}
54
+ end
55
+
56
+ # Add a select string to this action row.
57
+ # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions.
58
+ # There is a limit of 100 characters to each custom_id.
59
+ # @param options [Array<Hash>] Options that can be selected in this menu. Can also be provided via the yielded builder.
60
+ # @param placeholder [String, nil] Default text to show when no entries are selected.
61
+ # @param min_values [Integer, nil] The minimum amount of values a user must select.
62
+ # @param max_values [Integer, nil] The maximum amount of values a user can select.
63
+ # @param disabled [true, false, nil] Grey out the component to make it unusable.
64
+ # @yieldparam builder [SelectMenuBuilder]
65
+ def string_select(custom_id:, options: [], placeholder: nil, min_values: nil, max_values: nil, disabled: nil)
66
+ builder = SelectMenuBuilder.new(custom_id, options, placeholder, min_values, max_values, disabled, select_type: :string_select)
67
+
68
+ yield builder if block_given?
69
+
70
+ @components << builder.to_h
71
+ end
72
+
73
+ alias_method :select_menu, :string_select
74
+
75
+ # Add a select user to this action row.
76
+ # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions.
77
+ # There is a limit of 100 characters to each custom_id.
78
+ # @param placeholder [String, nil] Default text to show when no entries are selected.
79
+ # @param min_values [Integer, nil] The minimum amount of values a user must select.
80
+ # @param max_values [Integer, nil] The maximum amount of values a user can select.
81
+ # @param disabled [true, false, nil] Grey out the component to make it unusable.
82
+ def user_select(custom_id:, placeholder: nil, min_values: nil, max_values: nil, disabled: nil)
83
+ @components << SelectMenuBuilder.new(custom_id, [], placeholder, min_values, max_values, disabled, select_type: :user_select).to_h
84
+ end
85
+
86
+ # Add a select role to this action row.
87
+ # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions.
88
+ # There is a limit of 100 characters to each custom_id.
89
+ # @param placeholder [String, nil] Default text to show when no entries are selected.
90
+ # @param min_values [Integer, nil] The minimum amount of values a user must select.
91
+ # @param max_values [Integer, nil] The maximum amount of values a user can select.
92
+ # @param disabled [true, false, nil] Grey out the component to make it unusable.
93
+ def role_select(custom_id:, placeholder: nil, min_values: nil, max_values: nil, disabled: nil)
94
+ @components << SelectMenuBuilder.new(custom_id, [], placeholder, min_values, max_values, disabled, select_type: :role_select).to_h
95
+ end
96
+
97
+ # Add a select mentionable to this action row.
98
+ # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions.
99
+ # There is a limit of 100 characters to each custom_id.
100
+ # @param placeholder [String, nil] Default text to show when no entries are selected.
101
+ # @param min_values [Integer, nil] The minimum amount of values a user must select.
102
+ # @param max_values [Integer, nil] The maximum amount of values a user can select.
103
+ # @param disabled [true, false, nil] Grey out the component to make it unusable.
104
+ def mentionable_select(custom_id:, placeholder: nil, min_values: nil, max_values: nil, disabled: nil)
105
+ @components << SelectMenuBuilder.new(custom_id, [], placeholder, min_values, max_values, disabled, select_type: :mentionable_select).to_h
106
+ end
107
+
108
+ # Add a select channel to this action row.
109
+ # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions.
110
+ # There is a limit of 100 characters to each custom_id.
111
+ # @param placeholder [String, nil] Default text to show when no entries are selected.
112
+ # @param min_values [Integer, nil] The minimum amount of values a user must select.
113
+ # @param max_values [Integer, nil] The maximum amount of values a user can select.
114
+ # @param disabled [true, false, nil] Grey out the component to make it unusable.
115
+ def channel_select(custom_id:, placeholder: nil, min_values: nil, max_values: nil, disabled: nil)
116
+ @components << SelectMenuBuilder.new(custom_id, [], placeholder, min_values, max_values, disabled, select_type: :channel_select).to_h
117
+ end
118
+
119
+ # @!visibility private
120
+ def to_h
121
+ {type: COMPONENT_TYPES[:action_row], components: @components}
122
+ end
123
+ end
124
+
125
+ # A builder to assist in adding options to select menus.
126
+ class SelectMenuBuilder
127
+ # @!visibility hidden
128
+ def initialize(custom_id, options = [], placeholder = nil, min_values = nil, max_values = nil, disabled = nil, select_type: :string_select)
129
+ @custom_id = custom_id
130
+ @options = options
131
+ @placeholder = placeholder
132
+ @min_values = min_values
133
+ @max_values = max_values
134
+ @disabled = disabled
135
+ @select_type = select_type
136
+ end
137
+
138
+ # Add an option to this select menu.
139
+ # @param label [String] The title of this option.
140
+ # @param value [String] The value that this option represents.
141
+ # @param description [String, nil] An optional description of the option.
142
+ # @param emoji [#to_h, String, Integer] An emoji ID, or unicode emoji to attach to the button. Can also be a object
143
+ # that responds to `#to_h` which returns a hash in the format of `{ id: Integer, name: string }`.
144
+ # @param default [true, false, nil] Whether this is the default selected option.
145
+ def option(label:, value:, description: nil, emoji: nil, default: nil)
146
+ emoji = case emoji
147
+ when Integer, String
148
+ emoji.to_i.positive? ? {id: emoji} : {name: emoji}
149
+ else
150
+ emoji&.to_h
151
+ end
152
+
153
+ @options << {label: label, value: value, description: description, emoji: emoji, default: default}
154
+ end
155
+
156
+ # @!visibility private
157
+ def to_h
158
+ {
159
+ type: COMPONENT_TYPES[@select_type],
160
+ options: @options,
161
+ placeholder: @placeholder,
162
+ min_values: @min_values,
163
+ max_values: @max_values,
164
+ custom_id: @custom_id,
165
+ disabled: @disabled
166
+ }
167
+ end
168
+ end
169
+
170
+ attr_reader :rows
171
+
172
+ def initialize
173
+ @rows = []
174
+
175
+ yield self if block_given?
176
+ end
177
+
178
+ # Add a new ActionRow to the view
179
+ # @yieldparam [RowBuilder]
180
+ def row
181
+ new_row = RowBuilder.new
182
+
183
+ yield new_row
184
+
185
+ @rows << new_row
186
+ end
187
+
188
+ # @!visibility private
189
+ def to_a
190
+ @rows.map(&:to_h)
191
+ end
192
+ end
@@ -0,0 +1,12 @@
1
+ require "rubycord/webhooks/version"
2
+ require "rubycord/webhooks/embeds"
3
+ require "rubycord/webhooks/client"
4
+ require "rubycord/webhooks/builder"
5
+ require "rubycord/webhooks/view"
6
+ require "rubycord/webhooks/modal"
7
+
8
+ module Rubycord
9
+ # Webhook client
10
+ module Webhooks
11
+ end
12
+ end
@@ -0,0 +1,70 @@
1
+ require "websocket-client-simple"
2
+
3
+ # The WSCS module which we're hooking
4
+ # @see Websocket::Client::Simple::Client
5
+ module WebSocket::Client::Simple
6
+ # Patch to the WSCS class to allow reading the internal thread
7
+ class Client
8
+ # @return [Thread] the internal thread this client is using for the event loop.
9
+ attr_reader :thread
10
+ end
11
+ end
12
+
13
+ module Rubycord
14
+ # Utility wrapper class that abstracts an instance of WSCS. Useful should we decide that WSCS isn't good either -
15
+ # in that case we can just switch to something else
16
+ class WebSocket
17
+ attr_reader :open_handler, :message_handler, :close_handler, :error_handler
18
+
19
+ # Create a new WebSocket and connect to the given endpoint.
20
+ # @param endpoint [String] Where to connect to.
21
+ # @param open_handler [#call] The handler that should be called when the websocket has opened successfully.
22
+ # @param message_handler [#call] The handler that should be called when the websocket receives a message. The
23
+ # handler can take one parameter which will have a `data` attribute for normal messages and `code` and `data` for
24
+ # close frames.
25
+ # @param close_handler [#call] The handler that should be called when the websocket is closed due to an internal
26
+ # error. The error will be passed as the first parameter to the handler.
27
+ # @param error_handler [#call] The handler that should be called when an error occurs in another handler. The error
28
+ # will be passed as the first parameter to the handler.
29
+ def initialize(endpoint, open_handler, message_handler, close_handler, error_handler)
30
+ Rubycord::LOGGER.debug "Using WSCS version: #{::WebSocket::Client::Simple::VERSION}"
31
+
32
+ @open_handler = open_handler
33
+ @message_handler = message_handler
34
+ @close_handler = close_handler
35
+ @error_handler = error_handler
36
+
37
+ instance = self # to work around WSCS's weird way of handling blocks
38
+
39
+ @client = ::WebSocket::Client::Simple.connect(endpoint) do |ws|
40
+ ws.on(:open) { instance.open_handler.call }
41
+ ws.on(:message) do |msg|
42
+ # If the message has a code attribute, it is in reality a close message
43
+ if msg.code
44
+ instance.close_handler.call(msg)
45
+ else
46
+ instance.message_handler.call(msg.data)
47
+ end
48
+ end
49
+ ws.on(:close) { |err| instance.close_handler.call(err) }
50
+ ws.on(:error) { |err| instance.error_handler.call(err) }
51
+ end
52
+ end
53
+
54
+ # Send data over this WebSocket
55
+ # @param data [String] What to send
56
+ def send(data)
57
+ @client.send(data)
58
+ end
59
+
60
+ # Close the WebSocket connection
61
+ def close
62
+ @client.close
63
+ end
64
+
65
+ # @return [Thread] the internal WSCS thread
66
+ def thread
67
+ @client.thread
68
+ end
69
+ end
70
+ end