cronofy 0.5.3 → 0.6.0
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/README.md +59 -52
- data/lib/cronofy/client.rb +58 -9
- data/lib/cronofy/types.rb +19 -0
- data/lib/cronofy/version.rb +1 -1
- data/spec/lib/cronofy/client_spec.rb +188 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc7139bd209e180668455e51a5973e065bedd6b2
|
4
|
+
data.tar.gz: 830ebcf54b85a0aba2150e30ca5e0b2d5d0f1ae4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d93493fd9c16426323f15d9ffeb0b726bcb2bfaf341f838687b360807ef1cea427a05dbffb5b010694ff30b40ea1f43579711e30c96e6c32c4c0f181a6cd6060
|
7
|
+
data.tar.gz: 49c9dd164f765ca56629514bfa6ef07f69d7859b3f77a8162b7912a07429e4fa5b94a65e4daedec6f32ee241d653aef129789078267aead1ab2d2d86734cc5f3
|
data/README.md
CHANGED
@@ -2,9 +2,8 @@
|
|
2
2
|
|
3
3
|
[](https://travis-ci.org/cronofy/cronofy-ruby)
|
4
4
|
[](http://badge.fury.io/rb/cronofy)
|
5
|
-
[](https://gitter.im/cronofy/cronofy-ruby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
6
5
|
|
7
|
-
[Cronofy](
|
6
|
+
[Cronofy](https://www.cronofy.com) - one API for all the calendars (Google, iCloud, Exchange, Office 365, Outlook.com)
|
8
7
|
|
9
8
|
## Installation
|
10
9
|
|
@@ -14,92 +13,98 @@ Add this line to your application's Gemfile:
|
|
14
13
|
gem 'cronofy'
|
15
14
|
```
|
16
15
|
|
17
|
-
And then
|
16
|
+
And then at your command prompt run:
|
18
17
|
|
19
|
-
|
18
|
+
```
|
19
|
+
bundle install
|
20
|
+
```
|
20
21
|
|
21
|
-
|
22
|
+
## Usage
|
22
23
|
|
23
|
-
|
24
|
+
In order to use the Cronofy API you will need to [create a developer account](https://app.cronofy.com/sign_up/new).
|
24
25
|
|
25
|
-
|
26
|
+
From there you can [create personal access tokens](https://app.cronofy.com/oauth/applications/5447ae289bd94726da00000f/tokens)
|
27
|
+
to access your own calendars, or you can [create an OAuth application](https://app.cronofy.com/oauth/applications/new)
|
28
|
+
to obtain an OAuth `client_id` and `client_secret` to be able to use the full
|
29
|
+
API.
|
26
30
|
|
27
|
-
|
31
|
+
## Creating a client
|
28
32
|
|
29
|
-
|
33
|
+
To make calls to the Cronofy API you must create a `Cronofy::Client`. This takes
|
34
|
+
four keyword arguments, all of which are optional:
|
30
35
|
|
31
36
|
```ruby
|
32
|
-
cronofy = Cronofy::Client.new
|
37
|
+
cronofy = Cronofy::Client.new(
|
38
|
+
client_id: 'CLIENT_ID',
|
39
|
+
client_secret: 'CLIENT_SECRET',
|
40
|
+
access_token: 'ACCESS_TOKEN',
|
41
|
+
refresh_token: 'REFRESH_TOKEN'
|
42
|
+
)
|
33
43
|
```
|
34
44
|
|
35
|
-
|
45
|
+
When using a [personal access token](https://app.cronofy.com/oauth/applications/5447ae289bd94726da00000f/tokens)
|
46
|
+
you only need to provide the `access_token` argument.
|
36
47
|
|
37
|
-
|
38
|
-
|
39
|
-
|
48
|
+
When working against your own OAuth application you will need to provide the
|
49
|
+
`client_id` and `client_secret` when [going through the authorization process](https://www.cronofy.com/developers/api/#authorization)
|
50
|
+
for a user, and when [refreshing an access token](https://www.cronofy.com/developers/api/#token-refresh).
|
40
51
|
|
41
|
-
|
52
|
+
If `client_id` and `client_secret` are not specified explicitly the values from
|
53
|
+
the environment variables `CRONOFY_CLIENT_ID` and `CRONOFY_CLIENT_SECRET` will
|
54
|
+
be used if present.
|
42
55
|
|
43
|
-
|
44
|
-
cronofy = Cronofy::Client.new(access_token: 'ACCESS_TOKEN', refresh_token: 'REFRESH_TOKEN')
|
45
|
-
```
|
56
|
+
## Authorization
|
46
57
|
|
47
|
-
|
58
|
+
[API documentation](https://www.cronofy.com/developers/api/#authorization)
|
48
59
|
|
49
|
-
Generate a link for a user to grant access
|
60
|
+
Generate a link for a user to grant access to their calendars:
|
50
61
|
|
51
62
|
```ruby
|
52
|
-
cronofy.user_auth_link('http://
|
63
|
+
authorization_url = cronofy.user_auth_link('http://yoursite.dev/oauth2/callback')
|
53
64
|
```
|
54
65
|
|
55
|
-
The
|
66
|
+
The callback URL is a page on your website that will handle the OAuth 2.0
|
67
|
+
callback and receive a `code` parameter. You can then use that code to retrieve
|
68
|
+
an OAuth token granting access to the user's Cronofy account:
|
56
69
|
|
57
70
|
```ruby
|
58
|
-
|
71
|
+
response = cronofy.get_token_from_code(code, 'http://yoursite.dev/oauth2/callback')
|
59
72
|
```
|
60
73
|
|
61
|
-
You should save the `access_token` and `refresh_token` for later use.
|
74
|
+
You should save the response's `access_token` and `refresh_token` for later use.
|
62
75
|
|
63
|
-
|
76
|
+
Note that the **exact same** callback URL must be passed to both methods for
|
77
|
+
access to be granted.
|
64
78
|
|
65
|
-
|
79
|
+
If you use the [omniauth gem](https://rubygems.org/gems/omniauth), you can use
|
80
|
+
our [omniauth-cronofy strategy gem](https://rubygems.org/gems/omniauth-cronofy)
|
81
|
+
to perform this process.
|
66
82
|
|
67
|
-
|
68
|
-
cronofy.list_calendars
|
69
|
-
```
|
83
|
+
## List calendars
|
70
84
|
|
71
|
-
|
72
|
-
version of the following JSON structure:
|
73
|
-
|
74
|
-
```json
|
75
|
-
{
|
76
|
-
"provider_name": "google",
|
77
|
-
"profile_name": "YYYYYYYY@gmail.com",
|
78
|
-
"calendar_id": "cal_YYYYYYYY-UNIQUE_CAL_ID_HERE-YYYYYYYY",
|
79
|
-
"calendar_name": "Office Calendar",
|
80
|
-
"calendar_readonly": false,
|
81
|
-
"calendar_deleted": false
|
82
|
-
}
|
83
|
-
```
|
85
|
+
[API documentation](https://www.cronofy.com/developers/api/#calendars)
|
84
86
|
|
85
|
-
|
87
|
+
Get a list of all the user's calendars:
|
86
88
|
|
87
89
|
```ruby
|
88
|
-
|
89
|
-
calendar.calendar_id
|
90
|
-
# => "cal_YYYYYYYY-UNIQUE_CAL_ID_HERE-YYYYYYYY"
|
90
|
+
calendars = cronofy.list_calendars
|
91
91
|
```
|
92
92
|
|
93
|
-
|
93
|
+
## Read events
|
94
|
+
|
95
|
+
[API documentation](https://www.cronofy.com/developers/api/#read-events)
|
96
|
+
|
97
|
+
Get a list of events from the user's calendars:
|
94
98
|
|
95
99
|
```ruby
|
96
100
|
events = cronofy.read_events
|
97
|
-
events.first
|
98
|
-
# => {"calendar_id" => ....}
|
99
101
|
```
|
100
102
|
|
103
|
+
Note that the gem handles iterating through the pages on your behalf.
|
101
104
|
|
102
|
-
|
105
|
+
## Create or update events
|
106
|
+
|
107
|
+
[API documentation](https://www.cronofy.com/developers/api/#upsert-event)
|
103
108
|
|
104
109
|
To create/update an event in the user's calendar:
|
105
110
|
|
@@ -118,7 +123,9 @@ event_data = {
|
|
118
123
|
cronofy.upsert_event(calendar_id, event_data)
|
119
124
|
```
|
120
125
|
|
121
|
-
|
126
|
+
## Delete events
|
127
|
+
|
128
|
+
[API documentation](https://www.cronofy.com/developers/api/#delete-event)
|
122
129
|
|
123
130
|
To delete an event from user's calendar:
|
124
131
|
|
@@ -128,6 +135,6 @@ cronofy.delete_event(calendar_id, 'uniq-id')
|
|
128
135
|
|
129
136
|
## Links
|
130
137
|
|
131
|
-
* [API
|
138
|
+
* [API documentation](https://www.cronofy.com/developers/api)
|
132
139
|
* [API mailing list](https://groups.google.com/d/forum/cronofy-api)
|
133
140
|
|
data/lib/cronofy/client.rb
CHANGED
@@ -177,7 +177,49 @@ module Cronofy
|
|
177
177
|
end
|
178
178
|
|
179
179
|
url = ::Cronofy.api_url + "/v1/events"
|
180
|
-
|
180
|
+
PagedResultIterator.new(PagedEventsResult, :events, access_token!, url, params)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Public: Returns a lazily-evaluated Enumerable of FreeBusy that satisfy the
|
184
|
+
# given query criteria.
|
185
|
+
#
|
186
|
+
# options - The Hash options used to refine the selection (default: {}):
|
187
|
+
# :from - The minimum Date from which to return events
|
188
|
+
# (optional).
|
189
|
+
# :to - The Date to return events up until (optional).
|
190
|
+
# :tzid - A String representing a known time zone
|
191
|
+
# identifier from the IANA Time Zone Database
|
192
|
+
# (default: Etc/UTC).
|
193
|
+
# :include_managed - A Boolean specifying whether events that you
|
194
|
+
# are managing for the account should be
|
195
|
+
# included or excluded from the results
|
196
|
+
# (optional).
|
197
|
+
#
|
198
|
+
# The first page will be retrieved eagerly so that common errors will happen
|
199
|
+
# inline. However, subsequent pages (if any) will be requested lazily.
|
200
|
+
#
|
201
|
+
# See http://www.cronofy.com/developers/api/alpha#free-busy for reference.
|
202
|
+
#
|
203
|
+
# Returns a lazily-evaluated Enumerable of FreeBusy
|
204
|
+
#
|
205
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
206
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
207
|
+
# longer valid.
|
208
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
209
|
+
# include the required scope.
|
210
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
211
|
+
# parameters.
|
212
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
213
|
+
# limits for the application.
|
214
|
+
def free_busy(options = {})
|
215
|
+
params = FREE_BUSY_DEFAULT_PARAMS.merge(options)
|
216
|
+
|
217
|
+
FREE_BUSY_TIME_PARAMS.select { |tp| params.key?(tp) }.each do |tp|
|
218
|
+
params[tp] = to_iso8601(params[tp])
|
219
|
+
end
|
220
|
+
|
221
|
+
url = ::Cronofy.api_url + "/v1/free_busy"
|
222
|
+
PagedResultIterator.new(PagedFreeBusyResult, :free_busy, access_token!, url, params)
|
181
223
|
end
|
182
224
|
|
183
225
|
# Public: Deletes an event from the specified calendar
|
@@ -399,8 +441,13 @@ module Cronofy
|
|
399
441
|
|
400
442
|
private
|
401
443
|
|
402
|
-
|
444
|
+
FREE_BUSY_DEFAULT_PARAMS = { tzid: "Etc/UTC" }.freeze
|
445
|
+
FREE_BUSY_TIME_PARAMS = %i{
|
446
|
+
from
|
447
|
+
to
|
448
|
+
}.freeze
|
403
449
|
|
450
|
+
READ_EVENTS_DEFAULT_PARAMS = { tzid: "Etc/UTC" }.freeze
|
404
451
|
READ_EVENTS_TIME_PARAMS = %i{
|
405
452
|
from
|
406
453
|
to
|
@@ -460,10 +507,12 @@ module Cronofy
|
|
460
507
|
end
|
461
508
|
end
|
462
509
|
|
463
|
-
class
|
510
|
+
class PagedResultIterator
|
464
511
|
include Enumerable
|
465
512
|
|
466
|
-
def initialize(access_token, url, params)
|
513
|
+
def initialize(page_parser, items_key, access_token, url, params)
|
514
|
+
@page_parser = page_parser
|
515
|
+
@items_key = items_key
|
467
516
|
@access_token = access_token
|
468
517
|
@url = url
|
469
518
|
@params = params
|
@@ -473,15 +522,15 @@ module Cronofy
|
|
473
522
|
def each
|
474
523
|
page = @first_page
|
475
524
|
|
476
|
-
page.
|
477
|
-
yield
|
525
|
+
page[@items_key].each do |item|
|
526
|
+
yield item
|
478
527
|
end
|
479
528
|
|
480
529
|
while page.pages.next_page?
|
481
530
|
page = get_page(page.pages.next_page)
|
482
531
|
|
483
|
-
page.
|
484
|
-
yield
|
532
|
+
page[@items_key].each do |item|
|
533
|
+
yield item
|
485
534
|
end
|
486
535
|
end
|
487
536
|
end
|
@@ -511,7 +560,7 @@ module Cronofy
|
|
511
560
|
end
|
512
561
|
|
513
562
|
def parse_page(response)
|
514
|
-
ResponseParser.new(response).parse_json(
|
563
|
+
ResponseParser.new(response).parse_json(@page_parser)
|
515
564
|
end
|
516
565
|
end
|
517
566
|
end
|
data/lib/cronofy/types.rb
CHANGED
@@ -197,6 +197,25 @@ module Cronofy
|
|
197
197
|
coerce_key :events, Events
|
198
198
|
end
|
199
199
|
|
200
|
+
class FreeBusy < Hashie::Mash
|
201
|
+
include Hashie::Extensions::Coercion
|
202
|
+
|
203
|
+
coerce_key :start, EventTime
|
204
|
+
coerce_key :end, EventTime
|
205
|
+
end
|
206
|
+
|
207
|
+
module FreeBusyEnumerable
|
208
|
+
def self.coerce(values)
|
209
|
+
values.map { |v| FreeBusy.new(v) }
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
class PagedFreeBusyResult < Hashie::Mash
|
214
|
+
include Hashie::Extensions::Coercion
|
215
|
+
|
216
|
+
coerce_key :free_busy, FreeBusyEnumerable
|
217
|
+
end
|
218
|
+
|
200
219
|
class Profile < Hashie::Mash
|
201
220
|
end
|
202
221
|
end
|
data/lib/cronofy/version.rb
CHANGED
@@ -606,4 +606,192 @@ describe Cronofy::Client do
|
|
606
606
|
it_behaves_like 'a Cronofy request with mapped return value'
|
607
607
|
end
|
608
608
|
end
|
609
|
+
|
610
|
+
describe 'Free busy' do
|
611
|
+
describe '#free_busy' do
|
612
|
+
before do
|
613
|
+
stub_request(method, request_url)
|
614
|
+
.with(headers: request_headers,
|
615
|
+
body: request_body)
|
616
|
+
.to_return(status: correct_response_code,
|
617
|
+
headers: correct_response_headers,
|
618
|
+
body: correct_response_body.to_json)
|
619
|
+
|
620
|
+
stub_request(:get, next_page_url)
|
621
|
+
.with(headers: request_headers)
|
622
|
+
.to_return(status: correct_response_code,
|
623
|
+
headers: correct_response_headers,
|
624
|
+
body: next_page_body.to_json)
|
625
|
+
end
|
626
|
+
|
627
|
+
|
628
|
+
let(:request_url_prefix) { 'https://api.cronofy.com/v1/free_busy' }
|
629
|
+
let(:method) { :get }
|
630
|
+
let(:correct_response_code) { 200 }
|
631
|
+
let(:next_page_url) do
|
632
|
+
"https://next.page.com/08a07b034306679e"
|
633
|
+
end
|
634
|
+
|
635
|
+
let(:params) { Hash.new }
|
636
|
+
let(:request_url) { request_url_prefix + "?tzid=Etc/UTC" }
|
637
|
+
|
638
|
+
let(:correct_response_body) do
|
639
|
+
{
|
640
|
+
'pages' => {
|
641
|
+
'current' => 1,
|
642
|
+
'total' => 2,
|
643
|
+
'next_page' => next_page_url
|
644
|
+
},
|
645
|
+
'free_busy' => [
|
646
|
+
{
|
647
|
+
'calendar_id' => 'cal_U9uuErStTG@EAAAB_IsAsykA2DBTWqQTf-f0kJw',
|
648
|
+
'start' => '2014-09-06',
|
649
|
+
'end' => '2014-09-08',
|
650
|
+
'free_busy_status' => 'busy',
|
651
|
+
},
|
652
|
+
{
|
653
|
+
'calendar_id' => 'cal_U9uuErStTG@EAAAB_IsAsykA2DBTWqQTf-f0kJw',
|
654
|
+
'start' => '2014-09-13T19:00:00Z',
|
655
|
+
'end' => '2014-09-13T21:00:00Z',
|
656
|
+
'free_busy_status' => 'tentative',
|
657
|
+
}
|
658
|
+
]
|
659
|
+
}
|
660
|
+
end
|
661
|
+
|
662
|
+
let(:next_page_body) do
|
663
|
+
{
|
664
|
+
'pages' => {
|
665
|
+
'current' => 2,
|
666
|
+
'total' => 2,
|
667
|
+
},
|
668
|
+
'free_busy' => [
|
669
|
+
{
|
670
|
+
'calendar_id' => 'cal_U9uuErStTG@EAAAB_IsAsykA2DBTWqQTf-f0kJw',
|
671
|
+
'start' => '2014-09-07',
|
672
|
+
'end' => '2014-09-09',
|
673
|
+
'free_busy_status' => 'busy',
|
674
|
+
},
|
675
|
+
{
|
676
|
+
'calendar_id' => 'cal_U9uuErStTG@EAAAB_IsAsykA2DBTWqQTf-f0kJw',
|
677
|
+
'start' => '2014-09-14T19:00:00Z',
|
678
|
+
'end' => '2014-09-14T21:00:00Z',
|
679
|
+
'free_busy_status' => 'tentative',
|
680
|
+
}
|
681
|
+
]
|
682
|
+
}
|
683
|
+
end
|
684
|
+
|
685
|
+
let(:correct_mapped_result) do
|
686
|
+
first_page_items = correct_response_body['free_busy'].map { |period| Cronofy::FreeBusy.new(period) }
|
687
|
+
second_page_items = next_page_body['free_busy'].map { |period| Cronofy::FreeBusy.new(period) }
|
688
|
+
|
689
|
+
first_page_items + second_page_items
|
690
|
+
end
|
691
|
+
|
692
|
+
subject do
|
693
|
+
# By default force evaluation
|
694
|
+
client.free_busy(params).to_a
|
695
|
+
end
|
696
|
+
|
697
|
+
context 'when all params are passed' do
|
698
|
+
let(:params) do
|
699
|
+
{
|
700
|
+
from: Time.new(2014, 9, 1, 0, 0, 1, '+00:00'),
|
701
|
+
to: Time.new(2014, 10, 1, 0, 0, 1, '+00:00'),
|
702
|
+
tzid: 'Etc/UTC',
|
703
|
+
include_managed: true,
|
704
|
+
}
|
705
|
+
end
|
706
|
+
let(:request_url) do
|
707
|
+
"#{request_url_prefix}?from=2014-09-01T00:00:01Z" \
|
708
|
+
"&to=2014-10-01T00:00:01Z&tzid=Etc/UTC&include_managed=true"
|
709
|
+
end
|
710
|
+
|
711
|
+
it_behaves_like 'a Cronofy request'
|
712
|
+
it_behaves_like 'a Cronofy request with mapped return value'
|
713
|
+
end
|
714
|
+
|
715
|
+
context 'when some params are passed' do
|
716
|
+
let(:params) do
|
717
|
+
{
|
718
|
+
from: Time.new(2014, 9, 1, 0, 0, 1, '+00:00'),
|
719
|
+
}
|
720
|
+
end
|
721
|
+
let(:request_url) do
|
722
|
+
"#{request_url_prefix}?from=2014-09-01T00:00:01Z" \
|
723
|
+
"&tzid=Etc/UTC"
|
724
|
+
end
|
725
|
+
|
726
|
+
it_behaves_like 'a Cronofy request'
|
727
|
+
it_behaves_like 'a Cronofy request with mapped return value'
|
728
|
+
end
|
729
|
+
|
730
|
+
context "when unknown flags are passed" do
|
731
|
+
let(:params) do
|
732
|
+
{
|
733
|
+
unknown_bool: true,
|
734
|
+
unknown_number: 5,
|
735
|
+
unknown_string: "foo-bar-baz",
|
736
|
+
}
|
737
|
+
end
|
738
|
+
|
739
|
+
let(:request_url) do
|
740
|
+
"#{request_url_prefix}?tzid=Etc/UTC" \
|
741
|
+
"&unknown_bool=true" \
|
742
|
+
"&unknown_number=5" \
|
743
|
+
"&unknown_string=foo-bar-baz"
|
744
|
+
end
|
745
|
+
|
746
|
+
it_behaves_like 'a Cronofy request'
|
747
|
+
it_behaves_like 'a Cronofy request with mapped return value'
|
748
|
+
end
|
749
|
+
|
750
|
+
context "next page not found" do
|
751
|
+
before do
|
752
|
+
stub_request(:get, next_page_url)
|
753
|
+
.with(headers: request_headers)
|
754
|
+
.to_return(status: 404,
|
755
|
+
headers: correct_response_headers)
|
756
|
+
end
|
757
|
+
|
758
|
+
it "raises an error" do
|
759
|
+
expect{ subject }.to raise_error(::Cronofy::NotFoundError)
|
760
|
+
end
|
761
|
+
end
|
762
|
+
|
763
|
+
context "only first period" do
|
764
|
+
before do
|
765
|
+
# Ensure an error if second page is requested
|
766
|
+
stub_request(:get, next_page_url)
|
767
|
+
.with(headers: request_headers)
|
768
|
+
.to_return(status: 404,
|
769
|
+
headers: correct_response_headers)
|
770
|
+
end
|
771
|
+
|
772
|
+
let(:first_period) do
|
773
|
+
Cronofy::FreeBusy.new(correct_response_body["free_busy"].first)
|
774
|
+
end
|
775
|
+
|
776
|
+
subject do
|
777
|
+
client.free_busy(params).first
|
778
|
+
end
|
779
|
+
|
780
|
+
it "returns the first period from the first page" do
|
781
|
+
expect(subject).to eq(first_period)
|
782
|
+
end
|
783
|
+
end
|
784
|
+
|
785
|
+
context "without calling #to_a to force full evaluation" do
|
786
|
+
subject { client.free_busy(params) }
|
787
|
+
|
788
|
+
it_behaves_like 'a Cronofy request'
|
789
|
+
|
790
|
+
# We expect it to behave like a Cronofy request as the first page is
|
791
|
+
# requested eagerly so that the majority of errors will happen inline
|
792
|
+
# rather than lazily happening wherever the iterator may have been
|
793
|
+
# passed.
|
794
|
+
end
|
795
|
+
end
|
796
|
+
end
|
609
797
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cronofy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergii Paryzhskyi
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-10-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: oauth2
|