discordrb-webhooks 3.4.3 → 3.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79b0d69e96092e442b9602a6dd69088579af024ec84480209754831dcd0e39f8
4
- data.tar.gz: 17ddc58683c197db7bb8afc5153e3587bef92652eecb9a2430d7101356f730a4
3
+ metadata.gz: ac23678014708b3612c2b64182fc560e28fffaff546fe32068b6c80f92241a49
4
+ data.tar.gz: 1af3c1de510f8262df3074bbcb28af659ad233c0447feab33709ccafbb99bf9b
5
5
  SHA512:
6
- metadata.gz: 79f43ebe587deac54faf3745839fd0a39e13c62d9f8f00bcffb6f6aa23234d0fcec7b3b7be2d116cf4cb351d208837c8955b1d79e0382a1d42f94e3489c8c35f
7
- data.tar.gz: c697972d1a676d5f704f7d1b3f4160daeb1e0d72ee8841122e974b30f85ce63176195ef4fbf4258c6eb1f0be5b39bfe6c84effa9ba8bab3ad82f4d4fc5680805
6
+ metadata.gz: eb90480b721262fe38147e7f117ebd102ab05f9dc5435ef4fdf2263c0c4bb9b0886077f10ebb8f4b73db57e8cd751bad1e97f90917c5c3f4ad9b6714fd92212b
7
+ data.tar.gz: '0678b594744221149421bb72ed219ee9b916aca0e2ad58f4f7002fc94627d3d9aed6bcbaaca73cf8116eed7a0b7a5a5dd3f0c8a71cf5183a256d6af6471fe61d'
@@ -5,13 +5,14 @@ require 'discordrb/webhooks/embeds'
5
5
  module Discordrb::Webhooks
6
6
  # A class that acts as a builder for a webhook message object.
7
7
  class Builder
8
- def initialize(content: '', username: nil, avatar_url: nil, tts: false, file: nil, embeds: [])
8
+ def initialize(content: '', username: nil, avatar_url: nil, tts: false, file: nil, embeds: [], allowed_mentions: nil)
9
9
  @content = content
10
10
  @username = username
11
11
  @avatar_url = avatar_url
12
12
  @tts = tts
13
13
  @file = file
14
14
  @embeds = embeds
15
+ @allowed_mentions = allowed_mentions
15
16
  end
16
17
 
17
18
  # The content of the message. May be 2000 characters long at most.
@@ -70,6 +71,10 @@ module Discordrb::Webhooks
70
71
  # @return [Array<Embed>] the embeds attached to this message.
71
72
  attr_reader :embeds
72
73
 
74
+ # @return [Discordrb::AllowedMentions, Hash] Mentions that are allowed to ping in this message.
75
+ # @see https://discord.com/developers/docs/resources/channel#allowed-mentions-object
76
+ attr_accessor :allowed_mentions
77
+
73
78
  # @return [Hash] a hash representation of the created message, for JSON format.
74
79
  def to_json_hash
75
80
  {
@@ -77,7 +82,8 @@ module Discordrb::Webhooks
77
82
  username: @username,
78
83
  avatar_url: @avatar_url,
79
84
  tts: @tts,
80
- embeds: @embeds.map(&:to_hash)
85
+ embeds: @embeds.map(&:to_hash),
86
+ allowed_mentions: @allowed_mentions&.to_hash
81
87
  }
82
88
  end
83
89
 
@@ -88,7 +94,8 @@ module Discordrb::Webhooks
88
94
  username: @username,
89
95
  avatar_url: @avatar_url,
90
96
  tts: @tts,
91
- file: @file
97
+ file: @file,
98
+ allowed_mentions: @allowed_mentions&.to_hash
92
99
  }
93
100
  end
94
101
  end
@@ -38,33 +38,97 @@ module Discordrb::Webhooks
38
38
  # end
39
39
  # end
40
40
  # @return [RestClient::Response] the response returned by Discord.
41
- def execute(builder = nil, wait = false)
41
+ def execute(builder = nil, wait = false, components = nil)
42
42
  raise TypeError, 'builder needs to be nil or like a Discordrb::Webhooks::Builder!' unless
43
- builder.respond_to?(:file) && builder.respond_to?(:to_multipart_hash) || builder.respond_to?(:to_json_hash) || builder.nil?
43
+ (builder.respond_to?(:file) && builder.respond_to?(:to_multipart_hash)) || builder.respond_to?(:to_json_hash) || builder.nil?
44
44
 
45
45
  builder ||= Builder.new
46
+ view = View.new
46
47
 
47
- yield builder if block_given?
48
+ yield(builder, view) if block_given?
49
+
50
+ components ||= view
48
51
 
49
52
  if builder.file
50
- post_multipart(builder, wait)
53
+ post_multipart(builder, components, wait)
51
54
  else
52
- post_json(builder, wait)
55
+ post_json(builder, components, wait)
53
56
  end
54
57
  end
55
58
 
59
+ # Modify this webhook's properties.
60
+ # @param name [String, nil] The default name.
61
+ # @param avatar [String, #read, nil] The new avatar, in base64-encoded JPG format.
62
+ # @param channel_id [String, Integer, nil] The channel to move the webhook to.
63
+ # @return [RestClient::Response] the response returned by Discord.
64
+ def modify(name: nil, avatar: nil, channel_id: nil)
65
+ RestClient.patch(@url, { name: name, avatar: avatarise(avatar), channel_id: channel_id }.compact.to_json, content_type: :json)
66
+ end
67
+
68
+ # Delete this webhook.
69
+ # @param reason [String, nil] The reason this webhook was deleted.
70
+ # @return [RestClient::Response] the response returned by Discord.
71
+ # @note This is permanent and cannot be undone.
72
+ def delete(reason: nil)
73
+ RestClient.delete(@url, 'X-Audit-Log-Reason': reason)
74
+ end
75
+
76
+ # Edit a message from this webhook.
77
+ # @param message_id [String, Integer] The ID of the message to edit.
78
+ # @param builder [Builder, nil] The builder to start out with, or nil if one should be created anew.
79
+ # @param content [String] The message content.
80
+ # @param embeds [Array<Embed, Hash>]
81
+ # @param allowed_mentions [Hash]
82
+ # @return [RestClient::Response] the response returned by Discord.
83
+ # @example Edit message content
84
+ # client.edit_message(message_id, content: 'goodbye world!')
85
+ # @example Edit a message via builder
86
+ # client.edit_message(message_id) do |builder|
87
+ # builder.add_embed do |e|
88
+ # e.description = 'Hello World!'
89
+ # end
90
+ # end
91
+ # @note Not all builder options are available when editing.
92
+ def edit_message(message_id, builder: nil, content: nil, embeds: nil, allowed_mentions: nil)
93
+ builder ||= Builder.new
94
+
95
+ yield builder if block_given?
96
+
97
+ data = builder.to_json_hash.merge({ content: content, embeds: embeds, allowed_mentions: allowed_mentions }.compact)
98
+ RestClient.patch("#{@url}/messages/#{message_id}", data.compact.to_json, content_type: :json)
99
+ end
100
+
101
+ # Delete a message created by this webhook.
102
+ # @param message_id [String, Integer] The ID of the message to delete.
103
+ # @return [RestClient::Response] the response returned by Discord.
104
+ def delete_message(message_id)
105
+ RestClient.delete("#{@url}/messages/#{message_id}")
106
+ end
107
+
56
108
  private
57
109
 
58
- def post_json(builder, wait)
59
- RestClient.post(@url + (wait ? '?wait=true' : ''), builder.to_json_hash.to_json, content_type: :json)
110
+ # Convert an avatar to API ready data.
111
+ # @param avatar [String, #read] Avatar data.
112
+ def avatarise(avatar)
113
+ if avatar.respond_to? :read
114
+ "data:image/jpg;base64,#{Base64.strict_encode64(avatar.read)}"
115
+ else
116
+ avatar
117
+ end
118
+ end
119
+
120
+ def post_json(builder, components, wait)
121
+ data = builder.to_json_hash.merge({ components: components.to_a })
122
+ RestClient.post(@url + (wait ? '?wait=true' : ''), data.to_json, content_type: :json)
60
123
  end
61
124
 
62
- def post_multipart(builder, wait)
63
- RestClient.post(@url + (wait ? '?wait=true' : ''), builder.to_multipart_hash)
125
+ def post_multipart(builder, components, wait)
126
+ data = builder.to_multipart_hash.merge({ components: components.to_a })
127
+ RestClient.post(@url + (wait ? '?wait=true' : ''), data)
64
128
  end
65
129
 
66
130
  def generate_url(id, token)
67
- "https://discord.com/api/v6/webhooks/#{id}/#{token}"
131
+ "https://discord.com/api/v8/webhooks/#{id}/#{token}"
68
132
  end
69
133
  end
70
134
  end
@@ -51,7 +51,7 @@ module Discordrb::Webhooks
51
51
  elsif value.is_a? Array
52
52
  raise ArgumentError, 'Colour tuple must have three values!' if value.length != 3
53
53
 
54
- self.colour = value[0] << 16 | value[1] << 8 | value[2]
54
+ self.colour = (value[0] << 16) | (value[1] << 8) | value[2]
55
55
  else
56
56
  self.colour = value.to_i
57
57
  end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Modal component builder.
4
+ class Discordrb::Webhooks::Modal
5
+ # A mapping of names to types of components usable in a modal.
6
+ COMPONENT_TYPES = {
7
+ action_row: 1,
8
+ text_input: 4
9
+ }.freeze
10
+
11
+ # This builder is used when constructing an ActionRow. All current components must be within an action row, but this can
12
+ # change in the future. A message can have 5 action rows, each action row can hold a weight of 5. Buttons have a weight of 1,
13
+ # and dropdowns have a weight of 5.
14
+ class RowBuilder
15
+ # A mapping of short names to types of input styles. `short` is a single line where `paragraph` is a block.
16
+ TEXT_INPUT_STYLES = {
17
+ short: 1,
18
+ paragraph: 2
19
+ }.freeze
20
+
21
+ # @!visibility private
22
+ def initialize
23
+ @components = []
24
+ end
25
+
26
+ # Add a text input to this action row.
27
+ # @param style [Symbol, Integer] The text input's style type. See {TEXT_INPUT_STYLES}
28
+ # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions.
29
+ # There is a limit of 100 characters to each custom_id.
30
+ # @param label [String, nil] The text label for the field.
31
+ # @param min_length [Integer, nil] The minimum input length for a text input, min 0, max 4000.
32
+ # @param max_length [Integer, nil] The maximum input length for a text input, min 1, max 4000.
33
+ # @param required [true, false, nil] Whether this component is required to be filled, default true.
34
+ # @param value [String, nil] A pre-filled value for this component, max 4000 characters.
35
+ # @param placeholder [String, nil] Custom placeholder text if the input is empty, max 100 characters
36
+ def text_input(style:, custom_id:, label: nil, min_length: nil, max_length: nil, required: nil, value: nil, placeholder: nil)
37
+ style = TEXT_INPUT_STYLES[style] || style
38
+
39
+ @components << {
40
+ style: style,
41
+ custom_id: custom_id,
42
+ type: COMPONENT_TYPES[:text_input],
43
+ label: label,
44
+ min_length: min_length,
45
+ max_length: max_length,
46
+ required: required,
47
+ value: value,
48
+ placeholder: placeholder
49
+ }
50
+ end
51
+
52
+ # @!visibility private
53
+ def to_h
54
+ { type: COMPONENT_TYPES[:action_row], components: @components }
55
+ end
56
+ end
57
+
58
+ attr_reader :rows
59
+
60
+ def initialize
61
+ @rows = []
62
+
63
+ yield self if block_given?
64
+ end
65
+
66
+ # Add a new ActionRow to the view
67
+ # @yieldparam [RowBuilder]
68
+ def row
69
+ new_row = RowBuilder.new
70
+
71
+ yield new_row
72
+
73
+ @rows << new_row
74
+ end
75
+
76
+ # @!visibility private
77
+ def to_a
78
+ @rows.map(&:to_h)
79
+ end
80
+ end
@@ -4,6 +4,6 @@
4
4
  module Discordrb
5
5
  module Webhooks
6
6
  # The current version of discordrb-webhooks.
7
- VERSION = '3.4.3'
7
+ VERSION = '3.5.0'
8
8
  end
9
9
  end
@@ -0,0 +1,194 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A reusable view representing a component collection, with builder methods.
4
+ class Discordrb::Webhooks::View
5
+ # Possible button style names and values.
6
+ BUTTON_STYLES = {
7
+ primary: 1,
8
+ secondary: 2,
9
+ success: 3,
10
+ danger: 4,
11
+ link: 5
12
+ }.freeze
13
+
14
+ # Component types.
15
+ # @see https://discord.com/developers/docs/interactions/message-components#component-types
16
+ COMPONENT_TYPES = {
17
+ action_row: 1,
18
+ button: 2,
19
+ string_select: 3,
20
+ # text_input: 4, # (defined in modal.rb)
21
+ user_select: 5,
22
+ role_select: 6,
23
+ mentionable_select: 7,
24
+ channel_select: 8
25
+ }.freeze
26
+
27
+ # This builder is used when constructing an ActionRow. All current components must be within an action row, but this can
28
+ # change in the future. A message can have 5 action rows, each action row can hold a weight of 5. Buttons have a weight of 1,
29
+ # and dropdowns have a weight of 5.
30
+ class RowBuilder
31
+ # @!visibility private
32
+ def initialize
33
+ @components = []
34
+ end
35
+
36
+ # Add a button to this action row.
37
+ # @param style [Symbol, Integer] The button's style type. See {BUTTON_STYLES}
38
+ # @param label [String, nil] The text label for the button. Either a label or emoji must be provided.
39
+ # @param emoji [#to_h, String, Integer] An emoji ID, or unicode emoji to attach to the button. Can also be a object
40
+ # that responds to `#to_h` which returns a hash in the format of `{ id: Integer, name: string }`.
41
+ # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions.
42
+ # There is a limit of 100 characters to each custom_id.
43
+ # @param disabled [true, false] Whether this button is disabled and shown as greyed out.
44
+ # @param url [String, nil] The URL, when using a link style button.
45
+ def button(style:, label: nil, emoji: nil, custom_id: nil, disabled: nil, url: nil)
46
+ style = BUTTON_STYLES[style] || style
47
+
48
+ emoji = case emoji
49
+ when Integer, String
50
+ emoji.to_i.positive? ? { id: emoji } : { name: emoji }
51
+ else
52
+ emoji.to_h
53
+ end
54
+
55
+ @components << { type: COMPONENT_TYPES[:button], label: label, emoji: emoji, style: style, custom_id: custom_id, disabled: disabled, url: url }
56
+ end
57
+
58
+ # Add a select string to this action row.
59
+ # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions.
60
+ # There is a limit of 100 characters to each custom_id.
61
+ # @param options [Array<Hash>] Options that can be selected in this menu. Can also be provided via the yielded builder.
62
+ # @param placeholder [String, nil] Default text to show when no entries are selected.
63
+ # @param min_values [Integer, nil] The minimum amount of values a user must select.
64
+ # @param max_values [Integer, nil] The maximum amount of values a user can select.
65
+ # @param disabled [true, false, nil] Grey out the component to make it unusable.
66
+ # @yieldparam builder [SelectMenuBuilder]
67
+ def string_select(custom_id:, options: [], placeholder: nil, min_values: nil, max_values: nil, disabled: nil)
68
+ builder = SelectMenuBuilder.new(custom_id, options, placeholder, min_values, max_values, disabled, select_type: :string_select)
69
+
70
+ yield builder if block_given?
71
+
72
+ @components << builder.to_h
73
+ end
74
+
75
+ alias_method :select_menu, :string_select
76
+
77
+ # Add a select user to this action row.
78
+ # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions.
79
+ # There is a limit of 100 characters to each custom_id.
80
+ # @param placeholder [String, nil] Default text to show when no entries are selected.
81
+ # @param min_values [Integer, nil] The minimum amount of values a user must select.
82
+ # @param max_values [Integer, nil] The maximum amount of values a user can select.
83
+ # @param disabled [true, false, nil] Grey out the component to make it unusable.
84
+ def user_select(custom_id:, placeholder: nil, min_values: nil, max_values: nil, disabled: nil)
85
+ @components << SelectMenuBuilder.new(custom_id, [], placeholder, min_values, max_values, disabled, select_type: :user_select).to_h
86
+ end
87
+
88
+ # Add a select role to this action row.
89
+ # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions.
90
+ # There is a limit of 100 characters to each custom_id.
91
+ # @param placeholder [String, nil] Default text to show when no entries are selected.
92
+ # @param min_values [Integer, nil] The minimum amount of values a user must select.
93
+ # @param max_values [Integer, nil] The maximum amount of values a user can select.
94
+ # @param disabled [true, false, nil] Grey out the component to make it unusable.
95
+ def role_select(custom_id:, placeholder: nil, min_values: nil, max_values: nil, disabled: nil)
96
+ @components << SelectMenuBuilder.new(custom_id, [], placeholder, min_values, max_values, disabled, select_type: :role_select).to_h
97
+ end
98
+
99
+ # Add a select mentionable to this action row.
100
+ # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions.
101
+ # There is a limit of 100 characters to each custom_id.
102
+ # @param placeholder [String, nil] Default text to show when no entries are selected.
103
+ # @param min_values [Integer, nil] The minimum amount of values a user must select.
104
+ # @param max_values [Integer, nil] The maximum amount of values a user can select.
105
+ # @param disabled [true, false, nil] Grey out the component to make it unusable.
106
+ def mentionable_select(custom_id:, placeholder: nil, min_values: nil, max_values: nil, disabled: nil)
107
+ @components << SelectMenuBuilder.new(custom_id, [], placeholder, min_values, max_values, disabled, select_type: :mentionable_select).to_h
108
+ end
109
+
110
+ # Add a select channel to this action row.
111
+ # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions.
112
+ # There is a limit of 100 characters to each custom_id.
113
+ # @param placeholder [String, nil] Default text to show when no entries are selected.
114
+ # @param min_values [Integer, nil] The minimum amount of values a user must select.
115
+ # @param max_values [Integer, nil] The maximum amount of values a user can select.
116
+ # @param disabled [true, false, nil] Grey out the component to make it unusable.
117
+ def channel_select(custom_id:, placeholder: nil, min_values: nil, max_values: nil, disabled: nil)
118
+ @components << SelectMenuBuilder.new(custom_id, [], placeholder, min_values, max_values, disabled, select_type: :channel_select).to_h
119
+ end
120
+
121
+ # @!visibility private
122
+ def to_h
123
+ { type: COMPONENT_TYPES[:action_row], components: @components }
124
+ end
125
+ end
126
+
127
+ # A builder to assist in adding options to select menus.
128
+ class SelectMenuBuilder
129
+ # @!visibility hidden
130
+ def initialize(custom_id, options = [], placeholder = nil, min_values = nil, max_values = nil, disabled = nil, select_type: :string_select)
131
+ @custom_id = custom_id
132
+ @options = options
133
+ @placeholder = placeholder
134
+ @min_values = min_values
135
+ @max_values = max_values
136
+ @disabled = disabled
137
+ @select_type = select_type
138
+ end
139
+
140
+ # Add an option to this select menu.
141
+ # @param label [String] The title of this option.
142
+ # @param value [String] The value that this option represents.
143
+ # @param description [String, nil] An optional description of the option.
144
+ # @param emoji [#to_h, String, Integer] An emoji ID, or unicode emoji to attach to the button. Can also be a object
145
+ # that responds to `#to_h` which returns a hash in the format of `{ id: Integer, name: string }`.
146
+ # @param default [true, false, nil] Whether this is the default selected option.
147
+ def option(label:, value:, description: nil, emoji: nil, default: nil)
148
+ emoji = case emoji
149
+ when Integer, String
150
+ emoji.to_i.positive? ? { id: emoji } : { name: emoji }
151
+ else
152
+ emoji.to_h
153
+ end
154
+
155
+ @options << { label: label, value: value, description: description, emoji: emoji, default: default }
156
+ end
157
+
158
+ # @!visibility private
159
+ def to_h
160
+ {
161
+ type: COMPONENT_TYPES[@select_type],
162
+ options: @options,
163
+ placeholder: @placeholder,
164
+ min_values: @min_values,
165
+ max_values: @max_values,
166
+ custom_id: @custom_id,
167
+ disabled: @disabled
168
+ }
169
+ end
170
+ end
171
+
172
+ attr_reader :rows
173
+
174
+ def initialize
175
+ @rows = []
176
+
177
+ yield self if block_given?
178
+ end
179
+
180
+ # Add a new ActionRow to the view
181
+ # @yieldparam [RowBuilder]
182
+ def row
183
+ new_row = RowBuilder.new
184
+
185
+ yield new_row
186
+
187
+ @rows << new_row
188
+ end
189
+
190
+ # @!visibility private
191
+ def to_a
192
+ @rows.map(&:to_h)
193
+ end
194
+ end
@@ -4,6 +4,8 @@ require 'discordrb/webhooks/version'
4
4
  require 'discordrb/webhooks/embeds'
5
5
  require 'discordrb/webhooks/client'
6
6
  require 'discordrb/webhooks/builder'
7
+ require 'discordrb/webhooks/view'
8
+ require 'discordrb/webhooks/modal'
7
9
 
8
10
  module Discordrb
9
11
  # Webhook client
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: discordrb-webhooks
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.3
4
+ version: 3.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - meew0
@@ -36,11 +36,14 @@ files:
36
36
  - lib/discordrb/webhooks/builder.rb
37
37
  - lib/discordrb/webhooks/client.rb
38
38
  - lib/discordrb/webhooks/embeds.rb
39
+ - lib/discordrb/webhooks/modal.rb
39
40
  - lib/discordrb/webhooks/version.rb
41
+ - lib/discordrb/webhooks/view.rb
40
42
  homepage: https://github.com/shardlab/discordrb
41
43
  licenses:
42
44
  - MIT
43
- metadata: {}
45
+ metadata:
46
+ rubygems_mfa_required: 'true'
44
47
  post_install_message:
45
48
  rdoc_options: []
46
49
  require_paths:
@@ -49,7 +52,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
49
52
  requirements:
50
53
  - - ">="
51
54
  - !ruby/object:Gem::Version
52
- version: '2.5'
55
+ version: '2.7'
53
56
  required_rubygems_version: !ruby/object:Gem::Requirement
54
57
  requirements:
55
58
  - - ">="