slack_message 3.2.0 → 3.4.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 +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
|