discordrb 3.4.3 → 3.6.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/.devcontainer/Dockerfile +13 -0
- data/.devcontainer/devcontainer.json +29 -0
- data/.devcontainer/postcreate.sh +4 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -1
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -1
- 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 +45 -0
- data/.markdownlint.json +4 -0
- data/.rubocop.yml +58 -2
- data/CHANGELOG.md +485 -225
- data/LICENSE.txt +1 -1
- data/README.md +38 -26
- data/discordrb-webhooks.gemspec +4 -1
- data/discordrb.gemspec +18 -10
- data/lib/discordrb/api/application.rb +278 -0
- data/lib/discordrb/api/channel.rb +222 -18
- data/lib/discordrb/api/interaction.rb +63 -0
- data/lib/discordrb/api/invite.rb +2 -2
- data/lib/discordrb/api/server.rb +123 -66
- data/lib/discordrb/api/user.rb +20 -5
- data/lib/discordrb/api/webhook.rb +72 -0
- data/lib/discordrb/api.rb +35 -25
- data/lib/discordrb/bot.rb +437 -66
- data/lib/discordrb/cache.rb +41 -22
- data/lib/discordrb/commands/command_bot.rb +13 -21
- data/lib/discordrb/commands/container.rb +1 -1
- data/lib/discordrb/commands/parser.rb +7 -7
- data/lib/discordrb/commands/rate_limiter.rb +1 -1
- data/lib/discordrb/container.rb +178 -3
- data/lib/discordrb/data/activity.rb +1 -1
- data/lib/discordrb/data/application.rb +1 -0
- data/lib/discordrb/data/attachment.rb +38 -3
- data/lib/discordrb/data/audit_logs.rb +3 -3
- data/lib/discordrb/data/avatar_decoration.rb +26 -0
- data/lib/discordrb/data/call.rb +22 -0
- data/lib/discordrb/data/channel.rb +299 -30
- data/lib/discordrb/data/collectibles.rb +45 -0
- data/lib/discordrb/data/component.rb +229 -0
- data/lib/discordrb/data/embed.rb +10 -3
- data/lib/discordrb/data/emoji.rb +20 -1
- data/lib/discordrb/data/integration.rb +45 -3
- data/lib/discordrb/data/interaction.rb +937 -0
- data/lib/discordrb/data/invite.rb +1 -1
- data/lib/discordrb/data/member.rb +236 -44
- data/lib/discordrb/data/message.rb +278 -51
- data/lib/discordrb/data/overwrite.rb +15 -7
- data/lib/discordrb/data/primary_server.rb +60 -0
- data/lib/discordrb/data/profile.rb +2 -7
- data/lib/discordrb/data/reaction.rb +2 -1
- data/lib/discordrb/data/recipient.rb +1 -1
- data/lib/discordrb/data/role.rb +204 -18
- data/lib/discordrb/data/server.rb +194 -118
- data/lib/discordrb/data/server_preview.rb +68 -0
- data/lib/discordrb/data/snapshot.rb +110 -0
- data/lib/discordrb/data/user.rb +132 -12
- data/lib/discordrb/data/voice_region.rb +1 -0
- data/lib/discordrb/data/webhook.rb +99 -9
- data/lib/discordrb/data.rb +9 -0
- data/lib/discordrb/errors.rb +47 -3
- data/lib/discordrb/events/await.rb +1 -1
- data/lib/discordrb/events/channels.rb +38 -1
- data/lib/discordrb/events/generic.rb +2 -0
- data/lib/discordrb/events/guilds.rb +6 -1
- data/lib/discordrb/events/interactions.rb +575 -0
- data/lib/discordrb/events/invites.rb +2 -0
- data/lib/discordrb/events/members.rb +19 -2
- data/lib/discordrb/events/message.rb +42 -8
- data/lib/discordrb/events/presence.rb +23 -14
- data/lib/discordrb/events/raw.rb +1 -0
- data/lib/discordrb/events/reactions.rb +2 -1
- data/lib/discordrb/events/roles.rb +2 -0
- data/lib/discordrb/events/threads.rb +100 -0
- data/lib/discordrb/events/typing.rb +1 -0
- data/lib/discordrb/events/voice_server_update.rb +1 -0
- data/lib/discordrb/events/voice_state_update.rb +1 -0
- data/lib/discordrb/events/webhooks.rb +1 -0
- data/lib/discordrb/gateway.rb +57 -28
- data/lib/discordrb/paginator.rb +3 -3
- data/lib/discordrb/permissions.rb +71 -35
- data/lib/discordrb/version.rb +1 -1
- data/lib/discordrb/voice/encoder.rb +2 -2
- 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/websocket.rb +0 -10
- data/lib/discordrb.rb +54 -5
- metadata +87 -25
- data/.circleci/config.yml +0 -126
- data/.codeclimate.yml +0 -16
- data/.travis.yml +0 -32
- data/bin/travis_build_docs.sh +0 -17
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Discordrb
|
|
4
|
+
# A decoration displayed on a user's avatar.
|
|
5
|
+
class AvatarDecoration
|
|
6
|
+
# @return [Integer] ID of the avatar decoration's SKU.
|
|
7
|
+
attr_reader :sku_id
|
|
8
|
+
|
|
9
|
+
# @return [String] ID that can be used to generate an avatar decoration URL.
|
|
10
|
+
# @see #url
|
|
11
|
+
attr_reader :decoration_id
|
|
12
|
+
|
|
13
|
+
# @!visibility private
|
|
14
|
+
def initialize(data, bot)
|
|
15
|
+
@bot = bot
|
|
16
|
+
@sku_id = data['sku_id']&.to_i
|
|
17
|
+
@decoration_id = data['asset']
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Utility method to get an avatar decoration URL.
|
|
21
|
+
# @return [String] the URL to the avatar decoration.
|
|
22
|
+
def url
|
|
23
|
+
API.avatar_decoration_url(@decoration_id)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Discordrb
|
|
4
|
+
# A call in a private channel.
|
|
5
|
+
class Call
|
|
6
|
+
# @return [Time, nil] the time at when the call ended.
|
|
7
|
+
attr_reader :ended_at
|
|
8
|
+
|
|
9
|
+
# @!visibility private
|
|
10
|
+
def initialize(data, bot)
|
|
11
|
+
@bot = bot
|
|
12
|
+
@participant_ids = data['participants'] || []
|
|
13
|
+
@ended_at = Time.iso8601(data['ended_timestamp']) if data['ended_timestamp']
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Get the users that participated in this call.
|
|
17
|
+
# @return [Array<User>] the participants of this call.
|
|
18
|
+
def participants
|
|
19
|
+
@participants ||= @participant_ids.map { |participant| @bot.user(participant) }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -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,40 @@ 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, excluding deleted messages.
|
|
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
|
+
alias_method :archived?, :archived
|
|
76
|
+
|
|
77
|
+
# @return [Integer, nil] How long after the last message before a thread is automatically archived.
|
|
78
|
+
attr_reader :auto_archive_duration
|
|
79
|
+
|
|
80
|
+
# @return [Time, nil] The timestamp of when this threads status last changed.
|
|
81
|
+
attr_reader :archive_timestamp
|
|
82
|
+
|
|
83
|
+
# @return [true, false, nil] Whether this thread is locked or not.
|
|
84
|
+
attr_reader :locked
|
|
85
|
+
alias_method :locked?, :locked
|
|
86
|
+
|
|
87
|
+
# @return [Time, nil] When the current user joined this thread.
|
|
88
|
+
attr_reader :join_timestamp
|
|
89
|
+
|
|
90
|
+
# @return [Integer, nil] Member flags for this thread, used for notifications.
|
|
91
|
+
attr_reader :member_flags
|
|
92
|
+
|
|
93
|
+
# @return [true, false, nil] For private threads, determines whether non-moderators can add other non-moderators to
|
|
94
|
+
# a thread.
|
|
95
|
+
attr_reader :invitable
|
|
96
|
+
alias_method :invitable?, :invitable
|
|
97
|
+
|
|
98
|
+
# @return [Time, nil] The time at when the last pinned message was pinned in this channel.
|
|
99
|
+
attr_reader :last_pin_timestamp
|
|
100
|
+
|
|
59
101
|
# @return [true, false] whether or not this channel is a PM or group channel.
|
|
60
102
|
def private?
|
|
61
103
|
pm? || group?
|
|
@@ -99,15 +141,45 @@ module Discordrb
|
|
|
99
141
|
end
|
|
100
142
|
else
|
|
101
143
|
@name = data['name']
|
|
102
|
-
@
|
|
144
|
+
@server_id = server&.id || data['guild_id'].to_i
|
|
145
|
+
@server = server
|
|
103
146
|
end
|
|
104
147
|
|
|
105
148
|
@nsfw = data['nsfw'] || false
|
|
106
149
|
@rate_limit_per_user = data['rate_limit_per_user'] || 0
|
|
150
|
+
@message_count = data['message_count']
|
|
151
|
+
@member_count = data['member_count']
|
|
152
|
+
|
|
153
|
+
if (metadata = data['thread_metadata'])
|
|
154
|
+
@archived = metadata['archived']
|
|
155
|
+
@auto_archive_duration = metadata['auto_archive_duration']
|
|
156
|
+
@archive_timestamp = Time.iso8601(metadata['archive_timestamp'])
|
|
157
|
+
@locked = metadata['locked']
|
|
158
|
+
@invitable = metadata['invitable']
|
|
159
|
+
end
|
|
107
160
|
|
|
161
|
+
if (member = data['member'])
|
|
162
|
+
@member_join = Time.iso8601(member['join_timestamp'])
|
|
163
|
+
@member_flags = member['flags']
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
process_last_pin_timestamp(data['last_pin_timestamp'])
|
|
108
167
|
process_permission_overwrites(data['permission_overwrites'])
|
|
109
168
|
end
|
|
110
169
|
|
|
170
|
+
# @return [Server, nil] the server this channel is on. If this channel is a PM channel, it will be nil.
|
|
171
|
+
# @raise [Discordrb::Errors::NoPermission] This can happen when receiving interactions for servers in which the bot is not
|
|
172
|
+
# authorized with the `bot` scope.
|
|
173
|
+
def server
|
|
174
|
+
return @server if @server
|
|
175
|
+
return nil if private?
|
|
176
|
+
|
|
177
|
+
@server = @bot.server(@server_id)
|
|
178
|
+
raise Discordrb::Errors::NoPermission, 'The bot does not have access to this server' unless @server
|
|
179
|
+
|
|
180
|
+
@server
|
|
181
|
+
end
|
|
182
|
+
|
|
111
183
|
# @return [true, false] whether or not this channel is a text channel
|
|
112
184
|
def text?
|
|
113
185
|
@type.zero?
|
|
@@ -143,6 +215,26 @@ module Discordrb
|
|
|
143
215
|
@type == 6
|
|
144
216
|
end
|
|
145
217
|
|
|
218
|
+
# @return [true, false] whether or not this channel is a news thread.
|
|
219
|
+
def news_thread?
|
|
220
|
+
@type == 10
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# @return [true, false] whether or not this channel is a public thread.
|
|
224
|
+
def public_thread?
|
|
225
|
+
@type == 11
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# @return [true, false] whether or not this channel is a private thread.
|
|
229
|
+
def private_thread?
|
|
230
|
+
@type == 12
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# @return [true, false] whether or not this channel is a thread.
|
|
234
|
+
def thread?
|
|
235
|
+
news_thread? || public_thread? || private_thread?
|
|
236
|
+
end
|
|
237
|
+
|
|
146
238
|
# @return [Channel, nil] the category channel, if this channel is in a category
|
|
147
239
|
def category
|
|
148
240
|
@bot.channel(@parent_id) if @parent_id
|
|
@@ -199,7 +291,7 @@ module Discordrb
|
|
|
199
291
|
ids = if parent
|
|
200
292
|
parent.children
|
|
201
293
|
else
|
|
202
|
-
|
|
294
|
+
server.channels.reject(&:parent_id).select { |c| c.type == @type }
|
|
203
295
|
end.sort_by(&:position).map(&:id)
|
|
204
296
|
|
|
205
297
|
# Move our channel ID after the target ID by deleting it,
|
|
@@ -225,7 +317,7 @@ module Discordrb
|
|
|
225
317
|
move_argument << hash
|
|
226
318
|
end
|
|
227
319
|
|
|
228
|
-
API::Server.update_channel_positions(@bot.token, @
|
|
320
|
+
API::Server.update_channel_positions(@bot.token, @server_id, move_argument)
|
|
229
321
|
end
|
|
230
322
|
|
|
231
323
|
# Sets whether this channel is NSFW
|
|
@@ -262,9 +354,9 @@ module Discordrb
|
|
|
262
354
|
|
|
263
355
|
# Sets the amount of time (in seconds) users have to wait in between sending messages.
|
|
264
356
|
# @param rate [Integer]
|
|
265
|
-
# @raise [ArgumentError] if value isn't between 0 and
|
|
357
|
+
# @raise [ArgumentError] if value isn't between 0 and 21600
|
|
266
358
|
def rate_limit_per_user=(rate)
|
|
267
|
-
raise ArgumentError, 'rate_limit_per_user must be between 0 and
|
|
359
|
+
raise ArgumentError, 'rate_limit_per_user must be between 0 and 21600' unless rate.between?(0, 21_600)
|
|
268
360
|
|
|
269
361
|
update_channel_data(rate_limit_per_user: rate)
|
|
270
362
|
end
|
|
@@ -341,9 +433,11 @@ module Discordrb
|
|
|
341
433
|
# @param attachments [Array<File>] Files that can be referenced in embeds via `attachment://file.png`
|
|
342
434
|
# @param allowed_mentions [Hash, Discordrb::AllowedMentions, false, nil] Mentions that are allowed to ping on this message. `false` disables all pings
|
|
343
435
|
# @param message_reference [Message, String, Integer, nil] The message, or message ID, to reply to if any.
|
|
436
|
+
# @param components [View, Array<Hash>] Interaction components to associate with this message.
|
|
437
|
+
# @param flags [Integer] Flags for this message. Currently only SUPPRESS_EMBEDS (1 << 2) and SUPPRESS_NOTIFICATIONS (1 << 12) can be set.
|
|
344
438
|
# @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)
|
|
439
|
+
def send_message(content, tts = false, embed = nil, attachments = nil, allowed_mentions = nil, message_reference = nil, components = nil, flags = 0)
|
|
440
|
+
@bot.send_message(@id, content, tts, embed, attachments, allowed_mentions, message_reference, components, flags)
|
|
347
441
|
end
|
|
348
442
|
|
|
349
443
|
alias_method :send, :send_message
|
|
@@ -356,8 +450,10 @@ module Discordrb
|
|
|
356
450
|
# @param attachments [Array<File>] Files that can be referenced in embeds via `attachment://file.png`
|
|
357
451
|
# @param allowed_mentions [Hash, Discordrb::AllowedMentions, false, nil] Mentions that are allowed to ping on this message. `false` disables all pings
|
|
358
452
|
# @param message_reference [Message, String, Integer, nil] The message, or message ID, to reply to if any.
|
|
359
|
-
|
|
360
|
-
|
|
453
|
+
# @param components [View, Array<Hash>] Interaction components to associate with this message.
|
|
454
|
+
# @param flags [Integer] Flags for this message. Currently only SUPPRESS_EMBEDS (1 << 2) and SUPPRESS_NOTIFICATIONS (1 << 12) can be set.
|
|
455
|
+
def send_temporary_message(content, timeout, tts = false, embed = nil, attachments = nil, allowed_mentions = nil, message_reference = nil, components = nil, flags = 0)
|
|
456
|
+
@bot.send_temporary_message(@id, content, timeout, tts, embed, attachments, allowed_mentions, message_reference, components, flags)
|
|
361
457
|
end
|
|
362
458
|
|
|
363
459
|
# Convenience method to send a message with an embed.
|
|
@@ -372,19 +468,69 @@ module Discordrb
|
|
|
372
468
|
# @param tts [true, false] Whether or not this message should be sent using Discord text-to-speech.
|
|
373
469
|
# @param allowed_mentions [Hash, Discordrb::AllowedMentions, false, nil] Mentions that are allowed to ping on this message. `false` disables all pings
|
|
374
470
|
# @param message_reference [Message, String, Integer, nil] The message, or message ID, to reply to if any.
|
|
471
|
+
# @param components [View, Array<Hash>] Interaction components to associate with this message.
|
|
472
|
+
# @param flags [Integer] Flags for this message. Currently only SUPPRESS_EMBEDS (1 << 2) and SUPPRESS_NOTIFICATIONS (1 << 12) can be set.
|
|
375
473
|
# @yield [embed] Yields the embed to allow for easy building inside a block.
|
|
376
474
|
# @yieldparam embed [Discordrb::Webhooks::Embed] The embed from the parameters, or a new one.
|
|
377
475
|
# @return [Message] The resulting message.
|
|
378
|
-
def send_embed(message = '', embed = nil, attachments = nil, tts = false, allowed_mentions = nil, message_reference = nil)
|
|
476
|
+
def send_embed(message = '', embed = nil, attachments = nil, tts = false, allowed_mentions = nil, message_reference = nil, components = nil, flags = 0)
|
|
379
477
|
embed ||= Discordrb::Webhooks::Embed.new
|
|
380
|
-
|
|
381
|
-
|
|
478
|
+
view = Discordrb::Webhooks::View.new
|
|
479
|
+
|
|
480
|
+
yield(embed, view) if block_given?
|
|
481
|
+
|
|
482
|
+
send_message(message, tts, embed, attachments, allowed_mentions, message_reference, components || view.to_a, flags)
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
# Send a message to this channel.
|
|
486
|
+
# @example This sends a silent message with an embed.
|
|
487
|
+
# channel.send_message!(content: 'Hi <@171764626755813376>', flags: :suppress_notifications) do |builder|
|
|
488
|
+
# builder.add_embed do |embed|
|
|
489
|
+
# embed.title = 'The Ruby logo'
|
|
490
|
+
# embed.image = Discordrb::Webhooks::EmbedImage.new(url: 'https://www.ruby-lang.org/images/header-ruby-logo.png')
|
|
491
|
+
# end
|
|
492
|
+
# end
|
|
493
|
+
# @param content [String] The content of the message. Should not be longer than 2000 characters or it will result in an error.
|
|
494
|
+
# @param timeout [Float, nil] The amount of time in seconds after which the message sent will be deleted, or `nil` if the message should not be deleted.
|
|
495
|
+
# @param tts [true, false] Whether or not this message should be sent using Discord text-to-speech.
|
|
496
|
+
# @param embeds [Array<Hash, Webhooks::Embed>] The embeds that should be attached to the message.
|
|
497
|
+
# @param attachments [Array<File>] Files that can be referenced in embeds and components via `attachment://file.png`.
|
|
498
|
+
# @param allowed_mentions [Hash, Discordrb::AllowedMentions, nil] Mentions that are allowed to ping on this message.
|
|
499
|
+
# @param reference [Message, String, Integer, Hash, nil] The optional message, or message ID, to reply to or forward.
|
|
500
|
+
# @param components [View, Array<#to_h>] Interaction components to associate with this message.
|
|
501
|
+
# @param flags [Integer, Symbol, Array<Symbol, Integer>] Flags for this message. Currently only `:suppress_embeds` (1 << 2), `:suppress_notifications` (1 << 12), and `:uikit_components` (1 << 15) can be set.
|
|
502
|
+
# @param has_components [true, false] Whether this message includes any V2 components. Enabling this disables sending content and embeds.
|
|
503
|
+
# @param nonce [nil, String, Integer, false] The 25 character nonce that should be used when sending this message.
|
|
504
|
+
# @param enforce_nonce [true, false] Whether the provided nonce should be enforced and used for message de-duplication.
|
|
505
|
+
# @yieldparam builder [Webhooks::Builder] An optional message builder. Arguments passed to the builder overwrite method data.
|
|
506
|
+
# @yieldparam view [Webhooks::View] An optional component builder. Arguments passed to the builder overwrite method data.
|
|
507
|
+
# @return [Message, nil] The resulting message that was created, or `nil` if the `timeout` parameter was set to a non `nil` value.
|
|
508
|
+
def send_message!(content: '', timeout: nil, tts: false, embeds: [], attachments: nil, allowed_mentions: nil, reference: nil, components: nil, flags: 0, has_components: false, nonce: nil, enforce_nonce: false)
|
|
509
|
+
builder = Discordrb::Webhooks::Builder.new
|
|
510
|
+
view = Discordrb::Webhooks::View.new
|
|
511
|
+
|
|
512
|
+
builder.tts = tts
|
|
513
|
+
builder.content = content
|
|
514
|
+
embeds&.each { |embed| builder << embed }
|
|
515
|
+
builder.allowed_mentions = allowed_mentions
|
|
516
|
+
|
|
517
|
+
yield(builder, view) if block_given?
|
|
518
|
+
|
|
519
|
+
flags = Array(flags).map { |flag| Discordrb::Message::FLAGS[flag] || flag }.reduce(&:|)
|
|
520
|
+
flags |= (1 << 15) if has_components
|
|
521
|
+
builder = builder.to_json_hash
|
|
522
|
+
|
|
523
|
+
if timeout
|
|
524
|
+
@bot.send_temporary_message(@id, builder[:content], timeout, builder[:tts], builder[:embeds], attachments, builder[:allowed_mentions], reference, components&.to_a || view.to_a, flags, nonce, enforce_nonce)
|
|
525
|
+
else
|
|
526
|
+
@bot.send_message(@id, builder[:content], builder[:tts], builder[:embeds], attachments, builder[:allowed_mentions], reference, components&.to_a || view.to_a, flags, nonce, enforce_nonce)
|
|
527
|
+
end
|
|
382
528
|
end
|
|
383
529
|
|
|
384
530
|
# Sends multiple messages to a channel
|
|
385
531
|
# @param content [Array<String>] The messages to send.
|
|
386
532
|
def send_multiple(content)
|
|
387
|
-
content.each { |
|
|
533
|
+
content.each { |text| send_message!(content: text) }
|
|
388
534
|
end
|
|
389
535
|
|
|
390
536
|
# Splits a message into chunks whose length is at most the Discord character limit, then sends them individually.
|
|
@@ -502,6 +648,7 @@ module Discordrb
|
|
|
502
648
|
# @!visibility private
|
|
503
649
|
def update_from(other)
|
|
504
650
|
@name = other.name
|
|
651
|
+
@type = other.type
|
|
505
652
|
@position = other.position
|
|
506
653
|
@topic = other.topic
|
|
507
654
|
@recipients = other.recipients
|
|
@@ -511,6 +658,13 @@ module Discordrb
|
|
|
511
658
|
@nsfw = other.nsfw
|
|
512
659
|
@parent_id = other.parent_id
|
|
513
660
|
@rate_limit_per_user = other.rate_limit_per_user
|
|
661
|
+
@archived = other.archived?
|
|
662
|
+
@auto_archive_duration = other.auto_archive_duration
|
|
663
|
+
@archive_timestamp = other.archive_timestamp
|
|
664
|
+
@locked = other.locked?
|
|
665
|
+
@invitable = other.invitable?
|
|
666
|
+
@message_count = other.message_count
|
|
667
|
+
@last_pin_timestamp = other.last_pin_timestamp
|
|
514
668
|
end
|
|
515
669
|
|
|
516
670
|
# The list of users currently in this channel. For a voice channel, it will return all the members currently
|
|
@@ -518,9 +672,9 @@ module Discordrb
|
|
|
518
672
|
# @return [Array<Member>] the users in this channel
|
|
519
673
|
def users
|
|
520
674
|
if text?
|
|
521
|
-
|
|
675
|
+
server.online_members(include_idle: true).select { |u| u.can_read_messages? self }
|
|
522
676
|
elsif voice?
|
|
523
|
-
|
|
677
|
+
server.voice_states.filter_map { |id, voice_state| server.member(id) if !voice_state.voice_channel.nil? && voice_state.voice_channel.id == @id }
|
|
524
678
|
end
|
|
525
679
|
end
|
|
526
680
|
|
|
@@ -554,19 +708,37 @@ module Discordrb
|
|
|
554
708
|
# @param message_id [Integer] The ID of the message to retrieve.
|
|
555
709
|
# @return [Message, nil] the retrieved message, or `nil` if it couldn't be found.
|
|
556
710
|
def load_message(message_id)
|
|
711
|
+
raise ArgumentError, 'message_id cannot be nil' if message_id.nil?
|
|
712
|
+
|
|
557
713
|
response = API::Channel.message(@bot.token, @id, message_id)
|
|
558
714
|
Message.new(JSON.parse(response), @bot)
|
|
559
|
-
rescue
|
|
715
|
+
rescue Discordrb::Errors::UnknownMessage
|
|
560
716
|
nil
|
|
561
717
|
end
|
|
562
718
|
|
|
563
719
|
alias_method :message, :load_message
|
|
564
720
|
|
|
565
|
-
# Requests
|
|
566
|
-
# @
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
721
|
+
# Requests the pinned messages in a channel.
|
|
722
|
+
# @param limit [Integer, nil] the limit of how many pinned messages to retrieve. `nil` will return all the pinned messages.
|
|
723
|
+
# @return [Array<Message>] the messages pinned in the channel.
|
|
724
|
+
def pins(limit: 50)
|
|
725
|
+
get_pins = proc do |fetch_limit, before = nil|
|
|
726
|
+
resp = API::Channel.pinned_messages(@bot.token, @id, fetch_limit, before&.iso8601)
|
|
727
|
+
JSON.parse(resp)['items'].map { |pin| Message.new(pin['message'].merge({ 'pinned_at' => pin['pinned_at'] }), @bot) }
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
# Can be done without pagination.
|
|
731
|
+
return get_pins.call(limit) if limit && limit <= 50
|
|
732
|
+
|
|
733
|
+
paginator = Paginator.new(limit, :down) do |last_page|
|
|
734
|
+
if last_page && last_page.count < 50
|
|
735
|
+
[]
|
|
736
|
+
else
|
|
737
|
+
get_pins.call(50, last_page&.last&.pinned_at)
|
|
738
|
+
end
|
|
739
|
+
end
|
|
740
|
+
|
|
741
|
+
paginator.to_a
|
|
570
742
|
end
|
|
571
743
|
|
|
572
744
|
# Delete the last N messages on this channel.
|
|
@@ -742,9 +914,96 @@ module Discordrb
|
|
|
742
914
|
invites.map { |invite_data| Invite.new(invite_data, @bot) }
|
|
743
915
|
end
|
|
744
916
|
|
|
917
|
+
# Start a thread.
|
|
918
|
+
# @param name [String] The name of the thread.
|
|
919
|
+
# @param auto_archive_duration [60, 1440, 4320, 10080] How long before a thread is automatically
|
|
920
|
+
# archived.
|
|
921
|
+
# @param message [Message, Integer, String] The message to reference when starting this thread.
|
|
922
|
+
# @param type [Symbol, Integer] The type of thread to create. Can be a key from {TYPES} or the value.
|
|
923
|
+
# @return [Channel]
|
|
924
|
+
def start_thread(name, auto_archive_duration, message: nil, type: 11)
|
|
925
|
+
message_id = message&.id || message
|
|
926
|
+
type = TYPES[type] || type
|
|
927
|
+
|
|
928
|
+
data = if message
|
|
929
|
+
API::Channel.start_thread_with_message(@bot.token, @id, message_id, name, auto_archive_duration)
|
|
930
|
+
else
|
|
931
|
+
API::Channel.start_thread_without_message(@bot.token, @id, name, auto_archive_duration, type)
|
|
932
|
+
end
|
|
933
|
+
|
|
934
|
+
Channel.new(JSON.parse(data), @bot, @server)
|
|
935
|
+
end
|
|
936
|
+
|
|
937
|
+
# Start a thread in a forum or media channel.
|
|
938
|
+
# @param name [String] The name of the forum post to create.
|
|
939
|
+
# @param auto_archive_duration [Integer, nil] How long before the post is automatically archived.
|
|
940
|
+
# @param rate_limit_per_user [Integer, nil] The slowmode rate of the forum post to create.
|
|
941
|
+
# @param tags [Array<#resolve_id>, nil] The tags of the forum channel to apply onto the forum post.
|
|
942
|
+
# @param content [String, nil] The content of the forum post's starter message.
|
|
943
|
+
# @param embeds [Array<Hash, Webhooks::Embed>, nil] The embeds that should be attached to the forum post's starter message.
|
|
944
|
+
# @param allowed_mentions [Hash, Discordrb::AllowedMentions, nil] Mentions that are allowed to ping on this forum post's starter message.
|
|
945
|
+
# @param components [Webhooks::View, Array<#to_h>, nil] The interaction components to associate with this forum post's starter message.
|
|
946
|
+
# @param stickers [Array<#resolve_id>, nil] The stickers to include in the forum post's starter message.
|
|
947
|
+
# @param attachments [Array<File>, nil] Files that can be referenced in embeds and components via `attachment://file.png`.
|
|
948
|
+
# @param flags [Integer, Symbol, Array<Symbol, Integer>, nil] The flags to set on the forum post's starter message. Currently only `:suppress_embeds` (1 << 2), `:suppress_notifications` (1 << 12), and `:uikit_components` (1 << 15) can be set.
|
|
949
|
+
# @param has_components [true, false] Whether the starter message for this forum post includes any V2 components. Enabling this disables sending content and embeds.
|
|
950
|
+
# @param reason [String, nil] The reason for creating this forum post.
|
|
951
|
+
# @yieldparam builder [Webhooks::Builder] An optional message builder. Arguments passed to the builder overwrite method data.
|
|
952
|
+
# @yieldparam view [Webhooks::View] An optional component builder. Arguments passed to the builder overwrite method data.
|
|
953
|
+
# @return [Message] the starter message of the forum post. The forum post that was created can be accessed via {Message#thread}.
|
|
954
|
+
def start_forum_thread(name:, auto_archive_duration: nil, rate_limit_per_user: nil, tags: nil, content: nil, embeds: nil, allowed_mentions: nil, components: nil, stickers: nil, attachments: nil, flags: nil, has_components: false, reason: nil)
|
|
955
|
+
builder = Discordrb::Webhooks::Builder.new
|
|
956
|
+
view = Discordrb::Webhooks::View.new
|
|
957
|
+
|
|
958
|
+
builder.content = content
|
|
959
|
+
embeds&.each { |embed| builder << embed }
|
|
960
|
+
builder.allowed_mentions = allowed_mentions
|
|
961
|
+
|
|
962
|
+
yield(builder, view) if block_given?
|
|
963
|
+
|
|
964
|
+
flags = Array(flags).map { |flag| Discordrb::Message::FLAGS[flag] || flag }.reduce(&:|)
|
|
965
|
+
flags |= (1 << 15) if has_components
|
|
966
|
+
builder = builder.to_json_hash
|
|
967
|
+
|
|
968
|
+
message = { content: builder[:content], embeds: builder[:embeds], allowed_mentions: builder[:allowed_mentions], components: components&.to_a || view.to_a, sticker_ids: stickers&.map(&:resolve_id), flags: flags }
|
|
969
|
+
response = JSON.parse(API::Channel.start_thread_in_forum_or_media_channel(@bot.token, @id, name, message.compact, attachments, rate_limit_per_user, auto_archive_duration, tags&.map(&:resolve_id), reason))
|
|
970
|
+
|
|
971
|
+
Message.new(response['message'].merge!('channel_id' => response['id'], 'thread' => response), @bot)
|
|
972
|
+
end
|
|
973
|
+
|
|
974
|
+
# @!group Threads
|
|
975
|
+
|
|
976
|
+
# Join this thread.
|
|
977
|
+
def join_thread
|
|
978
|
+
@bot.join_thread(@id)
|
|
979
|
+
end
|
|
980
|
+
|
|
981
|
+
# Leave this thread
|
|
982
|
+
def leave_thread
|
|
983
|
+
@bot.leave_thread(@id)
|
|
984
|
+
end
|
|
985
|
+
|
|
986
|
+
# Members in the thread.
|
|
987
|
+
def members
|
|
988
|
+
@bot.thread_members[@id].collect { |id| @server_id ? @bot.member(@server_id, id) : @bot.user(id) }
|
|
989
|
+
end
|
|
990
|
+
|
|
991
|
+
# Add a member to the thread
|
|
992
|
+
# @param member [Member, Integer, String] The member, or ID of the member, to add to this thread.
|
|
993
|
+
def add_member(member)
|
|
994
|
+
@bot.add_thread_member(@id, member)
|
|
995
|
+
end
|
|
996
|
+
|
|
997
|
+
# @param member [Member, Integer, String] The member, or ID of the member, to remove from a thread.
|
|
998
|
+
def remove_member(member)
|
|
999
|
+
@bot.remove_thread_member(@id, member)
|
|
1000
|
+
end
|
|
1001
|
+
|
|
1002
|
+
# @!endgroup
|
|
1003
|
+
|
|
745
1004
|
# The default `inspect` method is overwritten to give more useful output.
|
|
746
1005
|
def inspect
|
|
747
|
-
"<Channel name=#{@name} id=#{@id} topic=\"#{@topic}\" type=#{@type} position=#{@position} server=#{@server}>"
|
|
1006
|
+
"<Channel name=#{@name} id=#{@id} topic=\"#{@topic}\" type=#{@type} position=#{@position} server=#{@server || @server_id}>"
|
|
748
1007
|
end
|
|
749
1008
|
|
|
750
1009
|
# Adds a recipient to a group channel.
|
|
@@ -771,6 +1030,14 @@ module Discordrb
|
|
|
771
1030
|
@recipients.delete(recipient)
|
|
772
1031
|
end
|
|
773
1032
|
|
|
1033
|
+
# Set the last pin timestamp of a channel.
|
|
1034
|
+
# @param time [String, nil] the time of the last pinned message in the channel
|
|
1035
|
+
# @note For internal use only
|
|
1036
|
+
# @!visibility private
|
|
1037
|
+
def process_last_pin_timestamp(time)
|
|
1038
|
+
@last_pin_timestamp = time ? Time.parse(time) : time
|
|
1039
|
+
end
|
|
1040
|
+
|
|
774
1041
|
# Updates the cached data with new data
|
|
775
1042
|
# @note For internal use only
|
|
776
1043
|
# @!visibility private
|
|
@@ -790,15 +1057,17 @@ module Discordrb
|
|
|
790
1057
|
|
|
791
1058
|
# @return [String] a URL that a user can use to navigate to this channel in the client
|
|
792
1059
|
def link
|
|
793
|
-
"https://discord.com/channels/#{@
|
|
1060
|
+
"https://discord.com/channels/#{@server_id || '@me'}/#{@channel.id}"
|
|
794
1061
|
end
|
|
795
1062
|
|
|
796
1063
|
alias_method :jump_link, :link
|
|
797
1064
|
|
|
798
1065
|
private
|
|
799
1066
|
|
|
1067
|
+
# rubocop:disable Lint/UselessConstantScoping
|
|
800
1068
|
# For bulk_delete checking
|
|
801
1069
|
TWO_WEEKS = 86_400 * 14
|
|
1070
|
+
# rubocop:enable Lint/UselessConstantScoping
|
|
802
1071
|
|
|
803
1072
|
# Deletes a list of messages on this channel using bulk delete.
|
|
804
1073
|
def bulk_delete(ids, strict = false, reason = nil)
|
|
@@ -821,7 +1090,7 @@ module Discordrb
|
|
|
821
1090
|
def update_channel_data(new_data)
|
|
822
1091
|
new_nsfw = new_data[:nsfw].is_a?(TrueClass) || new_data[:nsfw].is_a?(FalseClass) ? new_data[:nsfw] : @nsfw
|
|
823
1092
|
# send permission_overwrite only when explicitly set
|
|
824
|
-
overwrites = new_data[:permission_overwrites] ? new_data[:permission_overwrites].map
|
|
1093
|
+
overwrites = new_data[:permission_overwrites] ? new_data[:permission_overwrites].map(&:to_hash) : nil
|
|
825
1094
|
response = JSON.parse(API::Channel.update(@bot.token, @id,
|
|
826
1095
|
new_data[:name] || @name,
|
|
827
1096
|
new_data[:topic] || @topic,
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Discordrb
|
|
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
|
+
# @return [String] CDN url of this nameplate.
|
|
40
|
+
def url
|
|
41
|
+
API.nameplate_url(@asset)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|