slack_message 1.3.0 → 1.7.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 +16 -2
- data/README.md +38 -1
- data/lib/slack_message/api.rb +10 -1
- data/lib/slack_message/configuration.rb +2 -2
- data/lib/slack_message/dsl.rb +50 -6
- data/lib/slack_message.rb +19 -3
- data/slack_message.gemspec +1 -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: a2cd232d81a66a48c9543a5b910c335bca7a82474a60472d03f7cffab3fce0d0
|
4
|
+
data.tar.gz: c27312311ff02ee414f2882461fe5ea9b5c07d9d8e99847ae7af33faf4a31283
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69352d5eb8d4f6837f66ba042817bfe0a51c3483356bbc64ded0cbc60fc7e72c084ea39df542a93bf79a6c0a8c4ad860cdb9791f28d807edb5b1c859b13f129f
|
7
|
+
data.tar.gz: 740af84829c6b258b4788b5f83901f242a5732e98737781efb288ee426ed232726823d9fdde453da6c7d83eb55607733e1d4b55757580676921b37abba1c70ad
|
data/CHANGELOG.md
CHANGED
@@ -2,19 +2,33 @@
|
|
2
2
|
|
3
3
|
## [Unreleased]
|
4
4
|
|
5
|
+
## [1.7.0] - 2021-10-06
|
6
|
+
- Added new error messages when API configuration is wrong / missing.
|
7
|
+
- Fixed issue with `instance_eval` and using methods within block.
|
8
|
+
- Fixed issue with sectionless `list_item`.
|
9
|
+
|
10
|
+
## [1.6.0] - 2021-10-04
|
11
|
+
- Added `:default_channel` and `post_as` to deal with repetitive channel usage.
|
12
|
+
|
13
|
+
## [1.5.0] - 2021-10-01
|
14
|
+
- Added `ol` and `ul` to sections w/ some formatting.
|
15
|
+
|
16
|
+
## [1.4.0] - 2021-09-27
|
17
|
+
- Changed `image` to `accessory_image` to differentiate between the image block
|
18
|
+
and the accessory image within a block.
|
19
|
+
|
5
20
|
## [1.3.0] - 2021-09-27
|
6
21
|
- Added ability to use custom names when posting.
|
7
22
|
- Added ability to post images within sections.
|
8
23
|
- Added warnings for potentially invalid URLs.
|
9
24
|
|
10
25
|
## [1.2.0] - 2021-09-26
|
11
|
-
-
|
26
|
+
- Fixed gemspec, which was entirely broken.
|
12
27
|
|
13
28
|
## [1.1.0] - 2021-09-26
|
14
29
|
- Expanded the README significantly w/ usage instructions.
|
15
30
|
- Added lots of error handling to requests.
|
16
31
|
|
17
32
|
## [1.0.0] - 2021-09-25
|
18
|
-
|
19
33
|
- Added the base gem w/ a DSL for constructing blocks using sections.
|
20
34
|
- Added a changelog, apparently.
|
data/README.md
CHANGED
@@ -55,6 +55,28 @@ SlackMessage.configure do |config|
|
|
55
55
|
end
|
56
56
|
```
|
57
57
|
|
58
|
+
If you frequently ping the same channel with the same bot, and don't want to
|
59
|
+
continually specify the channel name, you can specify a default channel and
|
60
|
+
post using the `post_as` method. It is otherwise identical to `post_to`, but
|
61
|
+
allows you to omit the channel argument:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
SlackMessage.configure do |config|
|
65
|
+
config.add_profile(:prod_alert_bot,
|
66
|
+
name: 'Prod Alert Bot',
|
67
|
+
url: ENV['SLACK_PROD_ALERT_WEBHOOK_URL'],
|
68
|
+
default_channel: '#red_alerts'
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
SlackMessage.post_as(:prod_alert_bot) do
|
73
|
+
text ":ambulance: weeooo weeooo something went wrong"
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
Note that `post_as` does not allow you to choose a channel (because that's just
|
78
|
+
the same as using `post_to`), so you really do have to specify `default_channel`.
|
79
|
+
|
58
80
|
#### Configuring User Search
|
59
81
|
|
60
82
|
Slack's API no longer allows you to send DMs to users by username. You need to
|
@@ -69,7 +91,7 @@ SlackMessage.configure do |config|
|
|
69
91
|
end
|
70
92
|
```
|
71
93
|
|
72
|
-
###
|
94
|
+
### Posting Messages
|
73
95
|
|
74
96
|
As mentioned at the top, posting a message to Slack is dang easy:
|
75
97
|
|
@@ -192,6 +214,18 @@ SlackMessage.post_to('#general') do
|
|
192
214
|
end
|
193
215
|
```
|
194
216
|
|
217
|
+
Opinionated Stances
|
218
|
+
------------
|
219
|
+
|
220
|
+
Slack's API has a lot of options available to you! But this gem takes some
|
221
|
+
opinionated stances on how to make use of that API. For instance:
|
222
|
+
|
223
|
+
* Unless you request otherwise, text is always rendered using `mrkdwn`. If you
|
224
|
+
want plaintext, you'll need to ask for it.
|
225
|
+
* Generally, same goes for the `emoji` flag on almost every text element.
|
226
|
+
* It's possible to ask for a `blank_line` in sections, even though that concept
|
227
|
+
isn't real. In this case, a text line containing only an emspace is rendered.
|
228
|
+
|
195
229
|
What it Doesn't Do
|
196
230
|
------------
|
197
231
|
|
@@ -206,9 +240,12 @@ DSL to include more of the block API itself.
|
|
206
240
|
|
207
241
|
Also, some behaviors that are still planned but not yet added:
|
208
242
|
|
243
|
+
* some API documentation amirite?
|
209
244
|
* allow custom http_options in configuration
|
210
245
|
* more of BlockKit's options
|
211
246
|
* any interactive elements at all (I don't understand them yet)
|
247
|
+
* more interesting return types for your message
|
248
|
+
* richer text formatting (ul is currently a hack)
|
212
249
|
|
213
250
|
Contributing
|
214
251
|
------------
|
data/lib/slack_message/api.rb
CHANGED
@@ -17,9 +17,16 @@ class SlackMessage::Api
|
|
17
17
|
|
18
18
|
if response.code != "200"
|
19
19
|
raise "Got an error back from the Slack API (HTTP #{response.code}):\n#{response.body}"
|
20
|
+
elsif response.body == ""
|
21
|
+
raise "Received empty 200 response from Slack when looking up user info. Check your API key."
|
22
|
+
end
|
23
|
+
|
24
|
+
begin
|
25
|
+
payload = JSON.parse(response.body)
|
26
|
+
rescue
|
27
|
+
raise "Unable to parse JSON response from Slack API\n#{response.body}"
|
20
28
|
end
|
21
29
|
|
22
|
-
payload = JSON.parse(response.body)
|
23
30
|
if payload.include?("error") && payload["error"] == "invalid_auth"
|
24
31
|
raise "Received an error because your authentication token isn't properly configured:\n#{response.body}"
|
25
32
|
elsif payload.include?("error")
|
@@ -48,6 +55,8 @@ class SlackMessage::Api
|
|
48
55
|
raise "Tried to send Slack message to non-existent channel or user '#{target}'"
|
49
56
|
elsif response.body == "missing_text_or_fallback_or_attachments"
|
50
57
|
raise "Tried to send Slack message with invalid payload."
|
58
|
+
elsif response.code == "302"
|
59
|
+
raise "Got 302 response while posting to Slack. Check your webhook URL for '#{profile[:handle]}'."
|
51
60
|
elsif response.code != "200"
|
52
61
|
raise "Got an error back from the Slack API (HTTP #{response.code}):\n#{response.body}"
|
53
62
|
end
|
@@ -27,12 +27,12 @@ module SlackMessage::Configuration
|
|
27
27
|
|
28
28
|
###
|
29
29
|
|
30
|
-
def self.add_profile(handle = :default, name:, url:)
|
30
|
+
def self.add_profile(handle = :default, name:, url:, default_channel: nil)
|
31
31
|
if @@profiles.include?(handle)
|
32
32
|
warn "WARNING: Overriding profile '#{handle}' in SlackMessage config"
|
33
33
|
end
|
34
34
|
|
35
|
-
@@profiles[handle] = { name: name, url: url, handle: handle }
|
35
|
+
@@profiles[handle] = { name: name, url: url, handle: handle, default_channel: default_channel }
|
36
36
|
end
|
37
37
|
|
38
38
|
def self.profile(handle, custom_name: nil)
|
data/lib/slack_message/dsl.rb
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
class SlackMessage::Dsl
|
2
2
|
attr_reader :body, :default_section, :custom_bot_name
|
3
3
|
|
4
|
-
|
4
|
+
EMSPACE = " " # unicode emspace
|
5
|
+
|
6
|
+
def initialize(block)
|
7
|
+
# Delegate missing methods to caller scope. Thanks 2008:
|
8
|
+
# https://www.dan-manges.com/blog/ruby-dsls-instance-eval-with-delegation
|
9
|
+
@caller_self = eval("self", block.binding
|
10
|
+
|
5
11
|
@body = []
|
6
12
|
@default_section = Section.new
|
7
13
|
@custom_bot_name = nil
|
@@ -25,6 +31,24 @@ class SlackMessage::Dsl
|
|
25
31
|
@body.push({ type: "divider" })
|
26
32
|
end
|
27
33
|
|
34
|
+
def image(url, alt_text:, title: nil)
|
35
|
+
finalize_default_section
|
36
|
+
|
37
|
+
config = {
|
38
|
+
type: "image",
|
39
|
+
image_url: url,
|
40
|
+
alt_text: alt_text,
|
41
|
+
}
|
42
|
+
|
43
|
+
if !title.nil?
|
44
|
+
config[:title] = {
|
45
|
+
type: "plain_text", text: title, emoji: true
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
@body.push(config)
|
50
|
+
end
|
51
|
+
|
28
52
|
def context(text)
|
29
53
|
finalize_default_section
|
30
54
|
|
@@ -39,10 +63,12 @@ class SlackMessage::Dsl
|
|
39
63
|
|
40
64
|
def text(*args); default_section.text(*args); end
|
41
65
|
def link_button(*args); default_section.link_button(*args); end
|
42
|
-
def
|
66
|
+
def accessory_image(*args); default_section.accessory_image(*args); end
|
43
67
|
def blank_line(*args); default_section.blank_line(*args); end
|
44
68
|
def link(*args); default_section.link(*args); end
|
45
69
|
def list_item(*args); default_section.list_item(*args); end
|
70
|
+
def ul(*args); default_section.ul(*args); end
|
71
|
+
def ol(*args); default_section.ol(*args); end
|
46
72
|
|
47
73
|
# end delegation
|
48
74
|
|
@@ -59,13 +85,17 @@ class SlackMessage::Dsl
|
|
59
85
|
@body
|
60
86
|
end
|
61
87
|
|
88
|
+
def method_missing(meth, *args, &blk)
|
89
|
+
@caller_self.send meth, *args, &blk
|
90
|
+
end
|
91
|
+
|
62
92
|
private
|
63
93
|
|
64
94
|
# when doing things that would generate new top-levels, first try
|
65
95
|
# to finish the implicit section.
|
66
96
|
def finalize_default_section
|
67
97
|
if default_section.has_content?
|
68
|
-
@body.push(default_section.
|
98
|
+
@body.push(default_section.render)
|
69
99
|
end
|
70
100
|
|
71
101
|
@default_section = Section.new
|
@@ -88,6 +118,20 @@ class SlackMessage::Dsl
|
|
88
118
|
end
|
89
119
|
end
|
90
120
|
|
121
|
+
def ul(elements)
|
122
|
+
raise Arguments, "please pass an array" unless elements.respond_to?(:map)
|
123
|
+
text(
|
124
|
+
elements.map { |text| "#{EMSPACE}• #{text}" }.join("\n")
|
125
|
+
)
|
126
|
+
end
|
127
|
+
|
128
|
+
def ol(elements)
|
129
|
+
raise Arguments, "please pass an array" unless elements.respond_to?(:map)
|
130
|
+
text(
|
131
|
+
elements.map.with_index(1) { |text, idx| "#{EMSPACE}#{idx}. #{text}" }.join("\n")
|
132
|
+
)
|
133
|
+
end
|
134
|
+
|
91
135
|
# styles: default, primary, danger
|
92
136
|
def link_button(label, target, style: :primary)
|
93
137
|
if !@body[:accessory].nil?
|
@@ -118,10 +162,10 @@ class SlackMessage::Dsl
|
|
118
162
|
@body.merge!(config)
|
119
163
|
end
|
120
164
|
|
121
|
-
def
|
165
|
+
def accessory_image(url, alt_text: nil)
|
122
166
|
if !@body[:accessory].nil?
|
123
167
|
previous_type = @body[:accessory][:type]
|
124
|
-
warn "WARNING: Overriding previous #{previous_type} in section to use image instead: #{url}"
|
168
|
+
warn "WARNING: Overriding previous #{previous_type} in section to use accessory image instead: #{url}"
|
125
169
|
end
|
126
170
|
|
127
171
|
config = {
|
@@ -146,7 +190,7 @@ class SlackMessage::Dsl
|
|
146
190
|
end
|
147
191
|
|
148
192
|
def blank_line
|
149
|
-
text
|
193
|
+
text EMSPACE
|
150
194
|
end
|
151
195
|
|
152
196
|
def has_content?
|
data/lib/slack_message.rb
CHANGED
@@ -11,12 +11,12 @@ module SlackMessage
|
|
11
11
|
configuration.configure(&block)
|
12
12
|
end
|
13
13
|
|
14
|
-
def self.user_id_for(email)
|
14
|
+
def self.user_id_for(email) # spooky undocumented public method 👻
|
15
15
|
Api::user_id_for(email)
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.post_to(target, as: :default, &block)
|
19
|
-
payload = Dsl.new.tap do |instance|
|
19
|
+
payload = Dsl.new(block).tap do |instance|
|
20
20
|
instance.instance_eval(&block)
|
21
21
|
end
|
22
22
|
|
@@ -26,8 +26,24 @@ module SlackMessage
|
|
26
26
|
Api.post(payload.render, target, profile)
|
27
27
|
end
|
28
28
|
|
29
|
+
def self.post_as(profile_name, &block)
|
30
|
+
payload = Dsl.new(block).tap do |instance|
|
31
|
+
instance.instance_eval(&block)
|
32
|
+
end
|
33
|
+
|
34
|
+
profile = Configuration.profile(profile_name, custom_name: payload.custom_bot_name)
|
35
|
+
if profile[:default_channel].nil?
|
36
|
+
raise ArgumentError, "Sorry, you need to specify a default_channel for profile #{profile_name} to use post_as"
|
37
|
+
end
|
38
|
+
|
39
|
+
target = profile[:default_channel]
|
40
|
+
target = user_id_for(target) if target =~ /^\S{1,}@\S{2,}\.\S{2,}$/
|
41
|
+
|
42
|
+
Api.post(payload.render, target, profile)
|
43
|
+
end
|
44
|
+
|
29
45
|
def self.build(&block)
|
30
|
-
Dsl.new.tap do |instance|
|
46
|
+
Dsl.new(block).tap do |instance|
|
31
47
|
instance.instance_eval(&block)
|
32
48
|
end.send(:render)
|
33
49
|
end
|
data/slack_message.gemspec
CHANGED
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: 1.
|
4
|
+
version: 1.7.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: 2021-
|
11
|
+
date: 2021-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|