slacks 0.5.0 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0fe5955626325049c7ec170b8c67cb5b652d2d97
4
- data.tar.gz: b73672adfc7da3608a86453a6b6c7c6b5271a5c5
2
+ SHA256:
3
+ metadata.gz: ffbca3af38608a41841c035811bd052e30a2a2acd39bf58fbef037a1b4ab8bd1
4
+ data.tar.gz: 29e54298f59bbbca5b1eb25d90e7d7496bd7d77535a8b03c50afee5fbbaee43a
5
5
  SHA512:
6
- metadata.gz: 44dc3585e769b303e2f82e57cc50b8d83e023c3a9e7a0cbeff276c10da8ddd67965f5f463059adc6151a35fb29f5cf3d5577a0810cfe5e2781c8090777f3315e
7
- data.tar.gz: 71a0cc131fe1fc997093f8d0da62c971bcc50241699a80ce2cabd2cb8b7c7e0b0d25eb00058b226373ab0a96307bc1abec6a30f6ec3824775adacefa1c85626c
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
@@ -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
- @groups_by_id = {}
28
- @group_id_by_name = {}
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
- group = data["channel"]
121
- @groups_by_id[group["id"]] = group
122
- @group_id_by_name[group["name"]] = group["id"]
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 + group_id_by_name.keys + channel_id_by_name.keys
152
+ channels = user_id_by_name.keys + conversation_ids_by_name.keys
161
153
  if channels.empty?
162
- fetch_channels!
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).present?
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, channels_by_id.fetch(id) do
192
- raise ArgumentError, "Unable to find a channel with the ID #{id.inspect}"
193
- end)
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
- Slacks::User.new(self, users_by_id.fetch(id) do
199
- raise ArgumentError, "Unable to find a user with the ID #{id.inspect}"
200
- end)
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).present?
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
- :groups_by_id,
228
- :group_id_by_name,
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
- @channels_by_id = Hash[response.fetch("channels").map { |attrs| [attrs.fetch("id"), attrs] }]
242
- @channel_id_by_name = Hash[response.fetch("channels").map { |attrs| ["##{attrs.fetch("name")}", attrs.fetch("id")] }]
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
- def to_group_id(name)
263
- group_id_by_name[name] || fetch_groups![name] || missing_group!(name)
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("im.open", user: user_id)
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
- def fetch_channels!
284
- response = api("channels.list")
285
- @channels_by_id = response["channels"].index_by { |attrs| attrs["id"] }
286
- @channel_id_by_name = Hash[response["channels"].map { |attrs| ["##{attrs["name"]}", attrs["id"]] }]
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"].index_by { |attrs| attrs["id"] }
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 missing_channel!(name)
304
- raise ArgumentError, "Couldn't find a channel named #{name}"
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
- response = api("im.list")
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
- response = http.post(command, params.merge(token: token))
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.use Faraday::RaiseErrors
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
@@ -1,3 +1,3 @@
1
1
  module Slacks
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.4"
3
3
  end
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", "~> 1.10"
29
- spec.add_development_dependency "rake", "~> 10.0"
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.5.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: 2017-04-01 00:00:00.000000000 Z
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: faraday-raise-errors
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: concurrent-ruby
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: :runtime
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: '10.0'
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: '10.0'
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
- rubyforge_project:
215
- rubygems_version: 2.5.1
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: []