discordrb 3.4.0 → 3.5.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 +4 -4
- data/.circleci/config.yml +44 -18
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -1
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -1
- data/.github/workflows/codeql.yml +65 -0
- data/.markdownlint.json +4 -0
- data/.rubocop.yml +8 -2
- data/CHANGELOG.md +419 -222
- data/LICENSE.txt +1 -1
- data/README.md +37 -25
- data/discordrb-webhooks.gemspec +4 -1
- data/discordrb.gemspec +9 -6
- data/lib/discordrb/api/application.rb +202 -0
- data/lib/discordrb/api/channel.rb +182 -11
- data/lib/discordrb/api/interaction.rb +54 -0
- data/lib/discordrb/api/invite.rb +2 -2
- data/lib/discordrb/api/server.rb +42 -19
- data/lib/discordrb/api/user.rb +9 -3
- data/lib/discordrb/api/webhook.rb +57 -0
- data/lib/discordrb/api.rb +19 -5
- data/lib/discordrb/bot.rb +328 -33
- data/lib/discordrb/cache.rb +27 -22
- data/lib/discordrb/commands/command_bot.rb +14 -7
- data/lib/discordrb/commands/container.rb +1 -1
- data/lib/discordrb/commands/parser.rb +2 -2
- data/lib/discordrb/commands/rate_limiter.rb +1 -1
- data/lib/discordrb/container.rb +132 -3
- data/lib/discordrb/data/activity.rb +8 -1
- data/lib/discordrb/data/attachment.rb +15 -0
- data/lib/discordrb/data/audit_logs.rb +3 -3
- data/lib/discordrb/data/channel.rb +167 -23
- data/lib/discordrb/data/component.rb +229 -0
- data/lib/discordrb/data/integration.rb +42 -3
- data/lib/discordrb/data/interaction.rb +800 -0
- data/lib/discordrb/data/invite.rb +2 -2
- data/lib/discordrb/data/member.rb +108 -33
- data/lib/discordrb/data/message.rb +100 -20
- data/lib/discordrb/data/overwrite.rb +13 -7
- data/lib/discordrb/data/role.rb +58 -1
- data/lib/discordrb/data/server.rb +82 -80
- data/lib/discordrb/data/user.rb +69 -9
- data/lib/discordrb/data/webhook.rb +97 -4
- data/lib/discordrb/data.rb +3 -0
- data/lib/discordrb/errors.rb +44 -3
- data/lib/discordrb/events/channels.rb +1 -1
- data/lib/discordrb/events/interactions.rb +482 -0
- data/lib/discordrb/events/message.rb +9 -6
- data/lib/discordrb/events/presence.rb +21 -14
- data/lib/discordrb/events/reactions.rb +0 -1
- data/lib/discordrb/events/threads.rb +96 -0
- data/lib/discordrb/gateway.rb +30 -17
- data/lib/discordrb/permissions.rb +59 -34
- data/lib/discordrb/version.rb +1 -1
- data/lib/discordrb/voice/encoder.rb +13 -4
- data/lib/discordrb/voice/network.rb +18 -7
- data/lib/discordrb/voice/sodium.rb +3 -1
- data/lib/discordrb/voice/voice_bot.rb +3 -3
- data/lib/discordrb/webhooks.rb +2 -0
- data/lib/discordrb.rb +37 -4
- metadata +53 -19
- data/.codeclimate.yml +0 -16
- data/.travis.yml +0 -32
- data/bin/travis_build_docs.sh +0 -17
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'discordrb/webhooks/view'
|
4
|
+
require 'time'
|
5
|
+
|
3
6
|
module Discordrb
|
4
7
|
# A Discord channel, including data like the topic
|
5
8
|
class Channel
|
@@ -13,23 +16,28 @@ module Discordrb
|
|
13
16
|
group: 3,
|
14
17
|
category: 4,
|
15
18
|
news: 5,
|
16
|
-
store: 6
|
19
|
+
store: 6,
|
20
|
+
news_thread: 10,
|
21
|
+
public_thread: 11,
|
22
|
+
private_thread: 12,
|
23
|
+
stage_voice: 13,
|
24
|
+
directory: 14,
|
25
|
+
forum: 15
|
17
26
|
}.freeze
|
18
27
|
|
19
28
|
# @return [String] this channel's name.
|
20
29
|
attr_reader :name
|
21
30
|
|
22
|
-
# @return [
|
23
|
-
|
24
|
-
|
25
|
-
# @return [Integer, nil] the ID of the parent channel, if this channel is inside a category
|
31
|
+
# @return [Integer, nil] the ID of the parent channel, if this channel is inside a category. If this channel is a
|
32
|
+
# thread, this is the text channel it is a child to.
|
26
33
|
attr_reader :parent_id
|
27
34
|
|
28
35
|
# @return [Integer] the type of this channel
|
29
36
|
# @see TYPES
|
30
37
|
attr_reader :type
|
31
38
|
|
32
|
-
# @return [Integer, nil] the ID of the owner of the group channel or nil if this is not a group channel.
|
39
|
+
# @return [Integer, nil] the ID of the owner of the group channel or nil if this is not a group channel. If this
|
40
|
+
# channel is a thread, this is the member that started the thread.
|
33
41
|
attr_reader :owner_id
|
34
42
|
|
35
43
|
# @return [Array<Recipient>, nil] the array of recipients of the private messages, or nil if this is not a Private channel
|
@@ -56,6 +64,35 @@ module Discordrb
|
|
56
64
|
attr_reader :rate_limit_per_user
|
57
65
|
alias_method :slowmode_rate, :rate_limit_per_user
|
58
66
|
|
67
|
+
# @return [Integer, nil] An approximate count of messages sent in a thread. Stops counting at 50.
|
68
|
+
attr_reader :message_count
|
69
|
+
|
70
|
+
# @return [Integer, nil] An approximate count of members in a thread. Stops counting at 50.
|
71
|
+
attr_reader :member_count
|
72
|
+
|
73
|
+
# @return [true, false, nil] Whether or not this thread is archived.
|
74
|
+
attr_reader :archived
|
75
|
+
|
76
|
+
# @return [Integer, nil] How long after the last message before a thread is automatically archived.
|
77
|
+
attr_reader :auto_archive_duration
|
78
|
+
|
79
|
+
# @return [Time, nil] The timestamp of when this threads status last changed.
|
80
|
+
attr_reader :archive_timestamp
|
81
|
+
|
82
|
+
# @return [true, false, nil] Whether this thread is locked or not.
|
83
|
+
attr_reader :locked
|
84
|
+
alias_method :locked?, :locked
|
85
|
+
|
86
|
+
# @return [Time, nil] When the current user joined this thread.
|
87
|
+
attr_reader :join_timestamp
|
88
|
+
|
89
|
+
# @return [Integer, nil] Member flags for this thread, used for notifications.
|
90
|
+
attr_reader :member_flags
|
91
|
+
|
92
|
+
# @return [true, false] For private threads, determines whether non-moderators can add other non-moderators to
|
93
|
+
# a thread.
|
94
|
+
attr_reader :invitable
|
95
|
+
|
59
96
|
# @return [true, false] whether or not this channel is a PM or group channel.
|
60
97
|
def private?
|
61
98
|
pm? || group?
|
@@ -99,15 +136,44 @@ module Discordrb
|
|
99
136
|
end
|
100
137
|
else
|
101
138
|
@name = data['name']
|
102
|
-
@
|
139
|
+
@server_id = server&.id || data['guild_id'].to_i
|
140
|
+
@server = server
|
103
141
|
end
|
104
142
|
|
105
143
|
@nsfw = data['nsfw'] || false
|
106
144
|
@rate_limit_per_user = data['rate_limit_per_user'] || 0
|
145
|
+
@message_count = data['message_count']
|
146
|
+
@member_count = data['member_count']
|
147
|
+
|
148
|
+
if (metadata = data['thread_metadata'])
|
149
|
+
@archived = metadata['archived']
|
150
|
+
@auto_archive_duration = metadata['auto_archive_duration']
|
151
|
+
@archive_timestamp = Time.iso8601(metadata['archive_timestamp'])
|
152
|
+
@locked = metadata['locked']
|
153
|
+
@invitable = metadata['invitable']
|
154
|
+
end
|
155
|
+
|
156
|
+
if (member = data['member'])
|
157
|
+
@member_join = Time.iso8601(member['join_timestamp'])
|
158
|
+
@member_flags = member['flags']
|
159
|
+
end
|
107
160
|
|
108
161
|
process_permission_overwrites(data['permission_overwrites'])
|
109
162
|
end
|
110
163
|
|
164
|
+
# @return [Server, nil] the server this channel is on. If this channel is a PM channel, it will be nil.
|
165
|
+
# @raise [Discordrb::Errors::NoPermission] This can happen when receiving interactions for servers in which the bot is not
|
166
|
+
# authorized with the `bot` scope.
|
167
|
+
def server
|
168
|
+
return @server if @server
|
169
|
+
return nil if private?
|
170
|
+
|
171
|
+
@server = @bot.server(@server_id)
|
172
|
+
raise Discordrb::Errors::NoPermission, 'The bot does not have access to this server' unless @server
|
173
|
+
|
174
|
+
@server
|
175
|
+
end
|
176
|
+
|
111
177
|
# @return [true, false] whether or not this channel is a text channel
|
112
178
|
def text?
|
113
179
|
@type.zero?
|
@@ -143,6 +209,26 @@ module Discordrb
|
|
143
209
|
@type == 6
|
144
210
|
end
|
145
211
|
|
212
|
+
# @return [true, false] whether or not this channel is a news thread.
|
213
|
+
def news_thread?
|
214
|
+
@type == 10
|
215
|
+
end
|
216
|
+
|
217
|
+
# @return [true, false] whether or not this channel is a public thread.
|
218
|
+
def public_thread?
|
219
|
+
@type == 11
|
220
|
+
end
|
221
|
+
|
222
|
+
# @return [true, false] whether or not this channel is a private thread.
|
223
|
+
def private_thread?
|
224
|
+
@type == 12
|
225
|
+
end
|
226
|
+
|
227
|
+
# @return [true, false] whether or not this channel is a thread.
|
228
|
+
def thread?
|
229
|
+
news_thread? || public_thread? || private_thread?
|
230
|
+
end
|
231
|
+
|
146
232
|
# @return [Channel, nil] the category channel, if this channel is in a category
|
147
233
|
def category
|
148
234
|
@bot.channel(@parent_id) if @parent_id
|
@@ -199,7 +285,7 @@ module Discordrb
|
|
199
285
|
ids = if parent
|
200
286
|
parent.children
|
201
287
|
else
|
202
|
-
|
288
|
+
server.channels.reject(&:parent_id).select { |c| c.type == @type }
|
203
289
|
end.sort_by(&:position).map(&:id)
|
204
290
|
|
205
291
|
# Move our channel ID after the target ID by deleting it,
|
@@ -225,7 +311,7 @@ module Discordrb
|
|
225
311
|
move_argument << hash
|
226
312
|
end
|
227
313
|
|
228
|
-
API::Server.update_channel_positions(@bot.token, @
|
314
|
+
API::Server.update_channel_positions(@bot.token, @server_id, move_argument)
|
229
315
|
end
|
230
316
|
|
231
317
|
# Sets whether this channel is NSFW
|
@@ -262,9 +348,9 @@ module Discordrb
|
|
262
348
|
|
263
349
|
# Sets the amount of time (in seconds) users have to wait in between sending messages.
|
264
350
|
# @param rate [Integer]
|
265
|
-
# @raise [ArgumentError] if value isn't between 0 and
|
351
|
+
# @raise [ArgumentError] if value isn't between 0 and 21600
|
266
352
|
def rate_limit_per_user=(rate)
|
267
|
-
raise ArgumentError, 'rate_limit_per_user must be between 0 and
|
353
|
+
raise ArgumentError, 'rate_limit_per_user must be between 0 and 21600' unless rate.between?(0, 21_600)
|
268
354
|
|
269
355
|
update_channel_data(rate_limit_per_user: rate)
|
270
356
|
end
|
@@ -341,9 +427,10 @@ module Discordrb
|
|
341
427
|
# @param attachments [Array<File>] Files that can be referenced in embeds via `attachment://file.png`
|
342
428
|
# @param allowed_mentions [Hash, Discordrb::AllowedMentions, false, nil] Mentions that are allowed to ping on this message. `false` disables all pings
|
343
429
|
# @param message_reference [Message, String, Integer, nil] The message, or message ID, to reply to if any.
|
430
|
+
# @param components [View, Array<Hash>] Interaction components to associate with this message.
|
344
431
|
# @return [Message] the message that was sent.
|
345
|
-
def send_message(content, tts = false, embed = nil, attachments = nil, allowed_mentions = nil, message_reference = nil)
|
346
|
-
@bot.send_message(@id, content, tts, embed, attachments, allowed_mentions, message_reference)
|
432
|
+
def send_message(content, tts = false, embed = nil, attachments = nil, allowed_mentions = nil, message_reference = nil, components = nil)
|
433
|
+
@bot.send_message(@id, content, tts, embed, attachments, allowed_mentions, message_reference, components)
|
347
434
|
end
|
348
435
|
|
349
436
|
alias_method :send, :send_message
|
@@ -356,8 +443,9 @@ module Discordrb
|
|
356
443
|
# @param attachments [Array<File>] Files that can be referenced in embeds via `attachment://file.png`
|
357
444
|
# @param allowed_mentions [Hash, Discordrb::AllowedMentions, false, nil] Mentions that are allowed to ping on this message. `false` disables all pings
|
358
445
|
# @param message_reference [Message, String, Integer, nil] The message, or message ID, to reply to if any.
|
359
|
-
|
360
|
-
|
446
|
+
# @param components [View, Array<Hash>] Interaction components to associate with this message.
|
447
|
+
def send_temporary_message(content, timeout, tts = false, embed = nil, attachments = nil, allowed_mentions = nil, message_reference = nil, components = nil)
|
448
|
+
@bot.send_temporary_message(@id, content, timeout, tts, embed, attachments, allowed_mentions, message_reference, components)
|
361
449
|
end
|
362
450
|
|
363
451
|
# Convenience method to send a message with an embed.
|
@@ -372,13 +460,17 @@ module Discordrb
|
|
372
460
|
# @param tts [true, false] Whether or not this message should be sent using Discord text-to-speech.
|
373
461
|
# @param allowed_mentions [Hash, Discordrb::AllowedMentions, false, nil] Mentions that are allowed to ping on this message. `false` disables all pings
|
374
462
|
# @param message_reference [Message, String, Integer, nil] The message, or message ID, to reply to if any.
|
463
|
+
# @param components [View, Array<Hash>] Interaction components to associate with this message.
|
375
464
|
# @yield [embed] Yields the embed to allow for easy building inside a block.
|
376
465
|
# @yieldparam embed [Discordrb::Webhooks::Embed] The embed from the parameters, or a new one.
|
377
466
|
# @return [Message] The resulting message.
|
378
|
-
def send_embed(message = '', embed = nil, attachments = nil, tts = false, allowed_mentions = nil, message_reference = nil)
|
467
|
+
def send_embed(message = '', embed = nil, attachments = nil, tts = false, allowed_mentions = nil, message_reference = nil, components = nil)
|
379
468
|
embed ||= Discordrb::Webhooks::Embed.new
|
380
|
-
|
381
|
-
|
469
|
+
view = Discordrb::Webhooks::View.new
|
470
|
+
|
471
|
+
yield(embed, view) if block_given?
|
472
|
+
|
473
|
+
send_message(message, tts, embed, attachments, allowed_mentions, message_reference, components || view.to_a)
|
382
474
|
end
|
383
475
|
|
384
476
|
# Sends multiple messages to a channel
|
@@ -518,9 +610,9 @@ module Discordrb
|
|
518
610
|
# @return [Array<Member>] the users in this channel
|
519
611
|
def users
|
520
612
|
if text?
|
521
|
-
|
613
|
+
server.online_members(include_idle: true).select { |u| u.can_read_messages? self }
|
522
614
|
elsif voice?
|
523
|
-
|
615
|
+
server.voice_states.filter_map { |id, voice_state| server.member(id) if !voice_state.voice_channel.nil? && voice_state.voice_channel.id == @id }
|
524
616
|
end
|
525
617
|
end
|
526
618
|
|
@@ -554,9 +646,11 @@ module Discordrb
|
|
554
646
|
# @param message_id [Integer] The ID of the message to retrieve.
|
555
647
|
# @return [Message, nil] the retrieved message, or `nil` if it couldn't be found.
|
556
648
|
def load_message(message_id)
|
649
|
+
raise ArgumentError, 'message_id cannot be nil' if message_id.nil?
|
650
|
+
|
557
651
|
response = API::Channel.message(@bot.token, @id, message_id)
|
558
652
|
Message.new(JSON.parse(response), @bot)
|
559
|
-
rescue
|
653
|
+
rescue Discordrb::Errors::UnknownMessage
|
560
654
|
nil
|
561
655
|
end
|
562
656
|
|
@@ -742,9 +836,59 @@ module Discordrb
|
|
742
836
|
invites.map { |invite_data| Invite.new(invite_data, @bot) }
|
743
837
|
end
|
744
838
|
|
839
|
+
# Start a thread.
|
840
|
+
# @param name [String] The name of the thread.
|
841
|
+
# @param auto_archive_duration [60, 1440, 4320, 10080] How long before a thread is automatically
|
842
|
+
# archived.
|
843
|
+
# @param message [Message, Integer, String] The message to reference when starting this thread.
|
844
|
+
# @param type [Symbol, Integer] The type of thread to create. Can be a key from {TYPES} or the value.
|
845
|
+
# @return [Channel]
|
846
|
+
def start_thread(name, auto_archive_duration, message: nil, type: 11)
|
847
|
+
message_id = message&.id || message
|
848
|
+
type = TYPES[type] || type
|
849
|
+
|
850
|
+
data = if message
|
851
|
+
API::Channel.start_thread_with_message(@bot.token, @id, message_id, name, auto_archive_duration)
|
852
|
+
else
|
853
|
+
API::Channel.start_thread_without_message(@bot.token, @id, name, auto_archive_duration, type)
|
854
|
+
end
|
855
|
+
|
856
|
+
Channel.new(JSON.parse(data), @bot, @server)
|
857
|
+
end
|
858
|
+
|
859
|
+
# @!group Threads
|
860
|
+
|
861
|
+
# Join this thread.
|
862
|
+
def join_thread
|
863
|
+
@bot.join_thread(@id)
|
864
|
+
end
|
865
|
+
|
866
|
+
# Leave this thread
|
867
|
+
def leave_thread
|
868
|
+
@bot.leave_thread(@id)
|
869
|
+
end
|
870
|
+
|
871
|
+
# Members in the thread.
|
872
|
+
def members
|
873
|
+
@bot.thread_members[@id].collect { |id| @server_id ? @bot.member(@server_id, id) : @bot.user(id) }
|
874
|
+
end
|
875
|
+
|
876
|
+
# Add a member to the thread
|
877
|
+
# @param member [Member, Integer, String] The member, or ID of the member, to add to this thread.
|
878
|
+
def add_member(member)
|
879
|
+
@bot.add_thread_member(@id, member)
|
880
|
+
end
|
881
|
+
|
882
|
+
# @param member [Member, Integer, String] The member, or ID of the member, to remove from a thread.
|
883
|
+
def remove_member(member)
|
884
|
+
@bot.remove_thread_member(@id, member)
|
885
|
+
end
|
886
|
+
|
887
|
+
# @!endgroup
|
888
|
+
|
745
889
|
# The default `inspect` method is overwritten to give more useful output.
|
746
890
|
def inspect
|
747
|
-
"<Channel name=#{@name} id=#{@id} topic=\"#{@topic}\" type=#{@type} position=#{@position} server=#{@server}>"
|
891
|
+
"<Channel name=#{@name} id=#{@id} topic=\"#{@topic}\" type=#{@type} position=#{@position} server=#{@server || @server_id}>"
|
748
892
|
end
|
749
893
|
|
750
894
|
# Adds a recipient to a group channel.
|
@@ -790,7 +934,7 @@ module Discordrb
|
|
790
934
|
|
791
935
|
# @return [String] a URL that a user can use to navigate to this channel in the client
|
792
936
|
def link
|
793
|
-
"https://discord.com/channels/#{@
|
937
|
+
"https://discord.com/channels/#{@server_id || '@me'}/#{@channel.id}"
|
794
938
|
end
|
795
939
|
|
796
940
|
alias_method :jump_link, :link
|
@@ -0,0 +1,229 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Discordrb
|
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]
|
18
|
+
SelectMenu.new(data, bot)
|
19
|
+
when Webhooks::Modal::COMPONENT_TYPES[:text_input]
|
20
|
+
TextInput.new(data, bot)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Represents a row of components
|
25
|
+
class ActionRow
|
26
|
+
include Enumerable
|
27
|
+
|
28
|
+
# @return [Array<Button>]
|
29
|
+
attr_reader :components
|
30
|
+
|
31
|
+
# @!visibility private
|
32
|
+
def initialize(data, bot)
|
33
|
+
@bot = bot
|
34
|
+
@components = data['components'].map { |component_data| Components.from_data(component_data, @bot) }
|
35
|
+
end
|
36
|
+
|
37
|
+
# Iterate over each component in the row.
|
38
|
+
def each(&block)
|
39
|
+
@components.each(&block)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Get all buttons in this row
|
43
|
+
# @return [Array<Button>]
|
44
|
+
def buttons
|
45
|
+
select { |component| component.is_a? Button }
|
46
|
+
end
|
47
|
+
|
48
|
+
# Get all buttons in this row
|
49
|
+
# @return [Array<Button>]
|
50
|
+
def text_inputs
|
51
|
+
select { |component| component.is_a? TextInput }
|
52
|
+
end
|
53
|
+
|
54
|
+
# @!visibility private
|
55
|
+
def to_a
|
56
|
+
@components
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# An interactable button component.
|
61
|
+
class Button
|
62
|
+
# @return [String]
|
63
|
+
attr_reader :label
|
64
|
+
|
65
|
+
# @return [Integer]
|
66
|
+
attr_reader :style
|
67
|
+
|
68
|
+
# @return [String]
|
69
|
+
attr_reader :custom_id
|
70
|
+
|
71
|
+
# @return [true, false]
|
72
|
+
attr_reader :disabled
|
73
|
+
|
74
|
+
# @return [String, nil]
|
75
|
+
attr_reader :url
|
76
|
+
|
77
|
+
# @return [Emoji, nil]
|
78
|
+
attr_reader :emoji
|
79
|
+
|
80
|
+
# @!visibility private
|
81
|
+
def initialize(data, bot)
|
82
|
+
@bot = bot
|
83
|
+
|
84
|
+
@label = data['label']
|
85
|
+
@style = data['style']
|
86
|
+
@custom_id = data['custom_id']
|
87
|
+
@disabled = data['disabled']
|
88
|
+
@url = data['url']
|
89
|
+
@emoji = Emoji.new(data['emoji'], @bot) if data['emoji']
|
90
|
+
end
|
91
|
+
|
92
|
+
# @method primary?
|
93
|
+
# @return [true, false]
|
94
|
+
# @method secondary?
|
95
|
+
# @return [true, false]
|
96
|
+
# @method success?
|
97
|
+
# @return [true, false]
|
98
|
+
# @method danger?
|
99
|
+
# @return [true, false]
|
100
|
+
# @method link?
|
101
|
+
# @return [true, false]
|
102
|
+
Webhooks::View::BUTTON_STYLES.each do |name, value|
|
103
|
+
define_method("#{name}?") do
|
104
|
+
@style == value
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Await a button click
|
109
|
+
def await_click(key, **attributes, &block)
|
110
|
+
@bot.add_await(key, Discordrb::Events::ButtonEvent, { custom_id: @custom_id }.merge(attributes), &block)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Await a button click, blocking.
|
114
|
+
def await_click!(**attributes, &block)
|
115
|
+
@bot.add_await!(Discordrb::Events::ButtonEvent, { custom_id: @custom_id }.merge(attributes), &block)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# An interactable select menu component.
|
120
|
+
class SelectMenu
|
121
|
+
# A select menu option.
|
122
|
+
class Option
|
123
|
+
# @return [String]
|
124
|
+
attr_reader :label
|
125
|
+
|
126
|
+
# @return [String]
|
127
|
+
attr_reader :value
|
128
|
+
|
129
|
+
# @return [String, nil]
|
130
|
+
attr_reader :description
|
131
|
+
|
132
|
+
# @return [Emoji, nil]
|
133
|
+
attr_reader :emoji
|
134
|
+
|
135
|
+
# @!visibility hidden
|
136
|
+
def initialize(data)
|
137
|
+
@label = data['label']
|
138
|
+
@value = data['value']
|
139
|
+
@description = data['description']
|
140
|
+
@emoji = Emoji.new(data['emoji'], @bot) if data['emoji']
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# @return [String]
|
145
|
+
attr_reader :custom_id
|
146
|
+
|
147
|
+
# @return [Integer, nil]
|
148
|
+
attr_reader :max_values
|
149
|
+
|
150
|
+
# @return [Integer, nil]
|
151
|
+
attr_reader :min_values
|
152
|
+
|
153
|
+
# @return [String, nil]
|
154
|
+
attr_reader :placeholder
|
155
|
+
|
156
|
+
# @return [Array<Option>]
|
157
|
+
attr_reader :options
|
158
|
+
|
159
|
+
# @!visibility private
|
160
|
+
def initialize(data, bot)
|
161
|
+
@bot = bot
|
162
|
+
|
163
|
+
@max_values = data['max_values']
|
164
|
+
@min_values = data['min_values']
|
165
|
+
@placeholder = data['placeholder']
|
166
|
+
@custom_id = data['custom_id']
|
167
|
+
@emoji = Emoji.new(data['emoji'], @bot) if data['emoji']
|
168
|
+
@options = data['options'].map { |opt| Option.new(opt) }
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Text input component for use in modals. Can be either a line (`short`), or a multi line (`paragraph`) block.
|
173
|
+
class TextInput
|
174
|
+
# Single line text input
|
175
|
+
SHORT = 1
|
176
|
+
# Multi-line text input
|
177
|
+
PARAGRAPH = 2
|
178
|
+
|
179
|
+
# @return [String]
|
180
|
+
attr_reader :custom_id
|
181
|
+
|
182
|
+
# @return [Symbol]
|
183
|
+
attr_reader :style
|
184
|
+
|
185
|
+
# @return [String]
|
186
|
+
attr_reader :label
|
187
|
+
|
188
|
+
# @return [Integer, nil]
|
189
|
+
attr_reader :min_length
|
190
|
+
|
191
|
+
# @return [Integer, nil]
|
192
|
+
attr_reader :max_length
|
193
|
+
|
194
|
+
# @return [true, false]
|
195
|
+
attr_reader :required
|
196
|
+
|
197
|
+
# @return [String, nil]
|
198
|
+
attr_reader :value
|
199
|
+
|
200
|
+
# @return [String, nil]
|
201
|
+
attr_reader :placeholder
|
202
|
+
|
203
|
+
# @!visibility private
|
204
|
+
def initialize(data, bot)
|
205
|
+
@bot = bot
|
206
|
+
@style = data['style'] == SHORT ? :short : :paragraph
|
207
|
+
@label = data['label']
|
208
|
+
@min_length = data['min_length']
|
209
|
+
@max_length = data['max_length']
|
210
|
+
@required = data['required']
|
211
|
+
@value = data['value']
|
212
|
+
@placeholder = data['placeholder']
|
213
|
+
@custom_id = data['custom_id']
|
214
|
+
end
|
215
|
+
|
216
|
+
def short?
|
217
|
+
@style == :short
|
218
|
+
end
|
219
|
+
|
220
|
+
def paragraph?
|
221
|
+
@style == :paragraph
|
222
|
+
end
|
223
|
+
|
224
|
+
def required?
|
225
|
+
@required
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
@@ -15,6 +15,36 @@ module Discordrb
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
# Bot/OAuth2 application for discord integrations
|
19
|
+
class IntegrationApplication
|
20
|
+
# @return [Integer] the ID of the application.
|
21
|
+
attr_reader :id
|
22
|
+
|
23
|
+
# @return [String] the name of the application.
|
24
|
+
attr_reader :name
|
25
|
+
|
26
|
+
# @return [String, nil] the icon hash of the application.
|
27
|
+
attr_reader :icon
|
28
|
+
|
29
|
+
# @return [String] the description of the application.
|
30
|
+
attr_reader :description
|
31
|
+
|
32
|
+
# @return [String] the summary of the application.
|
33
|
+
attr_reader :summary
|
34
|
+
|
35
|
+
# @return [User, nil] the bot associated with this application.
|
36
|
+
attr_reader :bot
|
37
|
+
|
38
|
+
def initialize(data, bot)
|
39
|
+
@id = data['id'].to_i
|
40
|
+
@name = data['name']
|
41
|
+
@icon = data['icon']
|
42
|
+
@description = data['description']
|
43
|
+
@summary = data['summary']
|
44
|
+
@bot = Discordrb::User.new(data['user'], bot) if data['user']
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
18
48
|
# Server integration
|
19
49
|
class Integration
|
20
50
|
include IDObject
|
@@ -28,8 +58,8 @@ module Discordrb
|
|
28
58
|
# @return [User] the user the integration is linked to
|
29
59
|
attr_reader :user
|
30
60
|
|
31
|
-
# @return [
|
32
|
-
attr_reader :
|
61
|
+
# @return [Integer, nil] the role that this integration uses for "subscribers"
|
62
|
+
attr_reader :role_id
|
33
63
|
|
34
64
|
# @return [true, false] whether emoticons are enabled
|
35
65
|
attr_reader :emoticon
|
@@ -57,6 +87,12 @@ module Discordrb
|
|
57
87
|
# @return [Integer] the grace period before subscribers expire (in days)
|
58
88
|
attr_reader :expire_grace_period
|
59
89
|
|
90
|
+
# @return [Integer, nil] how many subscribers this integration has.
|
91
|
+
attr_reader :subscriber_count
|
92
|
+
|
93
|
+
# @return [true, false] has this integration been revoked.
|
94
|
+
attr_reader :revoked
|
95
|
+
|
60
96
|
def initialize(data, bot, server)
|
61
97
|
@bot = bot
|
62
98
|
|
@@ -71,8 +107,11 @@ module Discordrb
|
|
71
107
|
@expire_behaviour = %i[remove kick][data['expire_behavior']]
|
72
108
|
@expire_grace_period = data['expire_grace_period']
|
73
109
|
@user = @bot.ensure_user(data['user'])
|
74
|
-
@
|
110
|
+
@role_id = data['role_id']&.to_i
|
75
111
|
@emoticon = data['enable_emoticons']
|
112
|
+
@subscriber_count = data['subscriber_count']&.to_i
|
113
|
+
@revoked = data['revoked']
|
114
|
+
@application = IntegrationApplication.new(data['application'], bot) if data['application']
|
76
115
|
end
|
77
116
|
|
78
117
|
# The inspect method is overwritten to give more useful output
|