discorb 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +56 -0
  3. data/.yardopts +6 -0
  4. data/Changelog.md +5 -0
  5. data/Gemfile +23 -0
  6. data/Gemfile.lock +70 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +53 -0
  9. data/Rakefile +46 -0
  10. data/bin/console +15 -0
  11. data/bin/setup +8 -0
  12. data/discorb.gemspec +37 -0
  13. data/docs/Examples.md +26 -0
  14. data/docs/events.md +480 -0
  15. data/docs/voice_events.md +283 -0
  16. data/examples/components/authorization_button.rb +43 -0
  17. data/examples/components/select_menu.rb +61 -0
  18. data/examples/extension/main.rb +12 -0
  19. data/examples/extension/message_expander.rb +41 -0
  20. data/examples/simple/eval.rb +32 -0
  21. data/examples/simple/ping_pong.rb +16 -0
  22. data/examples/simple/rolepanel.rb +65 -0
  23. data/examples/simple/wait_for_message.rb +30 -0
  24. data/lib/discorb/application.rb +157 -0
  25. data/lib/discorb/asset.rb +57 -0
  26. data/lib/discorb/audit_logs.rb +323 -0
  27. data/lib/discorb/channel.rb +1101 -0
  28. data/lib/discorb/client.rb +363 -0
  29. data/lib/discorb/color.rb +173 -0
  30. data/lib/discorb/common.rb +123 -0
  31. data/lib/discorb/components.rb +290 -0
  32. data/lib/discorb/dictionary.rb +119 -0
  33. data/lib/discorb/embed.rb +345 -0
  34. data/lib/discorb/emoji.rb +218 -0
  35. data/lib/discorb/emoji_table.rb +3799 -0
  36. data/lib/discorb/error.rb +98 -0
  37. data/lib/discorb/event.rb +35 -0
  38. data/lib/discorb/extend.rb +18 -0
  39. data/lib/discorb/extension.rb +54 -0
  40. data/lib/discorb/file.rb +69 -0
  41. data/lib/discorb/flag.rb +109 -0
  42. data/lib/discorb/gateway.rb +967 -0
  43. data/lib/discorb/gateway_requests.rb +47 -0
  44. data/lib/discorb/guild.rb +1244 -0
  45. data/lib/discorb/guild_template.rb +211 -0
  46. data/lib/discorb/image.rb +43 -0
  47. data/lib/discorb/integration.rb +111 -0
  48. data/lib/discorb/intents.rb +137 -0
  49. data/lib/discorb/interaction.rb +333 -0
  50. data/lib/discorb/internet.rb +285 -0
  51. data/lib/discorb/invite.rb +145 -0
  52. data/lib/discorb/log.rb +70 -0
  53. data/lib/discorb/member.rb +232 -0
  54. data/lib/discorb/message.rb +583 -0
  55. data/lib/discorb/modules.rb +138 -0
  56. data/lib/discorb/permission.rb +270 -0
  57. data/lib/discorb/presence.rb +308 -0
  58. data/lib/discorb/reaction.rb +48 -0
  59. data/lib/discorb/role.rb +189 -0
  60. data/lib/discorb/sticker.rb +157 -0
  61. data/lib/discorb/user.rb +163 -0
  62. data/lib/discorb/utils.rb +16 -0
  63. data/lib/discorb/voice_state.rb +251 -0
  64. data/lib/discorb/webhook.rb +420 -0
  65. data/lib/discorb.rb +51 -0
  66. metadata +120 -0
@@ -0,0 +1,1101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "async"
4
+
5
+ module Discorb
6
+ #
7
+ # Represents a channel of Discord.
8
+ # @abstract
9
+ #
10
+ class Channel < DiscordModel
11
+ # @return [Discorb::Snowflake] The ID of the channel.
12
+ attr_reader :id
13
+ # @return [String] The name of the channel.
14
+ attr_reader :name
15
+
16
+ # @!attribute [r] type
17
+ # @return [Integer] The type of the channel as integer.
18
+
19
+ @channel_type = nil
20
+ @subclasses = []
21
+
22
+ # @!visibility private
23
+ def initialize(client, data, no_cache: false)
24
+ @client = client
25
+ @data = {}
26
+ @no_cache = no_cache
27
+ _set_data(data)
28
+ end
29
+
30
+ #
31
+ # Checks if the channel is other channel.
32
+ #
33
+ # @param [Discorb::Channel] other The channel to check.
34
+ #
35
+ # @return [Boolean] True if the channel is other channel.
36
+ #
37
+ def ==(other)
38
+ return false unless other.respond_to?(:id)
39
+
40
+ @id == other.id
41
+ end
42
+
43
+ def inspect
44
+ "#<#{self.class} \"##{@name}\" id=#{@id}>"
45
+ end
46
+
47
+ # @!visibility private
48
+ def self.descendants
49
+ ObjectSpace.each_object(Class).select { |klass| klass < self }
50
+ end
51
+
52
+ # @!visibility private
53
+ def self.make_channel(client, data, no_cache: false)
54
+ descendants.each do |klass|
55
+ return klass.new(client, data, no_cache: no_cache) if !klass.channel_type.nil? && klass.channel_type == data[:type]
56
+ end
57
+ client.log.warn("Unknown channel type #{data[:type]}, initialized GuildChannel")
58
+ GuildChannel.new(client, data)
59
+ end
60
+
61
+ class << self
62
+ # @!visibility private
63
+ attr_reader :channel_type
64
+ end
65
+
66
+ def type
67
+ self.class.channel_type
68
+ end
69
+
70
+ # @!visibility private
71
+ def base_url
72
+ Async do
73
+ "/channels/#{@id}"
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ def _set_data(data)
80
+ @id = Snowflake.new(data[:id])
81
+ @name = data[:name]
82
+ @client.channels[@id] = self if !@no_cache && !(data[:no_cache])
83
+ @data.update(data)
84
+ end
85
+ end
86
+
87
+ #
88
+ # Represents a channel in guild.
89
+ # @abstract
90
+ #
91
+ class GuildChannel < Channel
92
+ # @return [Integer] The position of the channel as integer.
93
+ attr_reader :position
94
+ # @return [Hash{Discorb::Role, Discorb::Member => PermissionOverwrite}] The permission overwrites of the channel.
95
+ attr_reader :permission_overwrites
96
+
97
+ # @!attribute [r] mention
98
+ # @return [String] The mention of the channel.
99
+ #
100
+ # @!attribute [r] parent
101
+ # @macro client_cache
102
+ # @return [Discorb::CategoryChannel] The parent of channel.
103
+ # @return [nil] If the channel is not a child of category.
104
+ #
105
+ # @!attribute [r] guild
106
+ # @return [Discorb::Guild] The guild of channel.
107
+ # @macro client_cache
108
+
109
+ include Comparable
110
+ @channel_type = nil
111
+
112
+ #
113
+ # Compares position of two channels.
114
+ #
115
+ # @param [Discorb::GuildChannel] other The channel to compare.
116
+ #
117
+ # @return [-1, 1] -1 if the channel is at lower than the other, 1 if the channel is at highter than the other.
118
+ #
119
+ def <=>(other)
120
+ return 0 unless other.respond_to?(:position)
121
+
122
+ @position <=> other.position
123
+ end
124
+
125
+ #
126
+ # Checks if the channel is same as another.
127
+ #
128
+ # @param [Discorb::GuildChannel] other The channel to check.
129
+ #
130
+ # @return [Boolean] `true` if the channel is same as another.
131
+ #
132
+ def ==(other)
133
+ return false unless other.respond_to?(:id)
134
+
135
+ @id == other.id
136
+ end
137
+
138
+ #
139
+ # Stringifies the channel.
140
+ #
141
+ # @return [String] The name of the channel with `#`.
142
+ #
143
+ def to_s
144
+ "##{@name}"
145
+ end
146
+
147
+ def mention
148
+ "<##{@id}>"
149
+ end
150
+
151
+ def parent
152
+ return nil unless @parent_id
153
+
154
+ @client.channels[@parent_id]
155
+ end
156
+
157
+ alias category parent
158
+
159
+ def guild
160
+ @client.guilds[@guild_id]
161
+ end
162
+
163
+ def inspect
164
+ "#<#{self.class} \"##{@name}\" id=#{@id}>"
165
+ end
166
+
167
+ #
168
+ # Deletes the channel.
169
+ # @macro async
170
+ # @macro http
171
+ #
172
+ # @param [String] reason The reason of deleting the channel.
173
+ #
174
+ # @return [self] The deleted channel.
175
+ #
176
+ def delete!(reason: nil)
177
+ Async do
178
+ @client.internet.delete(base_url.wait.to_s, audit_log_reason: reason).wait
179
+ @deleted = true
180
+ self
181
+ end
182
+ end
183
+
184
+ alias close! delete!
185
+ alias destroy! delete!
186
+
187
+ #
188
+ # Moves the channel to another position.
189
+ # @macro async
190
+ # @macro http
191
+ #
192
+ # @param [Integer] position The position to move the channel.
193
+ # @param [Boolean] lock_permissions Whether to lock the permissions of the channel.
194
+ # @param [Discorb::CategoryChannel] parent The parent of channel.
195
+ # @param [String] reason The reason of moving the channel.
196
+ #
197
+ # @return [self] The moved channel.
198
+ #
199
+ def move(position, lock_permissions: false, parent: :unset, reason: nil)
200
+ Async do
201
+ payload = {
202
+ position: position,
203
+ }
204
+ payload[:lock_permissions] = lock_permissions
205
+ payload[:parent_id] = parent&.id if parent != :unset
206
+ @client.internet.patch("/guilds/#{@guild_id}/channels", payload, audit_log_reason: reason).wait
207
+ end
208
+ end
209
+
210
+ private
211
+
212
+ def _set_data(data)
213
+ @guild_id = data[:guild_id]
214
+ @position = data[:position]
215
+ @permission_overwrites = if data[:permission_overwrites]
216
+ data[:permission_overwrites].map do |ow|
217
+ [(ow[:type] == 1 ? guild.roles : guild.members)[ow[:id]], PermissionOverwrite.new(ow[:allow], ow[:deny])]
218
+ end.to_h
219
+ else
220
+ {}
221
+ end
222
+ @parent_id = data[:parent_id]
223
+
224
+ super
225
+ end
226
+ end
227
+
228
+ #
229
+ # Represents a text channel.
230
+ #
231
+ class TextChannel < GuildChannel
232
+ # @return [String] The topic of the channel.
233
+ attr_reader :topic
234
+ # @return [Boolean] Whether the channel is nsfw.
235
+ attr_reader :nsfw
236
+ # @return [Discorb::Snowflake] The id of the last message.
237
+ attr_reader :last_message_id
238
+ # @return [Integer] The rate limit per user (Slowmode) in the channel.
239
+ attr_reader :rate_limit_per_user
240
+ alias slowmode rate_limit_per_user
241
+ # @return [Time] The time when the last pinned message was pinned.
242
+ attr_reader :last_pin_timestamp
243
+ alias last_pinned_at last_pin_timestamp
244
+ # @return [Array<Discorb::ThreadChannel>] The threads in the channel.
245
+ attr_reader :threads
246
+
247
+ include Messageable
248
+
249
+ @channel_type = 0
250
+
251
+ # @!visibility private
252
+ def initialize(client, data, no_cache: false)
253
+ super
254
+ @threads = Dictionary.new
255
+ end
256
+
257
+ #
258
+ # Edits the channel.
259
+ # @macro async
260
+ # @macro http
261
+ # @macro edit
262
+ #
263
+ # @param [String] name The name of the channel.
264
+ # @param [Integer] position The position of the channel.
265
+ # @param [Discorb::CategoryChannel, nil] category The parent of channel. Specify `nil` to remove the parent.
266
+ # @param [Discorb::CategoryChannel, nil] parent Alias of `category`.
267
+ # @param [String] topic The topic of the channel.
268
+ # @param [Boolean] nsfw Whether the channel is nsfw.
269
+ # @param [Boolean] announce Whether the channel is announce channel.
270
+ # @param [Integer] rate_limit_per_user The rate limit per user (Slowmode) in the channel.
271
+ # @param [Integer] slowmode Alias of `rate_limit_per_user`.
272
+ # @param [Integer] default_auto_archive_duration The default auto archive duration of the channel.
273
+ # @param [Integer] archive_in Alias of `default_auto_archive_duration`.
274
+ # @param [String] reason The reason of editing the channel.
275
+ #
276
+ # @return [self] The edited channel.
277
+ #
278
+ def edit(name: :unset, position: :unset, category: :unset, parent: :unset,
279
+ topic: :unset, nsfw: :unset, announce: :unset,
280
+ rate_limit_per_user: :unset, slowmode: :unset, default_auto_archive_duration: :unset,
281
+ archive_in: :unset, reason: nil)
282
+ Async do
283
+ payload = {}
284
+ payload[:name] = name if name != :unset
285
+ payload[:announce] = announce ? 5 : 0 if announce != :unset
286
+ payload[:position] = position if position != :unset
287
+ payload[:topic] = topic || "" if topic != :unset
288
+ payload[:nsfw] = nsfw if nsfw != :unset
289
+
290
+ slowmode = rate_limit_per_user if slowmode == :unset
291
+ payload[:rate_limit_per_user] = slowmode || 0 if slowmode != :unset
292
+ parent = category if parent == :unset
293
+ payload[:parent_id] = parent&.id if parent != :unset
294
+
295
+ default_auto_archive_duration ||= archive_in
296
+ payload[:default_auto_archive_duration] = default_auto_archive_duration if default_auto_archive_duration != :unset
297
+
298
+ @client.internet.patch("/channels/#{@id}", payload, audit_log_reason: reason).wait
299
+ self
300
+ end
301
+ end
302
+
303
+ alias modify edit
304
+
305
+ #
306
+ # Create webhook in the channel.
307
+ # @macro async
308
+ # @macro http
309
+ #
310
+ # @param [String] name The name of the webhook.
311
+ # @param [Discorb::Image] avatar The avatar of the webhook.
312
+ #
313
+ # @return [Discorb::Webhook::IncomingWebhook] The created webhook.
314
+ #
315
+ def create_webhook(name, avatar: nil)
316
+ Async do
317
+ payload = {}
318
+ payload[:name] = name
319
+ payload[:avatar] = avatar.to_s if avatar
320
+ _resp, data = @client.internet.post("/channels/#{@id}/webhooks", payload).wait
321
+ Webhook.new([@client, data])
322
+ end
323
+ end
324
+
325
+ #
326
+ # Fetch webhooks in the channel.
327
+ # @macro async
328
+ # @macro http
329
+ #
330
+ # @return [Array<Discorb::Webhook>] The webhooks in the channel.
331
+ #
332
+ def fetch_webhooks
333
+ Async do
334
+ _resp, data = @client.internet.get("/channels/#{@id}/webhooks").wait
335
+ data.map { |webhook| Webhook.new([@client, webhook]) }
336
+ end
337
+ end
338
+
339
+ #
340
+ # Bulk delete messages in the channel.
341
+ # @macro async
342
+ # @macro http
343
+ #
344
+ # @param [Discorb::Message] messages The messages to delete.
345
+ # @param [Boolean] force Whether to ignore the validation for message (14 days limit).
346
+ #
347
+ def delete_messages!(*messages, force: false)
348
+ Async do
349
+ messages = messages.first if messages.length == 1 && messages.first.is_a?(Array)
350
+ unless force
351
+ time = Time.now
352
+ messages.delete_if do |message|
353
+ next false unless message.is_a?(Message)
354
+
355
+ time - message.created_at > 60 * 60 * 24 * 14
356
+ end
357
+ end
358
+
359
+ message_ids = messages.map { |m| Discorb::Utils.try(m, :id).to_s }
360
+
361
+ @client.internet.post("/channels/#{@id}/messages/bulk-delete", { messages: message_ids }).wait
362
+ end
363
+ end
364
+
365
+ alias bulk_delete! delete_messages!
366
+ alias destroy_messages! delete_messages!
367
+
368
+ #
369
+ # Set the channel's permission overwrite.
370
+ # @macro async
371
+ # @macro http
372
+ #
373
+ # @param [Discorb::Role, Discorb::Member] target The target of the overwrite.
374
+ # @param [String] reason The reason of setting the overwrite.
375
+ # @param [Symbol => Boolean] perms The permission overwrites to replace.
376
+ #
377
+ def set_permissions(target, reason: nil, **perms)
378
+ Async do
379
+ allow_value = @permission_overwrites[target]&.allow_value.to_i
380
+ deny_value = @permission_overwrites[target]&.deny_value.to_i
381
+ perms.each do |perm, value|
382
+ allow_value[Discorb::Permission.bits[perm]] = 1 if value == true
383
+ deny_value[Discorb::Permission.bits[perm]] = 1 if value == false
384
+ end
385
+ payload = {
386
+ allow: allow_value,
387
+ deny: deny_value,
388
+ type: target.is_a?(Member) ? 1 : 0,
389
+ }
390
+ @client.internet.put("/channels/#{@id}/permissions/#{target.id}", payload, audit_log_reason: reason).wait
391
+ end
392
+ end
393
+
394
+ alias modify_permissions set_permissions
395
+ alias modify_permisssion set_permissions
396
+ alias edit_permissions set_permissions
397
+ alias edit_permission set_permissions
398
+
399
+ #
400
+ # Delete the channel's permission overwrite.
401
+ # @macro async
402
+ # @macro http
403
+ #
404
+ # @param [Discorb::Role, Discorb::Member] target The target of the overwrite.
405
+ # @param [String] reason The reason of deleting the overwrite.
406
+ #
407
+ def delete_permissions(target, reason: nil)
408
+ Async do
409
+ @client.internet.delete("/channels/#{@id}/permissions/#{target.id}", audit_log_reason: reason).wait
410
+ end
411
+ end
412
+
413
+ alias delete_permission delete_permissions
414
+ alias destroy_permissions delete_permissions
415
+ alias destroy_permission delete_permissions
416
+
417
+ #
418
+ # Fetch the channel's invites.
419
+ # @macro async
420
+ # @macro http
421
+ #
422
+ # @return [Array<Discorb::Invite>] The invites in the channel.
423
+ #
424
+ def fetch_invites
425
+ Async do
426
+ _resp, data = @client.internet.get("/channels/#{@id}/invites").wait
427
+ data.map { |invite| Invite.new(@client, invite) }
428
+ end
429
+ end
430
+
431
+ #
432
+ # Create an invite in the channel.
433
+ # @macro async
434
+ # @macro http
435
+ #
436
+ # @param [Integer] max_age The max age of the invite.
437
+ # @param [Integer] max_uses The max uses of the invite.
438
+ # @param [Boolean] temporary Whether the invite is temporary.
439
+ # @param [Boolean] unique Whether the invite is unique.
440
+ # @note if it's `false` it may return existing invite.
441
+ # @param [String] reason The reason of creating the invite.
442
+ #
443
+ # @return [Invite] The created invite.
444
+ #
445
+ def create_invite(max_age: nil, max_uses: nil, temporary: false, unique: false, reason: nil)
446
+ Async do
447
+ _resp, data = @client.internet.post("/channels/#{@id}/invites", {
448
+ max_age: max_age,
449
+ max_uses: max_uses,
450
+ temporary: temporary,
451
+ unique: unique,
452
+ }, audit_log_reason: reason).wait
453
+ Invite.new(@client, data)
454
+ end
455
+ end
456
+
457
+ #
458
+ # Follow the existing announcement channel.
459
+ # @macro async
460
+ # @macro http
461
+ #
462
+ # @param [Discorb::NewsChannel] target The channel to follow.
463
+ # @param [String] reason The reason of following the channel.
464
+ #
465
+ def follow_from(target, reason: nil)
466
+ Async do
467
+ @client.internet.post("/channels/#{target.id}/followers", { webhook_channel_id: @id }, audit_log_reason: reason).wait
468
+ end
469
+ end
470
+
471
+ #
472
+ # Follow the existing announcement channel from self.
473
+ # @macro async
474
+ # @macro http
475
+ #
476
+ # @param [Discorb::TextChannel] target The channel to follow to.
477
+ # @param [String] reason The reason of following the channel.
478
+ #
479
+ def follow_to(target, reason: nil)
480
+ Async do
481
+ @client.internet.post("/channels/#{@id}/followers", { webhook_channel_id: target.id }, audit_log_reason: reason).wait
482
+ end
483
+ end
484
+
485
+ #
486
+ # Fetch the pinned messages in the channel.
487
+ # @macro async
488
+ # @macro http
489
+ #
490
+ # @return [Array<Discorb::Message>] The pinned messages in the channel.
491
+ #
492
+ def fetch_pins
493
+ Async do
494
+ _resp, data = @client.internet.get("/channels/#{@id}/pins").wait
495
+ data.map { |pin| Message.new(@client, pin) }
496
+ end
497
+ end
498
+
499
+ #
500
+ # Pin a message in the channel.
501
+ # @macro async
502
+ # @macro http
503
+ #
504
+ # @param [Discorb::Message] message The message to pin.
505
+ # @param [String] reason The reason of pinning the message.
506
+ #
507
+ def pin_message(message, reason: nil)
508
+ Async do
509
+ @client.internet.put("/channels/#{@id}/pins/#{message.id}", {}, audit_log_reason: reason).wait
510
+ end
511
+ end
512
+
513
+ #
514
+ # Unpin a message in the channel.
515
+ # @macro async
516
+ # @macro http
517
+ #
518
+ # @param [Discorb::Message] message The message to unpin.
519
+ # @param [String] reason The reason of unpinning the message.
520
+ #
521
+ def unpin_message(message, reason: nil)
522
+ Async do
523
+ @client.internet.delete("/channels/#{@id}/pins/#{message.id}", {}, audit_log_reason: reason).wait
524
+ end
525
+ end
526
+
527
+ #
528
+ # Start thread in the channel.
529
+ # @macro async
530
+ # @macro http
531
+ #
532
+ # @param [String] name The name of the thread.
533
+ # @param [Discorb::Message] message The message to start the thread.
534
+ # @param [Integer] auto_archive_duration The duration of auto-archiving.
535
+ # @param [Boolean] public Whether the thread is public.
536
+ # @param [String] reason The reason of starting the thread.
537
+ #
538
+ # @return [Discorb::ThreadChannel] The started thread.
539
+ #
540
+ def start_thread(name, message: nil, auto_archive_duration: 1440, public: true, reason: nil)
541
+ Async do
542
+ _resp, data = if message.nil?
543
+ @client.internet.post("/channels/#{@id}/threads", {
544
+ name: name, auto_archive_duration: auto_archive_duration, type: public ? 11 : 10,
545
+ },
546
+ audit_log_reason: reason).wait
547
+ else
548
+ @client.internet.post("/channels/#{@id}/messages/#{Utils.try(message, :id)}/threads", {
549
+ name: name, auto_archive_duration: auto_archive_duration,
550
+ }, audit_log_reason: reason).wait
551
+ end
552
+ Channel.make_channel(@client, data)
553
+ end
554
+ end
555
+
556
+ alias create_thread start_thread
557
+
558
+ #
559
+ # Fetch archived threads in the channel.
560
+ # @macro async
561
+ # @macro http
562
+ #
563
+ # @return [Array<Discorb::ThreadChannel>] The archived threads in the channel.
564
+ #
565
+ def fetch_archived_public_threads
566
+ Async do
567
+ _resp, data = @client.internet.get("/channels/#{@id}/threads/archived/public").wait
568
+ data.map { |thread| Channel.make_channel(@client, thread) }
569
+ end
570
+ end
571
+
572
+ #
573
+ # Fetch archived private threads in the channel.
574
+ # @macro async
575
+ # @macro http
576
+ #
577
+ # @return [Array<Discorb::ThreadChannel>] The archived private threads in the channel.
578
+ #
579
+ def fetch_archived_private_threads
580
+ Async do
581
+ _resp, data = @client.internet.get("/channels/#{@id}/threads/archived/private").wait
582
+ data.map { |thread| Channel.make_channel(@client, thread) }
583
+ end
584
+ end
585
+
586
+ #
587
+ # Fetch joined archived private threads in the channel.
588
+ # @macro async
589
+ # @macro http
590
+ #
591
+ # @param [Integer] limit The limit of threads to fetch.
592
+ # @param [Time] before <description>
593
+ #
594
+ # @return [Array<Discorb::ThreadChannel>] The joined archived private threads in the channel.
595
+ #
596
+ def fetch_joined_archived_private_threads(limit: nil, before: nil)
597
+ Async do
598
+ if limit.nil?
599
+ before = 0
600
+ threads = []
601
+ loop do
602
+ _resp, data = @client.internet.get("/channels/#{@id}/users/@me/threads/archived/private?before=#{before}").wait
603
+ threads += data[:threads].map { |thread| Channel.make_channel(@client, thread) }
604
+ before = data[:threads][-1][:id]
605
+
606
+ break unless data[:has_more]
607
+ end
608
+ threads
609
+ else
610
+ _resp, data = @client.internet.get("/channels/#{@id}/users/@me/threads/archived/private?limit=#{limit}&before=#{before}").wait
611
+ data.map { |thread| Channel.make_channel(@client, thread) }
612
+ end
613
+ end
614
+ end
615
+
616
+ private
617
+
618
+ def _set_data(data)
619
+ @topic = data[:topic]
620
+ @nsfw = data[:nsfw]
621
+ @last_message_id = data[:last_message_id]
622
+ @rate_limit_per_user = data[:rate_limit_per_user]
623
+ @last_pin_timestamp = data[:last_pin_timestamp] && Time.iso8601(data[:last_pin_timestamp])
624
+ super
625
+ end
626
+ end
627
+
628
+ #
629
+ # Represents a news channel (announcement channel).
630
+ #
631
+ class NewsChannel < TextChannel
632
+ include Messageable
633
+
634
+ @channel_type = 5
635
+ end
636
+
637
+ #
638
+ # Represents a voice channel.
639
+ # @todo Implement connecting to voice channel.
640
+ #
641
+ class VoiceChannel < GuildChannel
642
+ # @return [Integer] The bitrate of the voice channel.
643
+ attr_reader :bitrate
644
+ # @return [Integer] The user limit of the voice channel.
645
+ # @return [nil] If the user limit is not set.
646
+ attr_reader :user_limit
647
+
648
+ @channel_type = 2
649
+ #
650
+ # Edit the voice channel.
651
+ # @macro async
652
+ # @macro http
653
+ # @macro edit
654
+ #
655
+ # @param [String] name The name of the voice channel.
656
+ # @param [Integer] position The position of the voice channel.
657
+ # @param [Integer] bitrate The bitrate of the voice channel.
658
+ # @param [Integer] user_limit The user limit of the voice channel.
659
+ # @param [Symbol] rtc_region The region of the voice channel.
660
+ # @param [String] reason The reason of editing the voice channel.
661
+ #
662
+ # @return [self] The edited voice channel.
663
+ #
664
+ def edit(name: :unset, position: :unset, bitrate: :unset, user_limit: :unset, rtc_region: :unset, reason: nil)
665
+ Async do
666
+ payload = {}
667
+ payload[:name] = name if name != :unset
668
+ payload[:position] = position if position != :unset
669
+ payload[:bitrate] = bitrate if bitrate != :unset
670
+ payload[:user_limit] = user_limit if user_limit != :unset
671
+ payload[:rtc_region] = rtc_region if rtc_region != :unset
672
+
673
+ @client.internet.patch("/channels/#{@id}", payload, audit_log_reason: reason).wait
674
+ self
675
+ end
676
+ end
677
+
678
+ alias modify edit
679
+
680
+ private
681
+
682
+ def _set_data(data)
683
+ @bitrate = data[:bitrate]
684
+ @user_limit = (data[:user_limit]).zero? ? nil : data[:user_limit]
685
+ @rtc_region = data[:rtc_region]&.to_sym
686
+ @video_quality_mode = data[:video_quality_mode] == 1 ? :auto : :full
687
+ super
688
+ end
689
+ end
690
+
691
+ #
692
+ # Represents a stage channel.
693
+ #
694
+ class StageChannel < GuildChannel
695
+ # @return [Integer] The bitrate of the voice channel.
696
+ attr_reader :bitrate
697
+ # @return [Integer] The user limit of the voice channel.
698
+ attr_reader :user_limit
699
+ # @!visibility private
700
+ attr_reader :stage_instances
701
+
702
+ # @!attribute [r] stage_instance
703
+ # @return [Discorb::StageInstance] The stage instance of the channel.
704
+
705
+ @channel_type = 13
706
+ # @!visibility private
707
+ def initialize(...)
708
+ @stage_instances = Dictionary.new
709
+ super(...)
710
+ end
711
+
712
+ def stage_instance
713
+ @stage_instances[0]
714
+ end
715
+
716
+ #
717
+ # Edit the stage channel.
718
+ # @macro async
719
+ # @macro http
720
+ # @macro edit
721
+ #
722
+ # @param [String] name The name of the stage channel.
723
+ # @param [Integer] position The position of the stage channel.
724
+ # @param [Integer] bitrate The bitrate of the stage channel.
725
+ # @param [Symbol] rtc_region The region of the stage channel.
726
+ # @param [String] reason The reason of editing the stage channel.
727
+ #
728
+ # @return [self] The edited stage channel.
729
+ #
730
+ def edit(name: :unset, position: :unset, bitrate: :unset, rtc_region: :unset, reason: nil)
731
+ Async do
732
+ payload = {}
733
+ payload[:name] = name if name != :unset
734
+ payload[:position] = position if position != :unset
735
+ payload[:bitrate] = bitrate if bitrate != :unset
736
+ payload[:rtc_region] = rtc_region if rtc_region != :unset
737
+ @client.internet.patch("/channels/#{@id}", payload, audit_log_reason: reason).wait
738
+ self
739
+ end
740
+ end
741
+
742
+ alias modify edit
743
+
744
+ #
745
+ # Start a stage instance.
746
+ # @macro async
747
+ # @macro http
748
+ #
749
+ # @param [String] topic The topic of the stage instance.
750
+ # @param [Boolean] public Whether the stage instance is public or not.
751
+ # @param [String] reason The reason of starting the stage instance.
752
+ #
753
+ # @return [Discorb::StageInstance] The started stage instance.
754
+ #
755
+ def start(topic, public: false, reason: nil)
756
+ Async do
757
+ _resp, data = @client.internet.post("/stage-instances", { channel_id: @id, topic: topic, public: public ? 2 : 1 }, audit_log_reason: reason).wait
758
+ StageInstance.new(@client, data)
759
+ end
760
+ end
761
+
762
+ #
763
+ # Fetch a current stage instance.
764
+ # @macro async
765
+ # @macro http
766
+ #
767
+ # @return [StageInstance] The current stage instance.
768
+ # @return [nil] If there is no current stage instance.
769
+ #
770
+ def fetch_stage_instance
771
+ Async do
772
+ _resp, data = @client.internet.get("/stage-instances/#{@id}").wait
773
+ rescue Discorb::NotFoundError
774
+ nil
775
+ else
776
+ StageInstance.new(@client, data)
777
+ end
778
+ end
779
+
780
+ private
781
+
782
+ def _set_data(data)
783
+ @bitrate = data[:bitrate]
784
+ @user_limit = data[:user_limit]
785
+ @topic = data[:topic]
786
+ @rtc_region = data[:rtc_region]&.to_sym
787
+ super
788
+ end
789
+ end
790
+
791
+ #
792
+ # Represents a thread.
793
+ # @abstract
794
+ #
795
+ class ThreadChannel < Channel
796
+ # @return [Discorb::Snowflake] The ID of the channel.
797
+ # @note This ID is same as the starter message's ID
798
+ attr_reader :id
799
+ # @return [String] The name of the thread.
800
+ attr_reader :name
801
+ # @return [Integer] The number of messages in the thread.
802
+ # @note This will stop counting at 50.
803
+ attr_reader :message_count
804
+ # @return [Integer] The number of recipients in the thread.
805
+ # @note This will stop counting at 50.
806
+ attr_reader :member_count
807
+ alias recipient_count member_count
808
+ # @return [Integer] The rate limit per user (slowmode) in the thread.
809
+ attr_reader :rate_limit_per_user
810
+ alias slowmode rate_limit_per_user
811
+ # @return [Array<Discorb::ThreadChannel::Member>] The members of the thread.
812
+ attr_reader :members
813
+ # @return [Time] The time the thread was archived.
814
+ # @return [nil] If the thread is not archived.
815
+ attr_reader :archived_timestamp
816
+ alias archived_at archived_timestamp
817
+ # @return [Integer] Auto archive duration in seconds.
818
+ attr_reader :auto_archive_duration
819
+ alias archive_in auto_archive_duration
820
+ # @return [Boolean] Whether the thread is archived or not.
821
+ attr_reader :archived
822
+ alias archived? archived
823
+
824
+ # @!attribute [r] parent
825
+ # @macro client_cache
826
+ # @return [Discorb::GuildChannel] The parent channel of the thread.
827
+
828
+ include Messageable
829
+ @channel_type = nil
830
+
831
+ # @!visibility private
832
+ def initialize(client, data, no_cache: false)
833
+ @members = Dictionary.new
834
+ super
835
+ @client.channels[@parent_id].threads[@id] = self
836
+
837
+ @client.channels[@id] = self unless no_cache
838
+ end
839
+
840
+ #
841
+ # Edit the thread.
842
+ # @macro async
843
+ # @macro http
844
+ # @macro edit
845
+ #
846
+ # @param [String] name The name of the thread.
847
+ # @param [Boolean] archived Whether the thread is archived or not.
848
+ # @param [Integer] auto_archive_duration The auto archive duration in seconds.
849
+ # @param [Integer] archive_in Alias of `auto_archive_duration`.
850
+ # @param [Boolean] locked Whether the thread is locked or not.
851
+ # @param [String] reason The reason of editing the thread.
852
+ #
853
+ # @return [self] The edited thread.
854
+ #
855
+ # @see #archive
856
+ # @see #lock
857
+ # @see #unarchive
858
+ # @see #unlock
859
+ #
860
+ def edit(name: :unset, archived: :unset, auto_archive_duration: :unset, archive_in: :unset, locked: :unset, reason: nil)
861
+ Async do
862
+ payload = {}
863
+ payload[:name] = name if name != :unset
864
+ payload[:archived] = archived if archived != :unset
865
+ auto_archive_duration ||= archive_in
866
+ payload[:auto_archive_duration] = auto_archive_duration if auto_archive_duration != :unset
867
+ payload[:locked] = locked if locked != :unset
868
+ @client.internet.patch("/channels/#{@id}", payload, audit_log_reason: reason).wait
869
+ self
870
+ end
871
+ end
872
+
873
+ #
874
+ # Helper method to archive the thread.
875
+ #
876
+ # @param [String] reason The reason of archiving the thread.
877
+ #
878
+ # @return [self] The archived thread.
879
+ #
880
+ def archive(reason: nil)
881
+ edit(archived: true, reason: reason)
882
+ end
883
+
884
+ #
885
+ # Helper method to lock the thread.
886
+ #
887
+ # @param [String] reason The reason of locking the thread.
888
+ #
889
+ # @return [self] The locked thread.
890
+ #
891
+ def lock(reason: nil)
892
+ edit(archived: true, locked: true, reason: reason)
893
+ end
894
+
895
+ #
896
+ # Helper method to unarchive the thread.
897
+ #
898
+ # @param [String] reason The reason of unarchiving the thread.
899
+ #
900
+ # @return [self] The unarchived thread.
901
+ #
902
+ def unarchive(reason: nil)
903
+ edit(archived: false, reason: reason)
904
+ end
905
+
906
+ #
907
+ # Helper method to unlock the thread.
908
+ #
909
+ # @param [String] reason The reason of unlocking the thread.
910
+ #
911
+ # @return [self] The unlocked thread.
912
+ #
913
+ # @note This method won't unarchive the thread. Use {#unarchive} instead.
914
+ #
915
+ def unlock(reason: nil)
916
+ edit(archived: !unarchive, locked: false, reason: reason)
917
+ end
918
+
919
+ def parent
920
+ return nil unless @parent_id
921
+
922
+ @client.channels[@parent_id]
923
+ end
924
+
925
+ alias channel parent
926
+
927
+ def me
928
+ @members[@client.user.id]
929
+ end
930
+
931
+ def joined?
932
+ @members[@client.user.id]
933
+ end
934
+
935
+ def guild
936
+ @client.guilds[@guild]
937
+ end
938
+
939
+ def owner
940
+ guild.members[@owner_id]
941
+ end
942
+
943
+ def inspect
944
+ "#<#{self.class} \"##{@name}\" id=#{@id}>"
945
+ end
946
+
947
+ def add_member(member = :me)
948
+ Async do
949
+ if member == :me
950
+ @client.internet.post("/channels/#{@id}/thread-members/@me").wait
951
+ else
952
+ @client.internet.post("/channels/#{@id}/thread-members/#{Utils.try(member, :id)}").wait
953
+ end
954
+ end
955
+ end
956
+
957
+ alias join add_member
958
+
959
+ def remove_member(member = :me)
960
+ Async do
961
+ if member == :me
962
+ @client.internet.delete("/channels/#{@id}/thread-members/@me").wait
963
+ else
964
+ @client.internet.delete("/channels/#{@id}/thread-members/#{Utils.try(member, :id)}").wait
965
+ end
966
+ end
967
+ end
968
+
969
+ alias leave remove_member
970
+
971
+ def fetch_members
972
+ Async do
973
+ _resp, data = @client.internet.get("/channels/#{@id}/thread-members").wait
974
+ data.map { |d| @members[d[:id]] = Member.new(@client, d) }
975
+ end
976
+ end
977
+
978
+ class Public < ThreadChannel
979
+ @channel_type = 11
980
+ end
981
+
982
+ class Private < ThreadChannel
983
+ @channel_type = 12
984
+ end
985
+
986
+ class << self
987
+ attr_reader :channel_type
988
+ end
989
+
990
+ class Member < DiscordModel
991
+ attr_reader :joined_at
992
+
993
+ def initialize(cilent, data)
994
+ @cilent = cilent
995
+ @thread_id = data[:id]
996
+ @user_id = data[:user_id]
997
+ @joined_at = Time.iso8601(data[:join_timestamp])
998
+ end
999
+
1000
+ def thread
1001
+ @client.channels[@thread_id]
1002
+ end
1003
+
1004
+ def member
1005
+ thread && thread.members[@user_id]
1006
+ end
1007
+
1008
+ def id
1009
+ @user_id
1010
+ end
1011
+
1012
+ def user
1013
+ @cilent.users[@user_id]
1014
+ end
1015
+
1016
+ def inspect
1017
+ "#<#{self.class} id=#{@id.inspect}>"
1018
+ end
1019
+ end
1020
+
1021
+ private
1022
+
1023
+ def _set_data(data)
1024
+ @id = Snowflake.new(data[:id])
1025
+ @name = data[:name]
1026
+ @guild_id = data[:guild_id]
1027
+ @parent_id = data[:parent_id]
1028
+ @archived = data[:thread_metadata][:archived]
1029
+ @owner_id = data[:owner_id]
1030
+ @archived_timestamp = data[:thread_metadata][:archived_timestamp] && Time.iso8601(data[:thread_metadata][:archived_timestamp])
1031
+ @auto_archive_duration = data[:thread_metadata][:auto_archive_duration]
1032
+ @locked = data[:thread_metadata][:locked]
1033
+ @member_count = data[:member_count]
1034
+ @message_count = data[:message_count]
1035
+ @members[@client.user.id] = ThreadChannel::Member.new(@client, data[:member].merge({ id: data[:id], user_id: @client.user.id })) if data[:member]
1036
+ @data.merge!(data)
1037
+ end
1038
+ end
1039
+
1040
+ class CategoryChannel < GuildChannel
1041
+ attr_reader :channels
1042
+
1043
+ @channel_type = 4
1044
+
1045
+ def text_channels
1046
+ @channels.filter { |c| c.is_a? TextChannel }
1047
+ end
1048
+
1049
+ def voice_channels
1050
+ @channels.filter { |c| c.is_a? VoiceChannel }
1051
+ end
1052
+
1053
+ def news_channel
1054
+ @channels.filter { |c| c.is_a? NewsChannel }
1055
+ end
1056
+
1057
+ def stage_channels
1058
+ @channels.filter { |c| c.is_a? StageChannel }
1059
+ end
1060
+
1061
+ def create_text_channel(*args, **kwargs)
1062
+ guild.create_text_channel(*args, parent: self, **kwargs)
1063
+ end
1064
+
1065
+ def create_voice_channel(*args, **kwargs)
1066
+ guild.create_voice_channel(*args, parent: self, **kwargs)
1067
+ end
1068
+
1069
+ def create_news_channel(*args, **kwargs)
1070
+ guild.create_news_channel(*args, parent: self, **kwargs)
1071
+ end
1072
+
1073
+ def create_stage_channel(*args, **kwargs)
1074
+ guild.create_stage_channel(*args, parent: self, **kwargs)
1075
+ end
1076
+
1077
+ private
1078
+
1079
+ def _set_data(data)
1080
+ @channels = @client.channels.values.filter { |channel| channel.parent == self }
1081
+ super
1082
+ end
1083
+ end
1084
+
1085
+ class DMChannel < Channel
1086
+ include Messageable
1087
+
1088
+ # @!visibility private
1089
+ def base_url
1090
+ Async do
1091
+ "/channels/#{@id}"
1092
+ end
1093
+ end
1094
+
1095
+ private
1096
+
1097
+ def _set_data(data)
1098
+ @id = Snowflake.new(data)
1099
+ end
1100
+ end
1101
+ end