laziness 0.2.4 → 0.2.5
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 +4 -4
- data/Gemfile.lock +22 -17
- data/README.md +14 -0
- data/lib/laziness/api/base.rb +8 -0
- data/lib/laziness/api/channels.rb +9 -3
- data/lib/laziness/api/conversations.rb +19 -11
- data/lib/laziness/api/groups.rb +9 -3
- data/lib/laziness/api/im.rb +6 -3
- data/lib/laziness/api/users.rb +6 -3
- data/lib/laziness/base.rb +8 -2
- data/lib/laziness/cursor.rb +60 -0
- data/lib/laziness/errors.rb +19 -0
- data/lib/laziness/pager.rb +32 -0
- data/lib/laziness/version.rb +1 -1
- data/lib/laziness.rb +2 -0
- data/spec/laziness/api/conversations_spec.rb +14 -0
- data/spec/laziness/base_spec.rb +20 -0
- data/spec/laziness/cursor_spec.rb +129 -0
- data/spec/laziness/errors_spec.rb +13 -0
- data/spec/laziness/message_spec.rb +8 -4
- data/spec/laziness/pager_spec.rb +60 -0
- data/spec/support/fixtures/conversations_list.json +4 -1
- data/spec/support/slack_stub_factory.rb +11 -2
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a76e439503c65d13c7c8ab8f00bdc5ee3d22dc06d60acf0ae8fe959808e63133
|
4
|
+
data.tar.gz: e6297370c3f3f22f01b468844d4ae79a3cd20e691c27d95e7471cc645133c66a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de5a77da3465d2a5a6ce098539c6802d515e6a57c1d88aafde8345f42448c747f0512bd6ead50c101a7ddbf90bc85bca5e65049059cfeb6e0989485eb60ecae1
|
7
|
+
data.tar.gz: 6f1b839c1a7d8235376564141a5323b050606870bd6907fa6909d57bbb77f1a1e4037c7937dcd798038296746ca458c22bd84d9509d37d2f84164a05a9f89be3
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
laziness (0.2.
|
4
|
+
laziness (0.2.5)
|
5
5
|
eventmachine
|
6
6
|
faye-websocket (>= 0.8.0)
|
7
7
|
hashie
|
@@ -10,14 +10,16 @@ PATH
|
|
10
10
|
GEM
|
11
11
|
remote: https://rubygems.org/
|
12
12
|
specs:
|
13
|
-
addressable (2.
|
14
|
-
|
13
|
+
addressable (2.6.0)
|
14
|
+
public_suffix (>= 2.0.2, < 4.0)
|
15
|
+
crack (0.4.3)
|
15
16
|
safe_yaml (~> 1.0.0)
|
16
|
-
diff-lcs (1.
|
17
|
+
diff-lcs (1.3)
|
17
18
|
eventmachine (1.2.7)
|
18
19
|
faye-websocket (0.10.7)
|
19
20
|
eventmachine (>= 0.12.0)
|
20
21
|
websocket-driver (>= 0.5.1)
|
22
|
+
hashdiff (0.3.8)
|
21
23
|
hashie (3.6.0)
|
22
24
|
httparty (0.16.4)
|
23
25
|
mime-types (~> 3.0)
|
@@ -26,23 +28,26 @@ GEM
|
|
26
28
|
mime-types-data (~> 3.2015)
|
27
29
|
mime-types-data (3.2018.0812)
|
28
30
|
multi_xml (0.6.0)
|
31
|
+
public_suffix (3.0.3)
|
29
32
|
rake (10.3.2)
|
30
|
-
rspec (3.
|
31
|
-
rspec-core (~> 3.
|
32
|
-
rspec-expectations (~> 3.
|
33
|
-
rspec-mocks (~> 3.
|
34
|
-
rspec-core (3.
|
35
|
-
rspec-support (~> 3.
|
36
|
-
rspec-expectations (3.
|
33
|
+
rspec (3.8.0)
|
34
|
+
rspec-core (~> 3.8.0)
|
35
|
+
rspec-expectations (~> 3.8.0)
|
36
|
+
rspec-mocks (~> 3.8.0)
|
37
|
+
rspec-core (3.8.0)
|
38
|
+
rspec-support (~> 3.8.0)
|
39
|
+
rspec-expectations (3.8.2)
|
37
40
|
diff-lcs (>= 1.2.0, < 2.0)
|
38
|
-
rspec-support (~> 3.
|
39
|
-
rspec-mocks (3.
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
rspec-support (~> 3.8.0)
|
42
|
+
rspec-mocks (3.8.0)
|
43
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
44
|
+
rspec-support (~> 3.8.0)
|
45
|
+
rspec-support (3.8.0)
|
46
|
+
safe_yaml (1.0.5)
|
47
|
+
webmock (3.5.1)
|
44
48
|
addressable (>= 2.3.6)
|
45
49
|
crack (>= 0.3.2)
|
50
|
+
hashdiff
|
46
51
|
websocket-driver (0.7.0)
|
47
52
|
websocket-extensions (>= 0.1.0)
|
48
53
|
websocket-extensions (0.1.3)
|
data/README.md
CHANGED
@@ -178,6 +178,20 @@ client.users.find(user_id) # get info about a specific user
|
|
178
178
|
client.users.set_active # sets the current user (defined by the access_token) as active
|
179
179
|
```
|
180
180
|
|
181
|
+
### Pagination
|
182
|
+
|
183
|
+
In order to support paging, you can provide a `page` parameter to all methods that support paging. If the `page` parameter exists, the method will map until all conversations are retrieved.
|
184
|
+
|
185
|
+
```
|
186
|
+
conversations = client.conversations.all(page: { limit: 10, sleep_interval: 2, max_retries: 20 })
|
187
|
+
```
|
188
|
+
|
189
|
+
If you want to limit the number of page retrievals, you can set the `page` parameter to the number of retrievals to retrieve. For example, if you just want to retrieve one page worth of 1000 results, you can do the following:
|
190
|
+
|
191
|
+
```
|
192
|
+
conversations = client.conversations.all(page: { limit: 1000 })
|
193
|
+
```
|
194
|
+
|
181
195
|
## REAL TIME API USAGE
|
182
196
|
|
183
197
|
The [Slack Real Time Messaging API](https://api.slack.com/rtm) is made up of Websocket events that allow you to communicate with Slack as a bot (or yourself) with an access token.
|
data/lib/laziness/api/base.rb
CHANGED
@@ -18,6 +18,12 @@ module Slack
|
|
18
18
|
nil
|
19
19
|
end
|
20
20
|
|
21
|
+
def with_paging(page)
|
22
|
+
Cursor.new(page).paginate do |pager|
|
23
|
+
yield(pager)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
21
27
|
def request(method, path, arguments={})
|
22
28
|
full_path = "#{base_path}#{path}"
|
23
29
|
full_path = "#{full_path}?token=#{access_token}" unless access_token.nil?
|
@@ -45,6 +51,8 @@ module Slack
|
|
45
51
|
klass = "#{parsed['error'].gsub(/(^|_)(.)/) { $2.upcase }}Error"
|
46
52
|
if Slack.const_defined? klass
|
47
53
|
raise Slack.const_get(klass)
|
54
|
+
elsif response.code == 429
|
55
|
+
raise Slack::TooManyRequestsError.new(response)
|
48
56
|
else
|
49
57
|
raise Slack::APIError.new parsed['error']
|
50
58
|
end
|
@@ -1,9 +1,15 @@
|
|
1
1
|
module Slack
|
2
2
|
module API
|
3
3
|
class Channels < Base
|
4
|
-
def all(exclude_archived=false)
|
5
|
-
|
6
|
-
|
4
|
+
def all(exclude_archived=false, page: nil)
|
5
|
+
responses = with_paging(page) do |pager|
|
6
|
+
request :get,
|
7
|
+
'channels.list',
|
8
|
+
exclude_archived: exclude_archived ? 1 : 0,
|
9
|
+
**pager.to_h
|
10
|
+
end
|
11
|
+
|
12
|
+
Slack::Channel.parse_all responses, 'channels'
|
7
13
|
end
|
8
14
|
|
9
15
|
def archive(id)
|
@@ -1,13 +1,16 @@
|
|
1
1
|
module Slack
|
2
2
|
module API
|
3
3
|
class Conversations < Base
|
4
|
-
def all(exclude_archived=false, types='public_channel')
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
def all(exclude_archived=false, types='public_channel', page: nil)
|
5
|
+
responses = with_paging(page) do |pager|
|
6
|
+
request :get,
|
7
|
+
'conversations.list',
|
8
|
+
exclude_archived: exclude_archived ? 1 : 0,
|
9
|
+
types: types,
|
10
|
+
**pager.to_h
|
11
|
+
end
|
9
12
|
|
10
|
-
Slack::Conversation.
|
13
|
+
Slack::Conversation.parse_all responses, 'channels'
|
11
14
|
end
|
12
15
|
|
13
16
|
def archive(id)
|
@@ -58,12 +61,17 @@ module Slack
|
|
58
61
|
with_nil_response { request :post, 'conversations.leave', channel: id }
|
59
62
|
end
|
60
63
|
|
61
|
-
def members(id)
|
62
|
-
|
63
|
-
|
64
|
-
|
64
|
+
def members(id, page: nil)
|
65
|
+
responses = with_paging(page) do |pager|
|
66
|
+
request :get,
|
67
|
+
'conversations.members',
|
68
|
+
channel: id,
|
69
|
+
**pager.to_h
|
70
|
+
end
|
65
71
|
|
66
|
-
|
72
|
+
responses.map do |response|
|
73
|
+
JSON.parse(response.body)["members"]
|
74
|
+
end.flatten
|
67
75
|
end
|
68
76
|
|
69
77
|
def open(users=[], id=nil, return_im: false)
|
data/lib/laziness/api/groups.rb
CHANGED
@@ -1,9 +1,15 @@
|
|
1
1
|
module Slack
|
2
2
|
module API
|
3
3
|
class Groups < Base
|
4
|
-
def all(exclude_archived=false)
|
5
|
-
|
6
|
-
|
4
|
+
def all(exclude_archived=false, page: nil)
|
5
|
+
responses = with_paging(page) do |pager|
|
6
|
+
request :get,
|
7
|
+
'groups.list',
|
8
|
+
exclude_archived: exclude_archived ? 1 : 0,
|
9
|
+
**pager.to_h
|
10
|
+
end
|
11
|
+
|
12
|
+
Slack::Group.parse_all responses, 'groups'
|
7
13
|
end
|
8
14
|
|
9
15
|
def archive(id)
|
data/lib/laziness/api/im.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
module Slack
|
2
2
|
module API
|
3
3
|
class IM < Base
|
4
|
-
def all
|
5
|
-
|
6
|
-
|
4
|
+
def all(page: nil)
|
5
|
+
responses = with_paging(page) do |pager|
|
6
|
+
request :get, 'im.list', **pager.to_h
|
7
|
+
end
|
8
|
+
|
9
|
+
Slack::Channel.parse_all responses, 'ims'
|
7
10
|
end
|
8
11
|
|
9
12
|
def close(channel)
|
data/lib/laziness/api/users.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
module Slack
|
2
2
|
module API
|
3
3
|
class Users < Base
|
4
|
-
def all
|
5
|
-
|
6
|
-
|
4
|
+
def all(page: nil)
|
5
|
+
responses = with_paging(page) do |pager|
|
6
|
+
request :get, 'users.list', **pager.to_h
|
7
|
+
end
|
8
|
+
|
9
|
+
Slack::User.parse_all responses, 'members'
|
7
10
|
end
|
8
11
|
|
9
12
|
def find(id)
|
data/lib/laziness/base.rb
CHANGED
@@ -3,8 +3,8 @@ require 'hashie'
|
|
3
3
|
module Slack
|
4
4
|
class Base < Hashie::Mash
|
5
5
|
class << self
|
6
|
-
def parse(
|
7
|
-
parsed = JSON.parse(
|
6
|
+
def parse(response, key=nil)
|
7
|
+
parsed = JSON.parse(response.body)
|
8
8
|
parsed = parsed[key] if key && parsed[key]
|
9
9
|
if parsed.is_a? Array
|
10
10
|
models = []
|
@@ -14,6 +14,12 @@ module Slack
|
|
14
14
|
new parsed
|
15
15
|
end
|
16
16
|
end
|
17
|
+
|
18
|
+
def parse_all(responses, key=nil)
|
19
|
+
responses.map do |response|
|
20
|
+
parse(response, key)
|
21
|
+
end.flatten
|
22
|
+
end
|
17
23
|
end
|
18
24
|
end
|
19
25
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Slack
|
2
|
+
class Cursor
|
3
|
+
attr_reader :page
|
4
|
+
|
5
|
+
def initialize(page)
|
6
|
+
@page = page
|
7
|
+
@max_retries = (page && page[:max_retries]) || 0
|
8
|
+
@sleep_interval = (page && page[:sleep_interval])
|
9
|
+
end
|
10
|
+
|
11
|
+
def paginate(&blk)
|
12
|
+
responses = []
|
13
|
+
|
14
|
+
if block_given?
|
15
|
+
pager = Pager.new(page)
|
16
|
+
retries = 0
|
17
|
+
|
18
|
+
loop do
|
19
|
+
begin
|
20
|
+
response = blk.call(pager)
|
21
|
+
rescue Slack::TooManyRequestsError => e
|
22
|
+
raise e if retries >= max_retries
|
23
|
+
|
24
|
+
retries += 1
|
25
|
+
|
26
|
+
sleep(e.retry_after_in_seconds)
|
27
|
+
next
|
28
|
+
end
|
29
|
+
|
30
|
+
responses << response
|
31
|
+
|
32
|
+
break unless has_cursor?(response)
|
33
|
+
|
34
|
+
retries = 0
|
35
|
+
|
36
|
+
pager = pager.next(next_cursor(response))
|
37
|
+
|
38
|
+
sleep(sleep_interval) if sleep_interval
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
responses
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
attr_reader :max_retries, :sleep_interval
|
48
|
+
|
49
|
+
def next_cursor(response)
|
50
|
+
response["response_metadata"]["next_cursor"] unless !has_cursor?(response)
|
51
|
+
end
|
52
|
+
|
53
|
+
def has_cursor?(response)
|
54
|
+
response.respond_to?(:[]) &&
|
55
|
+
!response["response_metadata"].nil? &&
|
56
|
+
!response["response_metadata"]["next_cursor"].nil? &&
|
57
|
+
!response["response_metadata"]["next_cursor"].empty?
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/laziness/errors.rb
CHANGED
@@ -94,4 +94,23 @@ module Slack
|
|
94
94
|
super "You cannot archive the last channel for a restricted account."
|
95
95
|
end
|
96
96
|
end
|
97
|
+
|
98
|
+
class TooManyRequestsError < APIError
|
99
|
+
def initialize(response)
|
100
|
+
@response = response
|
101
|
+
end
|
102
|
+
|
103
|
+
def message
|
104
|
+
"Retry after #{retry_after_in_seconds} seconds"
|
105
|
+
end
|
106
|
+
|
107
|
+
def retry_after_in_seconds
|
108
|
+
retry_after = response.headers["retry-after"]
|
109
|
+
(retry_after || 0).to_i
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
attr_reader :response
|
115
|
+
end
|
97
116
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "ostruct"
|
2
|
+
|
3
|
+
module Slack
|
4
|
+
class Pager
|
5
|
+
attr_reader :cursor, :limit, :page
|
6
|
+
|
7
|
+
def initialize(page)
|
8
|
+
@page = page.dup
|
9
|
+
@limit = @page[:limit] unless empty?
|
10
|
+
end
|
11
|
+
|
12
|
+
def empty?
|
13
|
+
page.nil? || page.empty?
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_h
|
17
|
+
{ cursor: cursor, limit: limit }
|
18
|
+
end
|
19
|
+
|
20
|
+
def next(cursor)
|
21
|
+
self.class.new(page).tap do |pager|
|
22
|
+
pager.cursor = cursor
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def cursor=(cursor)
|
29
|
+
@cursor = cursor
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/laziness/version.rb
CHANGED
data/lib/laziness.rb
CHANGED
@@ -6,11 +6,13 @@ require 'laziness/channel'
|
|
6
6
|
require 'laziness/chat'
|
7
7
|
require 'laziness/client'
|
8
8
|
require 'laziness/conversation'
|
9
|
+
require 'laziness/cursor'
|
9
10
|
require 'laziness/errors'
|
10
11
|
require 'laziness/group'
|
11
12
|
require 'laziness/message'
|
12
13
|
require 'laziness/oauth'
|
13
14
|
require 'laziness/observer'
|
15
|
+
require 'laziness/pager'
|
14
16
|
require 'laziness/real_time_client'
|
15
17
|
require 'laziness/registry'
|
16
18
|
require 'laziness/session'
|
@@ -13,6 +13,20 @@ describe Slack::API::Conversations do
|
|
13
13
|
expect(conversations.length).to eq 1
|
14
14
|
expect(conversations[0].id).to eq "C02BLAH"
|
15
15
|
end
|
16
|
+
|
17
|
+
context 'with paging' do
|
18
|
+
it 'pages through until there are no more pages left' do
|
19
|
+
stub_slack_request :get,
|
20
|
+
"conversations.list?token=#{access_token}&exclude_archived=0&"\
|
21
|
+
"limit=1000&"\
|
22
|
+
"types=public_channel",
|
23
|
+
"conversations_list.json"
|
24
|
+
|
25
|
+
conversations = subject.all(page: { limit: 1000 })
|
26
|
+
expect(conversations.length).to eq 1
|
27
|
+
expect(conversations[0].id).to eq "C02BLAH"
|
28
|
+
end
|
29
|
+
end
|
16
30
|
end
|
17
31
|
|
18
32
|
describe '.archive' do
|
@@ -0,0 +1,20 @@
|
|
1
|
+
describe Slack::Base do
|
2
|
+
describe "#parse_all" do
|
3
|
+
let(:responses) do
|
4
|
+
[
|
5
|
+
double(:response,
|
6
|
+
body: '{ "ok": true, "messages": [{ "id": "1234", "type": "blah" }] }'),
|
7
|
+
double(:response,
|
8
|
+
body: '{ "ok": true, "messages": [{ "id": "4567", "type": "bleh" }] }')
|
9
|
+
]
|
10
|
+
end
|
11
|
+
|
12
|
+
it "parses all of the messages in an array" do
|
13
|
+
result = described_class.parse_all responses, 'messages'
|
14
|
+
|
15
|
+
expect(result.count).to eq 2
|
16
|
+
expect(result.first.id).to eq "1234"
|
17
|
+
expect(result.last.id).to eq "4567"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
describe Slack::Cursor do
|
2
|
+
describe '#initialize' do
|
3
|
+
let(:page) { { limit: 10 } }
|
4
|
+
|
5
|
+
it 'initializes with page attributes' do
|
6
|
+
expect(described_class.new(page).page).to eq page
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#paginate' do
|
11
|
+
let(:first_response) do
|
12
|
+
{
|
13
|
+
"ok" => true,
|
14
|
+
"channels" => [{
|
15
|
+
"id" => "C01"
|
16
|
+
}],
|
17
|
+
"response_metadata" => {
|
18
|
+
"next_cursor" => "onto-second-request"
|
19
|
+
}
|
20
|
+
}
|
21
|
+
end
|
22
|
+
let(:last_response) do
|
23
|
+
{
|
24
|
+
"ok" => true,
|
25
|
+
"channels" => [{
|
26
|
+
"id" => "C03"
|
27
|
+
}],
|
28
|
+
"response_metadata" => {
|
29
|
+
"next_cursor" => ""
|
30
|
+
}
|
31
|
+
}
|
32
|
+
end
|
33
|
+
let(:page) { { limit: 10 } }
|
34
|
+
let(:second_response) do
|
35
|
+
{
|
36
|
+
"ok" => true,
|
37
|
+
"channels" => [{
|
38
|
+
"id" => "C02"
|
39
|
+
}],
|
40
|
+
"response_metadata" => {
|
41
|
+
"next_cursor" => "onto-last-request"
|
42
|
+
}
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
subject { described_class.new(page) }
|
47
|
+
|
48
|
+
it 'does not require a block' do
|
49
|
+
expect { subject.paginate }.to_not raise_error
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'yields a pager' do
|
53
|
+
expect { |b| subject.paginate(&b) }.to yield_with_args(Slack::Pager)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'returns the results of each yield' do
|
57
|
+
expected = [first_response, second_response, last_response]
|
58
|
+
index = 0
|
59
|
+
responses = subject.paginate do |pager|
|
60
|
+
response = expected[index]
|
61
|
+
index += 1
|
62
|
+
response
|
63
|
+
end
|
64
|
+
|
65
|
+
expect(responses).to eq(expected)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'updates the cursor on the pager' do
|
69
|
+
expect_any_instance_of(Slack::Pager).to \
|
70
|
+
receive(:next).with("onto-last-request").and_call_original
|
71
|
+
|
72
|
+
responses = [second_response, last_response]
|
73
|
+
subject.paginate do |pager|
|
74
|
+
responses.shift
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'with a too many requests error' do
|
79
|
+
let(:page) { { limit: 10, max_retries: 2 } }
|
80
|
+
let(:response) { OpenStruct.new(headers: { 'retry-after' => '0' }) }
|
81
|
+
|
82
|
+
it 'tries again when there is a max retries setting' do
|
83
|
+
number_of_tries = 0
|
84
|
+
|
85
|
+
expect {
|
86
|
+
subject.paginate do |pager|
|
87
|
+
number_of_tries += 1
|
88
|
+
raise Slack::TooManyRequestsError, response
|
89
|
+
end
|
90
|
+
}.to raise_error(Slack::TooManyRequestsError)
|
91
|
+
|
92
|
+
expect(number_of_tries).to eq 3
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'without a max retries' do
|
96
|
+
it 'bubbles up the error' do
|
97
|
+
expect do
|
98
|
+
subject.paginate do |pager|
|
99
|
+
raise Slack::TooManyRequestsError, response
|
100
|
+
end
|
101
|
+
end.to raise_error Slack::TooManyRequestsError
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'with a sleep interval' do
|
107
|
+
let(:page) { { limit: 10, sleep_interval: 2 } }
|
108
|
+
|
109
|
+
it 'sleeps in between requests' do
|
110
|
+
expect(subject).to receive(:sleep).with(2)
|
111
|
+
|
112
|
+
responses = [second_response, last_response]
|
113
|
+
subject.paginate do |pager|
|
114
|
+
responses.shift
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'with a nil page' do
|
120
|
+
subject { described_class.new(nil) }
|
121
|
+
|
122
|
+
it 'yields with an empty pager' do
|
123
|
+
subject.paginate do |pager|
|
124
|
+
expect(pager).to be_empty
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -154,6 +154,19 @@ describe 'API errors' do
|
|
154
154
|
expect { subject.channels.all }.to raise_error Slack::NoChannelError
|
155
155
|
end
|
156
156
|
|
157
|
+
it 'raises a too many requests error if the status is 429' do
|
158
|
+
response = {
|
159
|
+
ok: false,
|
160
|
+
error: "ratelimited"
|
161
|
+
}
|
162
|
+
stub_request(:get, "https://slack.com/api/users.list?token=#{access_token}").
|
163
|
+
to_return(status: 429,
|
164
|
+
body: response.to_json,
|
165
|
+
headers: { "Retry-After" => "30" })
|
166
|
+
expect { subject.users.all }.to \
|
167
|
+
raise_error Slack::TooManyRequestsError, "Retry after 30 seconds"
|
168
|
+
end
|
169
|
+
|
157
170
|
it 'raises an http error if the error is not known' do
|
158
171
|
response = {
|
159
172
|
ok: false,
|
@@ -1,7 +1,8 @@
|
|
1
1
|
describe Slack::Message do
|
2
2
|
describe "#parse" do
|
3
3
|
it "initializes a new message with a JSON string" do
|
4
|
-
message =
|
4
|
+
message = described_class.parse '{ "id": "1234", "type": "blah" }'
|
5
|
+
|
5
6
|
expect(message).to be_a Slack::Message
|
6
7
|
expect(message.id).to eq "1234"
|
7
8
|
expect(message.type).to eq :blah
|
@@ -10,15 +11,18 @@ describe Slack::Message do
|
|
10
11
|
|
11
12
|
describe "#generate" do
|
12
13
|
it "generates a new message with a random id and type" do
|
13
|
-
message =
|
14
|
+
message = described_class.generate text: "This is a test"
|
15
|
+
|
14
16
|
expect(message.id).to_not be_empty
|
15
17
|
expect(message.type).to eq :message
|
16
18
|
expect(message.text).to eq "This is a test"
|
17
19
|
end
|
18
20
|
|
19
21
|
it "can have an id specified" do
|
20
|
-
expect(
|
21
|
-
|
22
|
+
expect(described_class).to_not receive(:generate_id)
|
23
|
+
|
24
|
+
message = described_class.generate id: 12345
|
25
|
+
|
22
26
|
expect(message.id).to eq 12345
|
23
27
|
end
|
24
28
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
describe Slack::Pager do
|
2
|
+
describe "#initialize" do
|
3
|
+
let(:page) { { limit: 20 } }
|
4
|
+
|
5
|
+
it "initializes with a page" do
|
6
|
+
expect(described_class.new(page).page).to eq page
|
7
|
+
end
|
8
|
+
|
9
|
+
it "saves the limit" do
|
10
|
+
expect(described_class.new(page).limit).to eq 20
|
11
|
+
end
|
12
|
+
|
13
|
+
it "initializes a nil cursor" do
|
14
|
+
expect(described_class.new(page).cursor).to be_nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#empty?" do
|
19
|
+
context "with a non-empty page" do
|
20
|
+
it "is not empty" do
|
21
|
+
expect(described_class.new({ limit: 200 })).to_not be_empty
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "with an empty page" do
|
26
|
+
it "is empty" do
|
27
|
+
expect(described_class.new({})).to be_empty
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with a nil page" do
|
32
|
+
it "is empty" do
|
33
|
+
expect(described_class.new(nil)).to be_empty
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#to_h" do
|
39
|
+
subject { described_class.new({ limit: 200 }) }
|
40
|
+
|
41
|
+
it "returns a hash with the limit and the cursor" do
|
42
|
+
expect(subject.to_h).to eq({ limit: 200, cursor: nil })
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#next" do
|
47
|
+
subject { described_class.new({ limit: 200 }) }
|
48
|
+
|
49
|
+
it "returns a new instance of the pager" do
|
50
|
+
pager = subject.next("next")
|
51
|
+
|
52
|
+
expect(pager).to be_instance_of(described_class)
|
53
|
+
expect(pager).to_not equal subject
|
54
|
+
end
|
55
|
+
|
56
|
+
it "sets the cursor" do
|
57
|
+
expect(subject.next("next").cursor).to eq "next"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,7 +1,16 @@
|
|
1
1
|
module SlackStubFactory
|
2
|
-
def stub_slack_request(method, path,
|
2
|
+
def stub_slack_request(method, path, fixtures)
|
3
|
+
fixtures = [fixtures].flatten
|
4
|
+
|
3
5
|
full_path = "https://slack.com/api/#{path}"
|
4
|
-
|
6
|
+
|
7
|
+
stub = stub_request(method, full_path)
|
8
|
+
begin
|
9
|
+
fixture = fixtures.shift
|
10
|
+
stub.to_return(status: 200, body: slack_json_fixture(fixture))
|
11
|
+
end while !fixtures.empty?
|
12
|
+
|
13
|
+
stub
|
5
14
|
end
|
6
15
|
|
7
16
|
def slack_json_fixture(fixture)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: laziness
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jamie Wright
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: eventmachine
|
@@ -100,11 +100,13 @@ files:
|
|
100
100
|
- lib/laziness/chat.rb
|
101
101
|
- lib/laziness/client.rb
|
102
102
|
- lib/laziness/conversation.rb
|
103
|
+
- lib/laziness/cursor.rb
|
103
104
|
- lib/laziness/errors.rb
|
104
105
|
- lib/laziness/group.rb
|
105
106
|
- lib/laziness/message.rb
|
106
107
|
- lib/laziness/oauth.rb
|
107
108
|
- lib/laziness/observer.rb
|
109
|
+
- lib/laziness/pager.rb
|
108
110
|
- lib/laziness/real_time_client.rb
|
109
111
|
- lib/laziness/registry.rb
|
110
112
|
- lib/laziness/session.rb
|
@@ -119,10 +121,13 @@ files:
|
|
119
121
|
- spec/laziness/api/oauth_spec.rb
|
120
122
|
- spec/laziness/api/rtm_spec.rb
|
121
123
|
- spec/laziness/api/users_spec.rb
|
124
|
+
- spec/laziness/base_spec.rb
|
122
125
|
- spec/laziness/client_spec.rb
|
126
|
+
- spec/laziness/cursor_spec.rb
|
123
127
|
- spec/laziness/errors_spec.rb
|
124
128
|
- spec/laziness/message_spec.rb
|
125
129
|
- spec/laziness/observer_spec.rb
|
130
|
+
- spec/laziness/pager_spec.rb
|
126
131
|
- spec/laziness/real_time_client_spec.rb
|
127
132
|
- spec/laziness/registry_spec.rb
|
128
133
|
- spec/spec_helper.rb
|
@@ -181,10 +186,13 @@ test_files:
|
|
181
186
|
- spec/laziness/api/oauth_spec.rb
|
182
187
|
- spec/laziness/api/rtm_spec.rb
|
183
188
|
- spec/laziness/api/users_spec.rb
|
189
|
+
- spec/laziness/base_spec.rb
|
184
190
|
- spec/laziness/client_spec.rb
|
191
|
+
- spec/laziness/cursor_spec.rb
|
185
192
|
- spec/laziness/errors_spec.rb
|
186
193
|
- spec/laziness/message_spec.rb
|
187
194
|
- spec/laziness/observer_spec.rb
|
195
|
+
- spec/laziness/pager_spec.rb
|
188
196
|
- spec/laziness/real_time_client_spec.rb
|
189
197
|
- spec/laziness/registry_spec.rb
|
190
198
|
- spec/spec_helper.rb
|