discorb 0.13.4 → 0.15.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.github/workflows/build_version.yml +1 -1
  4. data/.github/workflows/codeql-analysis.yml +70 -0
  5. data/.github/workflows/lint-push.yml +20 -0
  6. data/.github/workflows/lint.yml +16 -0
  7. data/.rubocop.yml +74 -0
  8. data/Changelog.md +30 -0
  9. data/Gemfile +7 -3
  10. data/Rakefile +28 -22
  11. data/discorb.gemspec +1 -0
  12. data/docs/events.md +50 -0
  13. data/docs/faq.md +8 -8
  14. data/examples/commands/bookmarker.rb +2 -1
  15. data/examples/commands/hello.rb +1 -0
  16. data/examples/commands/inspect.rb +3 -2
  17. data/examples/components/authorization_button.rb +2 -1
  18. data/examples/components/select_menu.rb +2 -1
  19. data/examples/extension/main.rb +1 -0
  20. data/examples/extension/message_expander.rb +1 -0
  21. data/examples/simple/eval.rb +3 -2
  22. data/examples/simple/ping_pong.rb +1 -0
  23. data/examples/simple/rolepanel.rb +1 -0
  24. data/examples/simple/wait_for_message.rb +4 -3
  25. data/exe/discorb +8 -7
  26. data/lib/discorb/allowed_mentions.rb +71 -0
  27. data/lib/discorb/app_command/command.rb +336 -0
  28. data/lib/discorb/app_command/handler.rb +168 -0
  29. data/lib/discorb/app_command.rb +2 -426
  30. data/lib/discorb/application.rb +16 -7
  31. data/lib/discorb/asset.rb +11 -0
  32. data/lib/discorb/{file.rb → attachment.rb} +55 -33
  33. data/lib/discorb/audit_logs.rb +45 -7
  34. data/lib/discorb/channel.rb +65 -15
  35. data/lib/discorb/client.rb +34 -27
  36. data/lib/discorb/common.rb +19 -27
  37. data/lib/discorb/components/button.rb +105 -0
  38. data/lib/discorb/components/select_menu.rb +143 -0
  39. data/lib/discorb/components/text_input.rb +96 -0
  40. data/lib/discorb/components.rb +11 -276
  41. data/lib/discorb/dictionary.rb +5 -0
  42. data/lib/discorb/embed.rb +73 -40
  43. data/lib/discorb/emoji.rb +48 -5
  44. data/lib/discorb/error.rb +9 -5
  45. data/lib/discorb/event.rb +36 -24
  46. data/lib/discorb/exe/about.rb +1 -0
  47. data/lib/discorb/exe/irb.rb +4 -3
  48. data/lib/discorb/exe/new.rb +6 -7
  49. data/lib/discorb/exe/run.rb +2 -1
  50. data/lib/discorb/exe/setup.rb +8 -5
  51. data/lib/discorb/exe/show.rb +1 -0
  52. data/lib/discorb/extend.rb +19 -14
  53. data/lib/discorb/extension.rb +5 -1
  54. data/lib/discorb/gateway.rb +112 -51
  55. data/lib/discorb/gateway_requests.rb +4 -7
  56. data/lib/discorb/guild.rb +73 -41
  57. data/lib/discorb/guild_template.rb +26 -5
  58. data/lib/discorb/http.rb +38 -18
  59. data/lib/discorb/integration.rb +24 -9
  60. data/lib/discorb/intents.rb +16 -11
  61. data/lib/discorb/interaction/autocomplete.rb +6 -5
  62. data/lib/discorb/interaction/command.rb +66 -12
  63. data/lib/discorb/interaction/components.rb +19 -3
  64. data/lib/discorb/interaction/modal.rb +33 -0
  65. data/lib/discorb/interaction/response.rb +45 -4
  66. data/lib/discorb/interaction/root.rb +16 -0
  67. data/lib/discorb/interaction.rb +2 -1
  68. data/lib/discorb/invite.rb +11 -7
  69. data/lib/discorb/log.rb +5 -5
  70. data/lib/discorb/member.rb +22 -3
  71. data/lib/discorb/message.rb +39 -234
  72. data/lib/discorb/message_meta.rb +186 -0
  73. data/lib/discorb/modules.rb +39 -15
  74. data/lib/discorb/permission.rb +16 -7
  75. data/lib/discorb/presence.rb +45 -9
  76. data/lib/discorb/rate_limit.rb +7 -4
  77. data/lib/discorb/reaction.rb +6 -0
  78. data/lib/discorb/role.rb +12 -0
  79. data/lib/discorb/sticker.rb +22 -14
  80. data/lib/discorb/user.rb +12 -1
  81. data/lib/discorb/utils/colored_puts.rb +1 -0
  82. data/lib/discorb/voice_state.rb +23 -2
  83. data/lib/discorb/webhook.rb +54 -3
  84. data/lib/discorb.rb +5 -2
  85. data/sig/discorb.rbs +838 -702
  86. data/template-replace/scripts/arrow.rb +1 -0
  87. data/template-replace/scripts/favicon.rb +1 -0
  88. data/template-replace/scripts/index.rb +2 -1
  89. data/template-replace/scripts/locale_ja.rb +5 -4
  90. data/template-replace/scripts/sidebar.rb +1 -0
  91. data/template-replace/scripts/version.rb +7 -10
  92. data/template-replace/scripts/yard_replace.rb +5 -4
  93. metadata +17 -3
@@ -14,12 +14,22 @@ module Discorb
14
14
  module Gateway
15
15
  #
16
16
  # Represents an event.
17
+ # @abstract
17
18
  #
18
19
  class GatewayEvent
20
+ #
21
+ # Initializes a new instance of the GatewayEvent class.
19
22
  # @private
23
+ #
24
+ # @param [Hash] data The data of the event.
25
+ #
20
26
  def initialize(data)
21
27
  @data = data
22
28
  end
29
+
30
+ def inspect
31
+ "#<#{self.class}>"
32
+ end
23
33
  end
24
34
 
25
35
  #
@@ -61,7 +71,13 @@ module Discorb
61
71
  alias reactor fired_by
62
72
  alias from fired_by
63
73
 
74
+ #
75
+ # Initializes a new instance of the ReactionEvent class.
64
76
  # @private
77
+ #
78
+ # @param [Discorb::Client] client The client that instantiated the object.
79
+ # @param [Hash] data The data of the event.
80
+ #
65
81
  def initialize(client, data)
66
82
  @client = client
67
83
  @data = data
@@ -121,8 +137,15 @@ module Discorb
121
137
  # @macro client_cache
122
138
  # @return [Discorb::User] The user associated with the integration.
123
139
 
140
+ #
141
+ # Initialize a new instance of the IntegrationDeleteEvent class.
124
142
  # @private
125
- def initialize(client, data)
143
+ #
144
+ #
145
+ # @param [Hash] data The data of the event.
146
+ #
147
+ #
148
+ def initialize(_client, data)
126
149
  @id = Snowflake.new(data[:id])
127
150
  @guild_id = data[:guild_id]
128
151
  @user_id = data[:application_id]
@@ -157,7 +180,13 @@ module Discorb
157
180
  # @return [Discorb::Message] The message the reaction was sent in.
158
181
  attr_reader :message
159
182
 
183
+ #
184
+ # Initialize a new instance of the ReactionRemoveAllEvent class.
160
185
  # @private
186
+ #
187
+ # @param [Discorb::Client] client The client that instantiated the object.
188
+ # @param [Hash] data The data of the event.
189
+ #
161
190
  def initialize(client, data)
162
191
  @client = client
163
192
  @data = data
@@ -207,7 +236,13 @@ module Discorb
207
236
  # @return [Discorb::UnicodeEmoji, Discorb::PartialEmoji] The emoji that was reacted with.
208
237
  attr_reader :emoji
209
238
 
239
+ #
240
+ # Initialize a new instance of the ReactionRemoveEmojiEvent class.
210
241
  # @private
242
+ #
243
+ # @param [Discorb::Client] client The client that instantiated the object.
244
+ # @param [Hash] data The data of the event.
245
+ #
211
246
  def initialize(client, data)
212
247
  @client = client
213
248
  @data = data
@@ -246,7 +281,13 @@ module Discorb
246
281
  attr_reader :guild
247
282
  # @return [Discorb::ScheduledEvent] The scheduled event.
248
283
  attr_reader :scheduled_event
284
+ #
285
+ # Initialize a new instance of the ScheduledEventUserEvent class.
249
286
  # @private
287
+ #
288
+ # @param [Discorb::Client] client The client that instantiated the object.
289
+ # @param [Hash] data The data of the event.
290
+ #
250
291
  def initialize(client, data)
251
292
  @client = client
252
293
  @scheduled_event_id = Snowflake.new(data[:scheduled_event_id])
@@ -261,7 +302,6 @@ module Discorb
261
302
  #
262
303
  # Represents a `MESSAGE_UPDATE` event.
263
304
  #
264
-
265
305
  class MessageUpdateEvent < GatewayEvent
266
306
  # @return [Discorb::Message] The message before update.
267
307
  attr_reader :before
@@ -306,8 +346,8 @@ module Discorb
306
346
  @timestamp = Time.iso8601(data[:edited_timestamp])
307
347
  @mention_everyone = data[:mention_everyone]
308
348
  @mention_roles = data[:mention_roles].map { |r| guild.roles[r] } if data.key?(:mention_roles)
309
- @attachments = data[:attachments].map { |a| Attachment.new(a) } if data.key?(:attachments)
310
- @embeds = data[:embeds] ? data[:embeds].map { |e| Embed.new(data: e) } : [] if data.key?(:embeds)
349
+ @attachments = data[:attachments].map { |a| Attachment.from_hash(a) } if data.key?(:attachments)
350
+ @embeds = data[:embeds] ? data[:embeds].map { |e| Embed.from_hash(e) } : [] if data.key?(:embeds)
311
351
  end
312
352
 
313
353
  def channel
@@ -343,7 +383,13 @@ module Discorb
343
383
  # @macro client_cache
344
384
  # @return [Discorb::Guild] The guild the message was sent in.
345
385
 
386
+ #
387
+ # Initialize a new instance of the UnknownDeleteBulkMessage class.
346
388
  # @private
389
+ #
390
+ # @param [Discorb::Client] client The client that instantiated the object.
391
+ # @param [Hash] data The data of the event.
392
+ #
347
393
  def initialize(client, id, data)
348
394
  @client = client
349
395
  @id = id
@@ -375,7 +421,13 @@ module Discorb
375
421
  # @macro client_cache
376
422
  # @return [Discorb::Guild] The guild the message was sent in.
377
423
 
424
+ #
425
+ # Initialize a new instance of the InviteDeleteEvent class.
378
426
  # @private
427
+ #
428
+ # @param [Discorb::Client] client The client that instantiated the object.
429
+ # @param [Hash] data The data of the event.
430
+ #
379
431
  def initialize(client, data)
380
432
  @client = client
381
433
  @data = data
@@ -393,18 +445,6 @@ module Discorb
393
445
  end
394
446
  end
395
447
 
396
- class GuildIntegrationsUpdateEvent < GatewayEvent
397
- def initialize(client, data)
398
- @client = client
399
- @data = data
400
- @guild_id = Snowflake.new(data[:guild_id])
401
- end
402
-
403
- def guild
404
- @client.guilds[@guild_id]
405
- end
406
- end
407
-
408
448
  #
409
449
  # Represents a `TYPING_START` event.
410
450
  #
@@ -428,7 +468,13 @@ module Discorb
428
468
  # @macro client_cache
429
469
  # @return [Discorb::Member, Discorb::User] The member or user that started typing.
430
470
 
471
+ #
472
+ # Initialize a new instance of the TypingStartEvent class.
431
473
  # @private
474
+ #
475
+ # @param [Discorb::Client] client The client that instantiated the object.
476
+ # @param [Hash] data The data of the event.
477
+ #
432
478
  def initialize(client, data)
433
479
  @client = client
434
480
  @data = data
@@ -505,7 +551,13 @@ module Discorb
505
551
  # @macro client_cache
506
552
  # @return [Discorb::Guild] The guild where the webhook was updated.
507
553
 
554
+ #
555
+ # Initialize a new instance of the WebhooksUpdateEvent class.
508
556
  # @private
557
+ #
558
+ # @param [Discorb::Client] client The client that instantiated the object.
559
+ # @param [Hash] data The data of the event.
560
+ #
509
561
  def initialize(client, data)
510
562
  @client = client
511
563
  @data = data
@@ -528,26 +580,28 @@ module Discorb
528
580
  module Handler
529
581
  private
530
582
 
531
- def connect_gateway(reconnect, force_close: false)
583
+ def connect_gateway(reconnect)
532
584
  if reconnect
533
585
  @log.info "Reconnecting to gateway..."
534
586
  else
535
587
  @log.info "Connecting to gateway..."
536
588
  end
537
589
  Async do
538
- if @connection
590
+ if @connection && !@connection.closed?
539
591
  Async do
540
- if force_close
541
- @connection.force_close
542
- else
543
- @connection.close
544
- end
592
+ @connection.close
545
593
  end
546
594
  end
547
595
  @http = HTTP.new(self)
548
596
  _, gateway_response = @http.request(Route.new("/gateway", "//gateway", :get)).wait
549
597
  gateway_url = gateway_response[:url]
550
- endpoint = Async::HTTP::Endpoint.parse("#{gateway_url}?v=9&encoding=json&compress=zlib-stream",
598
+ gateway_version = if @intents.to_h[:message_content].nil?
599
+ warn "message_content intent not set, using gateway version 9. You should specify `message_content` intent for preventing unexpected changes in the future."
600
+ 9
601
+ else
602
+ 10
603
+ end
604
+ endpoint = Async::HTTP::Endpoint.parse("#{gateway_url}?v=#{gateway_version}&encoding=json&compress=zlib-stream",
551
605
  alpn_protocols: Async::HTTP::Protocol::HTTP11.names)
552
606
  begin
553
607
  @connection = Async::WebSocket::Client.connect(endpoint, headers: [["User-Agent", Discorb::USER_AGENT]], handler: RawConnection)
@@ -578,7 +632,8 @@ module Discorb
578
632
  Errno::ECONNRESET,
579
633
  IOError => e
580
634
  @log.error "Gateway connection closed accidentally: #{e.class}: #{e.message}"
581
- connect_gateway(true, force_close: true)
635
+ @connection.force_close
636
+ connect_gateway(true)
582
637
  else # should never happen
583
638
  connect_gateway(true)
584
639
  end
@@ -593,13 +648,13 @@ module Discorb
593
648
  when 4014
594
649
  raise ClientError.new("Disallowed intents were specified"), cause: nil
595
650
  when 4002, 4003, 4005, 4007
596
- raise ClientError.new(<<~EOS), cause: e
597
- Disconnected from gateway, probably due to library issues.
598
- #{e.message}
651
+ raise ClientError.new(<<~ERROR), cause: e
652
+ Disconnected from gateway, probably due to library issues.
653
+ #{e.message}
599
654
 
600
- Please report this to the library issue tracker.
601
- https://github.com/discorb-lib/discorb/issues
602
- EOS
655
+ Please report this to the library issue tracker.
656
+ https://github.com/discorb-lib/discorb/issues
657
+ ERROR
603
658
  when 1001
604
659
  @log.info "Gateway closed with code 1001, reconnecting."
605
660
  connect_gateway(true)
@@ -608,8 +663,9 @@ module Discorb
608
663
  @log.debug "#{e.message}"
609
664
  connect_gateway(false)
610
665
  end
611
- rescue => e
666
+ rescue StandardError => e
612
667
  @log.error "Discord WebSocket error: #{e.full_message}"
668
+ @connection.force_close
613
669
  connect_gateway(false)
614
670
  end
615
671
  end
@@ -622,7 +678,7 @@ module Discorb
622
678
  end
623
679
 
624
680
  def handle_gateway(payload, reconnect)
625
- Async do |task|
681
+ Async do |_task|
626
682
  data = payload[:d]
627
683
  @last_s = payload[:s] if payload[:s]
628
684
  @log.debug "Received message with opcode #{payload[:op]} from gateway:"
@@ -648,7 +704,7 @@ module Discorb
648
704
  send_gateway(2, **payload)
649
705
  end
650
706
  when 7
651
- @log.info "Received opcode 7, reconnecting"
707
+ @log.info "Received opcode 7, stopping tasks"
652
708
  @tasks.map(&:stop)
653
709
  when 9
654
710
  @log.warn "Received opcode 9, closed connection"
@@ -673,7 +729,7 @@ module Discorb
673
729
  end
674
730
 
675
731
  def handle_heartbeat
676
- Async do |task|
732
+ Async do |_task|
677
733
  interval = @heartbeat_interval
678
734
  sleep((interval / 1000.0 - 1) * rand)
679
735
  loop do
@@ -700,9 +756,7 @@ module Discorb
700
756
  @session_id = data[:session_id]
701
757
  @user = ClientUser.new(self, data[:user])
702
758
  @uncached_guilds = data[:guilds].map { |g| g[:id] }
703
- if @uncached_guilds == [] or !@intents.guilds
704
- ready
705
- end
759
+ ready if (@uncached_guilds == []) || !@intents.guilds
706
760
  dispatch(:ready)
707
761
  @tasks << handle_heartbeat
708
762
  when "GUILD_CREATE"
@@ -714,7 +768,7 @@ module Discorb
714
768
  ready
715
769
  end
716
770
  elsif @guilds.has?(data[:id])
717
- @guilds[data[:id]].send(:_set_data, data)
771
+ @guilds[data[:id]].send(:_set_data, data, true)
718
772
  dispatch(:guild_available, guild)
719
773
  else
720
774
  guild = Guild.new(self, data, true)
@@ -737,7 +791,7 @@ module Discorb
737
791
  return @log.warn "Unknown guild id #{data[:id]}, ignoring" unless (guild = @guilds.delete(data[:id]))
738
792
 
739
793
  dispatch(:guild_delete, guild)
740
- if guild.has?(:unavailable)
794
+ if data[:unavailable]
741
795
  dispatch(:guild_destroy, guild)
742
796
  else
743
797
  dispatch(:guild_leave, guild)
@@ -811,7 +865,7 @@ module Discorb
811
865
 
812
866
  if (member = thread.members[data[:id]])
813
867
  old = ThreadChannel::Member.new(self, member.instance_variable_get(:@data))
814
- member._set_data(data)
868
+ member.send(:_set_data, data)
815
869
  else
816
870
  old = nil
817
871
  member = ThreadChannel::Member.new(self, data)
@@ -898,14 +952,13 @@ module Discorb
898
952
  guild.emojis.delete(emoji)
899
953
  end
900
954
  when "GUILD_INTEGRATIONS_UPDATE"
901
- # dispatch(:guild_integrations_update, GuildIntegrationsUpdateEvent.new(self, data))
902
- # Currently not implemented
955
+ dispatch(:guild_integrations_update, @guilds[data[:guild_id]])
903
956
  when "INTEGRATION_CREATE"
904
957
  dispatch(:integration_create, Integration.new(self, data, data[:guild_id]))
905
958
  when "INTEGRATION_UPDATE"
906
959
  return @log.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
907
960
 
908
- before = Integration.new(self, data, data[:guild_id])
961
+ integration = Integration.new(self, data, data[:guild_id])
909
962
  dispatch(:integration_update, integration)
910
963
  when "INTEGRATION_DELETE"
911
964
  return @log.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
@@ -1091,12 +1144,12 @@ module Discorb
1091
1144
  (target_reaction = target_message.reactions.find { |r| data[:emoji][:id].nil? ? r.name == data[:emoji][:name] : r.id == data[:emoji][:id] })
1092
1145
  target_message.reactions.delete(target_reaction)
1093
1146
  end
1094
- dispatch(:reaction_remove_emoji, ReactionRemoveEmojiEvent.new(data))
1147
+ dispatch(:reaction_remove_emoji, ReactionRemoveEmojiEvent.new(self, data))
1095
1148
  when "TYPING_START"
1096
1149
  dispatch(:typing_start, TypingStartEvent.new(self, data))
1097
1150
  when "INTERACTION_CREATE"
1098
1151
  interaction = Interaction.make_interaction(self, data)
1099
- dispatch(:integration_create, interaction)
1152
+ dispatch(:interaction_create, interaction)
1100
1153
 
1101
1154
  dispatch(interaction.class.event_name, interaction)
1102
1155
  when "RESUMED"
@@ -1114,15 +1167,15 @@ module Discorb
1114
1167
  old = event.dup
1115
1168
  event.send(:_set_data, data)
1116
1169
  dispatch(:scheduled_event_update, old, event)
1117
- if old.status != event.status
1170
+ if old.status == event.status
1171
+ dispatch(:scheduled_event_edit, old, event)
1172
+ else
1118
1173
  case event.status
1119
1174
  when :active
1120
1175
  dispatch(:scheduled_event_start, event)
1121
1176
  when :completed
1122
1177
  dispatch(:scheduled_event_end, event)
1123
1178
  end
1124
- else
1125
- dispatch(:scheduled_event_edit, old, event)
1126
1179
  end
1127
1180
  when "GUILD_SCHEDULED_EVENT_DELETE"
1128
1181
  @log.warn("Unknown guild id #{data[:guild_id]}, ignoring") unless (guild = @guilds[data[:guild_id]])
@@ -1175,6 +1228,10 @@ module Discorb
1175
1228
  @closed = false
1176
1229
  end
1177
1230
 
1231
+ def inspect
1232
+ "<#{self.class.name} #{io.fileno}>"
1233
+ end
1234
+
1178
1235
  def closed?
1179
1236
  @closed
1180
1237
  end
@@ -1182,15 +1239,19 @@ module Discorb
1182
1239
  def close
1183
1240
  super
1184
1241
  @closed = true
1185
- rescue
1242
+ rescue StandardError
1186
1243
  force_close
1187
1244
  end
1188
1245
 
1189
1246
  def force_close
1190
- @framer.instance_variable_get(:@stream).close
1247
+ io.close
1191
1248
  @closed = true
1192
1249
  end
1193
1250
 
1251
+ def io
1252
+ @framer.instance_variable_get(:@stream).instance_variable_get(:@io).instance_variable_get(:@io).instance_variable_get(:@io)
1253
+ end
1254
+
1194
1255
  def parse(buffer)
1195
1256
  # noop
1196
1257
  buffer.to_s
@@ -5,7 +5,9 @@ module Discorb
5
5
  # Represents an activity for Gateway Command.
6
6
  #
7
7
  class Activity
8
- @types = {
8
+ # @private
9
+ # @return [{Symbol => Integer}] The mapping of activity types.
10
+ TYPES = {
9
11
  playing: 0,
10
12
  streaming: 1,
11
13
  listening: 2,
@@ -22,7 +24,7 @@ module Discorb
22
24
  #
23
25
  def initialize(name, type = :playing, url = nil)
24
26
  @name = name
25
- @type = self.class.types[type]
27
+ @type = TYPES[type] or raise ArgumentError, "Invalid activity type: #{type}"
26
28
  @url = url
27
29
  end
28
30
 
@@ -42,10 +44,5 @@ module Discorb
42
44
  def inspect
43
45
  "#<#{self.class} @type=#{@type}>"
44
46
  end
45
-
46
- class << self
47
- # @private
48
- attr_reader :types
49
- end
50
47
  end
51
48
  end
data/lib/discorb/guild.rb CHANGED
@@ -115,27 +115,36 @@ module Discorb
115
115
  # @!attribute [r] me
116
116
  # @return [Discorb::Member] The client's member in the guild.
117
117
 
118
- @mfa_levels = %i[none elevated].freeze
119
- @nsfw_levels = %i[default explicit safe age_restricted].freeze
120
- @verification_levels = %i[none low medium high very_high].freeze
121
- @default_message_notifications = %i[all_messages only_mentions].freeze
122
- @explicit_content_filter = %i[disabled_in_text members_without_roles all_members].freeze
118
+ # @private
119
+ # @return [Array<Symbol>] The mapping of mfa_level.
120
+ MFA_LEVELS = %i[none elevated].freeze
121
+ # @private
122
+ # @return [Array<Symbol>] The mapping of nsfw_level.
123
+ NSFW_LEVELS = %i[default explicit safe age_restricted].freeze
124
+ # @private
125
+ # @return [Array<Symbol>] The mapping of verification_level.
126
+ VERIFICATION_LEVELS = %i[none low medium high very_high].freeze
127
+ # @private
128
+ # @return [Array<Symbol>] The mapping of default_message_notifications.
129
+ DEFAULT_MESSAGE_NOTIFICATIONS = %i[all_messages only_mentions].freeze
130
+ # @private
131
+ # @return [Array<Symbol>] The mapping of explicit_content_filter.
132
+ EXPLICIT_CONTENT_FILTER = %i[disabled_in_text members_without_roles all_members].freeze
123
133
 
134
+ #
135
+ # Creates a new guild object.
124
136
  # @private
137
+ #
138
+ # @param [Discorb::Client] client The client that owns this guild.
139
+ # @param [Hash] data The data of the guild.
140
+ # @param [Boolean] is_create_event Whether the guild is created by a `GUILD_CREATE` event.
141
+ #
125
142
  def initialize(client, data, is_create_event)
126
143
  @client = client
127
144
  @data = {}
128
145
  _set_data(data, is_create_event)
129
146
  end
130
147
 
131
- # @private
132
- def update!
133
- Async do
134
- _, data = @client.get("/guilds/#{@id}").wait
135
- _set_data(data, false)
136
- end
137
- end
138
-
139
148
  def afk_channel
140
149
  @client.channels[@afk_channel_id]
141
150
  end
@@ -242,9 +251,9 @@ module Discorb
242
251
  description: description,
243
252
  scheduled_start_time: start_time.iso8601,
244
253
  scheduled_end_time: end_time&.iso8601,
245
- privacy_level: Discorb::ScheduledEvent.privacy_level.key(privacy_level),
254
+ privacy_level: Discorb::ScheduledEvent::PRIVACY_LEVEL.key(privacy_level),
246
255
  channel_id: channel&.id,
247
- entity_type: Discorb::ScheduledEvent.entity_type.key(:stage_instance),
256
+ entity_type: Discorb::ScheduledEvent::ENTITY_TYPE.key(:stage_instance),
248
257
  }
249
258
  when :voice
250
259
  raise ArgumentError, "channel must be provided for voice events" unless channel
@@ -253,9 +262,9 @@ module Discorb
253
262
  description: description,
254
263
  scheduled_start_time: start_time.iso8601,
255
264
  scheduled_end_time: end_time&.iso8601,
256
- privacy_level: Discorb::ScheduledEvent.privacy_level.key(privacy_level),
265
+ privacy_level: Discorb::ScheduledEvent::PRIVACY_LEVEL.key(privacy_level),
257
266
  channel_id: channel&.id,
258
- entity_type: Discorb::ScheduledEvent.entity_type.key(:voice),
267
+ entity_type: Discorb::ScheduledEvent::ENTITY_TYPE.key(:voice),
259
268
  }
260
269
  when :external
261
270
  raise ArgumentError, "location must be provided for external events" unless location
@@ -265,8 +274,8 @@ module Discorb
265
274
  description: description,
266
275
  scheduled_start_time: start_time.iso8601,
267
276
  scheduled_end_time: end_time.iso8601,
268
- privacy_level: Discorb::ScheduledEvent.privacy_level.key(privacy_level),
269
- entity_type: Discorb::ScheduledEvent.entity_type.key(:external),
277
+ privacy_level: Discorb::ScheduledEvent::PRIVACY_LEVEL.key(privacy_level),
278
+ entity_type: Discorb::ScheduledEvent::ENTITY_TYPE.key(:external),
270
279
  entity_metadata: {
271
280
  location: location,
272
281
  },
@@ -614,7 +623,7 @@ module Discorb
614
623
  #
615
624
  def fetch_members(limit: 0, after: nil)
616
625
  Async do
617
- unless limit == 0
626
+ unless limit.zero?
618
627
  _resp, data = @client.http.request(Route.new("/guilds/#{@id}/members?#{URI.encode_www_form({ after: after, limit: limit })}", "//guilds/:guild_id/members", :get)).wait
619
628
  next data[:members].map { |m| Member.new(@client, @id, m[:user], m) }
620
629
  end
@@ -625,9 +634,7 @@ module Discorb
625
634
  _resp, data = @client.http.request(Route.new("/guilds/#{@id}/members?#{URI.encode_www_form(params)}", "//guilds/:guild_id/members", :get)).wait
626
635
  ret += data.map { |m| Member.new(@client, @id, m[:user], m) }
627
636
  after = data.last[:user][:id]
628
- if data.length != 1000
629
- break
630
- end
637
+ break if data.length != 1000
631
638
  end
632
639
  ret
633
640
  end
@@ -860,7 +867,7 @@ module Discorb
860
867
  def fetch_voice_regions
861
868
  Async do
862
869
  _resp, data = @client.http.request(Route.new("/guilds/#{@id}/voice", "//guilds/:guild_id/voice", :get)).wait
863
- data.map { |d| VoiceRegion.new(@client, d) }
870
+ data.map { |d| VoiceRegion.new(d) }
864
871
  end
865
872
  end
866
873
 
@@ -873,7 +880,7 @@ module Discorb
873
880
  def fetch_invites
874
881
  Async do
875
882
  _resp, data = @client.http.request(Route.new("/guilds/#{@id}/invites", "//guilds/:guild_id/invites", :get)).wait
876
- data.map { |d| Invite.new(@client, d) }
883
+ data.map { |d| Invite.new(@client, d, false) }
877
884
  end
878
885
  end
879
886
 
@@ -886,7 +893,7 @@ module Discorb
886
893
  def fetch_integrations
887
894
  Async do
888
895
  _resp, data = @client.http.request(Route.new("/guilds/#{@id}/integrations", "//guilds/:guild_id/integrations", :get)).wait
889
- data.map { |d| Integration.new(@client, d) }
896
+ data.map { |d| Integration.new(@client, d, @id) }
890
897
  end
891
898
  end
892
899
 
@@ -1014,7 +1021,14 @@ module Discorb
1014
1021
  # @!attribute [r] url
1015
1022
  # @return [String] The vanity URL.
1016
1023
 
1024
+ #
1025
+ # Initialize a new instance of the {VanityInvite} class.
1017
1026
  # @private
1027
+ #
1028
+ # @param [Discorb::Client] client The client.
1029
+ # @param [Discorb::Guild] guild The guild.
1030
+ # @param [Hash] data The data of the invite.
1031
+ #
1018
1032
  def initialize(client, guild, data)
1019
1033
  @client = client
1020
1034
  @guild = guild
@@ -1049,7 +1063,14 @@ module Discorb
1049
1063
  # @!attribute [r] json_url
1050
1064
  # @return [String] The JSON URL.
1051
1065
 
1066
+ #
1067
+ # Initialize a new instance of the {Widget} class.
1052
1068
  # @private
1069
+ #
1070
+ # @param [Discorb::Client] client The client.
1071
+ # @param [Discorb::Snowflake] guild_id The guild ID.
1072
+ # @param [Hash] data The data from Discord.
1073
+ #
1053
1074
  def initialize(client, guild_id, data)
1054
1075
  @client = client
1055
1076
  @enabled = data[:enabled]
@@ -1113,7 +1134,14 @@ module Discorb
1113
1134
  # @return [String] The reason for the ban.
1114
1135
  attr_reader :reason
1115
1136
 
1137
+ #
1138
+ # Initialize a new instance of the {Ban} class.
1116
1139
  # @private
1140
+ #
1141
+ # @param [Discorb::Client] client The client.
1142
+ # @param [Discorb::Guild] guild The guild.
1143
+ # @param [Hash] data The data from Discord.
1144
+ #
1117
1145
  def initialize(client, guild, data)
1118
1146
  @client = client
1119
1147
  @guild = guild
@@ -1123,9 +1151,6 @@ module Discorb
1123
1151
  end
1124
1152
 
1125
1153
  class << self
1126
- # @private
1127
- attr_reader :nsfw_levels, :mfa_levels, :verification_levels, :default_message_notifications, :explicit_content_filter
1128
-
1129
1154
  #
1130
1155
  # Returns a banner url from the guild's ID.
1131
1156
  #
@@ -1152,9 +1177,9 @@ module Discorb
1152
1177
  @unavailable = false
1153
1178
  @name = data[:name]
1154
1179
  @members = Discorb::Dictionary.new
1155
- data[:members].each do |m|
1180
+ data[:members]&.each do |m|
1156
1181
  Member.new(@client, @id, m[:user], m)
1157
- end if data[:members]
1182
+ end
1158
1183
  @splash = data[:splash] && Asset.new(self, data[:splash], path: "splashes/#{@id}")
1159
1184
  @discovery_splash = data[:discovery_splash] && Asset.new(self, data[:discovery_splash], path: "discovery-splashes/#{@id}")
1160
1185
  @owner_id = data[:owner_id]
@@ -1172,10 +1197,10 @@ module Discorb
1172
1197
  @emojis[e[:id]] = CustomEmoji.new(@client, self, e)
1173
1198
  end
1174
1199
  @features = data[:features].map { |f| f.downcase.to_sym }
1175
- @mfa_level = self.class.mfa_levels[data[:mfa_level]]
1176
- @verification_level = self.class.verification_levels[data[:verification_level]]
1177
- @default_message_notifications = self.class.default_message_notifications[data[:default_message_notifications]]
1178
- @explicit_content_filter = self.class.explicit_content_filter[data[:explicit_content_filter]]
1200
+ @mfa_level = MFA_LEVELS[data[:mfa_level]]
1201
+ @verification_level = VERIFICATION_LEVELS[data[:verification_level]]
1202
+ @default_message_notifications = DEFAULT_MESSAGE_NOTIFICATIONS[data[:default_message_notifications]]
1203
+ @explicit_content_filter = EXPLICIT_CONTENT_FILTER[data[:explicit_content_filter]]
1179
1204
  @system_channel_id = data[:system_channel_id]
1180
1205
  @system_channel_flag = SystemChannelFlag.new(0b111 - data[:system_channel_flags])
1181
1206
  @rules_channel_id = data[:rules_channel_id]
@@ -1190,7 +1215,7 @@ module Discorb
1190
1215
  @approximate_member_count = data[:approximate_member_count]
1191
1216
  @approximate_presence_count = data[:approximate_presence_count]
1192
1217
  @welcome_screen = data[:welcome_screen].nil? ? nil : WelcomeScreen.new(@client, self, data[:welcome_screen])
1193
- @nsfw_level = self.class.nsfw_levels[data[:nsfw_level]]
1218
+ @nsfw_level = NSFW_LEVELS[data[:nsfw_level]]
1194
1219
  return unless is_create_event
1195
1220
 
1196
1221
  @stickers = data[:stickers].nil? ? [] : data[:stickers].map { |s| Sticker::GuildSticker.new(self, s) }
@@ -1200,13 +1225,13 @@ module Discorb
1200
1225
  tmp_channels = data[:channels].filter { |c| !c.key?(:thread_metadata) }.map do |c|
1201
1226
  Channel.make_channel(@client, c.merge({ guild_id: @id }))
1202
1227
  end
1203
- @channels = Dictionary.new(tmp_channels.map { |c| [c.id, c] }.to_h, sort: ->(c) { c[1].position })
1204
- @voice_states = Dictionary.new(data[:voice_states].map { |v| [Snowflake.new(v[:user_id]), VoiceState.new(@client, v.merge({ guild_id: @id }))] }.to_h)
1228
+ @channels = Dictionary.new(tmp_channels.to_h { |c| [c.id, c] }, sort: ->(c) { c[1].position })
1229
+ @voice_states = Dictionary.new(data[:voice_states].to_h { |v| [Snowflake.new(v[:user_id]), VoiceState.new(@client, v.merge({ guild_id: @id }))] })
1205
1230
  @threads = data[:threads] ? data[:threads].map { |t| Channel.make_channel(@client, t) } : []
1206
- @presences = Dictionary.new(data[:presences].map { |pr| [Snowflake.new(pr[:user][:id]), Presence.new(@client, pr)] }.to_h)
1231
+ @presences = Dictionary.new(data[:presences].to_h { |pr| [Snowflake.new(pr[:user][:id]), Presence.new(@client, pr)] })
1207
1232
  @max_presences = data[:max_presences]
1208
- @stage_instances = Dictionary.new(data[:stage_instances].map { |s| [Snowflake.new(s[:id]), StageInstance.new(@client, s)] }.to_h)
1209
- @scheduled_events = Dictionary.new(data[:guild_scheduled_events].map { |s| [Snowflake.new(s[:id]), ScheduledEvent.new(@client, s)] }.to_h)
1233
+ @stage_instances = Dictionary.new(data[:stage_instances].to_h { |s| [Snowflake.new(s[:id]), StageInstance.new(@client, s)] })
1234
+ @scheduled_events = Dictionary.new(data[:guild_scheduled_events].to_h { |s| [Snowflake.new(s[:id]), ScheduledEvent.new(@client, s)] })
1210
1235
  @data.update(data)
1211
1236
  end
1212
1237
  end
@@ -1241,7 +1266,14 @@ module Discorb
1241
1266
  # @return [Discorb::Guild] The guild the welcome screen belongs to.
1242
1267
  attr_reader :guild
1243
1268
 
1269
+ #
1270
+ # Initializes the welcome screen.
1244
1271
  # @private
1272
+ #
1273
+ # @param [Discorb::Client] client The client.
1274
+ # @param [Discorb::Guild] guild The guild the welcome screen belongs to.
1275
+ # @param [Hash] data The data of the welcome screen.
1276
+ #
1245
1277
  def initialize(client, guild, data)
1246
1278
  @client = client
1247
1279
  @description = data[:description]