slack_message 2.2.0 → 2.2.1

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: 368533ab7e4dae44ffbef5ccf8afef048def96d964a6af64c294c23ba617dfa3
4
- data.tar.gz: f9397472bbc5c5db81dd1c9d7715e5015f4ec455948e7a29afbb11ef8c8a3d01
3
+ metadata.gz: '008fdfc2e46435b3bb49aae67e30b3ef354ca0c923c935c918088ee25eec7bda'
4
+ data.tar.gz: 2fe7d85c853361d12f02f58d19e4bef43ffc81d3683ef5f8b3776657eb86c5ae
5
5
  SHA512:
6
- metadata.gz: 5cce143a95d508694221f1c667428f850ce7aa537e73f61c1869498b68a5751afe2ac386215b96702a1a27bcad3758c474ba09870a1cd7a31a7c33a17ebd4d53
7
- data.tar.gz: 7f81e1876f231899588b174c87c4a0a3ca3bcbc4057216092311b300cff7d23d6541083b5e481e811795042538e2e6713b1a9f5eb5f6eba345e79960335cad91
6
+ metadata.gz: 1c5cc5b43f1813b55b6d1433da88ca661bc692a21785ffad1c2e13c459f0d2b4cb6bbf6251f5e774924a73e8e60f8c2517deaf71a0a1f74f57b2094e822e82ac
7
+ data.tar.gz: 0bb8d97ef6338703e601bd964405c090823ceded7cfa3045d42618a575397ca057591f6aad1cad6d1a74a7f4b877de11bced2d566424c75b53d80d2ce018cda0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.2.1] - 2021-11-20
4
+ - Trying to fetch user ID for a string that isn't email-like raises an error.
5
+ - In tests, fetching user IDs is mocked out to prevent network requests.
6
+ - Tightened up and clarified README.
7
+ - Some internal cleanup and restructuring of modules.
8
+
3
9
  ## [2.2.0] - 2021-11-20
4
10
  - When sending text, it is now possible to mention users and have their user
5
11
  IDs automatically converted using `<email@email.com>` within text nodes.
data/README.md CHANGED
@@ -15,19 +15,21 @@ end
15
15
 
16
16
  To install, just add `slack_message` to your bundle and you're ready to go.
17
17
 
18
- Opinionated Stances
19
- ------------
18
+ #### Opinionated Stances
20
19
 
21
20
  Slack's API has a lot of options available to you! But this gem takes some
22
- opinionated stances on how to make use of that API. For instance:
21
+ opinionated stances about usage to try to minimize the pain of integrating
22
+ with it. For example:
23
23
 
24
- * No dependencies. Your lockfile is enough of a mess already.
24
+ * SlackMessage has no dependencies. Your lockfile is enough of a mess already.
25
+ * The code to build a message should look a lot like the message itself. Code
26
+ that is simple to read and understand is a priority.
25
27
  * Webhooks are passé. Only Slack Apps are supported now.
26
28
  * Unless you request otherwise, text is always rendered using `mrkdwn`. If you
27
29
  want plaintext, you'll need to ask for it. Same for the `emoji` flag.
28
30
  * As many API semantics as possible are hidden. For instance, if you post to
29
- something that looks like an email address, `slack_message` is going to try to
30
- look it up as an email address.
31
+ something that looks like an email address, `slack_message` is going to try
32
+ to look it up as an email address.
31
33
  * A few little hacks on the block syntax, such as adding a `blank_line` (which
32
34
  doesn't exist in the API), or leading spaces.
33
35
  * Configuration is kept as simple as possible. But, as much heavy lifting as
@@ -173,9 +175,7 @@ It's just as easy to send messages directly to users. SlackMessage will look for
173
175
  targets that are email-addressish, and look them up for you automatically:
174
176
 
175
177
  ```ruby
176
- user_email = 'hello@joemastey.com'
177
-
178
- SlackMessage.post_to(user_email) do
178
+ SlackMessage.post_to('hello@joemastey.com') do
179
179
  text "You specifically did it! :thumbsup:"
180
180
  end
181
181
  ```
@@ -207,15 +207,13 @@ SlackMessage.post_to('#general') do
207
207
  text "See more here: #{link('result', 'https://google.com')}"
208
208
  end
209
209
 
210
- text ":rocketship: hello@joemastey.com"
210
+ text ":rocketship: <hello@joemastey.com>"
211
211
 
212
212
  context ":custom_slack_emoji: An example footer *with some markdown*."
213
213
  end
214
214
  ```
215
215
 
216
216
  SlackMessage will compose this into Block Kit syntax and send it on its way!
217
- For now you'll need to read a bit of the source code to get the entire API. Sorry,
218
- working on it.
219
217
 
220
218
  If you've defined multiple profiles in configuration, you can specify which to
221
219
  use for your message by specifying its name:
@@ -223,6 +221,7 @@ use for your message by specifying its name:
223
221
  ```ruby
224
222
  SlackMessage.post_to('#general', as: :sidekiq_bot) do
225
223
  text ":octagonal_sign: A job has failed permanently and needs to be rescued."
224
+
226
225
  link_button "Sidekiq Dashboard", sidekiq_dashboard_url, style: :danger
227
226
  end
228
227
  ```
@@ -261,16 +260,16 @@ SlackMessage.post_to('#general') do
261
260
  end
262
261
  ```
263
262
 
264
- Emails that are not wrapped in tags will be rendered as normal clickable email
265
- addresses. Additionally, Slack will automatically convert a number of channel
266
- names and tags you're probably already used to:
263
+ Emails that are not wrapped in tags will be rendered as normal email addresses.
264
+ Additionally, Slack will automatically convert a number of channel names and
265
+ tags you're probably already used to:
267
266
 
268
267
  ```ruby
269
268
  SlackMessage.post_to('#general') do
270
269
  bot_name "CoffeeBot"
271
270
  bot_icon ":coffee:"
272
271
 
273
- text "@here there's no coffee left!"
272
+ text "@here There's no coffee left! Let #general know when you fix it."
274
273
  end
275
274
  ```
276
275
 
@@ -303,8 +302,8 @@ RSpec.configure do |config|
303
302
  end
304
303
  ```
305
304
 
306
- This will stop API calls for posting messages, and will allow you access to
307
- some custom matchers:
305
+ This will prevent API calls from leaking in your tests, and will allow you
306
+ access to some custom matchers:
308
307
 
309
308
  ```ruby
310
309
  expect {
@@ -340,12 +339,12 @@ of very complicated regexes.
340
339
  What it Doesn't Do
341
340
  ------------
342
341
 
343
- This gem is intended to stay fairly simple. Other gems have lots of config
344
- options and abilities, which is wonderful, but overall complicates usage. If
345
- you want to add a feature, open an issue on Github first to see if it's likely
346
- to be merged. This gem was built out of an existing need that _didn't_ include
347
- most of the block API, but I'd be inclined to merge features that sustainably
348
- expand the DSL to include more useful features.
342
+ This gem is intended to stay simple. Other Slack gems have lots of config
343
+ options and abilities, which makes them powerful, but makes them a pain to use.
344
+ If you want to add a feature, open an issue on Github first to see if it's
345
+ likely to be merged. This gem was built out of an existing need that _didn't_
346
+ include all of the block API, but I'd be inclined to merge features that
347
+ sustainably expand the DSL to include more useful features.
349
348
 
350
349
  Some behaviors that are still planned but not yet added:
351
350
 
@@ -357,6 +356,7 @@ Some behaviors that are still planned but not yet added:
357
356
  * multiple recipients
358
357
  * more interesting return types for your message
359
358
  * richer text formatting (for instance, `ul` is currently a hack)
359
+ * more and better organized testing capability
360
360
 
361
361
  Contributing
362
362
  ------------
@@ -2,18 +2,16 @@ require 'net/http'
2
2
  require 'net/https'
3
3
  require 'json'
4
4
 
5
- class SlackMessage::Api
6
- def self.user_id_for(email, profile)
7
- uri = URI("https://slack.com/api/users.lookupByEmail?email=#{email}")
8
- request = Net::HTTP::Get.new(uri).tap do |req|
9
- req['Authorization'] = "Bearer #{profile[:api_token]}"
10
- req['Content-type'] = "application/json; charset=utf-8"
11
- end
5
+ module SlackMessage::Api
6
+ extend self
12
7
 
13
- response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
14
- http.request(request)
8
+ def user_id_for(email, profile)
9
+ unless email =~ SlackMessage::EMAIL_PATTERN
10
+ raise ArgumentError, "Tried to find profile by invalid email address '#{email}'"
15
11
  end
16
12
 
13
+ response = look_up_user_by_email(email, profile)
14
+
17
15
  if response.code != "200"
18
16
  raise SlackMessage::ApiError, "Got an error back from the Slack API (HTTP #{response.code}):\n#{response.body}"
19
17
  elsif response.body == ""
@@ -37,7 +35,7 @@ class SlackMessage::Api
37
35
  payload["user"]["id"]
38
36
  end
39
37
 
40
- def self.post(payload, target, profile)
38
+ def post(payload, target, profile)
41
39
  params = {
42
40
  channel: target,
43
41
  username: payload.custom_bot_name || profile[:name],
@@ -80,8 +78,23 @@ class SlackMessage::Api
80
78
  response
81
79
  end
82
80
 
83
- # mostly test harness
84
- def self.post_message(profile, params)
81
+ private
82
+
83
+ # mostly for test harnesses
84
+
85
+ def look_up_user_by_email(email, profile)
86
+ uri = URI("https://slack.com/api/users.lookupByEmail?email=#{email}")
87
+ request = Net::HTTP::Get.new(uri).tap do |req|
88
+ req['Authorization'] = "Bearer #{profile[:api_token]}"
89
+ req['Content-type'] = "application/json; charset=utf-8"
90
+ end
91
+
92
+ Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
93
+ http.request(request)
94
+ end
95
+ end
96
+
97
+ def post_message(profile, params)
85
98
  uri = URI("https://slack.com/api/chat.postMessage")
86
99
  request = Net::HTTP::Post.new(uri).tap do |req|
87
100
  req['Authorization'] = "Bearer #{profile[:api_token]}"
@@ -93,6 +106,4 @@ class SlackMessage::Api
93
106
  http.request(request)
94
107
  end
95
108
  end
96
-
97
- private_class_method :post_message
98
109
  end
@@ -2,7 +2,7 @@ class SlackMessage::Dsl
2
2
  attr_reader :body, :default_section, :custom_bot_name, :custom_bot_icon, :profile
3
3
  attr_accessor :custom_notification
4
4
 
5
- EMSPACE = " " # unicode emspace
5
+ EMSPACE = " " # unicode emspace, Slack won't compress this
6
6
 
7
7
  def initialize(block, profile)
8
8
  # Delegate missing methods to caller scope. Thanks 2008:
@@ -108,11 +108,9 @@ class SlackMessage::Dsl
108
108
  @caller_self.send meth, *args, &blk
109
109
  end
110
110
 
111
- EMAIL_TAG_PATTERN = /<[^@ \t\r\n\<]+@[^@ \t\r\n]+\.[^@ \t\r\n]+>/
112
-
113
111
  # replace emails w/ real user IDs
114
112
  def enrich_text(text_body)
115
- text_body.scan(EMAIL_TAG_PATTERN).each do |email_tag|
113
+ text_body.scan(SlackMessage::EMAIL_TAG_PATTERN).each do |email_tag|
116
114
  raw_email = email_tag.gsub(/[><]/, '')
117
115
  user_id = SlackMessage::Api::user_id_for(raw_email, profile)
118
116
 
@@ -30,7 +30,7 @@ module SlackMessage::RSpec
30
30
  FauxResponse = Struct.new(:code, :body)
31
31
 
32
32
  def self.included(_)
33
- SlackMessage::Api.singleton_class.undef_method(:post_message)
33
+ SlackMessage::Api.undef_method(:post_message)
34
34
  SlackMessage::Api.define_singleton_method(:post_message) do |profile, params|
35
35
  @@listeners.each do |listener|
36
36
  listener.record_call(params.merge(profile: profile))
@@ -53,6 +53,12 @@ module SlackMessage::RSpec
53
53
 
54
54
  return FauxResponse.new('200', response.to_json)
55
55
  end
56
+
57
+ SlackMessage::Api.undef_method(:look_up_user_by_email)
58
+ SlackMessage::Api.define_singleton_method(:look_up_user_by_email) do |email, profile|
59
+ response = {"ok"=>true, "user"=>{"id"=>"U5432CBA"}}
60
+ return FauxResponse.new('200', response.to_json)
61
+ end
56
62
  end
57
63
 
58
64
  # w/ channel
data/lib/slack_message.rb CHANGED
@@ -3,6 +3,9 @@ module SlackMessage
3
3
  require 'slack_message/api'
4
4
  require 'slack_message/configuration'
5
5
 
6
+ EMAIL_TAG_PATTERN = /<[^@ \t\r\n\<]+@[^@ \t\r\n]+\.[^@ \t\r\n]+>/
7
+ EMAIL_PATTERN = /^\S{1,}@\S{2,}\.\S{2,}$/
8
+
6
9
  class ApiError < RuntimeError; end
7
10
 
8
11
  def self.configuration
@@ -25,7 +28,7 @@ module SlackMessage
25
28
  instance.instance_eval(&block)
26
29
  end
27
30
 
28
- target = Api::user_id_for(target, profile) if target =~ /^\S{1,}@\S{2,}\.\S{2,}$/
31
+ target = Api::user_id_for(target, profile) if target =~ EMAIL_PATTERN
29
32
 
30
33
  Api.post(payload, target, profile)
31
34
  end
@@ -41,7 +44,7 @@ module SlackMessage
41
44
  end
42
45
 
43
46
  target = profile[:default_channel]
44
- target = Api::user_id_for(target, profile) if target =~ /^\S{1,}@\S{2,}\.\S{2,}$/
47
+ target = Api::user_id_for(target, profile) if target =~ EMAIL_PATTERN
45
48
 
46
49
  Api.post(payload, target, profile)
47
50
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = 'slack_message'
3
- gem.version = "2.2.0"
3
+ gem.version = "2.2.1"
4
4
  gem.summary = "A nice DSL for composing rich messages in Slack"
5
5
  gem.authors = ["Joe Mastey"]
6
6
  gem.email = 'hello@joemastey.com'
@@ -132,15 +132,6 @@ RSpec.describe SlackMessage do
132
132
  end
133
133
  end
134
134
 
135
- it "can grab user IDs" do
136
- allow(Net::HTTP).to receive(:start).and_return(
137
- double(code: "200", body: '{ "user": { "id": "ABC123" }}')
138
- )
139
-
140
- result = SlackMessage::Api.user_id_for("hello@joemastey.com", profile)
141
- expect(result).to eq("ABC123")
142
- end
143
-
144
135
  it "converts user IDs within text when tagged properly" do
145
136
  allow(SlackMessage::Api).to receive(:user_id_for).and_return('ABC123')
146
137
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slack_message
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Mastey