discorb 0.14.0 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/build_version.yml +1 -1
- data/.github/workflows/lint-push.yml +4 -2
- data/.rubocop.yml +6 -2
- data/Changelog.md +27 -0
- data/Rakefile +6 -0
- data/docs/events.md +71 -5
- data/docs/faq.md +8 -8
- data/examples/simple/rolepanel.rb +1 -1
- data/examples/simple/shard.rb +17 -0
- data/lib/discorb/allowed_mentions.rb +7 -0
- data/lib/discorb/app_command/command.rb +64 -2
- data/lib/discorb/app_command/handler.rb +1 -1
- data/lib/discorb/application.rb +16 -7
- data/lib/discorb/asset.rb +9 -0
- data/lib/discorb/{file.rb → attachment.rb} +55 -33
- data/lib/discorb/audit_logs.rb +42 -4
- data/lib/discorb/channel.rb +47 -12
- data/lib/discorb/client.rb +135 -51
- data/lib/discorb/common.rb +18 -4
- data/lib/discorb/components/button.rb +5 -6
- data/lib/discorb/components/select_menu.rb +2 -16
- data/lib/discorb/dictionary.rb +2 -0
- data/lib/discorb/embed.rb +71 -38
- data/lib/discorb/emoji.rb +29 -2
- data/lib/discorb/emoji_table.rb +1 -1
- data/lib/discorb/error.rb +7 -1
- data/lib/discorb/event.rb +27 -17
- data/lib/discorb/exe/new.rb +5 -5
- data/lib/discorb/exe/run.rb +1 -15
- data/lib/discorb/gateway.rb +262 -161
- data/lib/discorb/gateway_requests.rb +4 -7
- data/lib/discorb/guild.rb +67 -33
- data/lib/discorb/guild_template.rb +24 -3
- data/lib/discorb/http.rb +25 -3
- data/lib/discorb/integration.rb +23 -8
- data/lib/discorb/intents.rb +15 -10
- data/lib/discorb/interaction/autocomplete.rb +4 -4
- data/lib/discorb/interaction/command.rb +34 -5
- data/lib/discorb/interaction/components.rb +15 -2
- data/lib/discorb/interaction/response.rb +12 -0
- data/lib/discorb/interaction/root.rb +16 -1
- data/lib/discorb/invite.rb +11 -7
- data/lib/discorb/member.rb +21 -0
- data/lib/discorb/message.rb +59 -3
- data/lib/discorb/message_meta.rb +36 -55
- data/lib/discorb/modules.rb +38 -14
- data/lib/discorb/permission.rb +14 -5
- data/lib/discorb/presence.rb +41 -8
- data/lib/discorb/rate_limit.rb +7 -2
- data/lib/discorb/reaction.rb +6 -0
- data/lib/discorb/role.rb +12 -0
- data/lib/discorb/shard.rb +74 -0
- data/lib/discorb/sticker.rb +22 -14
- data/lib/discorb/user.rb +11 -0
- data/lib/discorb/voice_state.rb +20 -2
- data/lib/discorb/webhook.rb +53 -2
- data/lib/discorb.rb +5 -3
- data/sig/discorb.rbs +7234 -6714
- metadata +5 -4
- data/lib/discorb/log.rb +0 -81
data/lib/discorb/gateway.rb
CHANGED
@@ -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,7 +137,14 @@ 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
|
143
|
+
#
|
144
|
+
#
|
145
|
+
# @param [Hash] data The data of the event.
|
146
|
+
#
|
147
|
+
#
|
125
148
|
def initialize(_client, data)
|
126
149
|
@id = Snowflake.new(data[:id])
|
127
150
|
@guild_id = data[:guild_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])
|
@@ -305,8 +346,8 @@ module Discorb
|
|
305
346
|
@timestamp = Time.iso8601(data[:edited_timestamp])
|
306
347
|
@mention_everyone = data[:mention_everyone]
|
307
348
|
@mention_roles = data[:mention_roles].map { |r| guild.roles[r] } if data.key?(:mention_roles)
|
308
|
-
@attachments = data[:attachments].map { |a| Attachment.
|
309
|
-
@embeds = data[:embeds] ? data[:embeds].map { |e| Embed.
|
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)
|
310
351
|
end
|
311
352
|
|
312
353
|
def channel
|
@@ -342,7 +383,13 @@ module Discorb
|
|
342
383
|
# @macro client_cache
|
343
384
|
# @return [Discorb::Guild] The guild the message was sent in.
|
344
385
|
|
386
|
+
#
|
387
|
+
# Initialize a new instance of the UnknownDeleteBulkMessage class.
|
345
388
|
# @private
|
389
|
+
#
|
390
|
+
# @param [Discorb::Client] client The client that instantiated the object.
|
391
|
+
# @param [Hash] data The data of the event.
|
392
|
+
#
|
346
393
|
def initialize(client, id, data)
|
347
394
|
@client = client
|
348
395
|
@id = id
|
@@ -374,7 +421,13 @@ module Discorb
|
|
374
421
|
# @macro client_cache
|
375
422
|
# @return [Discorb::Guild] The guild the message was sent in.
|
376
423
|
|
424
|
+
#
|
425
|
+
# Initialize a new instance of the InviteDeleteEvent class.
|
377
426
|
# @private
|
427
|
+
#
|
428
|
+
# @param [Discorb::Client] client The client that instantiated the object.
|
429
|
+
# @param [Hash] data The data of the event.
|
430
|
+
#
|
378
431
|
def initialize(client, data)
|
379
432
|
@client = client
|
380
433
|
@data = data
|
@@ -392,21 +445,6 @@ module Discorb
|
|
392
445
|
end
|
393
446
|
end
|
394
447
|
|
395
|
-
#
|
396
|
-
# Represents a `GUILD_INTEGRATIONS_UPDATE` event.
|
397
|
-
#
|
398
|
-
class GuildIntegrationsUpdateEvent < GatewayEvent
|
399
|
-
def initialize(client, data)
|
400
|
-
@client = client
|
401
|
-
@data = data
|
402
|
-
@guild_id = Snowflake.new(data[:guild_id])
|
403
|
-
end
|
404
|
-
|
405
|
-
def guild
|
406
|
-
@client.guilds[@guild_id]
|
407
|
-
end
|
408
|
-
end
|
409
|
-
|
410
448
|
#
|
411
449
|
# Represents a `TYPING_START` event.
|
412
450
|
#
|
@@ -430,7 +468,13 @@ module Discorb
|
|
430
468
|
# @macro client_cache
|
431
469
|
# @return [Discorb::Member, Discorb::User] The member or user that started typing.
|
432
470
|
|
471
|
+
#
|
472
|
+
# Initialize a new instance of the TypingStartEvent class.
|
433
473
|
# @private
|
474
|
+
#
|
475
|
+
# @param [Discorb::Client] client The client that instantiated the object.
|
476
|
+
# @param [Hash] data The data of the event.
|
477
|
+
#
|
434
478
|
def initialize(client, data)
|
435
479
|
@client = client
|
436
480
|
@data = data
|
@@ -507,7 +551,13 @@ module Discorb
|
|
507
551
|
# @macro client_cache
|
508
552
|
# @return [Discorb::Guild] The guild where the webhook was updated.
|
509
553
|
|
554
|
+
#
|
555
|
+
# Initialize a new instance of the WebhooksUpdateEvent class.
|
510
556
|
# @private
|
557
|
+
#
|
558
|
+
# @param [Discorb::Client] client The client that instantiated the object.
|
559
|
+
# @param [Hash] data The data of the event.
|
560
|
+
#
|
511
561
|
def initialize(client, data)
|
512
562
|
@client = client
|
513
563
|
@data = data
|
@@ -531,109 +581,129 @@ module Discorb
|
|
531
581
|
private
|
532
582
|
|
533
583
|
def connect_gateway(reconnect)
|
534
|
-
if reconnect
|
535
|
-
@log.info "Reconnecting to gateway..."
|
536
|
-
else
|
537
|
-
@log.info "Connecting to gateway..."
|
538
|
-
end
|
539
584
|
Async do
|
540
|
-
|
541
|
-
|
542
|
-
|
585
|
+
@mutex["gateway_#{shard_id}"] ||= Mutex.new
|
586
|
+
@mutex["gateway_#{shard_id}"].synchronize do
|
587
|
+
if reconnect
|
588
|
+
logger.info "Reconnecting to gateway..."
|
589
|
+
else
|
590
|
+
logger.info "Connecting to gateway..."
|
543
591
|
end
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
592
|
+
|
593
|
+
@http = HTTP.new(self)
|
594
|
+
_, gateway_response = @http.request(Route.new("/gateway", "//gateway", :get)).wait
|
595
|
+
gateway_url = gateway_response[:url]
|
596
|
+
gateway_version = if @intents.to_h[:message_content].nil?
|
597
|
+
warn "message_content intent not set, using gateway version 9. You should specify `message_content` intent for preventing unexpected changes in the future."
|
598
|
+
9
|
599
|
+
else
|
600
|
+
10
|
601
|
+
end
|
602
|
+
endpoint = Async::HTTP::Endpoint.parse(
|
603
|
+
"#{gateway_url}?v=#{gateway_version}&encoding=json&compress=zlib-stream&_=#{Time.now.to_i}",
|
604
|
+
alpn_protocols: Async::HTTP::Protocol::HTTP11.names,
|
605
|
+
)
|
554
606
|
begin
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
607
|
+
self.connection = Async::WebSocket::Client.connect(endpoint, headers: [["User-Agent", Discorb::USER_AGENT]], handler: RawConnection)
|
608
|
+
zlib_stream = Zlib::Inflate.new(Zlib::MAX_WBITS)
|
609
|
+
buffer = +""
|
610
|
+
begin
|
611
|
+
while (message = connection.read)
|
612
|
+
buffer << message
|
613
|
+
if message.end_with?((+"\x00\x00\xff\xff").force_encoding("ASCII-8BIT"))
|
614
|
+
begin
|
615
|
+
data = zlib_stream.inflate(buffer)
|
616
|
+
buffer = +""
|
617
|
+
message = JSON.parse(data, symbolize_names: true)
|
618
|
+
rescue JSON::ParserError
|
619
|
+
buffer = +""
|
620
|
+
logger.error "Received invalid JSON from gateway."
|
621
|
+
logger.debug "#{data}"
|
622
|
+
else
|
623
|
+
handle_gateway(message, reconnect)
|
624
|
+
end
|
568
625
|
end
|
569
626
|
end
|
627
|
+
rescue Async::Wrapper::Cancelled,
|
628
|
+
OpenSSL::SSL::SSLError,
|
629
|
+
Async::Wrapper::WaitError,
|
630
|
+
EOFError,
|
631
|
+
Errno::EPIPE,
|
632
|
+
Errno::ECONNRESET,
|
633
|
+
IOError => e
|
634
|
+
next if @status == :closed
|
635
|
+
logger.error "Gateway connection closed accidentally: #{e.class}: #{e.message}"
|
636
|
+
connection.force_close
|
637
|
+
connect_gateway(true)
|
638
|
+
next
|
570
639
|
end
|
571
|
-
rescue
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
@log.error "Discord WebSocket closed with code #{e.code}."
|
607
|
-
@log.debug "#{e.message}"
|
640
|
+
rescue Protocol::WebSocket::ClosedError => e
|
641
|
+
@tasks.map(&:stop)
|
642
|
+
case e.code
|
643
|
+
when 4004
|
644
|
+
raise ClientError.new("Authentication failed"), cause: nil
|
645
|
+
when 4009
|
646
|
+
logger.info "Session timed out, reconnecting."
|
647
|
+
connection.force_close
|
648
|
+
connect_gateway(true)
|
649
|
+
next
|
650
|
+
when 4014
|
651
|
+
raise ClientError.new("Disallowed intents were specified"), cause: nil
|
652
|
+
when 4001, 4002, 4003, 4005, 4007
|
653
|
+
raise ClientError.new(<<~ERROR), cause: e
|
654
|
+
Disconnected from gateway, probably due to library issues.
|
655
|
+
#{e.message}
|
656
|
+
|
657
|
+
Please report this to the library issue tracker.
|
658
|
+
https://github.com/discorb-lib/discorb/issues
|
659
|
+
ERROR
|
660
|
+
when 1001
|
661
|
+
logger.info "Gateway closed with code 1001, reconnecting."
|
662
|
+
connection.force_close
|
663
|
+
connect_gateway(true)
|
664
|
+
next
|
665
|
+
else
|
666
|
+
logger.error "Discord WebSocket closed with code #{e.code}."
|
667
|
+
logger.debug "#{e.message}"
|
668
|
+
connection.force_close
|
669
|
+
connect_gateway(false)
|
670
|
+
next
|
671
|
+
end
|
672
|
+
rescue StandardError => e
|
673
|
+
logger.error "Discord WebSocket error: #{e.full_message}"
|
674
|
+
connection.force_close
|
608
675
|
connect_gateway(false)
|
676
|
+
next
|
609
677
|
end
|
610
|
-
rescue StandardError => e
|
611
|
-
@log.error "Discord WebSocket error: #{e.full_message}"
|
612
|
-
@connection.force_close
|
613
|
-
connect_gateway(false)
|
614
678
|
end
|
615
679
|
end
|
616
680
|
end
|
617
681
|
|
618
682
|
def send_gateway(opcode, **value)
|
619
|
-
@
|
620
|
-
|
621
|
-
|
683
|
+
if @shards.any? && shard.nil?
|
684
|
+
@shards.map(&:connection)
|
685
|
+
else
|
686
|
+
[connection]
|
687
|
+
end.each do |con|
|
688
|
+
con.write({ op: opcode, d: value }.to_json)
|
689
|
+
con.flush
|
690
|
+
end
|
691
|
+
logger.debug "Sent message to fd #{connection.io.fileno}: #{{ op: opcode, d: value }.to_json.gsub(@token, "[Token]")}"
|
622
692
|
end
|
623
693
|
|
624
694
|
def handle_gateway(payload, reconnect)
|
625
695
|
Async do |_task|
|
626
696
|
data = payload[:d]
|
627
697
|
@last_s = payload[:s] if payload[:s]
|
628
|
-
|
629
|
-
|
698
|
+
logger.debug "Received message with opcode #{payload[:op]} from gateway."
|
699
|
+
logger.debug "#{payload.to_json.gsub(@token, "[Token]")}"
|
630
700
|
case payload[:op]
|
631
701
|
when 10
|
632
702
|
@heartbeat_interval = data[:heartbeat_interval]
|
633
703
|
if reconnect
|
634
704
|
payload = {
|
635
705
|
token: @token,
|
636
|
-
session_id:
|
706
|
+
session_id: session_id,
|
637
707
|
seq: @last_s,
|
638
708
|
}
|
639
709
|
send_gateway(6, **payload)
|
@@ -644,27 +714,29 @@ module Discorb
|
|
644
714
|
compress: false,
|
645
715
|
properties: { "$os" => RUBY_PLATFORM, "$browser" => "discorb", "$device" => "discorb" },
|
646
716
|
}
|
717
|
+
payload[:shard] = [shard_id, @shard_count] if shard_id
|
647
718
|
payload[:presence] = @identify_presence if @identify_presence
|
648
719
|
send_gateway(2, **payload)
|
649
720
|
end
|
650
721
|
when 7
|
651
|
-
|
722
|
+
logger.info "Received opcode 7, stopping tasks"
|
652
723
|
@tasks.map(&:stop)
|
653
724
|
when 9
|
654
|
-
|
725
|
+
logger.warn "Received opcode 9, closed connection"
|
655
726
|
@tasks.map(&:stop)
|
656
727
|
if data
|
657
|
-
|
658
|
-
|
728
|
+
logger.info "Connection is resumable, reconnecting"
|
729
|
+
connection.force_close
|
659
730
|
connect_gateway(true)
|
660
731
|
else
|
661
|
-
|
662
|
-
|
732
|
+
logger.info "Connection is not resumable, reconnecting with opcode 2"
|
733
|
+
connection.force_close
|
734
|
+
|
663
735
|
sleep(2)
|
664
736
|
connect_gateway(false)
|
665
737
|
end
|
666
738
|
when 11
|
667
|
-
|
739
|
+
logger.debug "Received opcode 11"
|
668
740
|
@ping = Time.now.to_f - @heartbeat_before
|
669
741
|
when 0
|
670
742
|
handle_event(payload[:t], data)
|
@@ -677,12 +749,12 @@ module Discorb
|
|
677
749
|
interval = @heartbeat_interval
|
678
750
|
sleep((interval / 1000.0 - 1) * rand)
|
679
751
|
loop do
|
680
|
-
unless
|
752
|
+
unless connection.closed?
|
681
753
|
@heartbeat_before = Time.now.to_f
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
754
|
+
connection.write({ op: 1, d: @last_s }.to_json)
|
755
|
+
connection.flush
|
756
|
+
logger.debug "Sent opcode 1."
|
757
|
+
logger.debug "Waiting for heartbeat."
|
686
758
|
end
|
687
759
|
sleep(interval / 1000.0 - 1)
|
688
760
|
end
|
@@ -690,29 +762,30 @@ module Discorb
|
|
690
762
|
end
|
691
763
|
|
692
764
|
def handle_event(event_name, data)
|
693
|
-
return
|
765
|
+
return logger.debug "Client isn't ready; event #{event_name} wasn't handled" if @wait_until_ready && !@ready && !%w[READY GUILD_CREATE].include?(event_name)
|
694
766
|
|
695
767
|
dispatch(:event_receive, event_name, data)
|
696
|
-
|
768
|
+
logger.debug "Handling event #{event_name}"
|
697
769
|
case event_name
|
698
770
|
when "READY"
|
699
771
|
@api_version = data[:v]
|
700
|
-
|
772
|
+
self.session_id = data[:session_id]
|
701
773
|
@user = ClientUser.new(self, data[:user])
|
702
774
|
@uncached_guilds = data[:guilds].map { |g| g[:id] }
|
703
775
|
ready if (@uncached_guilds == []) || !@intents.guilds
|
704
776
|
dispatch(:ready)
|
777
|
+
|
705
778
|
@tasks << handle_heartbeat
|
706
779
|
when "GUILD_CREATE"
|
707
780
|
if @uncached_guilds.include?(data[:id])
|
708
781
|
Guild.new(self, data, true)
|
709
782
|
@uncached_guilds.delete(data[:id])
|
710
783
|
if @uncached_guilds == []
|
711
|
-
|
784
|
+
logger.debug "All guilds cached"
|
712
785
|
ready
|
713
786
|
end
|
714
787
|
elsif @guilds.has?(data[:id])
|
715
|
-
@guilds[data[:id]].send(:_set_data, data)
|
788
|
+
@guilds[data[:id]].send(:_set_data, data, true)
|
716
789
|
dispatch(:guild_available, guild)
|
717
790
|
else
|
718
791
|
guild = Guild.new(self, data, true)
|
@@ -729,51 +802,51 @@ module Discorb
|
|
729
802
|
current.send(:_set_data, data, false)
|
730
803
|
dispatch(:guild_update, before, current)
|
731
804
|
else
|
732
|
-
|
805
|
+
logger.warn "Unknown guild id #{data[:id]}, ignoring"
|
733
806
|
end
|
734
807
|
when "GUILD_DELETE"
|
735
|
-
return
|
808
|
+
return logger.warn "Unknown guild id #{data[:id]}, ignoring" unless (guild = @guilds.delete(data[:id]))
|
736
809
|
|
737
810
|
dispatch(:guild_delete, guild)
|
738
|
-
if
|
811
|
+
if data[:unavailable]
|
739
812
|
dispatch(:guild_destroy, guild)
|
740
813
|
else
|
741
814
|
dispatch(:guild_leave, guild)
|
742
815
|
end
|
743
816
|
when "GUILD_ROLE_CREATE"
|
744
|
-
return
|
817
|
+
return logger.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
745
818
|
|
746
819
|
nr = Role.new(@client, guild, data[:role])
|
747
820
|
guild.roles[data[:role][:id]] = nr
|
748
821
|
dispatch(:role_create, nr)
|
749
822
|
when "GUILD_ROLE_UPDATE"
|
750
|
-
return
|
751
|
-
return
|
823
|
+
return logger.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
824
|
+
return logger.warn "Unknown role id #{data[:role][:id]}, ignoring" unless guild.roles.has?(data[:role][:id])
|
752
825
|
|
753
826
|
current = guild.roles[data[:role][:id]]
|
754
827
|
before = Role.new(@client, guild, current.instance_variable_get(:@data).update({ no_cache: true }))
|
755
828
|
current.send(:_set_data, data[:role])
|
756
829
|
dispatch(:role_update, before, current)
|
757
830
|
when "GUILD_ROLE_DELETE"
|
758
|
-
return
|
759
|
-
return
|
831
|
+
return logger.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
832
|
+
return logger.warn "Unknown role id #{data[:role_id]}, ignoring" unless (role = guild.roles.delete(data[:role_id]))
|
760
833
|
|
761
834
|
dispatch(:role_delete, role)
|
762
835
|
when "CHANNEL_CREATE"
|
763
|
-
return
|
836
|
+
return logger.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
764
837
|
|
765
838
|
nc = Channel.make_channel(self, data)
|
766
839
|
guild.channels[data[:id]] = nc
|
767
840
|
|
768
841
|
dispatch(:channel_create, nc)
|
769
842
|
when "CHANNEL_UPDATE"
|
770
|
-
return
|
843
|
+
return logger.warn "Unknown channel id #{data[:id]}, ignoring" unless (current = @channels[data[:id]])
|
771
844
|
|
772
845
|
before = Channel.make_channel(self, current.instance_variable_get(:@data), no_cache: true)
|
773
846
|
current.send(:_set_data, data)
|
774
847
|
dispatch(:channel_update, before, current)
|
775
848
|
when "CHANNEL_DELETE"
|
776
|
-
return
|
849
|
+
return logger.warn "Unknown channel id #{data[:id]}, ignoring" unless (channel = @channels.delete(data[:id]))
|
777
850
|
|
778
851
|
@guilds[data[:guild_id]]&.channels&.delete(data[:id])
|
779
852
|
dispatch(:channel_delete, channel)
|
@@ -789,13 +862,13 @@ module Discorb
|
|
789
862
|
dispatch(:thread_new, thread)
|
790
863
|
end
|
791
864
|
when "THREAD_UPDATE"
|
792
|
-
return
|
865
|
+
return logger.warn "Unknown thread id #{data[:id]}, ignoring" unless (thread = @channels[data[:id]])
|
793
866
|
|
794
867
|
before = Channel.make_channel(self, thread.instance_variable_get(:@data), no_cache: true)
|
795
868
|
thread.send(:_set_data, data)
|
796
869
|
dispatch(:thread_update, before, thread)
|
797
870
|
when "THREAD_DELETE"
|
798
|
-
return
|
871
|
+
return logger.warn "Unknown thread id #{data[:id]}, ignoring" unless (thread = @channels.delete(data[:id]))
|
799
872
|
|
800
873
|
@guilds[data[:guild_id]]&.channels&.delete(data[:id])
|
801
874
|
dispatch(:thread_delete, thread)
|
@@ -805,11 +878,11 @@ module Discorb
|
|
805
878
|
@channels[thread.id] = thread
|
806
879
|
end
|
807
880
|
when "THREAD_MEMBER_UPDATE"
|
808
|
-
return
|
881
|
+
return logger.warn "Unknown thread id #{data[:id]}, ignoring" unless (thread = @channels[data[:id]])
|
809
882
|
|
810
883
|
if (member = thread.members[data[:id]])
|
811
884
|
old = ThreadChannel::Member.new(self, member.instance_variable_get(:@data))
|
812
|
-
member._set_data
|
885
|
+
member.send(:_set_data, data)
|
813
886
|
else
|
814
887
|
old = nil
|
815
888
|
member = ThreadChannel::Member.new(self, data)
|
@@ -817,7 +890,7 @@ module Discorb
|
|
817
890
|
end
|
818
891
|
dispatch(:thread_member_update, thread, old, member)
|
819
892
|
when "THREAD_MEMBERS_UPDATE"
|
820
|
-
return
|
893
|
+
return logger.warn "Unknown thread id #{data[:id]}, ignoring" unless (thread = @channels[data[:id]])
|
821
894
|
|
822
895
|
thread.instance_variable_set(:@member_count, data[:member_count])
|
823
896
|
members = []
|
@@ -835,37 +908,37 @@ module Discorb
|
|
835
908
|
instance = StageInstance.new(self, data)
|
836
909
|
dispatch(:stage_instance_create, instance)
|
837
910
|
when "STAGE_INSTANCE_UPDATE"
|
838
|
-
return
|
839
|
-
return
|
911
|
+
return logger.warn "Unknown channel id #{data[:channel_id]} , ignoring" unless (channel = @channels[data[:channel_id]])
|
912
|
+
return logger.warn "Unknown stage instance id #{data[:id]}, ignoring" unless (instance = channel.stage_instances[data[:id]])
|
840
913
|
|
841
914
|
old = StageInstance.new(self, instance.instance_variable_get(:@data), no_cache: true)
|
842
915
|
current.send(:_set_data, data)
|
843
916
|
dispatch(:stage_instance_update, old, current)
|
844
917
|
when "STAGE_INSTANCE_DELETE"
|
845
|
-
return
|
846
|
-
return
|
918
|
+
return logger.warn "Unknown channel id #{data[:channel_id]} , ignoring" unless (channel = @channels[data[:channel_id]])
|
919
|
+
return logger.warn "Unknown stage instance id #{data[:id]}, ignoring" unless (instance = channel.stage_instances.delete(data[:id]))
|
847
920
|
|
848
921
|
dispatch(:stage_instance_delete, instance)
|
849
922
|
when "GUILD_MEMBER_ADD"
|
850
|
-
return
|
923
|
+
return logger.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
851
924
|
|
852
925
|
nm = Member.new(self, data[:guild_id], data[:user].update({ no_cache: true }), data)
|
853
926
|
guild.members[nm.id] = nm
|
854
927
|
dispatch(:member_add, nm)
|
855
928
|
when "GUILD_MEMBER_UPDATE"
|
856
|
-
return
|
857
|
-
return
|
929
|
+
return logger.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
930
|
+
return logger.warn "Unknown member id #{data[:user][:id]}, ignoring" unless (nm = guild.members[data[:user][:id]])
|
858
931
|
|
859
932
|
old = Member.new(self, data[:guild_id], data[:user], data.update({ no_cache: true }))
|
860
933
|
nm.send(:_set_data, data[:user], data)
|
861
934
|
dispatch(:member_update, old, nm)
|
862
935
|
when "GUILD_MEMBER_REMOVE"
|
863
|
-
return
|
864
|
-
return
|
936
|
+
return logger.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
937
|
+
return logger.warn "Unknown member id #{data[:user][:id]}, ignoring" unless (member = guild.members.delete(data[:user][:id]))
|
865
938
|
|
866
939
|
dispatch(:member_remove, member)
|
867
940
|
when "GUILD_BAN_ADD"
|
868
|
-
return
|
941
|
+
return logger.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
869
942
|
|
870
943
|
user = if @users.has? data[:user][:id]
|
871
944
|
@users[data[:user][:id]]
|
@@ -875,7 +948,7 @@ module Discorb
|
|
875
948
|
|
876
949
|
dispatch(:guild_ban_add, guild, user)
|
877
950
|
when "GUILD_BAN_REMOVE"
|
878
|
-
return
|
951
|
+
return logger.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
879
952
|
|
880
953
|
user = if @users.has? data[:user][:id]
|
881
954
|
@users[data[:user][:id]]
|
@@ -885,7 +958,7 @@ module Discorb
|
|
885
958
|
|
886
959
|
dispatch(:guild_ban_remove, guild, user)
|
887
960
|
when "GUILD_EMOJIS_UPDATE"
|
888
|
-
return
|
961
|
+
return logger.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
889
962
|
|
890
963
|
before_emojis = guild.emojis.values.map(&:id).to_set
|
891
964
|
data[:emojis].each do |emoji|
|
@@ -896,17 +969,16 @@ module Discorb
|
|
896
969
|
guild.emojis.delete(emoji)
|
897
970
|
end
|
898
971
|
when "GUILD_INTEGRATIONS_UPDATE"
|
899
|
-
|
900
|
-
# Currently not implemented
|
972
|
+
dispatch(:guild_integrations_update, @guilds[data[:guild_id]])
|
901
973
|
when "INTEGRATION_CREATE"
|
902
974
|
dispatch(:integration_create, Integration.new(self, data, data[:guild_id]))
|
903
975
|
when "INTEGRATION_UPDATE"
|
904
|
-
return
|
976
|
+
return logger.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
905
977
|
|
906
978
|
integration = Integration.new(self, data, data[:guild_id])
|
907
979
|
dispatch(:integration_update, integration)
|
908
980
|
when "INTEGRATION_DELETE"
|
909
|
-
return
|
981
|
+
return logger.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
910
982
|
|
911
983
|
dispatch(:integration_delete, IntegrationDeleteEvent.new(self, data))
|
912
984
|
when "WEBHOOKS_UPDATE"
|
@@ -916,7 +988,7 @@ module Discorb
|
|
916
988
|
when "INVITE_DELETE"
|
917
989
|
dispatch(:invite_delete, InviteDeleteEvent.new(self, data))
|
918
990
|
when "VOICE_STATE_UPDATE"
|
919
|
-
return
|
991
|
+
return logger.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
920
992
|
|
921
993
|
current = guild.voice_states[data[:user_id]]
|
922
994
|
if current.nil?
|
@@ -1013,7 +1085,7 @@ module Discorb
|
|
1013
1085
|
end
|
1014
1086
|
end
|
1015
1087
|
when "PRESENCE_UPDATE"
|
1016
|
-
return
|
1088
|
+
return logger.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
1017
1089
|
|
1018
1090
|
guild.presences[data[:user][:id]] = Presence.new(self, data)
|
1019
1091
|
when "MESSAGE_UPDATE"
|
@@ -1089,7 +1161,7 @@ module Discorb
|
|
1089
1161
|
(target_reaction = target_message.reactions.find { |r| data[:emoji][:id].nil? ? r.name == data[:emoji][:name] : r.id == data[:emoji][:id] })
|
1090
1162
|
target_message.reactions.delete(target_reaction)
|
1091
1163
|
end
|
1092
|
-
dispatch(:reaction_remove_emoji, ReactionRemoveEmojiEvent.new(data))
|
1164
|
+
dispatch(:reaction_remove_emoji, ReactionRemoveEmojiEvent.new(self, data))
|
1093
1165
|
when "TYPING_START"
|
1094
1166
|
dispatch(:typing_start, TypingStartEvent.new(self, data))
|
1095
1167
|
when "INTERACTION_CREATE"
|
@@ -1098,17 +1170,21 @@ module Discorb
|
|
1098
1170
|
|
1099
1171
|
dispatch(interaction.class.event_name, interaction)
|
1100
1172
|
when "RESUMED"
|
1101
|
-
|
1173
|
+
logger.info("Successfully resumed connection")
|
1102
1174
|
@tasks << handle_heartbeat
|
1103
|
-
|
1175
|
+
if shard
|
1176
|
+
dispatch(:shard_resumed, shard)
|
1177
|
+
else
|
1178
|
+
dispatch(:resumed)
|
1179
|
+
end
|
1104
1180
|
when "GUILD_SCHEDULED_EVENT_CREATE"
|
1105
|
-
|
1181
|
+
logger.warn("Unknown guild id #{data[:guild_id]}, ignoring") unless (guild = @guilds[data[:guild_id]])
|
1106
1182
|
event = ScheduledEvent.new(self, data)
|
1107
1183
|
guild.scheduled_events[data[:id]] = event
|
1108
1184
|
dispatch(:scheduled_event_create, event)
|
1109
1185
|
when "GUILD_SCHEDULED_EVENT_UPDATE"
|
1110
|
-
|
1111
|
-
|
1186
|
+
logger.warn("Unknown guild id #{data[:guild_id]}, ignoring") unless (guild = @guilds[data[:guild_id]])
|
1187
|
+
logger.warn("Unknown scheduled event id #{data[:id]}, ignoring") unless (event = guild.scheduled_events[data[:id]])
|
1112
1188
|
old = event.dup
|
1113
1189
|
event.send(:_set_data, data)
|
1114
1190
|
dispatch(:scheduled_event_update, old, event)
|
@@ -1123,22 +1199,22 @@ module Discorb
|
|
1123
1199
|
end
|
1124
1200
|
end
|
1125
1201
|
when "GUILD_SCHEDULED_EVENT_DELETE"
|
1126
|
-
|
1127
|
-
|
1202
|
+
logger.warn("Unknown guild id #{data[:guild_id]}, ignoring") unless (guild = @guilds[data[:guild_id]])
|
1203
|
+
logger.warn("Unknown scheduled event id #{data[:id]}, ignoring") unless (event = guild.scheduled_events[data[:id]])
|
1128
1204
|
guild.scheduled_events.remove(data[:id])
|
1129
1205
|
dispatch(:scheduled_event_delete, event)
|
1130
1206
|
dispatch(:scheduled_event_cancel, event)
|
1131
1207
|
when "GUILD_SCHEDULED_EVENT_USER_ADD"
|
1132
|
-
|
1208
|
+
logger.warn("Unknown guild id #{data[:guild_id]}, ignoring") unless (guild = @guilds[data[:guild_id]])
|
1133
1209
|
dispatch(:scheduled_event_user_add, ScheduledEventUserEvent.new(self, data))
|
1134
1210
|
when "GUILD_SCHEDULED_EVENT_USER_REMOVE"
|
1135
|
-
|
1211
|
+
logger.warn("Unknown guild id #{data[:guild_id]}, ignoring") unless (guild = @guilds[data[:guild_id]])
|
1136
1212
|
dispatch(:scheduled_event_user_remove, ScheduledEventUserEvent.new(self, data))
|
1137
1213
|
else
|
1138
1214
|
if respond_to?("event_" + event_name.downcase)
|
1139
1215
|
__send__("event_" + event_name.downcase, data)
|
1140
1216
|
else
|
1141
|
-
|
1217
|
+
logger.debug "Unhandled event: #{event_name}\n#{data.inspect}"
|
1142
1218
|
end
|
1143
1219
|
end
|
1144
1220
|
end
|
@@ -1146,7 +1222,7 @@ module Discorb
|
|
1146
1222
|
def ready
|
1147
1223
|
Async do
|
1148
1224
|
if @fetch_member
|
1149
|
-
|
1225
|
+
logger.debug "Fetching members"
|
1150
1226
|
barrier = Async::Barrier.new
|
1151
1227
|
|
1152
1228
|
@guilds.each do |guild|
|
@@ -1157,8 +1233,25 @@ module Discorb
|
|
1157
1233
|
barrier.wait
|
1158
1234
|
end
|
1159
1235
|
@ready = true
|
1160
|
-
|
1161
|
-
|
1236
|
+
|
1237
|
+
if self.shard
|
1238
|
+
logger.info("Shard #{shard_id} is ready!")
|
1239
|
+
self.shard&.tap do |shard|
|
1240
|
+
if shard.next_shard
|
1241
|
+
dispatch(:shard_standby, shard)
|
1242
|
+
shard.next_shard.tap do |next_shard|
|
1243
|
+
logger.debug("Starting shard #{next_shard.id}")
|
1244
|
+
next_shard.start
|
1245
|
+
end
|
1246
|
+
else
|
1247
|
+
logger.info("All shards are ready!")
|
1248
|
+
dispatch(:standby)
|
1249
|
+
end
|
1250
|
+
end
|
1251
|
+
else
|
1252
|
+
logger.info("Client is ready!")
|
1253
|
+
dispatch(:standby)
|
1254
|
+
end
|
1162
1255
|
end
|
1163
1256
|
end
|
1164
1257
|
end
|
@@ -1173,6 +1266,10 @@ module Discorb
|
|
1173
1266
|
@closed = false
|
1174
1267
|
end
|
1175
1268
|
|
1269
|
+
def inspect
|
1270
|
+
"<#{self.class.name} #{io.fileno}>"
|
1271
|
+
end
|
1272
|
+
|
1176
1273
|
def closed?
|
1177
1274
|
@closed
|
1178
1275
|
end
|
@@ -1185,10 +1282,14 @@ module Discorb
|
|
1185
1282
|
end
|
1186
1283
|
|
1187
1284
|
def force_close
|
1188
|
-
|
1285
|
+
io.close
|
1189
1286
|
@closed = true
|
1190
1287
|
end
|
1191
1288
|
|
1289
|
+
def io
|
1290
|
+
@framer.instance_variable_get(:@stream).instance_variable_get(:@io).instance_variable_get(:@io).instance_variable_get(:@io)
|
1291
|
+
end
|
1292
|
+
|
1192
1293
|
def parse(buffer)
|
1193
1294
|
# noop
|
1194
1295
|
buffer.to_s
|