slacks 0.5.0 → 0.6.4
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 +5 -5
- data/CHANGELOG.md +14 -0
- data/lib/slacks/connection.rb +76 -76
- data/lib/slacks/version.rb +1 -1
- data/slacks.gemspec +2 -3
- metadata +15 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ffbca3af38608a41841c035811bd052e30a2a2acd39bf58fbef037a1b4ab8bd1
|
4
|
+
data.tar.gz: 29e54298f59bbbca5b1eb25d90e7d7496bd7d77535a8b03c50afee5fbbaee43a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39d1b8223ac325f57bde88ab86134f0705a3d0ca28da6e88e5f0b3cf8f6e9853e361fb11b8bde50b4bb51d6c4d84a66df685f8b8a129f290cf9a69d09c61ad02
|
7
|
+
data.tar.gz: 2eab93bf02fcf7fef3a5c8844ac42a9a992fd1fd991f6ac708d1ec1d91cf001d5ebb0dfe42a7dec80d7640b624acaa3138431e445d3e63c6d0f4d19c795168f7
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
### v0.6.4
|
2
|
+
- Removed reliance on faraday-raise-errors in favor of using built-in Faraday::RaiseError middleware
|
3
|
+
|
4
|
+
### v0.6.3
|
5
|
+
- Removed remaining calls to `.present?`, since we're not actually dependent on ActiveSupport
|
6
|
+
|
7
|
+
### v0.6.2
|
8
|
+
- Fixed a regression where groups, DMs, and private channels were not fetched
|
9
|
+
|
10
|
+
### v0.6.1
|
11
|
+
- Fixed a typo with creating a DM associated with a user
|
12
|
+
|
13
|
+
### v0.6.0
|
14
|
+
- Switched to using the Slack Conversations API
|
data/lib/slacks/connection.rb
CHANGED
@@ -7,7 +7,6 @@ require "slacks/guest_channel"
|
|
7
7
|
require "slacks/team"
|
8
8
|
require "slacks/user"
|
9
9
|
require "faraday"
|
10
|
-
require "faraday/raise_errors"
|
11
10
|
|
12
11
|
module Slacks
|
13
12
|
class Connection
|
@@ -24,10 +23,8 @@ module Slacks
|
|
24
23
|
@user_ids_dm_ids = {}
|
25
24
|
@users_by_id = {}
|
26
25
|
@user_id_by_name = {}
|
27
|
-
@
|
28
|
-
@
|
29
|
-
@channels_by_id = {}
|
30
|
-
@channel_id_by_name = {}
|
26
|
+
@conversations_by_id = {}
|
27
|
+
@conversation_ids_by_name = {}
|
31
28
|
end
|
32
29
|
|
33
30
|
|
@@ -42,7 +39,7 @@ module Slacks
|
|
42
39
|
link_names: 1} # find and link channel names and user names
|
43
40
|
params.merge!(attachments: MultiJson.dump(attachments)) if attachments.any?
|
44
41
|
params.merge!(options.select { |key, _| SEND_MESSAGE_PARAMS.member?(key) })
|
45
|
-
api("chat.postMessage", params)
|
42
|
+
api("chat.postMessage", **params)
|
46
43
|
end
|
47
44
|
alias :say :send_message
|
48
45
|
|
@@ -50,7 +47,7 @@ module Slacks
|
|
50
47
|
params = {
|
51
48
|
channel: to_channel_id(channel),
|
52
49
|
timestamp: ts }
|
53
|
-
api("reactions.get", params)
|
50
|
+
api("reactions.get", **params)
|
54
51
|
end
|
55
52
|
|
56
53
|
def update_message(ts, message, options={})
|
@@ -65,15 +62,15 @@ module Slacks
|
|
65
62
|
params.merge!(attachments: MultiJson.dump(attachments)) if attachments.any?
|
66
63
|
params.merge!(options.select { |key, _| [:username, :as_user, :parse, :link_names,
|
67
64
|
:unfurl_links, :unfurl_media, :icon_url, :icon_emoji].member?(key) })
|
68
|
-
api("chat.update", params)
|
65
|
+
api("chat.update", **params)
|
69
66
|
end
|
70
67
|
|
71
68
|
def add_reaction(emojis, message)
|
72
69
|
Array(emojis).each do |emoji|
|
73
|
-
api("reactions.add",
|
70
|
+
api("reactions.add",
|
74
71
|
name: emoji.gsub(/^:|:$/, ""),
|
75
72
|
channel: message.channel.id,
|
76
|
-
timestamp: message.timestamp
|
73
|
+
timestamp: message.timestamp)
|
77
74
|
end
|
78
75
|
end
|
79
76
|
|
@@ -116,21 +113,16 @@ module Slacks
|
|
116
113
|
# one, we'll skill it.
|
117
114
|
next
|
118
115
|
|
119
|
-
when EVENT_GROUP_JOINED
|
120
|
-
|
121
|
-
@
|
122
|
-
@
|
116
|
+
when EVENT_GROUP_JOINED, EVENT_CHANNEL_CREATED
|
117
|
+
conversation = data["channel"]
|
118
|
+
@conversations_by_id[conversation["id"]] = conversation
|
119
|
+
@conversation_ids_by_name[conversation["name"]] = conversation["id"]
|
123
120
|
|
124
121
|
when EVENT_USER_JOINED
|
125
122
|
user = data["user"]
|
126
123
|
@users_by_id[user["id"]] = user
|
127
124
|
@user_id_by_name[user["name"]] = user["id"]
|
128
125
|
|
129
|
-
when EVENT_CHANNEL_CREATED
|
130
|
-
channel = data["channel"]
|
131
|
-
@channels_by_id[channel["id"]] = channel
|
132
|
-
@channel_id_by_name[channel["name"]] = channel["id"]
|
133
|
-
|
134
126
|
when EVENT_MESSAGE
|
135
127
|
# Don't respond to things that this bot said
|
136
128
|
next if data["user"] == bot.id
|
@@ -157,17 +149,17 @@ module Slacks
|
|
157
149
|
|
158
150
|
|
159
151
|
def channels
|
160
|
-
channels = user_id_by_name.keys +
|
152
|
+
channels = user_id_by_name.keys + conversation_ids_by_name.keys
|
161
153
|
if channels.empty?
|
162
|
-
|
163
|
-
fetch_groups!
|
154
|
+
fetch_conversations!
|
164
155
|
fetch_users!
|
165
156
|
end
|
166
157
|
channels
|
167
158
|
end
|
168
159
|
|
169
160
|
def can_see?(channel)
|
170
|
-
to_channel_id(channel)
|
161
|
+
channel_id = to_channel_id(channel)
|
162
|
+
channel_id && !channel_id.empty?
|
171
163
|
rescue ArgumentError
|
172
164
|
false
|
173
165
|
end
|
@@ -183,21 +175,28 @@ module Slacks
|
|
183
175
|
"id" => id,
|
184
176
|
"is_im" => true,
|
185
177
|
"name" => user.username }
|
186
|
-
when /^G/
|
187
|
-
Slacks::Channel.new(self, groups_by_id.fetch(id) do
|
188
|
-
raise ArgumentError, "Unable to find a group with the ID #{id.inspect}"
|
189
|
-
end)
|
190
178
|
else
|
191
|
-
Slacks::Channel.new(self,
|
192
|
-
|
193
|
-
|
179
|
+
Slacks::Channel.new(self, find_conversation(id))
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def find_conversation(id)
|
184
|
+
conversations_by_id.fetch(id) do
|
185
|
+
fetch_conversations!
|
186
|
+
conversations_by_id.fetch(id) do
|
187
|
+
raise ArgumentError, "Unable to find a conversation with the ID #{id.inspect}"
|
188
|
+
end
|
194
189
|
end
|
195
190
|
end
|
196
191
|
|
197
192
|
def find_user(id)
|
198
|
-
|
199
|
-
|
200
|
-
|
193
|
+
user = users_by_id.fetch(id) do
|
194
|
+
fetch_users!
|
195
|
+
users_by_id.fetch(id) do
|
196
|
+
raise ArgumentError, "Unable to find a user with the ID #{id.inspect}"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
Slacks::User.new(self, user)
|
201
200
|
end
|
202
201
|
|
203
202
|
def find_user_by_nickname(nickname)
|
@@ -208,7 +207,8 @@ module Slacks
|
|
208
207
|
|
209
208
|
def user_exists?(username)
|
210
209
|
return false if username.nil?
|
211
|
-
to_user_id(username)
|
210
|
+
user_id = to_user_id(username)
|
211
|
+
user_id && !user_id.empty?
|
212
212
|
rescue ArgumentError
|
213
213
|
false
|
214
214
|
end
|
@@ -224,10 +224,8 @@ module Slacks
|
|
224
224
|
attr_reader :user_ids_dm_ids,
|
225
225
|
:users_by_id,
|
226
226
|
:user_id_by_name,
|
227
|
-
:
|
228
|
-
:
|
229
|
-
:channels_by_id,
|
230
|
-
:channel_id_by_name,
|
227
|
+
:conversations_by_id,
|
228
|
+
:conversation_ids_by_name,
|
231
229
|
:websocket_url,
|
232
230
|
:websocket
|
233
231
|
|
@@ -238,14 +236,8 @@ module Slacks
|
|
238
236
|
@bot = BotUser.new(response.fetch("self"))
|
239
237
|
@team = Team.new(response.fetch("team"))
|
240
238
|
|
241
|
-
@
|
242
|
-
@
|
243
|
-
|
244
|
-
@users_by_id = Hash[response.fetch("users").map { |attrs| [attrs.fetch("id"), attrs] }]
|
245
|
-
@user_id_by_name = Hash[response.fetch("users").map { |attrs| ["@#{attrs.fetch("name")}", attrs.fetch("id")] }]
|
246
|
-
|
247
|
-
@groups_by_id = Hash[response.fetch("groups").map { |attrs| [attrs.fetch("id"), attrs] }]
|
248
|
-
@group_id_by_name = Hash[response.fetch("groups").map { |attrs| [attrs.fetch("name"), attrs.fetch("id")] }]
|
239
|
+
@conversations_by_id = Hash[response.fetch("channels").map { |attrs| [ attrs.fetch("id"), attrs ] }]
|
240
|
+
@conversation_ids_by_name = Hash[response.fetch("channels").map { |attrs| [ attrs["name"], attrs["id"] ] }]
|
249
241
|
end
|
250
242
|
|
251
243
|
|
@@ -254,13 +246,9 @@ module Slacks
|
|
254
246
|
return name.id if name.is_a?(Slacks::Channel)
|
255
247
|
return name if name =~ /^[DGC]/ # this already looks like a channel id
|
256
248
|
return get_dm_for_username(name) if name.start_with?("@")
|
257
|
-
return to_group_id(name) unless name.start_with?("#")
|
258
|
-
|
259
|
-
channel_id_by_name[name] || fetch_channels![name] || missing_channel!(name)
|
260
|
-
end
|
261
249
|
|
262
|
-
|
263
|
-
|
250
|
+
name = name.gsub(/^#/, "") # Leading hashes are no longer a thing in the conversations API
|
251
|
+
conversation_ids_by_name[name] || fetch_conversations![name] || missing_conversation!(name)
|
264
252
|
end
|
265
253
|
|
266
254
|
def to_user_id(name)
|
@@ -273,39 +261,29 @@ module Slacks
|
|
273
261
|
|
274
262
|
def get_dm_for_user_id(user_id)
|
275
263
|
user_ids_dm_ids[user_id] ||= begin
|
276
|
-
response = api("
|
264
|
+
response = api("conversations.open", users: user_id)
|
277
265
|
response["channel"]["id"]
|
278
266
|
end
|
279
267
|
end
|
280
268
|
|
281
269
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
@
|
286
|
-
@
|
287
|
-
end
|
288
|
-
|
289
|
-
def fetch_groups!
|
290
|
-
response = api("groups.list")
|
291
|
-
@groups_by_id = response["groups"].index_by { |attrs| attrs["id"] }
|
292
|
-
@group_id_by_name = Hash[response["groups"].map { |attrs| [attrs["name"], attrs["id"]] }]
|
270
|
+
def fetch_conversations!
|
271
|
+
conversations, ims = api("conversations.list", types: "public_channel,private_channel,mpim,im")["channels"].partition { |attrs| attrs["is_channel"] || attrs["is_group"] }
|
272
|
+
user_ids_dm_ids.merge! Hash[ims.map { |attrs| attrs.values_at("user", "id") }]
|
273
|
+
@conversations_by_id = Hash[conversations.map { |attrs| [ attrs.fetch("id"), attrs ] }]
|
274
|
+
@conversation_ids_by_name = Hash[conversations.map { |attrs| [ attrs["name"], attrs["id"] ] }]
|
293
275
|
end
|
294
276
|
|
295
277
|
def fetch_users!
|
296
278
|
response = api("users.list")
|
297
|
-
@users_by_id = response["members"].
|
279
|
+
@users_by_id = response["members"].each_with_object({}) { |attrs, hash| hash[attrs["id"]] = attrs }
|
298
280
|
@user_id_by_name = Hash[response["members"].map { |attrs| ["@#{attrs["name"]}", attrs["id"]] }]
|
299
281
|
end
|
300
282
|
|
301
283
|
|
302
284
|
|
303
|
-
def
|
304
|
-
raise ArgumentError, "Couldn't find a
|
305
|
-
end
|
306
|
-
|
307
|
-
def missing_group!(name)
|
308
|
-
raise ArgumentError, "Couldn't find a private group named #{name}"
|
285
|
+
def missing_conversation!(name)
|
286
|
+
raise ArgumentError, "Couldn't find a conversation named #{name}"
|
309
287
|
end
|
310
288
|
|
311
289
|
def missing_user!(name)
|
@@ -317,8 +295,7 @@ module Slacks
|
|
317
295
|
def get_user_id_for_dm(dm)
|
318
296
|
user_id = user_ids_dm_ids.key(dm)
|
319
297
|
unless user_id
|
320
|
-
|
321
|
-
user_ids_dm_ids.merge! Hash[response["ims"].map { |attrs| attrs.values_at("user", "id") }]
|
298
|
+
fetch_conversations!
|
322
299
|
user_id = user_ids_dm_ids.key(dm)
|
323
300
|
end
|
324
301
|
raise ArgumentError, "Unable to find a user for the direct message ID #{dm.inspect}" unless user_id
|
@@ -327,8 +304,29 @@ module Slacks
|
|
327
304
|
|
328
305
|
|
329
306
|
|
330
|
-
def api(command, params
|
331
|
-
|
307
|
+
def api(command, page_limit: MAX_PAGES, **params)
|
308
|
+
params_with_token = params.merge(token: token)
|
309
|
+
response = api_post command, params_with_token
|
310
|
+
fetched_pages = 1
|
311
|
+
cursor = response.dig("response_metadata", "next_cursor")
|
312
|
+
while cursor && !cursor.empty? && fetched_pages < page_limit do
|
313
|
+
api_post(command, params_with_token.merge(cursor: cursor)).each do |key, value|
|
314
|
+
if value.is_a?(Array)
|
315
|
+
response[key].concat value
|
316
|
+
elsif value.is_a?(Hash)
|
317
|
+
response[key].merge! value
|
318
|
+
else
|
319
|
+
response[key] = value
|
320
|
+
end
|
321
|
+
end
|
322
|
+
fetched_pages += 1
|
323
|
+
cursor = response.dig("response_metadata", "next_cursor")
|
324
|
+
end
|
325
|
+
response
|
326
|
+
end
|
327
|
+
|
328
|
+
def api_post(command, params)
|
329
|
+
response = http.post(command, params)
|
332
330
|
response = MultiJson.load(response.body)
|
333
331
|
unless response["ok"]
|
334
332
|
response["error"].split(/,\s*/).each do |error_code|
|
@@ -345,7 +343,7 @@ module Slacks
|
|
345
343
|
|
346
344
|
def http
|
347
345
|
@http ||= Faraday.new(url: "https://slack.com/api").tap do |connection|
|
348
|
-
connection.
|
346
|
+
connection.response :raise_error
|
349
347
|
end
|
350
348
|
end
|
351
349
|
|
@@ -364,5 +362,7 @@ module Slacks
|
|
364
362
|
reply_broadcast
|
365
363
|
}.freeze
|
366
364
|
|
365
|
+
MAX_PAGES = 9001
|
366
|
+
|
367
367
|
end
|
368
368
|
end
|
data/lib/slacks/version.rb
CHANGED
data/slacks.gemspec
CHANGED
@@ -22,11 +22,10 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_dependency "websocket-driver"
|
23
23
|
spec.add_dependency "multi_json"
|
24
24
|
spec.add_dependency "faraday"
|
25
|
-
spec.add_dependency "faraday-raise-errors"
|
26
25
|
spec.add_dependency "concurrent-ruby"
|
27
26
|
|
28
|
-
spec.add_development_dependency "bundler"
|
29
|
-
spec.add_development_dependency "rake"
|
27
|
+
spec.add_development_dependency "bundler"
|
28
|
+
spec.add_development_dependency "rake"
|
30
29
|
spec.add_development_dependency "minitest", "~> 5.0"
|
31
30
|
spec.add_development_dependency "pry"
|
32
31
|
spec.add_development_dependency "minitest-reporters"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slacks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Lail
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: websocket-driver
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: concurrent-ruby
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -67,47 +67,33 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: bundler
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
|
-
type: :
|
76
|
+
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: bundler
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '1.10'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - "~>"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '1.10'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: rake
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
100
86
|
requirements:
|
101
|
-
- - "
|
87
|
+
- - ">="
|
102
88
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
89
|
+
version: '0'
|
104
90
|
type: :development
|
105
91
|
prerelease: false
|
106
92
|
version_requirements: !ruby/object:Gem::Requirement
|
107
93
|
requirements:
|
108
|
-
- - "
|
94
|
+
- - ">="
|
109
95
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
96
|
+
version: '0'
|
111
97
|
- !ruby/object:Gem::Dependency
|
112
98
|
name: minitest
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -164,7 +150,7 @@ dependencies:
|
|
164
150
|
- - ">="
|
165
151
|
- !ruby/object:Gem::Version
|
166
152
|
version: '0'
|
167
|
-
description:
|
153
|
+
description:
|
168
154
|
email:
|
169
155
|
- bob.lailfamily@gmail.com
|
170
156
|
executables: []
|
@@ -173,6 +159,7 @@ extra_rdoc_files: []
|
|
173
159
|
files:
|
174
160
|
- ".gitignore"
|
175
161
|
- ".travis.yml"
|
162
|
+
- CHANGELOG.md
|
176
163
|
- Gemfile
|
177
164
|
- LICENSE.txt
|
178
165
|
- README.md
|
@@ -196,7 +183,7 @@ homepage: https://github.com/houston/slacks
|
|
196
183
|
licenses:
|
197
184
|
- MIT
|
198
185
|
metadata: {}
|
199
|
-
post_install_message:
|
186
|
+
post_install_message:
|
200
187
|
rdoc_options: []
|
201
188
|
require_paths:
|
202
189
|
- lib
|
@@ -211,9 +198,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
211
198
|
- !ruby/object:Gem::Version
|
212
199
|
version: '0'
|
213
200
|
requirements: []
|
214
|
-
|
215
|
-
|
216
|
-
signing_key:
|
201
|
+
rubygems_version: 3.1.2
|
202
|
+
signing_key:
|
217
203
|
specification_version: 4
|
218
204
|
summary: A library for communicating via Slack
|
219
205
|
test_files: []
|