slack_message 3.2.0 → 3.4.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 +4 -4
- data/CHANGELOG.md +10 -1
- data/lib/slack_message/api.rb +9 -3
- data/lib/slack_message/dsl.rb +2 -2
- data/lib/slack_message/error_handling.rb +22 -10
- data/lib/slack_message/rspec.rb +25 -23
- data/slack_message.gemspec +1 -1
- data/spec/slack_message_spec.rb +75 -20
- data/spec/spec_helper.rb +5 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 494d2f51af95a53df19c42dcaa9f88168cf44509b1675dbe001a42fdf39250dc
|
4
|
+
data.tar.gz: 306050272f54d60a1b6820f315ac51c0b563af71862847efdb2940464ca201b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8e43baeab730d3c6e7acbb1232b98d4a265b55260ab3c12bcc87325cb81d03f00b7ff05ff72667105e10e123c604630eac7331db238823374b8584d8242e611
|
7
|
+
data.tar.gz: 2c2709365ec780ca44c6960414861c9479eb3b2918d547ca3f3299745aa382e6affd6dfd46a364c27097f5e562939913e098c52bc72cb29911f7c9c669756d30
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [3.4.0] - 2023-02-21
|
4
|
+
- Add full support for ruby 3.0.x kwargs
|
5
|
+
|
6
|
+
## [3.3.0] - 2022-07-21
|
7
|
+
- Differentiate errors for bad JSON versus invalid block data.
|
8
|
+
- Expand tests to cover many more cases.
|
9
|
+
- Add validation for block size limit in Slack API.
|
10
|
+
- Add CI check to prevent checkin of `fit`, `fcontext` etc.
|
11
|
+
|
3
12
|
## [3.2.0] - 2022-06-23
|
4
|
-
- Fix bugs introduced by accidental checkin of incomplete refactor
|
13
|
+
- Fix bugs introduced by accidental checkin of incomplete refactor.
|
5
14
|
|
6
15
|
## [3.1.0] - 2022-04-18
|
7
16
|
- Methods from the calling context can now be called within a section block.
|
data/lib/slack_message/api.rb
CHANGED
@@ -41,6 +41,10 @@ module SlackMessage::Api
|
|
41
41
|
raise ArgumentError, "Tried to send an entirely empty message."
|
42
42
|
end
|
43
43
|
|
44
|
+
if params[:blocks].length > 50
|
45
|
+
raise ArgumentError, "Message cannot contain more than 50 blocks."
|
46
|
+
end
|
47
|
+
|
44
48
|
icon = payload.custom_bot_icon || profile[:icon]
|
45
49
|
if icon =~ /^:\w+:$/
|
46
50
|
params[:icon_emoji] = icon
|
@@ -80,15 +84,17 @@ module SlackMessage::Api
|
|
80
84
|
raise ArgumentError, "Tried to send an entirely empty message."
|
81
85
|
end
|
82
86
|
|
87
|
+
if params[:blocks].length > 50
|
88
|
+
raise ArgumentError, "Message cannot contain more than 50 blocks."
|
89
|
+
end
|
90
|
+
|
83
91
|
if SlackMessage::Configuration.debugging?
|
84
92
|
warn params.inspect
|
85
93
|
end
|
86
94
|
|
87
95
|
response = update_message(profile, params)
|
88
|
-
body = JSON.parse(response.body)
|
89
|
-
error = body.fetch("error", "")
|
90
96
|
|
91
|
-
SlackMessage::ErrorHandling.
|
97
|
+
SlackMessage::ErrorHandling.raise_update_response_errors(response, params, profile)
|
92
98
|
SlackMessage::Response.new(response, profile[:handle])
|
93
99
|
end
|
94
100
|
|
data/lib/slack_message/dsl.rb
CHANGED
@@ -80,8 +80,8 @@ class SlackMessage::Dsl
|
|
80
80
|
# delegation to allow terse syntax without e.g. `section`
|
81
81
|
|
82
82
|
def text(*args); default_section.text(*args); end
|
83
|
-
def link_button(*args); default_section.link_button(*args); end
|
84
|
-
def accessory_image(*args); default_section.accessory_image(*args); end
|
83
|
+
def link_button(*args, **kwargs); default_section.link_button(*args, **kwargs); end
|
84
|
+
def accessory_image(*args, **kwargs); default_section.accessory_image(*args, **kwargs); end
|
85
85
|
def blank_line(*args); default_section.blank_line(*args); end
|
86
86
|
def link(*args); default_section.link(*args); end
|
87
87
|
def list_item(*args); default_section.list_item(*args); end
|
@@ -7,8 +7,10 @@ class SlackMessage::ErrorHandling
|
|
7
7
|
body = JSON.parse(response.body)
|
8
8
|
error = body.fetch("error", "")
|
9
9
|
|
10
|
-
if
|
11
|
-
raise SlackMessage::ApiError, "Couldn't send Slack message because the
|
10
|
+
if error == "invalid_blocks"
|
11
|
+
raise SlackMessage::ApiError, "Couldn't send Slack message because the request contained invalid blocks:\n#{blocks_message(params[:blocks])}"
|
12
|
+
elsif error == "invalid_blocks_format"
|
13
|
+
raise SlackMessage::ApiError, "Couldn't send Slack message because blocks is not a valid JSON object or doesn't match the Block Kit syntax:\n#{blocks_message(params[:blocks])}"
|
12
14
|
elsif error == "channel_not_found"
|
13
15
|
raise SlackMessage::ApiError, "Tried to send Slack message to non-existent channel or user '#{params[:channel]}'"
|
14
16
|
|
@@ -34,21 +36,23 @@ class SlackMessage::ErrorHandling
|
|
34
36
|
elsif response.code != "200"
|
35
37
|
raise SlackMessage::ApiError, "Got an error back from the Slack API (HTTP #{response.code}):\n#{response.body}"
|
36
38
|
elsif !(error.nil? || error == "")
|
37
|
-
raise SlackMessage::ApiError, "Received error response from Slack during message posting:\n#{response.body}"
|
39
|
+
raise SlackMessage::ApiError, "Received error response '#{error}' from Slack during message posting:\n#{response.body}"
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
|
-
def self.raise_update_response_errors(response,
|
43
|
+
def self.raise_update_response_errors(response, params, profile)
|
42
44
|
body = JSON.parse(response.body)
|
43
45
|
error = body.fetch("error", "")
|
44
46
|
|
45
|
-
if
|
46
|
-
raise SlackMessage::ApiError, "Couldn't update Slack message because the
|
47
|
+
if error == "invalid_blocks"
|
48
|
+
raise SlackMessage::ApiError, "Couldn't update Slack message because the request contained invalid blocks:\n#{blocks_message(params[:blocks])}"
|
49
|
+
elsif error == "invalid_blocks_format"
|
50
|
+
raise SlackMessage::ApiError, "Couldn't update Slack message because blocks is not a valid JSON object or doesn't match the Block Kit syntax:\n#{blocks_message(params[:blocks])}"
|
47
51
|
elsif error == "channel_not_found"
|
48
|
-
raise SlackMessage::ApiError, "Tried to update Slack message to non-existent channel or user '#{
|
52
|
+
raise SlackMessage::ApiError, "Tried to update Slack message to non-existent channel or user '#{params[:channel]}'"
|
49
53
|
|
50
54
|
elsif error == "message_not_found"
|
51
|
-
raise SlackMessage::ApiError, "Tried to update Slack message, but the message wasn't found (timestamp '#{
|
55
|
+
raise SlackMessage::ApiError, "Tried to update Slack message, but the message wasn't found (timestamp '#{params[:ts]}' for channel '#{params[:channel]}'"
|
52
56
|
elsif error == "cant_update_message"
|
53
57
|
raise SlackMessage::ApiError, "Couldn't update message because the message type isn't able to be updated, or #{profile[:handle]} isn't allowed to update it"
|
54
58
|
elsif error == "edit_window_closed"
|
@@ -68,7 +72,7 @@ class SlackMessage::ErrorHandling
|
|
68
72
|
elsif response.code != "200"
|
69
73
|
raise SlackMessage::ApiError, "Got an error back from the Slack API (HTTP #{response.code}):\n#{response.body}"
|
70
74
|
elsif !(error.nil? || error == "")
|
71
|
-
raise SlackMessage::ApiError, "Received error response from Slack during message update:\n#{response.body}"
|
75
|
+
raise SlackMessage::ApiError, "Received error response '#{error}' from Slack during message update:\n#{response.body}"
|
72
76
|
end
|
73
77
|
end
|
74
78
|
|
@@ -98,7 +102,7 @@ class SlackMessage::ErrorHandling
|
|
98
102
|
elsif response.code != "200"
|
99
103
|
raise SlackMessage::ApiError, "Got an error back from the Slack API (HTTP #{response.code}):\n#{response.body}"
|
100
104
|
elsif !(error.nil? || error == "")
|
101
|
-
raise SlackMessage::ApiError, "Received error response from Slack during message delete:\n#{response.body}"
|
105
|
+
raise SlackMessage::ApiError, "Received error response '#{error}' from Slack during message delete:\n#{response.body}"
|
102
106
|
end
|
103
107
|
end
|
104
108
|
|
@@ -127,4 +131,12 @@ class SlackMessage::ErrorHandling
|
|
127
131
|
raise SlackMessage::ApiError, "Received error response from Slack during user lookup:\n#{response.body}"
|
128
132
|
end
|
129
133
|
end
|
134
|
+
|
135
|
+
def self.blocks_message(blocks)
|
136
|
+
if SlackMessage::Configuration.debugging?
|
137
|
+
JSON.pretty_generate(blocks)
|
138
|
+
else
|
139
|
+
"[Enable debugging in configuration to view block data.]"
|
140
|
+
end
|
141
|
+
end
|
130
142
|
end
|
data/lib/slack_message/rspec.rb
CHANGED
@@ -40,30 +40,32 @@ module SlackMessage::RSpec
|
|
40
40
|
FauxResponse = Struct.new(:code, :body)
|
41
41
|
|
42
42
|
def self.included(_)
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
[:post_message, :update_message, :delete_message].each do |method|
|
44
|
+
SlackMessage::Api.undef_method(method)
|
45
|
+
SlackMessage::Api.define_singleton_method(method) do |profile, params|
|
46
|
+
@@listeners.each do |listener|
|
47
|
+
listener.record_call(params.merge(profile: profile))
|
48
|
+
end
|
49
|
+
|
50
|
+
response = {
|
51
|
+
"ok" => true,
|
52
|
+
"channel" => "C12345678",
|
53
|
+
"ts" => "1635863996.002300",
|
54
|
+
"message" => { "type"=>"message", "subtype"=>"bot_message",
|
55
|
+
"text"=>"foo",
|
56
|
+
"ts"=>"1635863996.002300",
|
57
|
+
"username"=>"SlackMessage",
|
58
|
+
"icons"=>{"emoji"=>":successkid:"},
|
59
|
+
"bot_id"=>"B1234567890",
|
60
|
+
"blocks"=> [{"type"=>"section",
|
61
|
+
"block_id"=>"hAh7",
|
62
|
+
"text"=>{"type"=>"mrkdwn", "text"=>"foo", "verbatim"=>false}}
|
63
|
+
]
|
64
|
+
}
|
65
|
+
}.merge(@@custom_response).to_json
|
66
|
+
|
67
|
+
return FauxResponse.new(@@response_code, response)
|
47
68
|
end
|
48
|
-
|
49
|
-
response = {
|
50
|
-
"ok" => true,
|
51
|
-
"channel" => "C12345678",
|
52
|
-
"ts" => "1635863996.002300",
|
53
|
-
"message" => { "type"=>"message", "subtype"=>"bot_message",
|
54
|
-
"text"=>"foo",
|
55
|
-
"ts"=>"1635863996.002300",
|
56
|
-
"username"=>"SlackMessage",
|
57
|
-
"icons"=>{"emoji"=>":successkid:"},
|
58
|
-
"bot_id"=>"B1234567890",
|
59
|
-
"blocks"=> [{"type"=>"section",
|
60
|
-
"block_id"=>"hAh7",
|
61
|
-
"text"=>{"type"=>"mrkdwn", "text"=>"foo", "verbatim"=>false}}
|
62
|
-
]
|
63
|
-
}
|
64
|
-
}.merge(@@custom_response).to_json
|
65
|
-
|
66
|
-
return FauxResponse.new(@@response_code, response)
|
67
69
|
end
|
68
70
|
|
69
71
|
SlackMessage::Api.undef_method(:look_up_user_by_email)
|
data/slack_message.gemspec
CHANGED
data/spec/slack_message_spec.rb
CHANGED
@@ -127,6 +127,14 @@ RSpec.describe SlackMessage do
|
|
127
127
|
SlackMessage.post_to('#general') { text "foo" }
|
128
128
|
}.to post_to_slack.with_content_matching(/foo/)
|
129
129
|
end
|
130
|
+
|
131
|
+
it "lets you send links with custom styles" do
|
132
|
+
expect {
|
133
|
+
SlackMessage.post_to('#general') do
|
134
|
+
link_button 'Does this person exist?', 'https://thispersondoesnotexist.com/image', style: :danger
|
135
|
+
end
|
136
|
+
}.to post_to_slack.with_content_matching(/danger/)
|
137
|
+
end
|
130
138
|
end
|
131
139
|
|
132
140
|
describe "API convenience" do
|
@@ -176,18 +184,6 @@ RSpec.describe SlackMessage do
|
|
176
184
|
SlackMessage::RSpec.reset_mock_response
|
177
185
|
end
|
178
186
|
|
179
|
-
it "raises nice error messages when API methods return errors" do
|
180
|
-
SlackMessage::RSpec.respond_with({'error' => 'nuffin'})
|
181
|
-
|
182
|
-
expect {
|
183
|
-
SlackMessage.post_to('#general') { text 'nuh uh' }
|
184
|
-
}.to raise_error(SlackMessage::ApiError)
|
185
|
-
|
186
|
-
expect {
|
187
|
-
SlackMessage.post_as(:schmoebot) { text 'nuh uh' }
|
188
|
-
}.to raise_error(SlackMessage::ApiError)
|
189
|
-
end
|
190
|
-
|
191
187
|
it "raises for redirects" do
|
192
188
|
SlackMessage::RSpec.respond_with(code: '302')
|
193
189
|
|
@@ -196,24 +192,83 @@ RSpec.describe SlackMessage do
|
|
196
192
|
}.to raise_error(SlackMessage::ApiError)
|
197
193
|
end
|
198
194
|
|
199
|
-
it "raises errors
|
195
|
+
it "even raises errors during deletes" do
|
200
196
|
message = SlackMessage.post_to('#general') { text 'nuh uh' }
|
201
197
|
|
202
198
|
SlackMessage::RSpec.respond_with({'error' => 'bad choice'})
|
203
199
|
|
204
200
|
expect {
|
205
|
-
SlackMessage.
|
201
|
+
SlackMessage.delete(message)
|
206
202
|
}.to raise_error(SlackMessage::ApiError)
|
207
203
|
end
|
208
204
|
|
209
|
-
|
210
|
-
|
205
|
+
shared_examples 'post api error message' do |error, error_message|
|
206
|
+
it "responds to posts with error code '#{error}' with the expected message" do
|
207
|
+
SlackMessage::RSpec.respond_with({'error' => error})
|
211
208
|
|
212
|
-
|
209
|
+
expect {
|
210
|
+
SlackMessage.post_to('#general') { text 'nuh uh' }
|
211
|
+
}.to raise_error(SlackMessage::ApiError).with_message(error_message)
|
213
212
|
|
214
|
-
|
215
|
-
|
216
|
-
|
213
|
+
expect {
|
214
|
+
SlackMessage.post_as(:schmoebot) { text 'nuh uh' }
|
215
|
+
}.to raise_error(SlackMessage::ApiError).with_message(error_message)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
shared_examples 'update api error message' do |error, error_message|
|
220
|
+
it "responds to updates with error code '#{error}' with the expected message" do
|
221
|
+
message = SlackMessage.post_to('#general') { text 'nuh uh' }
|
222
|
+
|
223
|
+
SlackMessage::RSpec.respond_with({'error' => error})
|
224
|
+
|
225
|
+
expect {
|
226
|
+
SlackMessage.update(message) { text 'nuh uh' }
|
227
|
+
}.to raise_error(SlackMessage::ApiError).with_message(error_message)
|
228
|
+
end
|
217
229
|
end
|
230
|
+
|
231
|
+
shared_examples 'delete api error message' do |error, error_message|
|
232
|
+
it "responds to updates with error code '#{error}' with the expected message" do
|
233
|
+
message = SlackMessage.post_to('#general') { text 'nuh uh' }
|
234
|
+
|
235
|
+
SlackMessage::RSpec.respond_with({'error' => error})
|
236
|
+
|
237
|
+
expect {
|
238
|
+
SlackMessage.delete(message)
|
239
|
+
}.to raise_error(SlackMessage::ApiError).with_message(error_message)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
shared_examples 'block api error message' do |error, error_message|
|
244
|
+
include_examples 'post api error message', error, error_message
|
245
|
+
include_examples 'update api error message', error, error_message
|
246
|
+
end
|
247
|
+
|
248
|
+
include_examples 'block api error message', 'nuffin', /Received error response 'nuffin' from Slack/
|
249
|
+
include_examples 'block api error message', 'invalid_blocks', /because the request contained invalid blocks:\n\[Enable debugging in configuration to view block data\.\]/
|
250
|
+
include_examples 'block api error message', 'invalid_blocks_format', /because blocks is not a valid JSON object or doesn't match the Block Kit syntax:\n\[Enable debugging in configuration to view block data\.\]/
|
251
|
+
include_examples 'block api error message', 'channel_not_found', /Slack message to non-existent channel or user/
|
252
|
+
include_examples 'block api error message', 'invalid_auth', /because the API key for profile '.*' is wrong, or the app has insufficient permissions \(invalid_auth\)/
|
253
|
+
include_examples 'block api error message', 'message_too_long', /but the message was too long/
|
254
|
+
include_examples 'block api error message', 'invalid_arguments', /with invalid payload/
|
255
|
+
include_examples 'block api error message', 'rate_limited', /because you've reached your rate limit/
|
256
|
+
|
257
|
+
# Scheduling messages
|
258
|
+
include_examples 'post api error message', 'invalid_time', /because you requested an invalid time/
|
259
|
+
include_examples 'post api error message', 'time_in_past', /because you requested a time in the past \(or too close to now\)/
|
260
|
+
include_examples 'post api error message', 'time_too_far', /because you requested a time more than 120 days in the future/
|
261
|
+
|
262
|
+
# Updating messages
|
263
|
+
include_examples 'update api error message', 'message_not_found', /but the message wasn't found/
|
264
|
+
|
265
|
+
# Deleting messages
|
266
|
+
include_examples 'delete api error message', 'nuffin', /Received error response 'nuffin' from Slack/
|
267
|
+
include_examples 'delete api error message', 'invalid_scheduled_message_id', /Can't delete message because the ID was invalid, or the message has already posted/
|
268
|
+
include_examples 'delete api error message', 'message_not_found', /but the message wasn't found/
|
269
|
+
include_examples 'delete api error message', 'cant_delete_message', /Can't delete message because 'default' doesn't have permission to/
|
270
|
+
include_examples 'delete api error message', 'compliance_exports_prevent_deletion', /Can't delete message because team compliance settings prevent it/
|
271
|
+
include_examples 'delete api error message', 'invalid_auth', /because the API key for profile '.*' is wrong, or the app has insufficient permissions \(invalid_auth\)/
|
272
|
+
include_examples 'delete api error message', 'rate_limited', /because you've reached your rate limit/
|
218
273
|
end
|
219
274
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -26,7 +26,11 @@ RSpec.configure do |config|
|
|
26
26
|
# is tagged with `:focus`, all examples get run. RSpec also provides
|
27
27
|
# aliases for `it`, `describe`, and `context` that include `:focus`
|
28
28
|
# metadata: `fit`, `fdescribe` and `fcontext`, respectively.
|
29
|
-
|
29
|
+
if ENV['CI'] == "true"
|
30
|
+
config.filter_run_when_matching :focus => lambda { raise ArgumentError, "Don't filter tests on checked in code." }
|
31
|
+
else
|
32
|
+
config.filter_run_when_matching :focus
|
33
|
+
end
|
30
34
|
|
31
35
|
# Limits the available syntax to the non-monkey patched syntax that is
|
32
36
|
# recommended. For more details, see:
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slack_message
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joe Mastey
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-02-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|