discorb 0.13.2 → 0.15.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.
Files changed (92) 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 +70 -0
  8. data/CODE_OF_CONDUCT.md +128 -0
  9. data/Changelog.md +34 -0
  10. data/Gemfile +7 -3
  11. data/README.md +1 -1
  12. data/Rakefile +22 -22
  13. data/discorb.gemspec +13 -1
  14. data/docs/faq.md +8 -8
  15. data/examples/commands/bookmarker.rb +2 -1
  16. data/examples/commands/hello.rb +1 -0
  17. data/examples/commands/inspect.rb +3 -2
  18. data/examples/components/authorization_button.rb +2 -1
  19. data/examples/components/select_menu.rb +2 -1
  20. data/examples/extension/main.rb +1 -0
  21. data/examples/extension/message_expander.rb +1 -0
  22. data/examples/simple/eval.rb +3 -2
  23. data/examples/simple/ping_pong.rb +1 -0
  24. data/examples/simple/rolepanel.rb +1 -0
  25. data/examples/simple/wait_for_message.rb +4 -3
  26. data/exe/discorb +8 -7
  27. data/lib/discorb/allowed_mentions.rb +64 -0
  28. data/lib/discorb/app_command/command.rb +274 -0
  29. data/lib/discorb/app_command/handler.rb +168 -0
  30. data/lib/discorb/app_command.rb +2 -404
  31. data/lib/discorb/asset.rb +3 -1
  32. data/lib/discorb/{file.rb → attachment.rb} +42 -35
  33. data/lib/discorb/audit_logs.rb +3 -3
  34. data/lib/discorb/channel.rb +65 -61
  35. data/lib/discorb/client.rb +36 -33
  36. data/lib/discorb/common.rb +29 -22
  37. data/lib/discorb/components/button.rb +106 -0
  38. data/lib/discorb/components/select_menu.rb +157 -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 +13 -2
  42. data/lib/discorb/embed.rb +40 -33
  43. data/lib/discorb/emoji.rb +21 -5
  44. data/lib/discorb/emoji_table.rb +1 -1
  45. data/lib/discorb/error.rb +4 -6
  46. data/lib/discorb/event.rb +13 -11
  47. data/lib/discorb/exe/about.rb +1 -0
  48. data/lib/discorb/exe/irb.rb +4 -3
  49. data/lib/discorb/exe/new.rb +6 -7
  50. data/lib/discorb/exe/run.rb +2 -1
  51. data/lib/discorb/exe/setup.rb +8 -5
  52. data/lib/discorb/exe/show.rb +1 -0
  53. data/lib/discorb/extend.rb +19 -14
  54. data/lib/discorb/extension.rb +5 -1
  55. data/lib/discorb/gateway.rb +82 -29
  56. data/lib/discorb/guild.rb +58 -80
  57. data/lib/discorb/guild_template.rb +5 -5
  58. data/lib/discorb/http.rb +52 -170
  59. data/lib/discorb/integration.rb +32 -3
  60. data/lib/discorb/intents.rb +9 -4
  61. data/lib/discorb/interaction/autocomplete.rb +5 -4
  62. data/lib/discorb/interaction/command.rb +34 -9
  63. data/lib/discorb/interaction/components.rb +5 -2
  64. data/lib/discorb/interaction/modal.rb +33 -0
  65. data/lib/discorb/interaction/response.rb +41 -12
  66. data/lib/discorb/interaction/root.rb +1 -0
  67. data/lib/discorb/interaction.rb +2 -1
  68. data/lib/discorb/invite.rb +1 -1
  69. data/lib/discorb/log.rb +4 -3
  70. data/lib/discorb/member.rb +4 -6
  71. data/lib/discorb/message.rb +38 -241
  72. data/lib/discorb/message_meta.rb +157 -0
  73. data/lib/discorb/modules.rb +47 -23
  74. data/lib/discorb/permission.rb +2 -2
  75. data/lib/discorb/presence.rb +6 -3
  76. data/lib/discorb/rate_limit.rb +15 -21
  77. data/lib/discorb/role.rb +3 -3
  78. data/lib/discorb/sticker.rb +2 -2
  79. data/lib/discorb/user.rb +3 -3
  80. data/lib/discorb/utils/colored_puts.rb +1 -0
  81. data/lib/discorb/voice_state.rb +7 -2
  82. data/lib/discorb/webhook.rb +9 -6
  83. data/lib/discorb.rb +2 -1
  84. data/sig/discorb.rbs +5836 -6714
  85. data/template-replace/scripts/arrow.rb +1 -0
  86. data/template-replace/scripts/favicon.rb +1 -0
  87. data/template-replace/scripts/index.rb +2 -1
  88. data/template-replace/scripts/locale_ja.rb +5 -4
  89. data/template-replace/scripts/sidebar.rb +1 -0
  90. data/template-replace/scripts/version.rb +7 -10
  91. data/template-replace/scripts/yard_replace.rb +5 -4
  92. metadata +30 -5
@@ -108,6 +108,35 @@ module Discorb
108
108
  end
109
109
  end
110
110
 
111
+ #
112
+ # Represents a `INTEGRATION_DELETE` event.
113
+ #
114
+ class IntegrationDeleteEvent < GatewayEvent
115
+ # @return [Discorb::Snowflake] The ID of the integration.
116
+ attr_reader :id
117
+ # @!attribute [r] guild
118
+ # @macro client_cache
119
+ # @return [Discorb::Guild] The guild of the integration.
120
+ # @!attribute [r] user
121
+ # @macro client_cache
122
+ # @return [Discorb::User] The user associated with the integration.
123
+
124
+ # @private
125
+ def initialize(_client, data)
126
+ @id = Snowflake.new(data[:id])
127
+ @guild_id = data[:guild_id]
128
+ @user_id = data[:application_id]
129
+ end
130
+
131
+ def guild
132
+ @client.guilds[@guild_id]
133
+ end
134
+
135
+ def user
136
+ @client.users[@user_id]
137
+ end
138
+ end
139
+
111
140
  #
112
141
  # Represents a `MESSAGE_REACTION_REMOVE_ALL` event.
113
142
  #
@@ -232,7 +261,6 @@ module Discorb
232
261
  #
233
262
  # Represents a `MESSAGE_UPDATE` event.
234
263
  #
235
-
236
264
  class MessageUpdateEvent < GatewayEvent
237
265
  # @return [Discorb::Message] The message before update.
238
266
  attr_reader :before
@@ -277,8 +305,8 @@ module Discorb
277
305
  @timestamp = Time.iso8601(data[:edited_timestamp])
278
306
  @mention_everyone = data[:mention_everyone]
279
307
  @mention_roles = data[:mention_roles].map { |r| guild.roles[r] } if data.key?(:mention_roles)
280
- @attachments = data[:attachments].map { |a| Attachment.new(a) } if data.key?(:attachments)
281
- @embeds = data[:embeds] ? data[:embeds].map { |e| Embed.new(data: e) } : [] if data.key?(:embeds)
308
+ @attachments = data[:attachments].map { |a| Attachment.from_hash(a) } if data.key?(:attachments)
309
+ @embeds = data[:embeds] ? data[:embeds].map { |e| Embed.from_hash(e) } : [] if data.key?(:embeds)
282
310
  end
283
311
 
284
312
  def channel
@@ -364,6 +392,9 @@ module Discorb
364
392
  end
365
393
  end
366
394
 
395
+ #
396
+ # Represents a `GUILD_INTEGRATIONS_UPDATE` event.
397
+ #
367
398
  class GuildIntegrationsUpdateEvent < GatewayEvent
368
399
  def initialize(client, data)
369
400
  @client = client
@@ -499,18 +530,28 @@ module Discorb
499
530
  module Handler
500
531
  private
501
532
 
502
- def connect_gateway(reconnect, no_close: false)
533
+ def connect_gateway(reconnect)
503
534
  if reconnect
504
535
  @log.info "Reconnecting to gateway..."
505
536
  else
506
537
  @log.info "Connecting to gateway..."
507
538
  end
508
539
  Async do
509
- @connection&.close rescue nil unless no_close
540
+ if @connection && !@connection.closed?
541
+ Async do
542
+ @connection.close
543
+ end
544
+ end
510
545
  @http = HTTP.new(self)
511
- _, gateway_response = @http.get("/gateway").wait
546
+ _, gateway_response = @http.request(Route.new("/gateway", "//gateway", :get)).wait
512
547
  gateway_url = gateway_response[:url]
513
- endpoint = Async::HTTP::Endpoint.parse("#{gateway_url}?v=9&encoding=json&compress=zlib-stream",
548
+ gateway_version = if @intents.to_h[:message_content].nil?
549
+ warn "message_content intent not set, using gateway version 9. You should specify `message_content` intent for preventing unexpected changes in the future."
550
+ 9
551
+ else
552
+ 10
553
+ end
554
+ endpoint = Async::HTTP::Endpoint.parse("#{gateway_url}?v=#{gateway_version}&encoding=json&compress=zlib-stream",
514
555
  alpn_protocols: Async::HTTP::Protocol::HTTP11.names)
515
556
  begin
516
557
  @connection = Async::WebSocket::Client.connect(endpoint, headers: [["User-Agent", Discorb::USER_AGENT]], handler: RawConnection)
@@ -533,9 +574,16 @@ module Discorb
533
574
  end
534
575
  end
535
576
  end
536
- rescue Async::Wrapper::Cancelled, OpenSSL::SSL::SSLError, Async::Wrapper::WaitError, EOFError, Errno::EPIPE => e
577
+ rescue Async::Wrapper::Cancelled,
578
+ OpenSSL::SSL::SSLError,
579
+ Async::Wrapper::WaitError,
580
+ EOFError,
581
+ Errno::EPIPE,
582
+ Errno::ECONNRESET,
583
+ IOError => e
537
584
  @log.error "Gateway connection closed accidentally: #{e.class}: #{e.message}"
538
- connect_gateway(true, no_close: true)
585
+ @connection.force_close
586
+ connect_gateway(true)
539
587
  else # should never happen
540
588
  connect_gateway(true)
541
589
  end
@@ -550,13 +598,13 @@ module Discorb
550
598
  when 4014
551
599
  raise ClientError.new("Disallowed intents were specified"), cause: nil
552
600
  when 4002, 4003, 4005, 4007
553
- raise ClientError.new(<<~EOS), cause: e
554
- Disconnected from gateway, probably due to library issues.
555
- #{e.message}
601
+ raise ClientError.new(<<~ERROR), cause: e
602
+ Disconnected from gateway, probably due to library issues.
603
+ #{e.message}
556
604
 
557
- Please report this to the library issue tracker.
558
- https://github.com/discorb-lib/discorb/issues
559
- EOS
605
+ Please report this to the library issue tracker.
606
+ https://github.com/discorb-lib/discorb/issues
607
+ ERROR
560
608
  when 1001
561
609
  @log.info "Gateway closed with code 1001, reconnecting."
562
610
  connect_gateway(true)
@@ -565,8 +613,9 @@ module Discorb
565
613
  @log.debug "#{e.message}"
566
614
  connect_gateway(false)
567
615
  end
568
- rescue => e
616
+ rescue StandardError => e
569
617
  @log.error "Discord WebSocket error: #{e.full_message}"
618
+ @connection.force_close
570
619
  connect_gateway(false)
571
620
  end
572
621
  end
@@ -579,7 +628,7 @@ module Discorb
579
628
  end
580
629
 
581
630
  def handle_gateway(payload, reconnect)
582
- Async do |task|
631
+ Async do |_task|
583
632
  data = payload[:d]
584
633
  @last_s = payload[:s] if payload[:s]
585
634
  @log.debug "Received message with opcode #{payload[:op]} from gateway:"
@@ -605,7 +654,7 @@ module Discorb
605
654
  send_gateway(2, **payload)
606
655
  end
607
656
  when 7
608
- @log.info "Received opcode 7, reconnecting"
657
+ @log.info "Received opcode 7, stopping tasks"
609
658
  @tasks.map(&:stop)
610
659
  when 9
611
660
  @log.warn "Received opcode 9, closed connection"
@@ -630,7 +679,7 @@ module Discorb
630
679
  end
631
680
 
632
681
  def handle_heartbeat
633
- Async do |task|
682
+ Async do |_task|
634
683
  interval = @heartbeat_interval
635
684
  sleep((interval / 1000.0 - 1) * rand)
636
685
  loop do
@@ -657,9 +706,7 @@ module Discorb
657
706
  @session_id = data[:session_id]
658
707
  @user = ClientUser.new(self, data[:user])
659
708
  @uncached_guilds = data[:guilds].map { |g| g[:id] }
660
- if @uncached_guilds == [] or !@intents.guilds
661
- ready
662
- end
709
+ ready if (@uncached_guilds == []) || !@intents.guilds
663
710
  dispatch(:ready)
664
711
  @tasks << handle_heartbeat
665
712
  when "GUILD_CREATE"
@@ -862,13 +909,12 @@ module Discorb
862
909
  when "INTEGRATION_UPDATE"
863
910
  return @log.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
864
911
 
865
- before = Integration.new(self, data, data[:guild_id])
912
+ integration = Integration.new(self, data, data[:guild_id])
866
913
  dispatch(:integration_update, integration)
867
914
  when "INTEGRATION_DELETE"
868
915
  return @log.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
869
- return @log.warn "Unknown integration id #{data[:id]}, ignoring" unless (integration = guild.integrations.delete(data[:id]))
870
916
 
871
- dispatch(:integration_delete, integration)
917
+ dispatch(:integration_delete, IntegrationDeleteEvent.new(self, data))
872
918
  when "WEBHOOKS_UPDATE"
873
919
  dispatch(:webhooks_update, WebhooksUpdateEvent.new(self, data))
874
920
  when "INVITE_CREATE"
@@ -1054,7 +1100,7 @@ module Discorb
1054
1100
  dispatch(:typing_start, TypingStartEvent.new(self, data))
1055
1101
  when "INTERACTION_CREATE"
1056
1102
  interaction = Interaction.make_interaction(self, data)
1057
- dispatch(:integration_create, interaction)
1103
+ dispatch(:interaction_create, interaction)
1058
1104
 
1059
1105
  dispatch(interaction.class.event_name, interaction)
1060
1106
  when "RESUMED"
@@ -1072,15 +1118,15 @@ module Discorb
1072
1118
  old = event.dup
1073
1119
  event.send(:_set_data, data)
1074
1120
  dispatch(:scheduled_event_update, old, event)
1075
- if old.status != event.status
1121
+ if old.status == event.status
1122
+ dispatch(:scheduled_event_edit, old, event)
1123
+ else
1076
1124
  case event.status
1077
1125
  when :active
1078
1126
  dispatch(:scheduled_event_start, event)
1079
1127
  when :completed
1080
1128
  dispatch(:scheduled_event_end, event)
1081
1129
  end
1082
- else
1083
- dispatch(:scheduled_event_edit, old, event)
1084
1130
  end
1085
1131
  when "GUILD_SCHEDULED_EVENT_DELETE"
1086
1132
  @log.warn("Unknown guild id #{data[:guild_id]}, ignoring") unless (guild = @guilds[data[:guild_id]])
@@ -1140,6 +1186,13 @@ module Discorb
1140
1186
  def close
1141
1187
  super
1142
1188
  @closed = true
1189
+ rescue StandardError
1190
+ force_close
1191
+ end
1192
+
1193
+ def force_close
1194
+ @framer.instance_variable_get(:@stream).instance_variable_get(:@io).instance_variable_get(:@io).instance_variable_get(:@io).close
1195
+ @closed = true
1143
1196
  end
1144
1197
 
1145
1198
  def parse(buffer)