slacks 0.4.4 → 0.6.2

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