slacks 0.4.4 → 0.6.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
- SHA1:
3
- metadata.gz: f5dca8b35462a36816d2ac22a58904c7801e779d
4
- data.tar.gz: ea16047ea5dbafc775bbb6d79bdd30c85446aec8
2
+ SHA256:
3
+ metadata.gz: 500a2a7ea4fb23d0901e54e030ce2272a2938ca26cc25346cd8a24a0c6d8fc72
4
+ data.tar.gz: 18bae45d424a793ed7abcb591e7bbbc43f3ac1509bf4bf02751dc92821005d88
5
5
  SHA512:
6
- metadata.gz: 423b632d2810deaac520ea364122ff15030876e66dacdde761d957bd7bd8cabd8caaa6d7d0a1a33293bec184f16e8fe051be35eb94291c595cc28f78857e1a54
7
- data.tar.gz: 889dc9cbc90679e968006aebeac2c798981aa0dde9873e3c14bb4e21da3ab19a3756d2da0a27ee085f298c725f5db16c5bd8f53350a987c9ddad5f58c0fa0fa1
6
+ metadata.gz: 46de7ebf67ce468f1b361b672d36a4cf31a73342db741ce17c9bc6d67fc8cefb461d6edc51ca700cce9c87dd7e47e275134953e3bddfa285fd82d371610c0b5e
7
+ data.tar.gz: 773cb492a2dec48103df2269b0f45a14a6747e3c0d0b1788f691beea11d953446c2bff4f63f45c80b5e45a6bcbd9fbf3af8899edb9440a29a531da0320e77cbb
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ ### v0.6.2
2
+ - Fixed a regression where groups, DMs, and private channels were not fetched
3
+
4
+ ### v0.6.1
5
+ - Fixed a typo with creating a DM associated with a user
6
+
7
+ ### v0.6.0
8
+ - Switched to using the Slack Conversations API
@@ -12,17 +12,12 @@ module Slacks
12
12
  end
13
13
 
14
14
  def reply(*messages)
15
- messages.flatten!
16
15
  return unless messages.any?
17
16
 
18
- first_message = messages.shift
19
- message_options = {}
20
- message_options = messages.shift if messages.length == 1 && messages[0].is_a?(Hash)
21
- slack.send_message(first_message, message_options.merge(channel: id))
22
-
23
- messages.each do |message|
24
- sleep message.length / slack.typing_speed
25
- slack.send_message(message, channel: id)
17
+ if messages.first.is_a?(Array)
18
+ reply_many(messages[0])
19
+ else
20
+ reply_one(*messages)
26
21
  end
27
22
  end
28
23
  alias :say :reply
@@ -61,6 +56,19 @@ module Slacks
61
56
  "##{name}"
62
57
  end
63
58
 
59
+ protected
60
+
61
+ def reply_one(message, options={})
62
+ slack.send_message(message, options.merge(channel: id))
63
+ end
64
+
65
+ def reply_many(messages)
66
+ messages.each_with_index.map do |message, i|
67
+ sleep message.length / slack.typing_speed if i > 0
68
+ slack.send_message(message, channel: id)
69
+ end
70
+ end
71
+
64
72
  private
65
73
  attr_reader :slack
66
74
  end
@@ -24,10 +24,8 @@ module Slacks
24
24
  @user_ids_dm_ids = {}
25
25
  @users_by_id = {}
26
26
  @user_id_by_name = {}
27
- @groups_by_id = {}
28
- @group_id_by_name = {}
29
- @channels_by_id = {}
30
- @channel_id_by_name = {}
27
+ @conversations_by_id = {}
28
+ @conversation_ids_by_name = {}
31
29
  end
32
30
 
33
31
 
@@ -42,9 +40,7 @@ module Slacks
42
40
  link_names: 1} # find and link channel names and user names
43
41
  params.merge!(attachments: MultiJson.dump(attachments)) if attachments.any?
44
42
  params.merge!(options.select { |key, _| SEND_MESSAGE_PARAMS.member?(key) })
45
- api("chat.postMessage", params)
46
- rescue Slacks::ResponseError
47
- $!.response
43
+ api("chat.postMessage", **params)
48
44
  end
49
45
  alias :say :send_message
50
46
 
@@ -52,9 +48,7 @@ module Slacks
52
48
  params = {
53
49
  channel: to_channel_id(channel),
54
50
  timestamp: ts }
55
- api("reactions.get", params)
56
- rescue Slacks::ResponseError
57
- $!.response
51
+ api("reactions.get", **params)
58
52
  end
59
53
 
60
54
  def update_message(ts, message, options={})
@@ -69,34 +63,38 @@ module Slacks
69
63
  params.merge!(attachments: MultiJson.dump(attachments)) if attachments.any?
70
64
  params.merge!(options.select { |key, _| [:username, :as_user, :parse, :link_names,
71
65
  :unfurl_links, :unfurl_media, :icon_url, :icon_emoji].member?(key) })
72
- api("chat.update", params)
73
- rescue Slacks::ResponseError
74
- $!.response
66
+ api("chat.update", **params)
75
67
  end
76
68
 
77
69
  def add_reaction(emojis, message)
78
70
  Array(emojis).each do |emoji|
79
- api("reactions.add", {
71
+ api("reactions.add",
80
72
  name: emoji.gsub(/^:|:$/, ""),
81
73
  channel: message.channel.id,
82
- timestamp: message.timestamp })
74
+ timestamp: message.timestamp)
83
75
  end
84
- rescue Slacks::ResponseError
85
- $!.response
86
76
  end
87
77
 
78
+
79
+
88
80
  def typing_on(channel)
81
+ raise NotListeningError unless listening?
89
82
  websocket.write MultiJson.dump(type: "typing", channel: to_channel_id(channel))
90
83
  end
91
84
 
85
+ def ping
86
+ raise NotListeningError unless listening?
87
+ websocket.ping
88
+ end
89
+
90
+ def listening?
91
+ !websocket.nil?
92
+ end
93
+
92
94
 
93
95
 
94
96
  def listen!
95
97
  response = api("rtm.start")
96
- unless response["ok"]
97
- raise MigrationInProgress if response["error"] == "migration_in_progress"
98
- raise ResponseError.new(response, response["error"])
99
- end
100
98
  store_context!(response)
101
99
 
102
100
  @websocket = Slacks::Driver.new
@@ -116,21 +114,16 @@ module Slacks
116
114
  # one, we'll skill it.
117
115
  next
118
116
 
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"]
117
+ when EVENT_GROUP_JOINED, EVENT_CHANNEL_CREATED
118
+ conversation = data["channel"]
119
+ @conversations_by_id[conversation["id"]] = conversation
120
+ @conversation_ids_by_name[conversation["name"]] = conversation["id"]
123
121
 
124
122
  when EVENT_USER_JOINED
125
123
  user = data["user"]
126
124
  @users_by_id[user["id"]] = user
127
125
  @user_id_by_name[user["name"]] = user["id"]
128
126
 
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
127
  when EVENT_MESSAGE
135
128
  # Don't respond to things that this bot said
136
129
  next if data["user"] == bot.id
@@ -157,10 +150,9 @@ module Slacks
157
150
 
158
151
 
159
152
  def channels
160
- channels = user_id_by_name.keys + group_id_by_name.keys + channel_id_by_name.keys
153
+ channels = user_id_by_name.keys + conversation_ids_by_name.keys
161
154
  if channels.empty?
162
- fetch_channels!
163
- fetch_groups!
155
+ fetch_conversations!
164
156
  fetch_users!
165
157
  end
166
158
  channels
@@ -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)
@@ -224,10 +223,8 @@ module Slacks
224
223
  attr_reader :user_ids_dm_ids,
225
224
  :users_by_id,
226
225
  :user_id_by_name,
227
- :groups_by_id,
228
- :group_id_by_name,
229
- :channels_by_id,
230
- :channel_id_by_name,
226
+ :conversations_by_id,
227
+ :conversation_ids_by_name,
231
228
  :websocket_url,
232
229
  :websocket
233
230
 
@@ -238,16 +235,8 @@ module Slacks
238
235
  @bot = BotUser.new(response.fetch("self"))
239
236
  @team = Team.new(response.fetch("team"))
240
237
 
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")] }]
249
- rescue KeyError
250
- raise ResponseError.new(response, $!.message)
238
+ @conversations_by_id = Hash[response.fetch("channels").map { |attrs| [ attrs.fetch("id"), attrs ] }]
239
+ @conversation_ids_by_name = Hash[response.fetch("channels").map { |attrs| [ attrs["name"], attrs["id"] ] }]
251
240
  end
252
241
 
253
242
 
@@ -256,13 +245,9 @@ module Slacks
256
245
  return name.id if name.is_a?(Slacks::Channel)
257
246
  return name if name =~ /^[DGC]/ # this already looks like a channel id
258
247
  return get_dm_for_username(name) if name.start_with?("@")
259
- return to_group_id(name) unless name.start_with?("#")
260
-
261
- channel_id_by_name[name] || fetch_channels![name] || missing_channel!(name)
262
- end
263
248
 
264
- def to_group_id(name)
265
- group_id_by_name[name] || fetch_groups![name] || missing_group!(name)
249
+ name = name.gsub(/^#/, "") # Leading hashes are no longer a thing in the conversations API
250
+ conversation_ids_by_name[name] || fetch_conversations![name] || missing_conversation!(name)
266
251
  end
267
252
 
268
253
  def to_user_id(name)
@@ -275,40 +260,29 @@ module Slacks
275
260
 
276
261
  def get_dm_for_user_id(user_id)
277
262
  user_ids_dm_ids[user_id] ||= begin
278
- response = api("im.open", user: user_id)
279
- raise UnableToDirectMessageError.new(response, user_id) unless response["ok"]
263
+ response = api("conversations.open", users: user_id)
280
264
  response["channel"]["id"]
281
265
  end
282
266
  end
283
267
 
284
268
 
285
-
286
- def fetch_channels!
287
- response = api("channels.list")
288
- @channels_by_id = response["channels"].index_by { |attrs| attrs["id"] }
289
- @channel_id_by_name = Hash[response["channels"].map { |attrs| ["##{attrs["name"]}", attrs["id"]] }]
290
- end
291
-
292
- def fetch_groups!
293
- response = api("groups.list")
294
- @groups_by_id = response["groups"].index_by { |attrs| attrs["id"] }
295
- @group_id_by_name = Hash[response["groups"].map { |attrs| [attrs["name"], attrs["id"]] }]
269
+ def fetch_conversations!
270
+ conversations, ims = api("conversations.list", types: "public_channel,private_channel,mpim,im")["channels"].partition { |attrs| attrs["is_channel"] || attrs["is_group"] }
271
+ user_ids_dm_ids.merge! Hash[ims.map { |attrs| attrs.values_at("user", "id") }]
272
+ @conversations_by_id = Hash[conversations.map { |attrs| [ attrs.fetch("id"), attrs ] }]
273
+ @conversation_ids_by_name = Hash[conversations.map { |attrs| [ attrs["name"], attrs["id"] ] }]
296
274
  end
297
275
 
298
276
  def fetch_users!
299
277
  response = api("users.list")
300
- @users_by_id = response["members"].index_by { |attrs| attrs["id"] }
278
+ @users_by_id = response["members"].each_with_object({}) { |attrs, hash| hash[attrs["id"]] = attrs }
301
279
  @user_id_by_name = Hash[response["members"].map { |attrs| ["@#{attrs["name"]}", attrs["id"]] }]
302
280
  end
303
281
 
304
282
 
305
283
 
306
- def missing_channel!(name)
307
- raise ArgumentError, "Couldn't find a channel named #{name}"
308
- end
309
-
310
- def missing_group!(name)
311
- raise ArgumentError, "Couldn't find a private group named #{name}"
284
+ def missing_conversation!(name)
285
+ raise ArgumentError, "Couldn't find a conversation named #{name}"
312
286
  end
313
287
 
314
288
  def missing_user!(name)
@@ -320,8 +294,7 @@ module Slacks
320
294
  def get_user_id_for_dm(dm)
321
295
  user_id = user_ids_dm_ids.key(dm)
322
296
  unless user_id
323
- response = api("im.list")
324
- user_ids_dm_ids.merge! Hash[response["ims"].map { |attrs| attrs.values_at("user", "id") }]
297
+ fetch_conversations!
325
298
  user_id = user_ids_dm_ids.key(dm)
326
299
  end
327
300
  raise ArgumentError, "Unable to find a user for the direct message ID #{dm.inspect}" unless user_id
@@ -330,9 +303,36 @@ module Slacks
330
303
 
331
304
 
332
305
 
333
- def api(command, options={})
334
- response = http.post(command, options.merge(token: token))
335
- MultiJson.load(response.body)
306
+ def api(command, page_limit: MAX_PAGES, **params)
307
+ params_with_token = params.merge(token: token)
308
+ response = api_post command, params_with_token
309
+ fetched_pages = 1
310
+ cursor = response.dig("response_metadata", "next_cursor")
311
+ while cursor && !cursor.empty? && fetched_pages < page_limit do
312
+ api_post(command, params_with_token.merge(cursor: cursor)).each do |key, value|
313
+ if value.is_a?(Array)
314
+ response[key].concat value
315
+ elsif value.is_a?(Hash)
316
+ response[key].merge! value
317
+ else
318
+ response[key] = value
319
+ end
320
+ end
321
+ fetched_pages += 1
322
+ cursor = response.dig("response_metadata", "next_cursor")
323
+ end
324
+ response
325
+ end
326
+
327
+ def api_post(command, params)
328
+ response = http.post(command, params)
329
+ response = MultiJson.load(response.body)
330
+ unless response["ok"]
331
+ response["error"].split(/,\s*/).each do |error_code|
332
+ raise ::Slacks::Response.fetch(error_code).new(command, params, response)
333
+ end
334
+ end
335
+ response
336
336
 
337
337
  rescue MultiJson::ParseError
338
338
  $!.additional_information[:response_body] = response.body
@@ -361,5 +361,7 @@ module Slacks
361
361
  reply_broadcast
362
362
  }.freeze
363
363
 
364
+ MAX_PAGES = 9001
365
+
364
366
  end
365
367
  end
data/lib/slacks/driver.rb CHANGED
@@ -70,6 +70,10 @@ module Slacks
70
70
  @driver.text(message)
71
71
  end
72
72
 
73
+ def ping
74
+ @driver.ping
75
+ end
76
+
73
77
  def connected?
74
78
  @connected || false
75
79
  end
data/lib/slacks/errors.rb CHANGED
@@ -1,19 +1,79 @@
1
1
  require "slacks/core_ext/exception"
2
2
 
3
3
  module Slacks
4
- class MigrationInProgress < RuntimeError
5
- def initialize
6
- super "Team is being migrated between servers. Try the request again in a few seconds."
4
+ module Response
5
+ class Error < RuntimeError
6
+ attr_reader :command, :params, :response
7
+
8
+ def initialize(command, params, response, message)
9
+ super message
10
+ @command = command
11
+ @params = params
12
+ @response = response
13
+ additional_information[:command] = command
14
+ additional_information[:params] = params
15
+ additional_information[:response] = response
16
+ end
7
17
  end
8
- end
9
18
 
10
- class ResponseError < RuntimeError
11
- attr_reader :response
19
+ class UnspecifiedError < ::Slacks::Response::Error
20
+ def initialize(command, params, response)
21
+ super command, params, response, "Request failed with #{response["error"].inspect}"
22
+ end
23
+ end
24
+
25
+ @_errors = {}
26
+
27
+ def self.fetch(error_code)
28
+ @_errors.fetch(error_code, ::Slacks::Response::UnspecifiedError)
29
+ end
30
+
31
+ {
32
+ "account_inactive" => "Authentication token is for a deleted user or team.",
33
+ "already_reacted" => "The specified item already has the user/reaction combination.",
34
+ "bad_timestamp" => "Value passed for timestamp was invalid.",
35
+ "cant_update_message" => "Authenticated user does not have permission to update this message.",
36
+ "channel_not_found" => "Value passed for channel was invalid.",
37
+ "edit_window_closed" => "The message cannot be edited due to the team message edit settings",
38
+ "fatal_error" => "",
39
+ "file_comment_not_found" => "File comment specified by file_comment does not exist.",
40
+ "file_not_found" => "File specified by file does not exist.",
41
+ "invalid_arg_name" => "The method was passed an argument whose name falls outside the bounds of common decency. This includes very long names and names with non-alphanumeric characters other than _. If you get this error, it is typically an indication that you have made a very malformed API call.",
42
+ "invalid_array_arg" => "The method was passed a PHP-style array argument (e.g. with a name like foo[7]). These are never valid with the Slack API.",
43
+ "invalid_auth" => "Invalid authentication token.",
44
+ "invalid_charset" => "The method was called via a POST request, but the charset specified in the Content-Type header was invalid. Valid charset names are: utf-8 iso-8859-1.",
45
+ "invalid_form_data" => "The method was called via a POST request with Content-Type application/x-www-form-urlencoded or multipart/form-data, but the form data was either missing or syntactically invalid.",
46
+ "invalid_name" => "Value passed for name was invalid.",
47
+ "invalid_post_type" => "The method was called via a POST request, but the specified Content-Type was invalid. Valid types are: application/json application/x-www-form-urlencoded multipart/form-data text/plain.",
48
+ "is_archived" => "Channel has been archived.",
49
+ "message_not_found" => "Message specified by channel and timestamp does not exist.",
50
+ "migration_in_progress" => "Team is being migrated between servers. See the team_migration_started event documentation for details.",
51
+ "missing_post_type" => "The method was called via a POST request and included a data payload, but the request did not include a Content-Type header.",
52
+ "msg_too_long" => "Message text is too long",
53
+ "no_item_specified" => "file, file_comment, or combination of channel and timestamp was not specified.",
54
+ "no_text" => "No message text provided",
55
+ "not_authed" => "No authentication token provided.",
56
+ "not_in_channel" => "Cannot post user messages to a channel they are not in.",
57
+ "rate_limited" => "Application has posted too many messages, read the Rate Limit documentation for more information",
58
+ "request_timeout" => "The method was called via a POST request, but the POST data was either missing or truncated.",
59
+ "too_many_attachments" => "Too many attachments were provided with this message. A maximum of 100 attachments are allowed on a message.",
60
+ "too_many_emoji" => "The limit for distinct reactions (i.e emoji) on the item has been reached.",
61
+ "too_many_reactions" => "The limit for reactions a person may add to the item has been reached."
62
+ }.each do |error_code, message|
63
+ class_name = error_code.gsub(/(?:^|_)([a-z]+)/) { $1.capitalize }
64
+ class_name = {
65
+ "MsgTooLong" => "MessageTooLong"
66
+ }.fetch(class_name, class_name)
67
+
68
+ module_eval <<-RUBY, __FILE__, __LINE__ + 1
69
+ class #{class_name} < ::Slacks::Response::Error
70
+ def initialize(command, params, response)
71
+ super command, params, response, "#{message}"
72
+ end
73
+ end
12
74
 
13
- def initialize(response, message)
14
- super message
15
- @response = response
16
- additional_information[:response] = response
75
+ @_errors["#{error_code}"] = ::Slacks::Response::#{class_name}
76
+ RUBY
17
77
  end
18
78
  end
19
79
 
@@ -24,21 +84,21 @@ module Slacks
24
84
  end
25
85
  end
26
86
 
27
- class AlreadyRespondedError < RuntimeError
28
- def initialize(message=nil)
29
- super message || "You have already replied to this Slash Command; you can only reply once"
30
- end
31
- end
32
-
33
87
  class NotInChannelError < RuntimeError
34
88
  def initialize(channel)
35
89
  super "The bot is not in the channel #{channel} and cannot reply"
36
90
  end
37
91
  end
38
92
 
39
- class UnableToDirectMessageError < ResponseError
40
- def initialize(response, user_id)
41
- super response, "Unable to direct message the user #{user_id.inspect}: #{response["error"]}"
93
+ class MissingTokenError < ArgumentError
94
+ def initialize
95
+ super "Unable to connect to Slack; a token has no"
96
+ end
97
+ end
98
+
99
+ class NotListeningError < ArgumentError
100
+ def initialize
101
+ super "Not connected to the RTM API; call `listen!` first"
42
102
  end
43
103
  end
44
104
  end
@@ -1,3 +1,3 @@
1
1
  module Slacks
2
- VERSION = "0.4.4"
2
+ VERSION = "0.6.2"
3
3
  end
data/slacks.gemspec CHANGED
@@ -25,8 +25,8 @@ Gem::Specification.new do |spec|
25
25
  spec.add_dependency "faraday-raise-errors"
26
26
  spec.add_dependency "concurrent-ruby"
27
27
 
28
- spec.add_development_dependency "bundler", "~> 1.10"
29
- spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "bundler"
29
+ spec.add_development_dependency "rake"
30
30
  spec.add_development_dependency "minitest", "~> 5.0"
31
31
  spec.add_development_dependency "pry"
32
32
  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.4
4
+ version: 0.6.2
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-01-19 00:00:00.000000000 Z
11
+ date: 2021-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: websocket-driver
@@ -84,30 +84,30 @@ dependencies:
84
84
  name: bundler
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: '1.10'
89
+ version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: '1.10'
96
+ version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rake
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: '10.0'
103
+ version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
- version: '10.0'
110
+ version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: minitest
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -164,7 +164,7 @@ dependencies:
164
164
  - - ">="
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
- description:
167
+ description:
168
168
  email:
169
169
  - bob.lailfamily@gmail.com
170
170
  executables: []
@@ -173,6 +173,7 @@ extra_rdoc_files: []
173
173
  files:
174
174
  - ".gitignore"
175
175
  - ".travis.yml"
176
+ - CHANGELOG.md
176
177
  - Gemfile
177
178
  - LICENSE.txt
178
179
  - README.md
@@ -196,7 +197,7 @@ homepage: https://github.com/houston/slacks
196
197
  licenses:
197
198
  - MIT
198
199
  metadata: {}
199
- post_install_message:
200
+ post_install_message:
200
201
  rdoc_options: []
201
202
  require_paths:
202
203
  - lib
@@ -211,9 +212,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
211
212
  - !ruby/object:Gem::Version
212
213
  version: '0'
213
214
  requirements: []
214
- rubyforge_project:
215
- rubygems_version: 2.2.2
216
- signing_key:
215
+ rubygems_version: 3.1.2
216
+ signing_key:
217
217
  specification_version: 4
218
218
  summary: A library for communicating via Slack
219
219
  test_files: []