immosquare-slack 0.2.0 → 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 +4 -4
- data/lib/immosquare-slack/channel.rb +86 -26
- data/lib/immosquare-slack/configuration.rb +5 -4
- data/lib/immosquare-slack/user.rb +1 -0
- data/lib/immosquare-slack/version.rb +1 -1
- data/lib/immosquare-slack.rb +5 -5
- 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: 8ee55a9d9a3ffafa9f99139fbe4931f30bff4138ea4e77ff1ba8d5e1b005f55a
|
|
4
|
+
data.tar.gz: 1e2c4c73dc40c6caf741b983317e878204b9f1e42a865fdb7ca8ede4c2921510
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cc6d87db38e715bb3804a6f86755d9a055d55753bac17d5799bd99462d1e4b61e65a177af45c57da4777ddeb61e9689972e51b212debca92723d5bcbba015502
|
|
7
|
+
data.tar.gz: 3bec4651abf9eafeec9aecbc40581ed4f54733c614a3e370bedd7f2b6161f391f1b79acf88c8d2b5d466168a58a65e442f1b81437dfc1019803a9ac41c287773
|
|
@@ -8,10 +8,17 @@ module ImmosquareSlack
|
|
|
8
8
|
|
|
9
9
|
##============================================================##
|
|
10
10
|
## Fetches the list of channels (public + private, including
|
|
11
|
-
## archived)
|
|
12
|
-
##
|
|
11
|
+
## archived), memoized per process for the lifetime of that
|
|
12
|
+
## process (a Puma worker or Sidekiq runs for hours/days).
|
|
13
|
+
##
|
|
14
|
+
## Piège : le cache ne reflète que l'état du workspace au
|
|
15
|
+
## premier appel. Un channel créé ou renommé ensuite n'y est
|
|
16
|
+
## pas. `force: true` vide le cache et refetch — à utiliser sur
|
|
17
|
+
## un miss de lookup pour distinguer un channel réellement
|
|
18
|
+
## absent d'un cache périmé avant tout fallback.
|
|
13
19
|
##============================================================##
|
|
14
|
-
def list_channels
|
|
20
|
+
def list_channels(force: false)
|
|
21
|
+
@list_channels = nil if force
|
|
15
22
|
@list_channels ||= begin
|
|
16
23
|
extra_params = {
|
|
17
24
|
:types => ["public_channel", "private_channel"].join(","),
|
|
@@ -33,6 +40,13 @@ module ImmosquareSlack
|
|
|
33
40
|
## If no channel can be resolved after fallback, raises an
|
|
34
41
|
## ArgumentError immediately (clearer than the cryptic error
|
|
35
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.
|
|
36
50
|
##============================================================##
|
|
37
51
|
def post_message(text, channel_name: nil, notify: nil, notify_text: nil, bot_name: nil, notify_general_if_invalid_channel: true)
|
|
38
52
|
channel_name ||= ImmosquareSlack.configuration.default_channel
|
|
@@ -40,27 +54,27 @@ module ImmosquareSlack
|
|
|
40
54
|
|
|
41
55
|
raise(ArgumentError, "channel_name is required (or set ImmosquareSlack.configuration.default_channel)") if channel_name.nil?
|
|
42
56
|
|
|
43
|
-
|
|
57
|
+
##============================================================##
|
|
58
|
+
## A miss can mean the channel really doesn't exist, or that
|
|
59
|
+
## the memoized list predates its creation. Retry once on a
|
|
60
|
+
## freshly fetched list before declaring it missing.
|
|
61
|
+
##============================================================##
|
|
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) : []
|
|
44
65
|
|
|
45
66
|
if channel_id.nil?
|
|
46
|
-
|
|
47
|
-
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
|
|
48
68
|
|
|
49
|
-
|
|
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)
|
|
50
72
|
end
|
|
51
73
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
body = {
|
|
57
|
-
:channel => channel_id,
|
|
58
|
-
:text => text
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
body[:username] = bot_name if bot_name
|
|
62
|
-
|
|
63
|
-
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
|
|
64
78
|
end
|
|
65
79
|
|
|
66
80
|
private
|
|
@@ -70,8 +84,8 @@ module ImmosquareSlack
|
|
|
70
84
|
## via the `is_general` flag because workspaces can rename
|
|
71
85
|
## their general channel.
|
|
72
86
|
##============================================================##
|
|
73
|
-
def get_channel_id_by_name(channel_name)
|
|
74
|
-
channels = list_channels
|
|
87
|
+
def get_channel_id_by_name(channel_name, force: false)
|
|
88
|
+
channels = list_channels(:force => force)
|
|
75
89
|
channel = channels.find do |c|
|
|
76
90
|
if channel_name == GENERAL_CHANNEL
|
|
77
91
|
c["is_general"]
|
|
@@ -79,7 +93,7 @@ module ImmosquareSlack
|
|
|
79
93
|
c["name"] == channel_name && c["is_archived"] == false
|
|
80
94
|
end
|
|
81
95
|
end
|
|
82
|
-
channel
|
|
96
|
+
channel&.[]("id")
|
|
83
97
|
end
|
|
84
98
|
|
|
85
99
|
##============================================================##
|
|
@@ -89,6 +103,54 @@ module ImmosquareSlack
|
|
|
89
103
|
fetch_paginated_data("https://slack.com/api/conversations.members", "members", {:channel => channel_id})
|
|
90
104
|
end
|
|
91
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
|
+
|
|
92
154
|
##============================================================##
|
|
93
155
|
## Builds the notification prefix prepended to the message
|
|
94
156
|
## body. `notify` may be:
|
|
@@ -99,12 +161,10 @@ module ImmosquareSlack
|
|
|
99
161
|
## Note: avoids `in?` and `present?` so the gem stays usable
|
|
100
162
|
## from plain Ruby (no Rails / ActiveSupport required).
|
|
101
163
|
##============================================================##
|
|
102
|
-
def build_notification_text(channel_id, notify, text = "Hello")
|
|
164
|
+
def build_notification_text(channel_id, notify, mentioned_members, text = "Hello")
|
|
103
165
|
final =
|
|
104
166
|
if notify.is_a?(Array)
|
|
105
|
-
|
|
106
|
-
members = members.select {|m| notify.include?(m["profile"]["email"]) }
|
|
107
|
-
members.map {|m| "<@#{m["id"]}>" }.join(", ")
|
|
167
|
+
mentioned_members.map {|m| "<@#{m["id"]}>" }.join(", ")
|
|
108
168
|
elsif notify.to_sym == :all
|
|
109
169
|
members = get_channel_members(channel_id)
|
|
110
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
|
|
8
|
-
@default_channel
|
|
9
|
-
@default_bot_name
|
|
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
|
data/lib/immosquare-slack.rb
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|