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.
- checksums.yaml +7 -0
- data/.devcontainer/Dockerfile +13 -0
- data/.devcontainer/devcontainer.json +29 -0
- data/.devcontainer/postcreate.sh +4 -0
- data/.github/CONTRIBUTING.md +13 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
- data/.github/pull_request_template.md +37 -0
- data/.github/workflows/ci.yml +78 -0
- data/.github/workflows/codeql.yml +65 -0
- data/.github/workflows/deploy.yml +54 -0
- data/.github/workflows/release.yml +51 -0
- data/.gitignore +16 -0
- data/.markdownlint.json +4 -0
- data/.overcommit.yml +7 -0
- data/.rspec +2 -0
- data/.rubocop.yml +129 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +0 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +305 -0
- data/Rakefile +17 -0
- data/bin/console +15 -0
- data/bin/setup +7 -0
- data/lib/onyxcord/allowed_mentions.rb +43 -0
- data/lib/onyxcord/api/application.rb +316 -0
- data/lib/onyxcord/api/channel.rb +700 -0
- data/lib/onyxcord/api/interaction.rb +67 -0
- data/lib/onyxcord/api/invite.rb +44 -0
- data/lib/onyxcord/api/server.rb +775 -0
- data/lib/onyxcord/api/user.rb +158 -0
- data/lib/onyxcord/api/webhook.rb +163 -0
- data/lib/onyxcord/api.rb +335 -0
- data/lib/onyxcord/await.rb +51 -0
- data/lib/onyxcord/bot.rb +1971 -0
- data/lib/onyxcord/cache.rb +326 -0
- data/lib/onyxcord/colour_rgb.rb +43 -0
- data/lib/onyxcord/commands/command_bot.rb +511 -0
- data/lib/onyxcord/commands/container.rb +112 -0
- data/lib/onyxcord/commands/events.rb +11 -0
- data/lib/onyxcord/commands/parser.rb +327 -0
- data/lib/onyxcord/commands/rate_limiter.rb +144 -0
- data/lib/onyxcord/configuration.rb +125 -0
- data/lib/onyxcord/container.rb +988 -0
- data/lib/onyxcord/data/activity.rb +271 -0
- data/lib/onyxcord/data/application.rb +341 -0
- data/lib/onyxcord/data/attachment.rb +91 -0
- data/lib/onyxcord/data/audit_logs.rb +438 -0
- data/lib/onyxcord/data/avatar_decoration.rb +26 -0
- data/lib/onyxcord/data/call.rb +22 -0
- data/lib/onyxcord/data/channel.rb +1355 -0
- data/lib/onyxcord/data/channel_tag.rb +69 -0
- data/lib/onyxcord/data/collectibles.rb +47 -0
- data/lib/onyxcord/data/component.rb +583 -0
- data/lib/onyxcord/data/embed.rb +258 -0
- data/lib/onyxcord/data/emoji.rb +123 -0
- data/lib/onyxcord/data/install_params.rb +24 -0
- data/lib/onyxcord/data/integration.rb +144 -0
- data/lib/onyxcord/data/interaction.rb +1141 -0
- data/lib/onyxcord/data/invite.rb +137 -0
- data/lib/onyxcord/data/member.rb +528 -0
- data/lib/onyxcord/data/message.rb +612 -0
- data/lib/onyxcord/data/message_activity.rb +41 -0
- data/lib/onyxcord/data/overwrite.rb +109 -0
- data/lib/onyxcord/data/poll.rb +365 -0
- data/lib/onyxcord/data/primary_server.rb +60 -0
- data/lib/onyxcord/data/profile.rb +79 -0
- data/lib/onyxcord/data/reaction.rb +64 -0
- data/lib/onyxcord/data/recipient.rb +34 -0
- data/lib/onyxcord/data/role.rb +449 -0
- data/lib/onyxcord/data/role_connection_data.rb +69 -0
- data/lib/onyxcord/data/role_subscription.rb +41 -0
- data/lib/onyxcord/data/scheduled_event.rb +513 -0
- data/lib/onyxcord/data/server.rb +1614 -0
- data/lib/onyxcord/data/server_preview.rb +68 -0
- data/lib/onyxcord/data/snapshot.rb +112 -0
- data/lib/onyxcord/data/team.rb +98 -0
- data/lib/onyxcord/data/timestamp.rb +69 -0
- data/lib/onyxcord/data/user.rb +324 -0
- data/lib/onyxcord/data/voice_region.rb +46 -0
- data/lib/onyxcord/data/voice_state.rb +41 -0
- data/lib/onyxcord/data/webhook.rb +238 -0
- data/lib/onyxcord/data.rb +57 -0
- data/lib/onyxcord/errors.rb +246 -0
- data/lib/onyxcord/event_executor.rb +80 -0
- data/lib/onyxcord/events/await.rb +48 -0
- data/lib/onyxcord/events/bans.rb +60 -0
- data/lib/onyxcord/events/channels.rb +225 -0
- data/lib/onyxcord/events/generic.rb +129 -0
- data/lib/onyxcord/events/guilds.rb +269 -0
- data/lib/onyxcord/events/integrations.rb +100 -0
- data/lib/onyxcord/events/interactions.rb +624 -0
- data/lib/onyxcord/events/invites.rb +127 -0
- data/lib/onyxcord/events/lifetime.rb +31 -0
- data/lib/onyxcord/events/members.rb +110 -0
- data/lib/onyxcord/events/message.rb +399 -0
- data/lib/onyxcord/events/polls.rb +118 -0
- data/lib/onyxcord/events/presence.rb +131 -0
- data/lib/onyxcord/events/raw.rb +74 -0
- data/lib/onyxcord/events/reactions.rb +218 -0
- data/lib/onyxcord/events/roles.rb +87 -0
- data/lib/onyxcord/events/scheduled_events.rb +171 -0
- data/lib/onyxcord/events/threads.rb +100 -0
- data/lib/onyxcord/events/typing.rb +73 -0
- data/lib/onyxcord/events/voice_server_update.rb +48 -0
- data/lib/onyxcord/events/voice_state_update.rb +106 -0
- data/lib/onyxcord/events/webhooks.rb +65 -0
- data/lib/onyxcord/gateway.rb +890 -0
- data/lib/onyxcord/id_object.rb +39 -0
- data/lib/onyxcord/light/data.rb +62 -0
- data/lib/onyxcord/light/integrations.rb +73 -0
- data/lib/onyxcord/light/light_bot.rb +58 -0
- data/lib/onyxcord/light.rb +8 -0
- data/lib/onyxcord/logger.rb +120 -0
- data/lib/onyxcord/message_components.rb +70 -0
- data/lib/onyxcord/paginator.rb +60 -0
- data/lib/onyxcord/permissions.rb +255 -0
- data/lib/onyxcord/rate_limiter/gateway.rb +42 -0
- data/lib/onyxcord/rate_limiter/rest.rb +89 -0
- data/lib/onyxcord/version.rb +7 -0
- data/lib/onyxcord/voice/encoder.rb +115 -0
- data/lib/onyxcord/voice/network.rb +380 -0
- data/lib/onyxcord/voice/opcodes.rb +29 -0
- data/lib/onyxcord/voice/sodium.rb +157 -0
- data/lib/onyxcord/voice/timer.rb +19 -0
- data/lib/onyxcord/voice/voice_bot.rb +386 -0
- data/lib/onyxcord/webhooks.rb +14 -0
- data/lib/onyxcord/websocket.rb +62 -0
- data/lib/onyxcord.rb +180 -0
- data/onyxcord-webhooks.gemspec +30 -0
- data/onyxcord.gemspec +50 -0
- metadata +421 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnyxCord
|
|
4
|
+
# A forum or media tag that can be applied to threads.
|
|
5
|
+
class ChannelTag
|
|
6
|
+
include IDObject
|
|
7
|
+
|
|
8
|
+
# @return [String] the 1-20 character name of the channel tag.
|
|
9
|
+
attr_reader :name
|
|
10
|
+
|
|
11
|
+
# @return [Channel] the channel associated with the channel tag.
|
|
12
|
+
attr_reader :channel
|
|
13
|
+
|
|
14
|
+
# @return [true, false] whether or not the channel tag is moderated.
|
|
15
|
+
attr_reader :moderated
|
|
16
|
+
alias_method :moderated?, :moderated
|
|
17
|
+
|
|
18
|
+
# @!visibility private
|
|
19
|
+
def initialize(data, channel, bot)
|
|
20
|
+
@bot = bot
|
|
21
|
+
@channel = channel
|
|
22
|
+
@id = data['id'].to_i
|
|
23
|
+
@name = data['name']
|
|
24
|
+
@moderated = data['moderated']
|
|
25
|
+
@emoji_id = data['emoji_id']&.to_i
|
|
26
|
+
@emoji_name = Emoji.new({ 'name' => data['emoji_name'] }, @bot) if data['emoji_name']
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Get the emoji of the channel tag.
|
|
30
|
+
# @return [Emoji, nil] the emoji of the channel tag, or `nil` if no emoji has been set.
|
|
31
|
+
def emoji
|
|
32
|
+
@emoji_id ? @channel.server.emojis[@emoji_id] : @emoji_name
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Modify the properties of the channel tag.
|
|
36
|
+
# @param name [String] The new 1-20 character name of the channel tag.
|
|
37
|
+
# @param emoji [Emoji, Integer, String, nil] The new emoji of the channel tag.
|
|
38
|
+
# @param moderated [true, false] Whether or not the channel tag should be moderated.
|
|
39
|
+
# @param reason [String, nil] The reason to show in the audit log for modifying the tag.
|
|
40
|
+
# @return [nil]
|
|
41
|
+
def modify(name: :undef, emoji: :undef, moderated: :undef, reason: nil)
|
|
42
|
+
data = {
|
|
43
|
+
name: name,
|
|
44
|
+
moderated: moderated,
|
|
45
|
+
**(Emoji.build_emoji_hash(emoji) if emoji != :undef)
|
|
46
|
+
}.reject { |_, value| value == :undef }
|
|
47
|
+
|
|
48
|
+
@channel.update_tags(to_h.merge(data), reason)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Permenantly delete the channel tag.
|
|
52
|
+
# @param reason [String, nil] The reason to show in the audit log for deleting the tag.
|
|
53
|
+
# @return [nil]
|
|
54
|
+
def delete(reason: nil)
|
|
55
|
+
@channel.update_tags({ id: @id, d: true }, reason)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @!visibility private
|
|
59
|
+
def to_h
|
|
60
|
+
{
|
|
61
|
+
id: @id,
|
|
62
|
+
name: @name,
|
|
63
|
+
emoji_id: @emoji_id,
|
|
64
|
+
moderated: @moderated,
|
|
65
|
+
emoji_name: @emoji_name&.name
|
|
66
|
+
}
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnyxCord
|
|
4
|
+
# Collectibles are resources such as nameplates that can be collected by users.
|
|
5
|
+
class Collectibles
|
|
6
|
+
# @return [Nameplate, nil] the nameplate the user has collected or nil.
|
|
7
|
+
attr_reader :nameplate
|
|
8
|
+
|
|
9
|
+
# @!visibility private
|
|
10
|
+
def initialize(data, bot)
|
|
11
|
+
@bot = bot
|
|
12
|
+
@nameplate = Nameplate.new(data['nameplate'], bot) if data['nameplate']
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Collectable background images shown on a user's name in the member's tab.
|
|
16
|
+
class Nameplate
|
|
17
|
+
# @return [Integer] ID of the nameplate's SKU.
|
|
18
|
+
attr_reader :sku_id
|
|
19
|
+
|
|
20
|
+
# @return [String] the path to the nameplate asset.
|
|
21
|
+
attr_reader :asset
|
|
22
|
+
|
|
23
|
+
# @return [String] the label of the nameplate.
|
|
24
|
+
attr_reader :label
|
|
25
|
+
|
|
26
|
+
# @return [Symbol] the background color of the nameplate.
|
|
27
|
+
attr_reader :palette
|
|
28
|
+
|
|
29
|
+
# @!visibility private
|
|
30
|
+
def initialize(data, bot)
|
|
31
|
+
@bot = bot
|
|
32
|
+
@sku_id = data['sku_id']&.to_i
|
|
33
|
+
@asset = data['asset']
|
|
34
|
+
@label = data['label']
|
|
35
|
+
@palette = data['palette'].to_sym
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Utility method to get the URL of this nameplate.
|
|
39
|
+
# @param static [true, false] Whether to return the static URL of this
|
|
40
|
+
# nameplate instead of the animated URL.
|
|
41
|
+
# @return [String] The CDN url of this nameplate.
|
|
42
|
+
def url(static: false)
|
|
43
|
+
static ? API.static_nameplate_url(@asset) : API.nameplate_url(@asset)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,583 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnyxCord
|
|
4
|
+
# Components are interactable interfaces that can be attached to messages.
|
|
5
|
+
module Components
|
|
6
|
+
# @deprecated This alias will be removed in future releases.
|
|
7
|
+
class View < Webhooks::View
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# @!visibility private
|
|
11
|
+
def self.from_data(data, bot)
|
|
12
|
+
case data['type']
|
|
13
|
+
when Webhooks::View::COMPONENT_TYPES[:action_row]
|
|
14
|
+
ActionRow.new(data, bot)
|
|
15
|
+
when Webhooks::View::COMPONENT_TYPES[:button]
|
|
16
|
+
Button.new(data, bot)
|
|
17
|
+
when Webhooks::View::COMPONENT_TYPES[:string_select], Webhooks::View::COMPONENT_TYPES[:user_select], Webhooks::View::COMPONENT_TYPES[:role_select], Webhooks::View::COMPONENT_TYPES[:mentionable_select], Webhooks::View::COMPONENT_TYPES[:channel_select]
|
|
18
|
+
SelectMenu.new(data, bot)
|
|
19
|
+
when Webhooks::Modal::COMPONENT_TYPES[:text_input]
|
|
20
|
+
TextInput.new(data, bot)
|
|
21
|
+
when Webhooks::View::COMPONENT_TYPES[:section]
|
|
22
|
+
Section.new(data, bot)
|
|
23
|
+
when Webhooks::View::COMPONENT_TYPES[:text_display]
|
|
24
|
+
TextDisplay.new(data, bot)
|
|
25
|
+
when Webhooks::View::COMPONENT_TYPES[:thumbnail]
|
|
26
|
+
Thumbnail.new(data, bot)
|
|
27
|
+
when Webhooks::View::COMPONENT_TYPES[:media_gallery]
|
|
28
|
+
MediaGallery.new(data, bot)
|
|
29
|
+
when Webhooks::View::COMPONENT_TYPES[:file]
|
|
30
|
+
File.new(data, bot)
|
|
31
|
+
when Webhooks::View::COMPONENT_TYPES[:separator]
|
|
32
|
+
Separator.new(data, bot)
|
|
33
|
+
when Webhooks::View::COMPONENT_TYPES[:container]
|
|
34
|
+
Container.new(data, bot)
|
|
35
|
+
when Webhooks::Modal::COMPONENT_TYPES[:label]
|
|
36
|
+
Label.new(data, bot)
|
|
37
|
+
when Webhooks::Modal::COMPONENT_TYPES[:file_upload]
|
|
38
|
+
FileUpload.new(data, bot)
|
|
39
|
+
when Webhooks::Modal::COMPONENT_TYPES[:radio_group]
|
|
40
|
+
RadioGroup.new(data, bot)
|
|
41
|
+
when Webhooks::Modal::COMPONENT_TYPES[:checkbox_group]
|
|
42
|
+
CheckboxGroup.new(data, bot)
|
|
43
|
+
when Webhooks::Modal::COMPONENT_TYPES[:checkbox]
|
|
44
|
+
Checkbox.new(data, bot)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Represents a row of components.
|
|
49
|
+
class ActionRow
|
|
50
|
+
include Enumerable
|
|
51
|
+
|
|
52
|
+
# @return [Integer] the numeric identifier of the action row.
|
|
53
|
+
attr_reader :id
|
|
54
|
+
|
|
55
|
+
# @return [Array<Button>] the components contained within this action row.
|
|
56
|
+
attr_reader :components
|
|
57
|
+
|
|
58
|
+
# @!visibility private
|
|
59
|
+
def initialize(data, bot)
|
|
60
|
+
@bot = bot
|
|
61
|
+
@id = data['id']
|
|
62
|
+
@components = data['components'].filter_map { |component| Components.from_data(component, @bot) }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Iterate over each component in the row.
|
|
66
|
+
# @return [Array, Enumerator]
|
|
67
|
+
def each(&block)
|
|
68
|
+
@components.each(&block)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Get all the buttons in this action row.
|
|
72
|
+
# @return [Array<Button>] All of the buttons in this action row.
|
|
73
|
+
def buttons
|
|
74
|
+
select { |component| component.is_a?(Button) }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Get all the text inputs in this action row.
|
|
78
|
+
# @return [Array<TextInput>] All of the text inputs in this action row.
|
|
79
|
+
def text_inputs
|
|
80
|
+
select { |component| component.is_a?(TextInput) }
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# @!visibility private
|
|
84
|
+
def to_a
|
|
85
|
+
@components
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# An interactable button component.
|
|
90
|
+
class Button
|
|
91
|
+
# @return [Integer] the numeric identifier of the button.
|
|
92
|
+
attr_reader :id
|
|
93
|
+
|
|
94
|
+
# @return [String] the label of the button.
|
|
95
|
+
attr_reader :label
|
|
96
|
+
|
|
97
|
+
# @return [Integer] the style of the button.
|
|
98
|
+
attr_reader :style
|
|
99
|
+
|
|
100
|
+
# @return [String] the custom ID of the button.
|
|
101
|
+
attr_reader :custom_id
|
|
102
|
+
|
|
103
|
+
# @return [true, false] whether or not the button is disabled.
|
|
104
|
+
attr_reader :disabled
|
|
105
|
+
|
|
106
|
+
# @return [String, nil] the URL of the button if applicable.
|
|
107
|
+
attr_reader :url
|
|
108
|
+
|
|
109
|
+
# @return [Integer, nil] the SKU ID of the button if it is a premium button.
|
|
110
|
+
attr_reader :sku_id
|
|
111
|
+
|
|
112
|
+
# @return [Emoji, nil] the custom emoji of the button component.
|
|
113
|
+
attr_reader :emoji
|
|
114
|
+
|
|
115
|
+
# @!visibility private
|
|
116
|
+
def initialize(data, bot)
|
|
117
|
+
@bot = bot
|
|
118
|
+
@id = data['id']
|
|
119
|
+
@label = data['label']
|
|
120
|
+
@style = data['style']
|
|
121
|
+
@custom_id = data['custom_id']
|
|
122
|
+
@disabled = data['disabled']
|
|
123
|
+
@url = data['url']
|
|
124
|
+
@sku_id = data['sku_id']&.to_i
|
|
125
|
+
@emoji = Emoji.new(data['emoji'], @bot) if data['emoji']
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# @!method primary?
|
|
129
|
+
# @return [true, false] whether the button is a primary option in the group.
|
|
130
|
+
# @!method secondary?
|
|
131
|
+
# @return [true, false] whether the button denotes a secondary option in the group.
|
|
132
|
+
# @!method success?
|
|
133
|
+
# @return [true, false] whether the button denotes a success action in the group.
|
|
134
|
+
# @!method danger?
|
|
135
|
+
# @return [true, false] whether the button denotes a dangerous action in the group.
|
|
136
|
+
# @!method link?
|
|
137
|
+
# @return [true, false] whether the button is a container for a URL that will open upon click.
|
|
138
|
+
# @!method premium?
|
|
139
|
+
# @return [true, false] whether the button starts a premium SKU purchase.
|
|
140
|
+
Webhooks::View::BUTTON_STYLES.each do |name, value|
|
|
141
|
+
define_method("#{name}?") do
|
|
142
|
+
@style == value
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Await a button click.
|
|
147
|
+
def await_click(key, **attributes, &block)
|
|
148
|
+
@bot.add_await(key, OnyxCord::Events::ButtonEvent, { custom_id: @custom_id }.merge!(attributes), &block)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Await a button click, blocking.
|
|
152
|
+
def await_click!(**attributes, &block)
|
|
153
|
+
@bot.add_await!(OnyxCord::Events::ButtonEvent, { custom_id: @custom_id }.merge!(attributes), &block)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# An interactable select menu component.
|
|
158
|
+
class SelectMenu
|
|
159
|
+
# A select menu option.
|
|
160
|
+
class Option
|
|
161
|
+
# @return [String] the label of the option.
|
|
162
|
+
attr_reader :label
|
|
163
|
+
|
|
164
|
+
# @return [String] the value of the option.
|
|
165
|
+
attr_reader :value
|
|
166
|
+
|
|
167
|
+
# @return [String, nil] the description of the option.
|
|
168
|
+
attr_reader :description
|
|
169
|
+
|
|
170
|
+
# @return [Emoji, nil] the emoji of the option, or `nil`.
|
|
171
|
+
attr_reader :emoji
|
|
172
|
+
|
|
173
|
+
# @!visibility private
|
|
174
|
+
def initialize(data)
|
|
175
|
+
@label = data['label']
|
|
176
|
+
@value = data['value']
|
|
177
|
+
@description = data['description']
|
|
178
|
+
@emoji = Emoji.new(data['emoji'], @bot) if data['emoji']
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# @return [Integer] the numeric identifier of the select menu.
|
|
183
|
+
attr_reader :id
|
|
184
|
+
|
|
185
|
+
# @return [Array<String>] the submitted values from the modal.
|
|
186
|
+
attr_reader :values
|
|
187
|
+
|
|
188
|
+
# @return [String] the custom ID used to identify the select menu.
|
|
189
|
+
attr_reader :custom_id
|
|
190
|
+
|
|
191
|
+
# @return [Integer, nil] the minimum amount of values that be selected.
|
|
192
|
+
attr_reader :max_values
|
|
193
|
+
|
|
194
|
+
# @return [Integer, nil] the maximum amount of values that can be selected.
|
|
195
|
+
attr_reader :min_values
|
|
196
|
+
|
|
197
|
+
# @return [String, nil] the default placeholder text shown on the select menu.
|
|
198
|
+
attr_reader :placeholder
|
|
199
|
+
|
|
200
|
+
# @return [Array<Option>] the options in the select menu, or the selected options.
|
|
201
|
+
attr_reader :options
|
|
202
|
+
|
|
203
|
+
# @!visibility private
|
|
204
|
+
def initialize(data, bot)
|
|
205
|
+
@bot = bot
|
|
206
|
+
@id = data['id']
|
|
207
|
+
@values = data['values'] || []
|
|
208
|
+
@custom_id = data['custom_id']
|
|
209
|
+
@max_values = data['max_values']
|
|
210
|
+
@min_values = data['min_values']
|
|
211
|
+
@placeholder = data['placeholder']
|
|
212
|
+
@options = data['options']&.map { |option| Option.new(option) } || []
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# A free-form text input bar in a modal.
|
|
217
|
+
class TextInput
|
|
218
|
+
# @!visibility private
|
|
219
|
+
PLACEHOLDERS = %i[
|
|
220
|
+
label
|
|
221
|
+
min_length
|
|
222
|
+
max_length
|
|
223
|
+
required
|
|
224
|
+
required?
|
|
225
|
+
placeholder
|
|
226
|
+
].freeze
|
|
227
|
+
|
|
228
|
+
# @!visibility private
|
|
229
|
+
SHORT = 1
|
|
230
|
+
|
|
231
|
+
# @!visibility private
|
|
232
|
+
PARAGRAPH = 2
|
|
233
|
+
|
|
234
|
+
# @return [Integer] the numeric identifier of the text input.
|
|
235
|
+
attr_reader :id
|
|
236
|
+
|
|
237
|
+
# @return [Symbol] This is deprecated and not accurate. This will
|
|
238
|
+
# be removed in the next major version (4.0.0).
|
|
239
|
+
attr_reader :style
|
|
240
|
+
|
|
241
|
+
# @return [String, nil] the value the user typed into the text input.
|
|
242
|
+
attr_reader :value
|
|
243
|
+
|
|
244
|
+
# @return [String] the developer-defined identifier for the text input.
|
|
245
|
+
attr_reader :custom_id
|
|
246
|
+
|
|
247
|
+
# @!visibility private
|
|
248
|
+
def initialize(data, bot)
|
|
249
|
+
@bot = bot
|
|
250
|
+
@id = data['id']
|
|
251
|
+
@style = :paragraph
|
|
252
|
+
@value = data['value']
|
|
253
|
+
@custom_id = data['custom_id']
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# @!visibility private
|
|
257
|
+
PLACEHOLDERS.each { |name| define_method(name) { nil } }
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# A grouping of components with a contextual accessory.
|
|
261
|
+
class Section
|
|
262
|
+
# @return [Integer] the numeric identifier of the section.
|
|
263
|
+
attr_reader :id
|
|
264
|
+
|
|
265
|
+
# @return [Component] the contextual accessory of the section.
|
|
266
|
+
attr_reader :accessory
|
|
267
|
+
|
|
268
|
+
# @return [Array<Component>] the child components of the section.
|
|
269
|
+
attr_reader :components
|
|
270
|
+
|
|
271
|
+
# @!visibility private
|
|
272
|
+
def initialize(data, bot)
|
|
273
|
+
@bot = bot
|
|
274
|
+
@id = data['id']
|
|
275
|
+
@accessory = Components.from_data(data['accessory'], @bot)
|
|
276
|
+
@components = data['components'].filter_map { |component| Components.from_data(component, @bot) }
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# A content component representing message content.
|
|
281
|
+
class TextDisplay
|
|
282
|
+
# @return [Integer] the numeric identifier of the text display.
|
|
283
|
+
attr_reader :id
|
|
284
|
+
|
|
285
|
+
# @return [String] the content to be displayed for the text display.
|
|
286
|
+
attr_reader :content
|
|
287
|
+
|
|
288
|
+
# @!visibility private
|
|
289
|
+
def initialize(data, bot)
|
|
290
|
+
@bot = bot
|
|
291
|
+
@id = data['id']
|
|
292
|
+
@content = data['content']
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# A content component that compactly displays media.
|
|
297
|
+
class Thumbnail
|
|
298
|
+
# @return [Integer] the numeric identifier of the thumbnail.
|
|
299
|
+
attr_reader :id
|
|
300
|
+
|
|
301
|
+
# @return [MediaItem] the unfurled media content of the thumbnail.
|
|
302
|
+
attr_reader :media
|
|
303
|
+
|
|
304
|
+
# @return [true, false] whether or not the thumbnail's media should
|
|
305
|
+
# be blurred out.
|
|
306
|
+
attr_reader :spoiler
|
|
307
|
+
alias spoiler? spoiler
|
|
308
|
+
|
|
309
|
+
# @return [String, nil] the alternative text for the thumbnail's media.
|
|
310
|
+
attr_reader :description
|
|
311
|
+
|
|
312
|
+
# @!visibility private
|
|
313
|
+
def initialize(data, bot)
|
|
314
|
+
@bot = bot
|
|
315
|
+
@id = data['id']
|
|
316
|
+
@spoiler = data['spoiler']
|
|
317
|
+
@description = data['description']
|
|
318
|
+
@media = MediaItem.new(data['media'], @bot)
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
# A grouping of media attachments in an organized gallery format.
|
|
323
|
+
class MediaGallery
|
|
324
|
+
# @return [Integer] the numeric identifier of the media gallery.
|
|
325
|
+
attr_reader :id
|
|
326
|
+
|
|
327
|
+
# @return [Array<Item>] the media items contained within the media gallery.
|
|
328
|
+
attr_reader :items
|
|
329
|
+
|
|
330
|
+
# @!visibility private
|
|
331
|
+
def initialize(data, bot)
|
|
332
|
+
@bot = bot
|
|
333
|
+
@id = data['id']
|
|
334
|
+
@items = data['items'].map { |item| Item.new(item, @bot) }
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
# A singular media attachment.
|
|
338
|
+
class Item
|
|
339
|
+
# @return [MediaItem] the unfurled media content of the gallery item.
|
|
340
|
+
attr_reader :media
|
|
341
|
+
|
|
342
|
+
# @return [true, false] whether or not the gallery item's media should
|
|
343
|
+
# be blurred out.
|
|
344
|
+
attr_reader :spoiler
|
|
345
|
+
alias spoiler? spoiler
|
|
346
|
+
|
|
347
|
+
# @return [String, nil] the alternative text for the gallery item's media.
|
|
348
|
+
attr_reader :description
|
|
349
|
+
|
|
350
|
+
# @!visibility private
|
|
351
|
+
def initialize(data, bot)
|
|
352
|
+
@bot = bot
|
|
353
|
+
@spoiler = data['spoiler']
|
|
354
|
+
@description = data['description']
|
|
355
|
+
@media = MediaItem.new(data['media'], @bot)
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# A component that adds vertical padding and visual division.
|
|
361
|
+
class Separator
|
|
362
|
+
# @return [Integer] the numeric identifier of the separator.
|
|
363
|
+
attr_reader :id
|
|
364
|
+
|
|
365
|
+
# @return [true, false] whether or not a visual divider should be displayed.
|
|
366
|
+
attr_reader :divider
|
|
367
|
+
alias divider? divider
|
|
368
|
+
|
|
369
|
+
# @return [Integer] the size of the separator's padding. `1` for little padding,
|
|
370
|
+
# and `2` for big padding.
|
|
371
|
+
attr_reader :spacing
|
|
372
|
+
|
|
373
|
+
# @!visibility private
|
|
374
|
+
def initialize(data, bot)
|
|
375
|
+
@bot = bot
|
|
376
|
+
@id = data['id']
|
|
377
|
+
@divider = data['divider']
|
|
378
|
+
@spacing = data['spacing']
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
# A collection of components in an embed-like format.
|
|
383
|
+
class Container
|
|
384
|
+
# @return [Integer] the numeric identifier of the container.
|
|
385
|
+
attr_reader :id
|
|
386
|
+
|
|
387
|
+
# @return [ColourRGB, nil] the accent colour of the container.
|
|
388
|
+
attr_reader :color
|
|
389
|
+
alias colour color
|
|
390
|
+
|
|
391
|
+
# @return [true, false] whether or not the container should be
|
|
392
|
+
# blurred out.
|
|
393
|
+
attr_reader :spoiler
|
|
394
|
+
alias spoiler? spoiler
|
|
395
|
+
|
|
396
|
+
# @return [Array<Component>] the child components of the container.
|
|
397
|
+
attr_reader :components
|
|
398
|
+
|
|
399
|
+
# @!visibility private
|
|
400
|
+
def initialize(data, bot)
|
|
401
|
+
@bot = bot
|
|
402
|
+
@id = data['id']
|
|
403
|
+
@spoiler = data['spoiler']
|
|
404
|
+
@color = ColourRGB.new(data['accent_color']) if data['accent_color']
|
|
405
|
+
@components = data['components'].filter_map { |component| Components.from_data(component, @bot) }
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
# Get the buttons contained within the container.
|
|
409
|
+
# @return [Array<Button>] The buttons within the container.
|
|
410
|
+
def buttons
|
|
411
|
+
@components.flat_map do |component|
|
|
412
|
+
case component
|
|
413
|
+
when ActionRow
|
|
414
|
+
component.buttons
|
|
415
|
+
when Section
|
|
416
|
+
component.accessory if component.accessory.is_a?(Button)
|
|
417
|
+
end
|
|
418
|
+
end.compact
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
# A component that allows you to display an attachment.
|
|
423
|
+
class File
|
|
424
|
+
# @return [Integer] the numeric identifier of the file.
|
|
425
|
+
attr_reader :id
|
|
426
|
+
|
|
427
|
+
# @return [String] the name of the file that was uploaded.
|
|
428
|
+
attr_reader :name
|
|
429
|
+
|
|
430
|
+
# @return [Integer] the size of the file that was uploaded
|
|
431
|
+
# in bytes.
|
|
432
|
+
attr_reader :size
|
|
433
|
+
|
|
434
|
+
# @return [MediaItem] the unfurled media item of the file.
|
|
435
|
+
attr_reader :media
|
|
436
|
+
|
|
437
|
+
# @return [true, false] whether or not the file should be
|
|
438
|
+
# blurred out.
|
|
439
|
+
attr_reader :spoiler
|
|
440
|
+
alias spoiler? spoiler
|
|
441
|
+
|
|
442
|
+
# @!visibility private
|
|
443
|
+
def initialize(data, bot)
|
|
444
|
+
@bot = bot
|
|
445
|
+
@id = data['id']
|
|
446
|
+
@name = data['name']
|
|
447
|
+
@size = data['size']
|
|
448
|
+
@spoiler = data['spoiler']
|
|
449
|
+
@media = MediaItem.new(data['file'], @bot)
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
# Resolved metadata about a piece of media.
|
|
454
|
+
class MediaItem
|
|
455
|
+
# @return [String] the URL to the media item.
|
|
456
|
+
attr_reader :url
|
|
457
|
+
|
|
458
|
+
# @return [Integer, nil] the width of the media item.
|
|
459
|
+
attr_reader :width
|
|
460
|
+
|
|
461
|
+
# @return [Integer, nil] the height of the media item.
|
|
462
|
+
attr_reader :height
|
|
463
|
+
|
|
464
|
+
# @return [String, nil] the proxied URL to the media item.
|
|
465
|
+
attr_reader :proxy_url
|
|
466
|
+
|
|
467
|
+
# @return [String, nil] the content type of the media item.
|
|
468
|
+
attr_reader :content_type
|
|
469
|
+
|
|
470
|
+
# @return [Integer, nil] the ID of the uploaded attachment. Only present
|
|
471
|
+
# when the media item was uploaded via an `attachment://<filename>` reference.
|
|
472
|
+
attr_reader :attachment_id
|
|
473
|
+
|
|
474
|
+
# @!visibility private
|
|
475
|
+
def initialize(data, bot)
|
|
476
|
+
@bot = bot
|
|
477
|
+
@url = data['url']
|
|
478
|
+
@width = data['width']
|
|
479
|
+
@height = data['height']
|
|
480
|
+
@proxy_url = data['proxy_url']
|
|
481
|
+
@content_type = data['content_type']
|
|
482
|
+
@attachment_id = data['attachment_id']&.to_i
|
|
483
|
+
end
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
# A parent component for interactive modal components.
|
|
487
|
+
class Label
|
|
488
|
+
# @return [Integer] the numeric identifier of the label.
|
|
489
|
+
attr_reader :id
|
|
490
|
+
|
|
491
|
+
# @return [Component] the interactive component of the label.
|
|
492
|
+
attr_reader :component
|
|
493
|
+
|
|
494
|
+
# @!visibility private
|
|
495
|
+
def initialize(data, bot)
|
|
496
|
+
@bot = bot
|
|
497
|
+
@id = data['id']
|
|
498
|
+
@component = Components.from_data(data['component'], @bot)
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
# A surface that allows users to upload files in a modal.
|
|
503
|
+
class FileUpload
|
|
504
|
+
# @return [Integer] the numeric identifier of the file upload.
|
|
505
|
+
attr_reader :id
|
|
506
|
+
|
|
507
|
+
# @return [Array<Integer>] the IDs of the uploaded attachments.
|
|
508
|
+
attr_reader :values
|
|
509
|
+
|
|
510
|
+
# @return [String] the developer-defined identifier for the file upload.
|
|
511
|
+
attr_reader :custom_id
|
|
512
|
+
|
|
513
|
+
# @!visibility private
|
|
514
|
+
def initialize(data, bot)
|
|
515
|
+
@bot = bot
|
|
516
|
+
@id = data['id']
|
|
517
|
+
@custom_id = data['custom_id']
|
|
518
|
+
@values = data['values'].map(&:to_i)
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
# A grouping of radio buttons in a modal.
|
|
523
|
+
class RadioGroup
|
|
524
|
+
# @return [Integer] the numeric identifier of the radio group.
|
|
525
|
+
attr_reader :id
|
|
526
|
+
|
|
527
|
+
# @return [String, nil] whether or not a radio button was selected.
|
|
528
|
+
attr_reader :value
|
|
529
|
+
|
|
530
|
+
# @return [String] the developer-defined identifier of the radio group.
|
|
531
|
+
attr_reader :custom_id
|
|
532
|
+
|
|
533
|
+
# @!visibility private
|
|
534
|
+
def initialize(data, bot)
|
|
535
|
+
@bot = bot
|
|
536
|
+
@id = data['id']
|
|
537
|
+
@value = data['value']
|
|
538
|
+
@custom_id = data['custom_id']
|
|
539
|
+
end
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
# A grouping of checkboxes in a modal.
|
|
543
|
+
class CheckboxGroup
|
|
544
|
+
# @return [Integer] the numeric identifier of the checkbox group.
|
|
545
|
+
attr_reader :id
|
|
546
|
+
|
|
547
|
+
# @return [Array<String>] the values of the selected checkbox buttons.
|
|
548
|
+
attr_reader :values
|
|
549
|
+
|
|
550
|
+
# @return [String] the developer-defined identifier of the checkbox group.
|
|
551
|
+
attr_reader :custom_id
|
|
552
|
+
|
|
553
|
+
# @!visibility private
|
|
554
|
+
def initialize(data, bot)
|
|
555
|
+
@bot = bot
|
|
556
|
+
@id = data['id']
|
|
557
|
+
@values = data['values']
|
|
558
|
+
@custom_id = data['custom_id']
|
|
559
|
+
end
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
# A checkbox that can be ticked in a modal.
|
|
563
|
+
class Checkbox
|
|
564
|
+
# @return [Integer] the numeric identifier of the checkbox.
|
|
565
|
+
attr_reader :id
|
|
566
|
+
|
|
567
|
+
# @return [true, false] whether or not the checkbox was selected.
|
|
568
|
+
attr_reader :value
|
|
569
|
+
alias value? value
|
|
570
|
+
|
|
571
|
+
# @return [String] the developer-defined identifier of the checkbox.
|
|
572
|
+
attr_reader :custom_id
|
|
573
|
+
|
|
574
|
+
# @!visibility private
|
|
575
|
+
def initialize(data, bot)
|
|
576
|
+
@bot = bot
|
|
577
|
+
@id = data['id']
|
|
578
|
+
@value = data['value']
|
|
579
|
+
@custom_id = data['custom_id']
|
|
580
|
+
end
|
|
581
|
+
end
|
|
582
|
+
end
|
|
583
|
+
end
|