immosquare-slack 0.2.1 → 0.2.2

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: 382c2959d5d7d3869803f78d02a7247288a194045513777288caff5c2fa7abae
4
- data.tar.gz: 403787e3740082733bb3966bd58bde6ccb45d4e3768e8f06027c1470e66872d3
3
+ metadata.gz: 8ee55a9d9a3ffafa9f99139fbe4931f30bff4138ea4e77ff1ba8d5e1b005f55a
4
+ data.tar.gz: 1e2c4c73dc40c6caf741b983317e878204b9f1e42a865fdb7ca8ede4c2921510
5
5
  SHA512:
6
- metadata.gz: c93db1d79831bfbaab04b9e00b8fba3236c5e0e5bd040207498d573c05897575de36ef6ec38ecfadfc35481c4469e0a1fd8dce97c674d846ec57ee9606f3c78d
7
- data.tar.gz: 233f3fe54d124c757f3c07369ca7a9d1e615d42b6c09d98d86e931d5dd98e22d7cd9abd9d042375d1a70b2c2aa9878ed79719ce11864a91ecf32e333b92d1c22
6
+ metadata.gz: cc6d87db38e715bb3804a6f86755d9a055d55753bac17d5799bd99462d1e4b61e65a177af45c57da4777ddeb61e9689972e51b212debca92723d5bcbba015502
7
+ data.tar.gz: 3bec4651abf9eafeec9aecbc40581ed4f54733c614a3e370bedd7f2b6161f391f1b79acf88c8d2b5d466168a58a65e442f1b81437dfc1019803a9ac41c287773
@@ -40,6 +40,13 @@ module ImmosquareSlack
40
40
  ## If no channel can be resolved after fallback, raises an
41
41
  ## ArgumentError immediately (clearer than the cryptic error
42
42
  ## returned by the Slack API).
43
+ ##
44
+ ## Slack only notifies a mention to members of the channel the
45
+ ## message lands in. When `notify` is an Array of emails, the
46
+ ## mentioned users outside that channel (all of them when the
47
+ ## message falls back to the general channel) also receive it
48
+ ## as a direct message from the bot, unless
49
+ ## `direct_message_unreachable_mentions` is disabled.
43
50
  ##============================================================##
44
51
  def post_message(text, channel_name: nil, notify: nil, notify_text: nil, bot_name: nil, notify_general_if_invalid_channel: true)
45
52
  channel_name ||= ImmosquareSlack.configuration.default_channel
@@ -52,28 +59,22 @@ module ImmosquareSlack
52
59
  ## the memoized list predates its creation. Retry once on a
53
60
  ## freshly fetched list before declaring it missing.
54
61
  ##============================================================##
55
- channel_id = get_channel_id_by_name(channel_name)
56
- channel_id = get_channel_id_by_name(channel_name, :force => true) if channel_id.nil?
62
+ channel_id = get_channel_id_by_name(channel_name)
63
+ channel_id = get_channel_id_by_name(channel_name, :force => true) if channel_id.nil?
64
+ mentioned_members = notify.is_a?(Array) ? members_with_emails(notify) : []
57
65
 
58
66
  if channel_id.nil?
59
- text = "immosquare-slack missing channel *#{channel_name}*\nmessage:\n#{text}"
60
- return post_message(text, :channel_name => GENERAL_CHANNEL, :notify => :channel, :notify_text => "", :bot_name => bot_name, :notify_general_if_invalid_channel => false) if channel_name != GENERAL_CHANNEL && notify_general_if_invalid_channel
67
+ raise("channel '#{channel_name}' not found on slack") if channel_name == GENERAL_CHANNEL || !notify_general_if_invalid_channel
61
68
 
62
- raise("channel '#{channel_name}' not found on slack")
69
+ direct_message_unreachable_members(mentioned_members, nil, "Mentioned in *##{channel_name}* (channel not found):\n#{text}", bot_name)
70
+ text = "immosquare-slack missing channel *#{channel_name}*\nmessage:\n#{text}"
71
+ return post_message(text, :channel_name => GENERAL_CHANNEL, :notify => :channel, :notify_text => "", :bot_name => bot_name, :notify_general_if_invalid_channel => false)
63
72
  end
64
73
 
65
- url = "https://slack.com/api/chat.postMessage"
66
- notification_text = notify ? build_notification_text(channel_id, notify, *notify_text) : nil
67
- text = "#{notification_text}#{text}"
68
-
69
- body = {
70
- :channel => channel_id,
71
- :text => text
72
- }
73
-
74
- body[:username] = bot_name if bot_name
75
-
76
- make_slack_api_call(url, :method => :post, :body => body)
74
+ notification_text = notify ? build_notification_text(channel_id, notify, mentioned_members, *notify_text) : nil
75
+ response = send_message(channel_id, "#{notification_text}#{text}", bot_name)
76
+ direct_message_unreachable_members(mentioned_members, channel_id, "Mentioned in <##{channel_id}>:\n#{text}", bot_name)
77
+ response
77
78
  end
78
79
 
79
80
  private
@@ -102,6 +103,54 @@ module ImmosquareSlack
102
103
  fetch_paginated_data("https://slack.com/api/conversations.members", "members", {:channel => channel_id})
103
104
  end
104
105
 
106
+ ##============================================================##
107
+ ## Posts `text` to a conversation: a channel id, or a user id
108
+ ## for a direct message from the bot.
109
+ ##============================================================##
110
+ def send_message(conversation_id, text, bot_name)
111
+ body = {
112
+ :channel => conversation_id,
113
+ :text => text
114
+ }
115
+
116
+ body[:username] = bot_name if bot_name
117
+
118
+ make_slack_api_call("https://slack.com/api/chat.postMessage", :method => :post, :body => body)
119
+ end
120
+
121
+ ##============================================================##
122
+ ## Active workspace members whose `profile.email` is in
123
+ ## `emails`. Without the `users:read.email` scope no profile
124
+ ## carries an email, so nobody matches.
125
+ ##
126
+ ## Piège : `users.list` renvoie aussi les comptes désactivés,
127
+ ## qui gardent leur email mais ne peuvent recevoir aucun DM.
128
+ ##============================================================##
129
+ def members_with_emails(emails)
130
+ ImmosquareSlack::User.list_users.select {|m| !m["deleted"] && emails.include?(m.dig("profile", "email")) }
131
+ end
132
+
133
+ ##============================================================##
134
+ ## Sends `text` as a direct message to the mentioned members who
135
+ ## are not in the channel (`channel_id` nil: none of them is
136
+ ## reachable), since Slack would not notify them.
137
+ ##
138
+ ## Best effort : un DM refusé par Slack est ignoré. Le laisser
139
+ ## remonter ferait échouer `post_message` après le post dans le
140
+ ## channel (doublon au retry de l'appelant) ou avant le repli
141
+ ## sur general (message perdu).
142
+ ##============================================================##
143
+ def direct_message_unreachable_members(mentioned_members, channel_id, text, bot_name)
144
+ return if mentioned_members.empty? || !ImmosquareSlack.configuration.direct_message_unreachable_mentions
145
+
146
+ channel_member_ids = channel_id ? get_channel_members(channel_id) : []
147
+ mentioned_members.reject {|m| channel_member_ids.include?(m["id"]) }.each do |member|
148
+ send_message(member["id"], text, bot_name)
149
+ rescue RuntimeError
150
+ next
151
+ end
152
+ end
153
+
105
154
  ##============================================================##
106
155
  ## Builds the notification prefix prepended to the message
107
156
  ## body. `notify` may be:
@@ -112,12 +161,10 @@ module ImmosquareSlack
112
161
  ## Note: avoids `in?` and `present?` so the gem stays usable
113
162
  ## from plain Ruby (no Rails / ActiveSupport required).
114
163
  ##============================================================##
115
- def build_notification_text(channel_id, notify, text = "Hello")
164
+ def build_notification_text(channel_id, notify, mentioned_members, text = "Hello")
116
165
  final =
117
166
  if notify.is_a?(Array)
118
- members = ImmosquareSlack::User.list_users
119
- members = members.select {|m| notify.include?(m["profile"]["email"]) }
120
- members.map {|m| "<@#{m["id"]}>" }.join(", ")
167
+ mentioned_members.map {|m| "<@#{m["id"]}>" }.join(", ")
121
168
  elsif notify.to_sym == :all
122
169
  members = get_channel_members(channel_id)
123
170
  members.map {|m| "<@#{m}>" }.join(", ")
@@ -1,12 +1,13 @@
1
1
  module ImmosquareSlack
2
2
  class Configuration
3
3
 
4
- attr_accessor :slack_api_token_bot, :default_channel, :default_bot_name
4
+ attr_accessor :slack_api_token_bot, :default_channel, :default_bot_name, :direct_message_unreachable_mentions
5
5
 
6
6
  def initialize
7
- @slack_api_token_bot = nil
8
- @default_channel = nil
9
- @default_bot_name = nil
7
+ @slack_api_token_bot = nil
8
+ @default_channel = nil
9
+ @default_bot_name = nil
10
+ @direct_message_unreachable_mentions = true
10
11
  end
11
12
 
12
13
  end
@@ -1,6 +1,7 @@
1
1
  module ImmosquareSlack
2
2
  module User
3
3
  extend SharedMethods
4
+
4
5
  class << self
5
6
 
6
7
 
@@ -1,3 +1,3 @@
1
1
  module ImmosquareSlack
2
- VERSION = "0.2.1".freeze
2
+ VERSION = "0.2.2".freeze
3
3
  end
@@ -4,15 +4,15 @@ require_relative "immosquare-slack/channel"
4
4
  require_relative "immosquare-slack/user"
5
5
 
6
6
 
7
- ##===========================================================================##
8
- ##
9
- ##===========================================================================##
7
+ ##============================================================##
8
+ ## ...
9
+ ##============================================================##
10
10
  module ImmosquareSlack
11
11
  class << self
12
12
 
13
- ##===========================================================================##
13
+ ##============================================================##
14
14
  ## Gem configuration
15
- ##===========================================================================##
15
+ ##============================================================##
16
16
  attr_writer :configuration
17
17
 
18
18
  def configuration
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: immosquare-slack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - immosquare
@@ -58,7 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
58
58
  - !ruby/object:Gem::Version
59
59
  version: '0'
60
60
  requirements: []
61
- rubygems_version: 4.0.12
61
+ rubygems_version: 4.0.23
62
62
  specification_version: 4
63
63
  summary: A Ruby gem for integrating with Slack API to perform various actions like
64
64
  posting messages.