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 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: []