discorb 0.14.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build_version.yml +1 -1
  3. data/.github/workflows/lint-push.yml +4 -2
  4. data/.rubocop.yml +6 -2
  5. data/Changelog.md +27 -0
  6. data/Rakefile +6 -0
  7. data/docs/events.md +71 -5
  8. data/docs/faq.md +8 -8
  9. data/examples/simple/rolepanel.rb +1 -1
  10. data/examples/simple/shard.rb +17 -0
  11. data/lib/discorb/allowed_mentions.rb +7 -0
  12. data/lib/discorb/app_command/command.rb +64 -2
  13. data/lib/discorb/app_command/handler.rb +1 -1
  14. data/lib/discorb/application.rb +16 -7
  15. data/lib/discorb/asset.rb +9 -0
  16. data/lib/discorb/{file.rb → attachment.rb} +55 -33
  17. data/lib/discorb/audit_logs.rb +42 -4
  18. data/lib/discorb/channel.rb +47 -12
  19. data/lib/discorb/client.rb +135 -51
  20. data/lib/discorb/common.rb +18 -4
  21. data/lib/discorb/components/button.rb +5 -6
  22. data/lib/discorb/components/select_menu.rb +2 -16
  23. data/lib/discorb/dictionary.rb +2 -0
  24. data/lib/discorb/embed.rb +71 -38
  25. data/lib/discorb/emoji.rb +29 -2
  26. data/lib/discorb/emoji_table.rb +1 -1
  27. data/lib/discorb/error.rb +7 -1
  28. data/lib/discorb/event.rb +27 -17
  29. data/lib/discorb/exe/new.rb +5 -5
  30. data/lib/discorb/exe/run.rb +1 -15
  31. data/lib/discorb/gateway.rb +262 -161
  32. data/lib/discorb/gateway_requests.rb +4 -7
  33. data/lib/discorb/guild.rb +67 -33
  34. data/lib/discorb/guild_template.rb +24 -3
  35. data/lib/discorb/http.rb +25 -3
  36. data/lib/discorb/integration.rb +23 -8
  37. data/lib/discorb/intents.rb +15 -10
  38. data/lib/discorb/interaction/autocomplete.rb +4 -4
  39. data/lib/discorb/interaction/command.rb +34 -5
  40. data/lib/discorb/interaction/components.rb +15 -2
  41. data/lib/discorb/interaction/response.rb +12 -0
  42. data/lib/discorb/interaction/root.rb +16 -1
  43. data/lib/discorb/invite.rb +11 -7
  44. data/lib/discorb/member.rb +21 -0
  45. data/lib/discorb/message.rb +59 -3
  46. data/lib/discorb/message_meta.rb +36 -55
  47. data/lib/discorb/modules.rb +38 -14
  48. data/lib/discorb/permission.rb +14 -5
  49. data/lib/discorb/presence.rb +41 -8
  50. data/lib/discorb/rate_limit.rb +7 -2
  51. data/lib/discorb/reaction.rb +6 -0
  52. data/lib/discorb/role.rb +12 -0
  53. data/lib/discorb/shard.rb +74 -0
  54. data/lib/discorb/sticker.rb +22 -14
  55. data/lib/discorb/user.rb +11 -0
  56. data/lib/discorb/voice_state.rb +20 -2
  57. data/lib/discorb/webhook.rb +53 -2
  58. data/lib/discorb.rb +5 -3
  59. data/sig/discorb.rbs +7234 -6714
  60. metadata +5 -4
  61. data/lib/discorb/log.rb +0 -81
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 810e9b14c77e49e9fca7afc4fe6b98389b26cb17dc1617213f38d7655b990a49
4
- data.tar.gz: bbaa999265ac212f90ab60d57ec772fe7ade0e47f264a136130c679b85a46952
3
+ metadata.gz: 6537aa3c45f64e6b0e8040a5a0d989934fb58d766ee6de305bf04132630a7b94
4
+ data.tar.gz: 68512bc0d2abd0738cc6e81ba2b794feb87480d6d84197a51a6deba739d31d5a
5
5
  SHA512:
6
- metadata.gz: 120828736edcf7eef9d78410914651edeb41ae85eadef012050b105b03c80f07f835d812105d3cfe954c7237e344b3bbc540af8840a7dde1a69f590b008a759e
7
- data.tar.gz: f29b0399c65f180b05bf6c0c3d5f253689ff08c734f60ee7681b57c060d99e36dd85fc275f9652354933478b8139aa76c8ad854f6963fd1c074a8a260ffb6bde
6
+ metadata.gz: 239e4658a2ade0ea8382655970a1eecbb3c62c7c3619e3de8fdf932c1c0a4053e35b722bef5dcdbd67477754388cc3c157c9be6360ef7625fe9f84504b5ecf90
7
+ data.tar.gz: d830a06c7a505ee31aeb3242e7aa59dadf6abab24a26c357b9e29e5f94d5fef7a889b114d4b7793ffda3f50b19a6be0c3f87921934393b03e71c5f50bfa96de4
@@ -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/.rubocop.yml CHANGED
@@ -10,10 +10,14 @@ Metrics:
10
10
  Enabled: false
11
11
 
12
12
  Style/TrailingCommaInHashLiteral: # Disabled for rufo
13
- Enabled: false
13
+ EnforcedStyleForMultiline: consistent_comma
14
+
15
+ Style/TrailingCommaInArrayLiteral: # Disabled for rufo
16
+ EnforcedStyleForMultiline: consistent_comma
14
17
 
15
18
  Style/StringLiterals: # Disabled for rufo
16
- Enabled: false
19
+ Enabled: true
20
+ EnforcedStyle: double_quotes
17
21
 
18
22
  Style/TrailingCommaInArguments: # Disabled for rufo
19
23
  Enabled: false
data/Changelog.md CHANGED
@@ -4,6 +4,33 @@
4
4
 
5
5
  # Changelog
6
6
 
7
+ ## v0.16
8
+
9
+ ### v0.16.0
10
+
11
+ - Change!: Use built-in Logger instead of custom Logger.
12
+ - Delete!: `--log-level`, `--[no-]log-color` is deleted.
13
+ - Add: Support sharding
14
+ - Add: Use Mutex for preventing connection duplications.
15
+
16
+ ## v0.15
17
+
18
+ ### v0.15.1
19
+
20
+ - Add: Add `Member#can_manage?`
21
+ - Add: Add `Discorb::VERSION_ARRAY`
22
+ - Fix: `Snowflake#timestamp` includes milliseconds now
23
+ - Fix: `TextChannel#create_invite` will no longer return `ArgumentError`
24
+ - Fix: Connection will not closed with 4001 when `Client#update_presence`
25
+ is called
26
+
27
+ ### v0.15.0
28
+
29
+ - Add: Migrate to API v10
30
+ - Add: Add `TextChannel#threads`
31
+ - Add: Support editing attachments
32
+ - Delete!: Delete File class - Use Attachment class instead
33
+
7
34
  ## v0.14
8
35
 
9
36
  ### v0.14.0
data/Rakefile CHANGED
@@ -320,6 +320,12 @@ end
320
320
 
321
321
  task document: %i[document:yard document:replace]
322
322
 
323
+ desc "Lint code with rubocop"
323
324
  task :lint do
324
325
  sh "rubocop lib"
325
326
  end
327
+
328
+ desc "Autofix code with rubocop"
329
+ task "lint:fix" do
330
+ sh "rubocop lib -A"
331
+ end
data/docs/events.md CHANGED
@@ -30,13 +30,13 @@ class << client
30
30
  end
31
31
  ```
32
32
 
33
- If you want to seperate event handlers from the client, consider using {Discorb::Extension}. {file:docs/extension.md Learn more about extensions}.
33
+ If you want to separate event handlers from the client, consider using {Discorb::Extension}. {file:docs/extension.md Learn more about extensions}.
34
34
 
35
- Since v0.6.1, you can set `:override` to `true` to register overridable event handlers.
35
+ Since v0.6.1, you can set `:override` to `true` to register event handlers that can be overridden.
36
36
 
37
37
  ```ruby
38
38
  client.on :message, override: true do |event|
39
- puts "This event handler is overrideable!"
39
+ puts "This event handler can be overridden."
40
40
  end
41
41
 
42
42
  client.on :message do |event|
@@ -44,8 +44,8 @@ client.on :message do |event|
44
44
  end
45
45
  ```
46
46
 
47
- This example will print `Override!`, but not `This event handler is overrideable!`.
48
- This is useful for registering event handlers as default behaviour, such as error handlers.
47
+ This example will print `Override!`, but not `This event handler can be overridden.`.
48
+ This is useful for registering event handlers as default behavior, such as error handlers.
49
49
 
50
50
  ```ruby
51
51
  # In the library...
@@ -95,6 +95,22 @@ Defaults to printing the error to stderr, override to handle it yourself.
95
95
  Fires when `discorb setup` is run.
96
96
  This is useful for setting up some dependencies, such as the database.
97
97
 
98
+ #### `shard_standby(shard)`
99
+
100
+ Fires when a shard is standby.
101
+
102
+ | Parameter | Type | Description |
103
+ | ---------- | ----- | ----------- |
104
+ |`shard` | {Discorb::Shard} | The shard that is standby. |
105
+
106
+ #### `shard_resumed(shard)`
107
+
108
+ Fires when a shard is resumed connection.
109
+
110
+ | Parameter | Type | Description |
111
+ | ---------- | ----- | ----------- |
112
+ |`shard` | {Discorb::Shard} | The shard that is standby. |
113
+
98
114
  ### Guild events
99
115
 
100
116
  #### `guild_join(guild)`
@@ -487,6 +503,46 @@ Fires when an invitation is deleted.
487
503
 
488
504
  ### Interaction events
489
505
 
506
+ #### `interaction_create(interaction)`
507
+
508
+ Fires when an interaction is created. This will fire for all interactions.
509
+
510
+ | Parameter | Type | Description |
511
+ | ---------- | ----- | ----------- |
512
+ | `interaction` | {Discorb::Interaction}| The created interaction. |
513
+
514
+ #### `application_command(interaction)`
515
+
516
+ Fires when an application command is used.
517
+
518
+ | Parameter | Type | Description |
519
+ | ---------- | ----- | ----------- |
520
+ | `interaction` | {Discorb::CommandInteraction}| The created interaction. |
521
+
522
+ #### `slash_command(interaction)`
523
+
524
+ Fires when a slash command is used.
525
+
526
+ | Parameter | Type | Description |
527
+ | ---------- | ----- | ----------- |
528
+ | `interaction` | {Discorb::CommandInteraction::SlashCommand}| The created interaction. |
529
+
530
+ #### `message_command(interaction)`
531
+
532
+ Fires when a message command is used.
533
+
534
+ | Parameter | Type | Description |
535
+ | ---------- | ----- | ----------- |
536
+ | `interaction` | {Discorb::CommandInteraction::MessageMenuCommand}| The created interaction. |
537
+
538
+ #### `user_command(interaction)`
539
+
540
+ Fires when a user command is used.
541
+
542
+ | Parameter | Type | Description |
543
+ | ---------- | ----- | ----------- |
544
+ | `interaction` | {Discorb::CommandInteraction::UserMenuCommand}| The created interaction. |
545
+
490
546
  #### `button_click(interaction)`
491
547
 
492
548
  Fires when a button is clicked.
@@ -503,6 +559,16 @@ Fires when a select menu is selected.
503
559
  | ---------- | ----- | ----------- |
504
560
  |`interaction`| {Discorb::MessageComponentInteraction::SelectMenu}| The interaction object. |
505
561
 
562
+ #### `form_submit(interaction)`
563
+
564
+ Fires when a form is submitted.
565
+
566
+ | Parameter | Type | Description |
567
+ | ---------- | ----- | ----------- |
568
+ | `interaction` | {Discorb::ModalInteraction} | The interaction object. |
569
+
570
+ #### `slash_command
571
+
506
572
  ### Voice events
507
573
 
508
574
  Because it's big, it's documented in {file:docs/voice_events.md}.
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?
@@ -2,7 +2,7 @@
2
2
  require "discorb"
3
3
  intents = Discorb::Intents.new
4
4
  intents.members = true
5
- client = Discorb::Client.new(intents: intents, log: $stdout, colorize_log: true)
5
+ client = Discorb::Client.new(intents: intents)
6
6
 
7
7
  def convert_role(guild, string)
8
8
  guild.roles.find do |role|
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ require "discorb"
3
+
4
+ client = Discorb::Client.new(log: Logger.new($stdout))
5
+
6
+ client.once :standby do
7
+ puts "Logged in as #{client.user}"
8
+ end
9
+
10
+ client.on :message do |message|
11
+ next if message.author.bot?
12
+ next unless message.content == "!inspect"
13
+
14
+ message.channel.post("I'm #{client.user}, running on shard #{client.shard_id}!")
15
+ end
16
+
17
+ client.run(ENV["DISCORD_BOT_TOKEN"], shards: [0, 1], shard_count: 2)
@@ -32,7 +32,14 @@ module Discorb
32
32
  "#<#{self.class} @everyone=#{@everyone} @roles=#{@roles} @users=#{@users} @replied_user=#{@replied_user}>"
33
33
  end
34
34
 
35
+ #
36
+ # Converts the object to a hash.
35
37
  # @private
38
+ #
39
+ # @param [Discorb::AllowedMentions, nil] other The object to merge.
40
+ #
41
+ # @return [Hash] The hash.
42
+ #
36
43
  def to_hash(other = nil)
37
44
  payload = {
38
45
  parse: %w[everyone roles users],
@@ -23,24 +23,39 @@ module Discorb
23
23
  # @return [Discorb::Dictionary{Discorb::Snowflake, :global => Discorb::Snowflake}] The ID mapping.
24
24
  attr_reader :id_map
25
25
 
26
- @types = {
26
+ # @private
27
+ # @return [{Integer => Symbol}] The mapping of raw types to types.
28
+ TYPES = {
27
29
  1 => :chat_input,
28
30
  2 => :user,
29
31
  3 => :message,
30
32
  }.freeze
31
33
 
34
+ #
35
+ # Initialize a new command.
32
36
  # @private
37
+ #
38
+ # @param [String] name The name of the command.
39
+ # @param [Array<#to_s>] guild_ids The guild ids that the command is enabled in.
40
+ # @param [Proc] block The block of the command.
41
+ # @param [:chat_input, :user, :message] type The type of the command.
42
+ #
33
43
  def initialize(name, guild_ids, block, type)
34
44
  @name = name
35
45
  @guild_ids = guild_ids&.map(&:to_s)
36
46
  @block = block
37
47
  @raw_type = type
38
- @type = Discorb::ApplicationCommand::Command.types[type]
48
+ @type = Discorb::ApplicationCommand::Command::TYPES[type]
39
49
  @type_raw = type
40
50
  @id_map = Discorb::Dictionary.new
41
51
  end
42
52
 
53
+ #
54
+ # Changes the self pointer to the given object.
43
55
  # @private
56
+ #
57
+ # @param [Object] instance The object to change the self pointer to.
58
+ #
44
59
  def replace_block(instance)
45
60
  current_block = @block.dup
46
61
  @block = proc do |*args|
@@ -48,7 +63,12 @@ module Discorb
48
63
  end
49
64
  end
50
65
 
66
+ #
67
+ # Converts the object to a hash.
51
68
  # @private
69
+ #
70
+ # @return [Hash] The hash represents the object.
71
+ #
52
72
  def to_hash
53
73
  {
54
74
  name: @name,
@@ -66,7 +86,18 @@ module Discorb
66
86
  # @return [Hash{String => Hash}] The options of the command.
67
87
  attr_reader :options
68
88
 
89
+ #
90
+ # Initialize a new slash command.
69
91
  # @private
92
+ #
93
+ # @param [String] name The name of the command.
94
+ # @param [String] description The description of the command.
95
+ # @param [Hash{String => Hash}] options The options of the command.
96
+ # @param [Array<#to_s>] guild_ids The guild ids that the command is enabled in.
97
+ # @param [Proc] block The block of the command.
98
+ # @param [:chat_input, :user, :message] type The type of the command.
99
+ # @param [Discorb::ApplicationCommand::Command, nil] parent The parent command.
100
+ #
70
101
  def initialize(name, description, options, guild_ids, block, type, parent)
71
102
  super(name, guild_ids, block, type)
72
103
  @description = description
@@ -85,7 +116,12 @@ module Discorb
85
116
  (@parent + " " + @name).strip
86
117
  end
87
118
 
119
+ #
120
+ # Converts the object to a hash.
88
121
  # @private
122
+ #
123
+ # @return [Hash] The hash represents the object.
124
+ #
89
125
  def to_hash
90
126
  options_payload = options.map do |name, value|
91
127
  ret = {
@@ -145,7 +181,16 @@ module Discorb
145
181
  # @return [String] The description of the command.
146
182
  attr_reader :description
147
183
 
184
+ #
185
+ # Initialize a new group command.
148
186
  # @private
187
+ #
188
+ # @param [String] name The name of the command.
189
+ # @param [String] description The description of the command.
190
+ # @param [Array<#to_s>] guild_ids The guild ids that the command is enabled in.
191
+ # @param [:chat_input, :user, :message] type The type of the command.
192
+ # @param [Discorb::Client] client The client of the command.
193
+ #
149
194
  def initialize(name, description, guild_ids, type, client)
150
195
  super(name, guild_ids, block, type)
151
196
  @description = description
@@ -196,13 +241,23 @@ module Discorb
196
241
  @name
197
242
  end
198
243
 
244
+ #
245
+ # Changes the self pointer to the given object.
199
246
  # @private
247
+ #
248
+ # @param [Object] instance The object to change to.
249
+ #
200
250
  def block_replace(instance)
201
251
  super
202
252
  @commands.each { |c| c.replace_block(instance) }
203
253
  end
204
254
 
255
+ #
256
+ # Converts the object to a hash.
205
257
  # @private
258
+ #
259
+ # @return [Hash] The hash represents the object.
260
+ #
206
261
  def to_hash
207
262
  options_payload = @commands.map do |command|
208
263
  if command.is_a?(SlashCommand)
@@ -240,7 +295,14 @@ module Discorb
240
295
  # @return [Array<Discorb::ApplicationCommand::Command::SlashCommand>] The subcommands of the command.
241
296
  attr_reader :commands
242
297
 
298
+ #
299
+ # Initialize a new subcommand group.
243
300
  # @private
301
+ #
302
+ # @param [String] name The name of the command.
303
+ # @param [String] description The description of the command.
304
+ # @param [Discorb::ApplicationCommand::Command::GroupCommand] parent The parent command.
305
+ # @param [Discorb::Client] client The client.
244
306
  def initialize(name, description, parent, client)
245
307
  super(name, description, [], 1, client)
246
308
 
@@ -160,7 +160,7 @@ module Discorb
160
160
  end
161
161
  end
162
162
  end
163
- @log.info "Successfully setup commands"
163
+ @logger.info "Successfully setup commands"
164
164
  end
165
165
  end
166
166
  end
@@ -29,7 +29,13 @@ module Discorb
29
29
  alias bot_require_code_grant? bot_require_code_grant
30
30
  # @return [Discorb::Application::Flag] The application's flags.
31
31
  attr_reader :flags
32
+ #
33
+ # Initializes a new instance of the Application class.
32
34
  # @private
35
+ #
36
+ # @param [Discorb::Client] client The client that instantiated the object.
37
+ # @param [Hash] data The data of the object.
38
+ #
33
39
  def initialize(client, data)
34
40
  @client = client
35
41
  @data = data
@@ -97,7 +103,13 @@ module Discorb
97
103
  # @return [Discorb::Application::Team::Member] The team's member.
98
104
  attr_reader :members
99
105
 
106
+ #
107
+ # Initializes a new instance of the Team class.
100
108
  # @private
109
+ #
110
+ # @param [Discorb::Client] client The client that instantiated the object.
111
+ # @param [Hash] data The data of the object.
112
+ #
101
113
  def initialize(client, data)
102
114
  @client = client
103
115
  @id = Snowflake.new(data[:id])
@@ -142,7 +154,9 @@ module Discorb
142
154
  # @!attribute [r] owner?
143
155
  # @return [Boolean] Whether the member is the team's owner.
144
156
 
145
- @membership_state = {
157
+ # @private
158
+ # @return [{Integer => Symbol}] The permission map.
159
+ MEMBERSHIP_STATE = {
146
160
  1 => :invited,
147
161
  2 => :accepted,
148
162
  }.freeze
@@ -153,7 +167,7 @@ module Discorb
153
167
  @team = team
154
168
  @user = client.users[data[:user][:id]] || User.new(client, data[:user])
155
169
  @team_id = Snowflake.new(data[:team_id])
156
- @membership_state = self.class.membership_state[data[:membership_state]]
170
+ @membership_state = MEMBERSHIP_STATE[data[:membership_state]]
157
171
  @permissions = data[:permissions].map(&:to_sym)
158
172
  end
159
173
 
@@ -176,11 +190,6 @@ module Discorb
176
190
  def ==(other)
177
191
  super || @user == other
178
192
  end
179
-
180
- class << self
181
- # @private
182
- attr_reader :membership_state
183
- end
184
193
  end
185
194
  end
186
195
  end
data/lib/discorb/asset.rb CHANGED
@@ -11,7 +11,13 @@ module Discorb
11
11
  # @!attribute [r] animated?
12
12
  # @return [Boolean] Whether the asset is animated.
13
13
 
14
+ #
15
+ # Initialize a new instance of the Asset class.
14
16
  # @private
17
+ #
18
+ # @param [Discorb::Client] client The client that instantiated the object.
19
+ # @param [Hash] data The data of the object.
20
+ #
15
21
  def initialize(target, hash, path: nil)
16
22
  @hash = hash
17
23
  @target = target
@@ -63,7 +69,10 @@ module Discorb
63
69
  # @!attribute [r] animated?
64
70
  # @return [false] For compatibility with {Asset}, always `false`.
65
71
 
72
+ #
73
+ # Initialize a new instance of the DefaultAvatar class.
66
74
  # @private
75
+ #
67
76
  def initialize(discriminator)
68
77
  @discriminator = discriminator.to_s.rjust(4, "0")
69
78
  end
@@ -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,44 @@ 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
+ # @return [Boolean] Whether the attachment will be closed after it is sent.
37
+ attr_reader :will_close
31
38
 
32
39
  # @!attribute [r] image?
33
40
  # @return [Boolean] whether the file is an image.
34
41
 
42
+ #
43
+ # Creates a new attachment.
44
+ #
45
+ # @param [#read, String] source The Source of the attachment.
46
+ # @param [String] filename The filename of the attachment. If not set, path or object_id of the IO is used.
47
+ # @param [String] description The description of the attachment.
48
+ # @param [String] content_type The content type of the attachment. If not set, it is guessed from the filename.
49
+ # If failed to guess, it is set to `application/octet-stream`.
50
+ # @param [Boolean] will_close Whether the IO will be closed after the attachment is sent.
51
+ #
52
+ def initialize(source, filename = nil, description: nil, content_type: nil, will_close: true)
53
+ @io = if source.respond_to?(:read)
54
+ source
55
+ else
56
+ File.open(source, "rb")
57
+ end
58
+ @filename = filename || (@io.respond_to?(:path) ? @io.path : @io.object_id)
59
+ @description = description
60
+ @content_type = content_type || MIME::Types.type_for(@filename.to_s)[0].to_s
61
+ @content_type = "application/octet-stream" if @content_type == ""
62
+ @will_close = will_close
63
+ @created_by = :client
64
+ end
65
+
66
+ #
67
+ # Initializes the object from a hash.
35
68
  # @private
36
- def initialize(data)
69
+ #
70
+ def initialize_hash(data)
37
71
  @id = Snowflake.new(data[:id])
38
72
  @filename = data[:filename]
39
73
  @content_type = data[:content_type]
@@ -42,37 +76,29 @@ module Discorb
42
76
  @proxy_url = data[:proxy_url]
43
77
  @height = data[:height]
44
78
  @width = data[:width]
79
+ @created_by = :discord
45
80
  end
46
81
 
47
82
  def image?
48
83
  @content_type.start_with? "image/"
49
84
  end
50
- end
51
85
 
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
86
+ def inspect
87
+ if @created_by == :discord
88
+ "<#{self.class} #{@id}: #{@filename}>"
89
+ else
90
+ "<#{self.class} #{io.fileno}: #{@filename}>"
91
+ end
92
+ end
62
93
 
63
94
  #
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`.
95
+ # Creates a new file from a hash.
96
+ # @private
70
97
  #
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 == ""
98
+ def self.from_hash(data)
99
+ inst = allocate
100
+ inst.initialize_hash(data)
101
+ inst
76
102
  end
77
103
 
78
104
  #
@@ -82,16 +108,12 @@ module Discorb
82
108
  # @param [String] filename The filename of the file. object_id of the string is used if not set.
83
109
  # @param [String] content_type The content type of the file. If not set, it is guessed from the filename.
84
110
  #
85
- # @return [File] The new file.
111
+ # @return [Discorb::Attachment] The new file.
86
112
  #
87
- def self.from_string(string, filename: nil, content_type: nil)
113
+ def self.from_string(string, filename = nil, content_type: nil, description: nil)
88
114
  io = StringIO.new(string)
89
115
  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}>"
116
+ new(io, filename, content_type: content_type, description: description, will_close: true)
95
117
  end
96
118
  end
97
119
  end