discorb 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 810e9b14c77e49e9fca7afc4fe6b98389b26cb17dc1617213f38d7655b990a49
4
- data.tar.gz: bbaa999265ac212f90ab60d57ec772fe7ade0e47f264a136130c679b85a46952
3
+ metadata.gz: 497fc76081f6183ccd3ec7c14768e80d81a172c092afa67f26bcec625f7b204f
4
+ data.tar.gz: 5d0d4070c729b2b63d6a746fa559900b2205d51f737105d8c8653c59eec01e97
5
5
  SHA512:
6
- metadata.gz: 120828736edcf7eef9d78410914651edeb41ae85eadef012050b105b03c80f07f835d812105d3cfe954c7237e344b3bbc540af8840a7dde1a69f590b008a759e
7
- data.tar.gz: f29b0399c65f180b05bf6c0c3d5f253689ff08c734f60ee7681b57c060d99e36dd85fc275f9652354933478b8139aa76c8ad854f6963fd1c074a8a260ffb6bde
6
+ metadata.gz: bf93daa59116cbd29d408e361b0cebf0e4b681c21eb2e07466f2ea2659f7bec959a58c4bf168c8b5058bb4221bb26352770c94e6bc61a9713a82d72bf98316e8
7
+ data.tar.gz: aa07fe600a6397f69584a33d4b79dfd2d64952c4c1fff83a08a84418e0547a78c9b2261fce7e96a46bf19d4dab9ff0972ebe09b2ddf59371d5d74a761282c45e
@@ -33,7 +33,7 @@ jobs:
33
33
  git clone git@github.com:discorb-lib/discorb-lib.github.io /tmp/pages
34
34
  - name: Install dependencies
35
35
  run: |
36
- bundle config --local with 'docs development'
36
+ bundle config --local with 'docs development lint'
37
37
  bundle install
38
38
  gem update uri
39
39
  - name: Generate document
@@ -1,6 +1,8 @@
1
1
  name: Lint with RuboCop
2
2
  on:
3
- - push
3
+ push:
4
+ branches:
5
+ - main
4
6
  jobs:
5
7
  rubocop:
6
8
  runs-on: ubuntu-latest
@@ -15,4 +17,4 @@ jobs:
15
17
  gem install rubocop
16
18
  - name: Run rubocop
17
19
  run: |
18
- rubocop lib
20
+ rubocop lib
data/Changelog.md CHANGED
@@ -4,6 +4,15 @@
4
4
 
5
5
  # Changelog
6
6
 
7
+ ## v0.15
8
+
9
+ ### v0.15.0
10
+
11
+ - Add: Migrate to API v10
12
+ - Add: Add `TextChannel#threads`
13
+ - Add: Support editing attachments
14
+ - Delete!: Delete File class - Use Attachment class instead
15
+
7
16
  ## v0.14
8
17
 
9
18
  ### v0.14.0
data/docs/faq.md CHANGED
@@ -62,19 +62,19 @@ client.on :ready do
62
62
  end
63
63
  ```
64
64
 
65
- ### How can I send files?
65
+ ### How can I send attachments?
66
66
 
67
- Use {Discorb::File} class.
67
+ Use {Discorb::Attachment} class.
68
68
 
69
69
  ```ruby
70
- # Send a file
71
- message.channel.post file: Discorb::File.new(File.open("./README.md"))
70
+ # Send an attachment
71
+ message.channel.post attachment: Discorb::Attachment.new(File.open("./README.md"))
72
72
 
73
- # Send some files with text
74
- message.channel.post "File!", files: [Discorb::File.new(File.open("./README.md")), Discorb::File.new(File.open("./License.txt"))]
73
+ # Send some attachment with text
74
+ message.channel.post "File!", attachments: [Discorb::Attachment.new("./README.md"), Discorb::Attachment.new(File.open("./License.txt"))]
75
75
 
76
- # Send a string as a file
77
- message.channel.post file: Discorb::File.from_string("Hello world!", "hello.txt")
76
+ # Send a string as an attachment
77
+ message.channel.post attachments: Discorb::Attachment.from_string("Hello world!", "hello.txt")
78
78
  ```
79
79
 
80
80
  ### How can I add reactions?
@@ -7,15 +7,17 @@ module Discorb
7
7
  #
8
8
  # Represents a attachment file.
9
9
  #
10
- class Attachment < DiscordModel
10
+ class Attachment
11
11
  # @return [#read] The file content.
12
12
  attr_reader :io
13
- # @return [Discorb::Snowflake] The attachment id.
14
- attr_reader :id
15
13
  # @return [String] The attachment filename.
16
14
  attr_reader :filename
17
15
  # @return [String] The attachment content type.
18
16
  attr_reader :content_type
17
+ # @return [String] The attachment description.
18
+ attr_reader :description
19
+ # @return [Discorb::Snowflake] The attachment id.
20
+ attr_reader :id
19
21
  # @return [Integer] The attachment size in bytes.
20
22
  attr_reader :size
21
23
  # @return [String] The attachment url.
@@ -28,12 +30,40 @@ module Discorb
28
30
  # @return [Integer] The image width.
29
31
  # @return [nil] If the attachment is not an image.
30
32
  attr_reader :width
33
+ # @return [:client, :discord] The attachment was created by.
34
+ attr_reader :created_by
35
+ # @private
36
+ attr_reader :will_close
31
37
 
32
38
  # @!attribute [r] image?
33
39
  # @return [Boolean] whether the file is an image.
34
40
 
41
+ #
42
+ # Creates a new attachment.
43
+ #
44
+ # @param [#read, String] source The Source of the attachment.
45
+ # @param [String] filename The filename of the attachment. If not set, path or object_id of the IO is used.
46
+ # @param [String] description The description of the attachment.
47
+ # @param [String] content_type The content type of the attachment. If not set, it is guessed from the filename.
48
+ # If failed to guess, it is set to `application/octet-stream`.
49
+ # @param [Boolean] will_close Whether the IO will be closed after the attachment is sent.
50
+ #
51
+ def initialize(source, filename = nil, description: nil, content_type: nil, will_close: true)
52
+ @io = if source.respond_to?(:read)
53
+ source
54
+ else
55
+ File.open(source, "rb")
56
+ end
57
+ @filename = filename || (@io.respond_to?(:path) ? @io.path : @io.object_id)
58
+ @description = description
59
+ @content_type = content_type || MIME::Types.type_for(@filename.to_s)[0].to_s
60
+ @content_type = "application/octet-stream" if @content_type == ""
61
+ @will_close = will_close
62
+ @created_by = :client
63
+ end
64
+
35
65
  # @private
36
- def initialize(data)
66
+ def initialize_hash(data)
37
67
  @id = Snowflake.new(data[:id])
38
68
  @filename = data[:filename]
39
69
  @content_type = data[:content_type]
@@ -42,37 +72,18 @@ module Discorb
42
72
  @proxy_url = data[:proxy_url]
43
73
  @height = data[:height]
44
74
  @width = data[:width]
75
+ @created_by = :discord
45
76
  end
46
77
 
47
78
  def image?
48
79
  @content_type.start_with? "image/"
49
80
  end
50
- end
51
81
 
52
- #
53
- # Represents a file to send as an attachment.
54
- #
55
- class File
56
- # @return [#read] The IO of the file.
57
- attr_accessor :io
58
- # @return [String] The filename of the file. If not set, path or object_id of the IO is used.
59
- attr_accessor :filename
60
- # @return [String] The content type of the file. If not set, it is guessed from the filename.
61
- attr_accessor :content_type
62
-
63
- #
64
- # Creates a new file from IO.
65
- #
66
- # @param [#read] io The IO of the file.
67
- # @param [String] filename The filename of the file. If not set, path or object_id of the IO is used.
68
- # @param [String] content_type The content type of the file. If not set, it is guessed from the filename.
69
- # If failed to guess, it is set to `application/octet-stream`.
70
- #
71
- def initialize(io, filename = nil, content_type: nil)
72
- @io = io
73
- @filename = filename || (io.respond_to?(:path) ? io.path : io.object_id)
74
- @content_type = content_type || MIME::Types.type_for(@filename.to_s)[0].to_s
75
- @content_type = "application/octet-stream" if @content_type == ""
82
+ # @private
83
+ def self.from_hash(data)
84
+ inst = allocate
85
+ inst.initialize_hash(data)
86
+ inst
76
87
  end
77
88
 
78
89
  #
@@ -84,14 +95,10 @@ module Discorb
84
95
  #
85
96
  # @return [File] The new file.
86
97
  #
87
- def self.from_string(string, filename: nil, content_type: nil)
98
+ def self.from_string(string, filename = nil, content_type: nil, description: nil)
88
99
  io = StringIO.new(string)
89
100
  filename ||= string.object_id.to_s + ".txt"
90
- new(io, filename, content_type: content_type)
91
- end
92
-
93
- def inspect
94
- "#<#{self.class} filename=#{@filename} content_type=#{@content_type}>"
101
+ new(io, filename, content_type: content_type, description: description, will_close: true)
95
102
  end
96
103
  end
97
104
  end
@@ -239,17 +239,15 @@ module Discorb
239
239
  # @return [Time] The time when the last pinned message was pinned.
240
240
  attr_reader :last_pin_timestamp
241
241
  alias last_pinned_at last_pin_timestamp
242
- # @return [Array<Discorb::ThreadChannel>] The threads in the channel.
243
- attr_reader :threads
244
242
 
245
243
  include Messageable
246
244
 
247
245
  @channel_type = 0
248
246
 
249
- # @private
250
- def initialize(client, data, no_cache: false)
251
- super
252
- @threads = Dictionary.new
247
+ # @!attribute [r] threads
248
+ # @return [Array<Discorb::ThreadChannel>] The threads in the channel.
249
+ def threads
250
+ guild.threads.select { |thread| thread.parent == self }
253
251
  end
254
252
 
255
253
  #
@@ -829,8 +827,6 @@ module Discorb
829
827
  def initialize(client, data, no_cache: false)
830
828
  @members = Dictionary.new
831
829
  super
832
- @client.channels[@parent_id].threads[@id] = self
833
-
834
830
  @client.channels[@id] = self unless no_cache
835
831
  end
836
832
 
@@ -2,9 +2,9 @@
2
2
 
3
3
  module Discorb
4
4
  # @return [String] The API base URL.
5
- API_BASE_URL = "https://discord.com/api/v9"
5
+ API_BASE_URL = "https://discord.com/api/v10"
6
6
  # @return [String] The version of discorb.
7
- VERSION = "0.14.0"
7
+ VERSION = "0.15.0"
8
8
  # @return [String] The user agent for the bot.
9
9
  USER_AGENT = "DiscordBot (https://discorb-lib.github.io #{VERSION}) Ruby/#{RUBY_VERSION}".freeze
10
10
 
data/lib/discorb/embed.rb CHANGED
@@ -45,37 +45,38 @@ module Discorb
45
45
  # @param [Discorb::Embed::Thumbnail, String] thumbnail The thumbnail of embed.
46
46
  #
47
47
  def initialize(title = nil, description = nil, color: nil, url: nil, timestamp: nil, author: nil,
48
- fields: nil, footer: nil, image: nil, thumbnail: nil, data: nil)
49
- if data.nil?
50
- @title = title
51
- @description = description
52
- @url = url
53
- @timestamp = timestamp
54
- @color = color
55
- @author = author
56
- @fields = fields || []
57
- @footer = footer
58
- @image = image && (image.is_a?(String) ? Image.new(image) : image)
59
- @thumbnail = thumbnail && (thumbnail.is_a?(String) ? Thumbnail.new(thumbnail) : thumbnail)
60
- @type = "rich"
61
- else
62
- @title = data[:title]
63
- @description = data[:description]
64
- @url = data[:url]
65
- @timestamp = data[:timestamp] && Time.iso8601(data[:timestamp])
66
- @type = data[:type]
67
- @color = data[:color] && Color.new(data[:color])
68
- @footer = data[:footer] && Footer.new(data[:footer][:text], icon: data[:footer][:icon_url])
69
- @author = if data[:author]
70
- Author.new(data[:author][:name], icon: data[:author][:icon_url],
71
- url: data[:author][:url])
72
- end
73
- @thumbnail = data[:thumbnail] && Thumbnail.new(data[:thumbnail])
74
- @image = data[:image] && Image.new(data[:image])
75
- @video = data[:video] && Video.new(data[:video])
76
- @provider = data[:provider] && Provider.new(data[:provider])
77
- @fields = data[:fields] ? data[:fields].map { |f| Field.new(f[:name], f[:value], inline: f[:inline]) } : []
78
- end
48
+ fields: nil, footer: nil, image: nil, thumbnail: nil)
49
+ @title = title
50
+ @description = description
51
+ @url = url
52
+ @timestamp = timestamp
53
+ @color = color
54
+ @author = author
55
+ @fields = fields || []
56
+ @footer = footer
57
+ @image = image && (image.is_a?(String) ? Image.new(image) : image)
58
+ @thumbnail = thumbnail && (thumbnail.is_a?(String) ? Thumbnail.new(thumbnail) : thumbnail)
59
+ @type = "rich"
60
+ end
61
+
62
+ # @private
63
+ def initialize_hash(data)
64
+ @title = data[:title]
65
+ @description = data[:description]
66
+ @url = data[:url]
67
+ @timestamp = data[:timestamp] && Time.iso8601(data[:timestamp])
68
+ @type = data[:type]
69
+ @color = data[:color] && Color.new(data[:color])
70
+ @footer = data[:footer] && Footer.new(data[:footer][:text], icon: data[:footer][:icon_url])
71
+ @author = if data[:author]
72
+ Author.new(data[:author][:name], icon: data[:author][:icon_url],
73
+ url: data[:author][:url])
74
+ end
75
+ @thumbnail = data[:thumbnail] && Thumbnail.new(data[:thumbnail])
76
+ @image = data[:image] && Image.new(data[:image])
77
+ @video = data[:video] && Video.new(data[:video])
78
+ @provider = data[:provider] && Provider.new(data[:provider])
79
+ @fields = data[:fields] ? data[:fields].map { |f| Field.new(f[:name], f[:value], inline: f[:inline]) } : []
79
80
  end
80
81
 
81
82
  def image=(value)
@@ -111,6 +112,12 @@ module Discorb
111
112
  ret
112
113
  end
113
114
 
115
+ def self.from_hash(data)
116
+ inst = allocate
117
+ inst.initialize_hash(data)
118
+ inst
119
+ end
120
+
114
121
  #
115
122
  # Represents an author of embed.
116
123
  #
@@ -305,8 +305,8 @@ module Discorb
305
305
  @timestamp = Time.iso8601(data[:edited_timestamp])
306
306
  @mention_everyone = data[:mention_everyone]
307
307
  @mention_roles = data[:mention_roles].map { |r| guild.roles[r] } if data.key?(:mention_roles)
308
- @attachments = data[:attachments].map { |a| Attachment.new(a) } if data.key?(:attachments)
309
- @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)
310
310
  end
311
311
 
312
312
  def channel
@@ -545,7 +545,13 @@ module Discorb
545
545
  @http = HTTP.new(self)
546
546
  _, gateway_response = @http.request(Route.new("/gateway", "//gateway", :get)).wait
547
547
  gateway_url = gateway_response[:url]
548
- 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",
549
555
  alpn_protocols: Async::HTTP::Protocol::HTTP11.names)
550
556
  begin
551
557
  @connection = Async::WebSocket::Client.connect(endpoint, headers: [["User-Agent", Discorb::USER_AGENT]], handler: RawConnection)
data/lib/discorb/http.rb CHANGED
@@ -70,12 +70,23 @@ module Discorb
70
70
  ]
71
71
  files&.each_with_index do |file, i|
72
72
  next if file.nil?
73
- data << ["files[#{i}]", file.io, { filename: file.filename, content_type: file.content_type }]
73
+ if file.created_by == :discord
74
+ request_io = StringIO.new(
75
+ cdn_http.get(URI.parse(file.url).path, {
76
+ "Content-Type" => nil,
77
+ "User-Agent" => Discorb::USER_AGENT,
78
+ }).body
79
+ )
80
+ data << ["files[#{i}]", request_io, { filename: file.filename, content_type: file.content_type }]
81
+ else
82
+ data << ["files[#{i}]", file.io, { filename: file.filename, content_type: file.content_type }]
83
+ end
74
84
  end
75
85
  req.set_form(data, "multipart/form-data")
76
86
  session = Net::HTTP.new("discord.com", 443)
77
87
  session.use_ssl = true
78
88
  resp = session.request(req)
89
+ files&.then { _1.filter(&:will_close).each { |f| f.io.close } }
79
90
  data = get_response_data(resp)
80
91
  @ratelimit_handler.save(path, resp)
81
92
  handle_response(resp, data, path, body, headers, audit_log_reason, kwargs)
@@ -159,6 +170,12 @@ module Discorb
159
170
  https
160
171
  end
161
172
 
173
+ def cdn_http
174
+ https = Net::HTTP.new("cdn.discordapp.com", 443)
175
+ https.use_ssl = true
176
+ https
177
+ end
178
+
162
179
  def recr_utf8(data)
163
180
  case data
164
181
  when Hash
@@ -19,6 +19,7 @@ module Discorb
19
19
  dm_messages: 1 << 12,
20
20
  dm_reactions: 1 << 13,
21
21
  dm_typing: 1 << 14,
22
+ message_content: 1 << 15,
22
23
  scheduled_events: 1 << 16,
23
24
  }.freeze
24
25
 
@@ -39,9 +40,13 @@ module Discorb
39
40
  # @param dm_messages [Boolean] Whether dm messages related events are enabled.
40
41
  # @param dm_reactions [Boolean] Whether dm reactions related events are enabled.
41
42
  # @param dm_typing [Boolean] Whether dm typing related events are enabled.
43
+ # @param message_content [Boolean] Whether message content will be sent with events.
42
44
  # @param scheduled_events [Boolean] Whether events related scheduled events are enabled.
43
45
  #
44
46
  # @note You must enable privileged intents to use `members` and/or `presences` intents.
47
+ # @note Message Content Intent is not required to use `message_content` intents for now,
48
+ # this will be required in April 30, 2022. [Learn More](https://support-dev.discord.com/hc/en-us/articles/4404772028055).
49
+ # You should specify `message_content` intent for preventing unexpected changes in the future.
45
50
  #
46
51
  def initialize(guilds: true,
47
52
  members: false,
@@ -58,6 +63,7 @@ module Discorb
58
63
  dm_messages: true,
59
64
  dm_reactions: true,
60
65
  dm_typing: true,
66
+ message_content: nil,
61
67
  scheduled_events: true)
62
68
  @raw_value = {
63
69
  guilds: guilds,
@@ -75,6 +81,7 @@ module Discorb
75
81
  dm_messages: dm_messages,
76
82
  dm_reactions: dm_reactions,
77
83
  dm_typing: dm_typing,
84
+ message_content: message_content,
78
85
  scheduled_events: scheduled_events,
79
86
  }
80
87
  end
@@ -129,9 +136,7 @@ module Discorb
129
136
 
130
137
  # Create new intent object with default values.
131
138
  # This will return intents without members and presence.
132
- def default
133
- from_value(@intent_bits.values.reduce(:+) - @intent_bits[:members] - @intent_bits[:presences])
134
- end
139
+ alias default new
135
140
 
136
141
  # Create new intent object with all intents.
137
142
  def all
@@ -244,16 +244,17 @@ module Discorb
244
244
  # @param [Discorb::Embed] embed The embed to send.
245
245
  # @param [Array<Discorb::Embed>] embeds The embeds to send.
246
246
  # @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions.
247
+ # @param [Array<Discorb::Attachment>] attachments The new attachments.
247
248
  # @param [Array<Discorb::Component>, Array<Array<Discorb::Component>>] components The components to send.
248
249
  # @param [Boolean] supress Whether to supress embeds.
249
250
  #
250
251
  # @return [Async::Task<void>] The task.
251
252
  #
252
- def edit(content = nil, embed: nil, embeds: nil, allowed_mentions: nil,
253
- components: nil, supress: nil)
253
+ def edit(content = Discorb::Unset, embed: Discorb::Unset, embeds: Discorb::Unset, allowed_mentions: Discorb::Unset,
254
+ attachments: Discorb::Unset, components: Discorb::Unset, supress: Discorb::Unset)
254
255
  Async do
255
256
  channel.edit_message(@id, content, embed: embed, embeds: embeds, allowed_mentions: allowed_mentions,
256
- components: components, supress: supress).wait
257
+ attachments: attachments, components: components, supress: supress).wait
257
258
  end
258
259
  end
259
260
 
@@ -445,6 +446,53 @@ module Discorb
445
446
  "#<#{self.class} #{@content.inspect} id=#{@id}>"
446
447
  end
447
448
 
449
+ # @private
450
+ def _set_data(data)
451
+ @id = Snowflake.new(data[:id])
452
+ @channel_id = data[:channel_id]
453
+
454
+ if data[:guild_id]
455
+ @guild_id = data[:guild_id]
456
+ @dm = nil
457
+ else
458
+ @dm = Discorb::DMChannel.new(@client, data[:channel_id])
459
+ @guild_id = nil
460
+ end
461
+
462
+ if data[:member].nil? && data[:webhook_id]
463
+ @webhook_id = Snowflake.new(data[:webhook_id])
464
+ @author = Webhook::Message::Author.new(data[:author])
465
+ elsif data[:guild_id].nil? || data[:guild_id].empty? || data[:member].nil?
466
+ @author = @client.users[data[:author][:id]] || User.new(@client, data[:author])
467
+ else
468
+ @author = guild&.members&.get(data[:author][:id]) || Member.new(@client,
469
+ @guild_id, data[:author], data[:member])
470
+ end
471
+ @content = data[:content]
472
+ @created_at = Time.iso8601(data[:timestamp])
473
+ @updated_at = data[:edited_timestamp].nil? ? nil : Time.iso8601(data[:edited_timestamp])
474
+
475
+ @tts = data[:tts]
476
+ @mention_everyone = data[:mention_everyone]
477
+ @mention_roles = data[:mention_roles].map { |r| guild.roles[r] }
478
+ @attachments = data[:attachments].map { |a| Attachment.from_hash(a) }
479
+ @embeds = data[:embeds] ? data[:embeds].map { |e| Embed.from_hash(e) } : []
480
+ @reactions = data[:reactions] ? data[:reactions].map { |r| Reaction.new(self, r) } : []
481
+ @pinned = data[:pinned]
482
+ @type = self.class.message_type[data[:type]]
483
+ @activity = data[:activity] && Activity.new(data[:activity])
484
+ @application_id = data[:application_id]
485
+ @message_reference = data[:message_reference] && Reference.from_hash(data[:message_reference])
486
+ @flag = Flag.new(0b111 - data[:flags])
487
+ @sticker_items = data[:sticker_items] ? data[:sticker_items].map { |s| Message::Sticker.new(s) } : []
488
+ # @referenced_message = data[:referenced_message] && Message.new(@client, data[:referenced_message])
489
+ @interaction = data[:interaction] && Message::Interaction.new(@client, data[:interaction])
490
+ @thread = data[:thread] && Channel.make_channel(@client, data[:thread])
491
+ @components = data[:components].map { |c| c[:components].map { |co| Component.from_hash(co) } }
492
+ @data.update(data)
493
+ @deleted = false
494
+ end
495
+
448
496
  class << self
449
497
  # @private
450
498
  attr_reader :message_type
@@ -103,54 +103,6 @@ module Discorb
103
103
  end
104
104
  end
105
105
 
106
- private
107
-
108
- def _set_data(data)
109
- @id = Snowflake.new(data[:id])
110
- @channel_id = data[:channel_id]
111
-
112
- if data[:guild_id]
113
- @guild_id = data[:guild_id]
114
- @dm = nil
115
- else
116
- @dm = Discorb::DMChannel.new(@client, data[:channel_id])
117
- @guild_id = nil
118
- end
119
-
120
- if data[:member].nil? && data[:webhook_id]
121
- @webhook_id = Snowflake.new(data[:webhook_id])
122
- @author = Webhook::Message::Author.new(data[:author])
123
- elsif data[:guild_id].nil? || data[:guild_id].empty? || data[:member].nil?
124
- @author = @client.users[data[:author][:id]] || User.new(@client, data[:author])
125
- else
126
- @author = guild&.members&.get(data[:author][:id]) || Member.new(@client,
127
- @guild_id, data[:author], data[:member])
128
- end
129
- @content = data[:content]
130
- @created_at = Time.iso8601(data[:timestamp])
131
- @updated_at = data[:edited_timestamp].nil? ? nil : Time.iso8601(data[:edited_timestamp])
132
-
133
- @tts = data[:tts]
134
- @mention_everyone = data[:mention_everyone]
135
- @mention_roles = data[:mention_roles].map { |r| guild.roles[r] }
136
- @attachments = data[:attachments].map { |a| Attachment.new(a) }
137
- @embeds = data[:embeds] ? data[:embeds].map { |e| Embed.new(data: e) } : []
138
- @reactions = data[:reactions] ? data[:reactions].map { |r| Reaction.new(self, r) } : []
139
- @pinned = data[:pinned]
140
- @type = self.class.message_type[data[:type]]
141
- @activity = data[:activity] && Activity.new(data[:activity])
142
- @application_id = data[:application_id]
143
- @message_reference = data[:message_reference] && Reference.from_hash(data[:message_reference])
144
- @flag = Flag.new(0b111 - data[:flags])
145
- @sticker_items = data[:sticker_items] ? data[:sticker_items].map { |s| Message::Sticker.new(s) } : []
146
- # @referenced_message = data[:referenced_message] && Message.new(@client, data[:referenced_message])
147
- @interaction = data[:interaction] && Message::Interaction.new(@client, data[:interaction])
148
- @thread = data[:thread] && Channel.make_channel(@client, data[:thread])
149
- @components = data[:components].map { |c| c[:components].map { |co| Component.from_hash(co) } }
150
- @data.update(data)
151
- @deleted = false
152
- end
153
-
154
106
  #
155
107
  # Represents a interaction of message.
156
108
  #