slack_message 3.2.0 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -1
- data/lib/slack_message/api.rb +9 -3
- 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 +67 -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: 0b35e974e04457e2d9e3b55af0c5c7562d0381c76477e9a85143c66e8d605071
|
4
|
+
data.tar.gz: 21892df8e52b365ade154424d2c98a55434efb541e144d046d208fe8b1243f24
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 720e5bcf8d91f355939474b09f9d2a9830178037dca5c067ecfc4c6585631673e2ea13d888338ff1fb7a3d25ae1009b5f1a97f7a8244f1f06696b437227f6260
|
7
|
+
data.tar.gz: b7fa2c16e3d5a31ac18605bda1e1eacdd367c6e94f34779c50964a92c679b8edcdc1168d3fa808392401669f55bbeae30aec607ec44a2cfd55b916d0ad0fe70d
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [3.3.0] - 2022-07-21
|
4
|
+
- Differentiate errors for bad JSON versus invalid block data.
|
5
|
+
- Expand tests to cover many more cases.
|
6
|
+
- Add validation for block size limit in Slack API.
|
7
|
+
- Add CI check to prevent checkin of `fit`, `fcontext` etc.
|
8
|
+
|
3
9
|
## [3.2.0] - 2022-06-23
|
4
|
-
- Fix bugs introduced by accidental checkin of incomplete refactor
|
10
|
+
- Fix bugs introduced by accidental checkin of incomplete refactor.
|
5
11
|
|
6
12
|
## [3.1.0] - 2022-04-18
|
7
13
|
- 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
|
|
@@ -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
@@ -176,18 +176,6 @@ RSpec.describe SlackMessage do
|
|
176
176
|
SlackMessage::RSpec.reset_mock_response
|
177
177
|
end
|
178
178
|
|
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
179
|
it "raises for redirects" do
|
192
180
|
SlackMessage::RSpec.respond_with(code: '302')
|
193
181
|
|
@@ -196,24 +184,83 @@ RSpec.describe SlackMessage do
|
|
196
184
|
}.to raise_error(SlackMessage::ApiError)
|
197
185
|
end
|
198
186
|
|
199
|
-
it "raises errors
|
187
|
+
it "even raises errors during deletes" do
|
200
188
|
message = SlackMessage.post_to('#general') { text 'nuh uh' }
|
201
189
|
|
202
190
|
SlackMessage::RSpec.respond_with({'error' => 'bad choice'})
|
203
191
|
|
204
192
|
expect {
|
205
|
-
SlackMessage.
|
193
|
+
SlackMessage.delete(message)
|
206
194
|
}.to raise_error(SlackMessage::ApiError)
|
207
195
|
end
|
208
196
|
|
209
|
-
|
210
|
-
|
197
|
+
shared_examples 'post api error message' do |error, error_message|
|
198
|
+
it "responds to posts with error code '#{error}' with the expected message" do
|
199
|
+
SlackMessage::RSpec.respond_with({'error' => error})
|
211
200
|
|
212
|
-
|
201
|
+
expect {
|
202
|
+
SlackMessage.post_to('#general') { text 'nuh uh' }
|
203
|
+
}.to raise_error(SlackMessage::ApiError).with_message(error_message)
|
213
204
|
|
214
|
-
|
215
|
-
|
216
|
-
|
205
|
+
expect {
|
206
|
+
SlackMessage.post_as(:schmoebot) { text 'nuh uh' }
|
207
|
+
}.to raise_error(SlackMessage::ApiError).with_message(error_message)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
shared_examples 'update api error message' do |error, error_message|
|
212
|
+
it "responds to updates with error code '#{error}' with the expected message" do
|
213
|
+
message = SlackMessage.post_to('#general') { text 'nuh uh' }
|
214
|
+
|
215
|
+
SlackMessage::RSpec.respond_with({'error' => error})
|
216
|
+
|
217
|
+
expect {
|
218
|
+
SlackMessage.update(message) { text 'nuh uh' }
|
219
|
+
}.to raise_error(SlackMessage::ApiError).with_message(error_message)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
shared_examples 'delete api error message' do |error, error_message|
|
224
|
+
it "responds to updates with error code '#{error}' with the expected message" do
|
225
|
+
message = SlackMessage.post_to('#general') { text 'nuh uh' }
|
226
|
+
|
227
|
+
SlackMessage::RSpec.respond_with({'error' => error})
|
228
|
+
|
229
|
+
expect {
|
230
|
+
SlackMessage.delete(message)
|
231
|
+
}.to raise_error(SlackMessage::ApiError).with_message(error_message)
|
232
|
+
end
|
217
233
|
end
|
234
|
+
|
235
|
+
shared_examples 'block api error message' do |error, error_message|
|
236
|
+
include_examples 'post api error message', error, error_message
|
237
|
+
include_examples 'update api error message', error, error_message
|
238
|
+
end
|
239
|
+
|
240
|
+
include_examples 'block api error message', 'nuffin', /Received error response 'nuffin' from Slack/
|
241
|
+
include_examples 'block api error message', 'invalid_blocks', /because the request contained invalid blocks:\n\[Enable debugging in configuration to view block data\.\]/
|
242
|
+
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\.\]/
|
243
|
+
include_examples 'block api error message', 'channel_not_found', /Slack message to non-existent channel or user/
|
244
|
+
include_examples 'block api error message', 'invalid_auth', /because the API key for profile '.*' is wrong, or the app has insufficient permissions \(invalid_auth\)/
|
245
|
+
include_examples 'block api error message', 'message_too_long', /but the message was too long/
|
246
|
+
include_examples 'block api error message', 'invalid_arguments', /with invalid payload/
|
247
|
+
include_examples 'block api error message', 'rate_limited', /because you've reached your rate limit/
|
248
|
+
|
249
|
+
# Scheduling messages
|
250
|
+
include_examples 'post api error message', 'invalid_time', /because you requested an invalid time/
|
251
|
+
include_examples 'post api error message', 'time_in_past', /because you requested a time in the past \(or too close to now\)/
|
252
|
+
include_examples 'post api error message', 'time_too_far', /because you requested a time more than 120 days in the future/
|
253
|
+
|
254
|
+
# Updating messages
|
255
|
+
include_examples 'update api error message', 'message_not_found', /but the message wasn't found/
|
256
|
+
|
257
|
+
# Deleting messages
|
258
|
+
include_examples 'delete api error message', 'nuffin', /Received error response 'nuffin' from Slack/
|
259
|
+
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/
|
260
|
+
include_examples 'delete api error message', 'message_not_found', /but the message wasn't found/
|
261
|
+
include_examples 'delete api error message', 'cant_delete_message', /Can't delete message because 'default' doesn't have permission to/
|
262
|
+
include_examples 'delete api error message', 'compliance_exports_prevent_deletion', /Can't delete message because team compliance settings prevent it/
|
263
|
+
include_examples 'delete api error message', 'invalid_auth', /because the API key for profile '.*' is wrong, or the app has insufficient permissions \(invalid_auth\)/
|
264
|
+
include_examples 'delete api error message', 'rate_limited', /because you've reached your rate limit/
|
218
265
|
end
|
219
266
|
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.3.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: 2022-
|
11
|
+
date: 2022-07-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|