google_calendar 0.6.2 → 0.7.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 +5 -2
- data/.env.test +1 -1
- data/.github/workflows/ci.yml +27 -0
- data/Gemfile +2 -3
- data/Gemfile.lock +74 -48
- data/LICENSE.txt +1 -1
- data/README.rdoc +20 -15
- data/VERSION +1 -1
- data/google_calendar.gemspec +13 -10
- data/lib/google/calendar.rb +120 -16
- data/lib/google/calendar_list.rb +1 -1
- data/lib/google/connection.rb +25 -5
- data/lib/google/errors.rb +74 -4
- data/lib/google/event.rb +7 -6
- data/lib/google/freebusy.rb +3 -4
- data/readme_code.rb +2 -2
- data/test/helper.rb +1 -1
- data/test/mocks/400.json +15 -0
- data/test/mocks/401.json +13 -13
- data/test/mocks/403_calendar_rate_limit.json +13 -0
- data/test/mocks/403_daily_limit.json +13 -0
- data/test/mocks/403_forbidden.json +13 -0
- data/test/mocks/403_rate_limit.json +13 -0
- data/test/mocks/403_unknown.json +13 -0
- data/test/mocks/403_user_rate_limit.json +13 -0
- data/test/mocks/409.json +13 -0
- data/test/mocks/410.json +13 -0
- data/test/mocks/412.json +15 -0
- data/test/mocks/500.json +13 -0
- data/test/mocks/create_calendar.json +6 -0
- data/test/mocks/get_calendar.json +9 -0
- data/test/mocks/update_calendar.json +7 -0
- data/test/test_google_calendar.rb +264 -21
- metadata +93 -27
- data/.travis.yml +0 -15
data/lib/google/errors.rb
CHANGED
|
@@ -1,8 +1,78 @@
|
|
|
1
1
|
module Google
|
|
2
|
-
|
|
2
|
+
# Signet::AuthorizationError
|
|
3
|
+
# Not part of Google Calendar API Errors
|
|
3
4
|
class HTTPAuthorizationFailed < StandardError; end
|
|
5
|
+
|
|
6
|
+
# Google Calendar API Errors per documentation
|
|
7
|
+
# https://developers.google.com/google-apps/calendar/v3/errors
|
|
8
|
+
|
|
9
|
+
# 400: Bad Request
|
|
10
|
+
#
|
|
11
|
+
# User error. This can mean that a required field or parameter has not been
|
|
12
|
+
# provided, the value supplied is invalid, or the combination of provided
|
|
13
|
+
# fields is invalid.
|
|
14
|
+
class HTTPRequestFailed < StandardError; end
|
|
15
|
+
|
|
16
|
+
# 401: Invalid Credentials
|
|
17
|
+
#
|
|
18
|
+
# Invalid authorization header. The access token you're using is either
|
|
19
|
+
# expired or invalid.
|
|
20
|
+
class InvalidCredentialsError < StandardError; end
|
|
21
|
+
|
|
22
|
+
# 403: Daily Limit Exceeded
|
|
23
|
+
#
|
|
24
|
+
# The Courtesy API limit for your project has been reached.
|
|
25
|
+
class DailyLimitExceededError < StandardError; end
|
|
26
|
+
|
|
27
|
+
# 403: User Rate Limit Exceeded
|
|
28
|
+
#
|
|
29
|
+
# The per-user limit from the Developer Console has been reached.
|
|
30
|
+
class UserRateLimitExceededError < StandardError; end
|
|
31
|
+
|
|
32
|
+
# 403: Rate Limit Exceeded
|
|
33
|
+
#
|
|
34
|
+
# The user has reached Google Calendar API's maximum request rate per
|
|
35
|
+
# calendar or per authenticated user.
|
|
36
|
+
class RateLimitExceededError < StandardError; end
|
|
37
|
+
|
|
38
|
+
# 403: Calendar usage limits exceeded
|
|
39
|
+
#
|
|
40
|
+
# The user reached one of the Google Calendar limits in place to protect
|
|
41
|
+
# Google users and infrastructure from abusive behavior.
|
|
42
|
+
class CalendarUsageLimitExceededError < StandardError; end
|
|
43
|
+
|
|
44
|
+
# 404: Not Found
|
|
45
|
+
#
|
|
46
|
+
# The specified resource was not found.
|
|
4
47
|
class HTTPNotFound < StandardError; end
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
48
|
+
|
|
49
|
+
# 409: The requested identifier already exists
|
|
50
|
+
#
|
|
51
|
+
# An instance with the given ID already exists in the storage.
|
|
52
|
+
class RequestedIdentifierAlreadyExistsError < StandardError; end
|
|
53
|
+
|
|
54
|
+
# 410: Gone
|
|
55
|
+
#
|
|
56
|
+
# SyncToken or updatedMin parameters are no longer valid. This error can also
|
|
57
|
+
# occur if a request attempts to delete an event that has already been
|
|
58
|
+
# deleted.
|
|
59
|
+
class GoneError < StandardError; end
|
|
60
|
+
|
|
61
|
+
# 412: Precondition Failed
|
|
62
|
+
#
|
|
63
|
+
# The etag supplied in the If-match header no longer corresponds to the
|
|
64
|
+
# current etag of the resource.
|
|
65
|
+
class PreconditionFailedError < StandardError; end
|
|
66
|
+
|
|
67
|
+
# 500: Backend Error
|
|
68
|
+
#
|
|
69
|
+
# An unexpected error occurred while processing the request.
|
|
70
|
+
class BackendError < StandardError; end
|
|
71
|
+
|
|
72
|
+
#
|
|
73
|
+
# 403: Forbidden Error
|
|
74
|
+
#
|
|
75
|
+
# User has no authority to conduct the requested operation on the resource.
|
|
76
|
+
# This is not a part of official Google Calendar API Errors documentation.
|
|
77
|
+
class ForbiddenError < StandardError; end
|
|
8
78
|
end
|
data/lib/google/event.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'time'
|
|
2
2
|
require 'json'
|
|
3
|
+
require 'sorted_set' # TimezoneParser relies on the top-level SortedSet, removed from stdlib in Ruby 3.2+
|
|
3
4
|
require 'timezone_parser'
|
|
4
5
|
|
|
5
6
|
module Google
|
|
@@ -120,7 +121,7 @@ module Google
|
|
|
120
121
|
# Returns whether the Event is an all-day event, based on whether the event starts at the beginning and ends at the end of the day.
|
|
121
122
|
#
|
|
122
123
|
def all_day?
|
|
123
|
-
time = (@start_time.is_a?
|
|
124
|
+
time = (@start_time.is_a? String) ? Time.parse(@start_time) : @start_time.dup.utc
|
|
124
125
|
duration % (24 * 60 * 60) == 0 && time == Time.local(time.year,time.month,time.day)
|
|
125
126
|
end
|
|
126
127
|
|
|
@@ -216,10 +217,10 @@ module Google
|
|
|
216
217
|
# You can pass true or false. Defaults to transparent.
|
|
217
218
|
#
|
|
218
219
|
def transparency=(val)
|
|
219
|
-
if val ==
|
|
220
|
-
@transparency = 'opaque'
|
|
221
|
-
else
|
|
220
|
+
if val == true || val.to_s.downcase == 'transparent'
|
|
222
221
|
@transparency = 'transparent'
|
|
222
|
+
else
|
|
223
|
+
@transparency = 'opaque'
|
|
223
224
|
end
|
|
224
225
|
end
|
|
225
226
|
|
|
@@ -314,7 +315,7 @@ module Google
|
|
|
314
315
|
return {} unless @attendees
|
|
315
316
|
|
|
316
317
|
attendees = @attendees.map do |attendee|
|
|
317
|
-
attendee.select { |k,
|
|
318
|
+
attendee.select { |k,_v| ['displayName', 'email', 'responseStatus'].include?(k) }
|
|
318
319
|
end
|
|
319
320
|
|
|
320
321
|
{ "attendees" => attendees }
|
|
@@ -396,7 +397,7 @@ module Google
|
|
|
396
397
|
def extended_properties_attributes
|
|
397
398
|
return {} unless @extended_properties && (@extended_properties['shared'] || @extended_properties['private'])
|
|
398
399
|
|
|
399
|
-
{ "extendedProperties" => @extended_properties.select {|k,
|
|
400
|
+
{ "extendedProperties" => @extended_properties.select {|k,_v| ['shared', 'private'].include?(k) } }
|
|
400
401
|
end
|
|
401
402
|
|
|
402
403
|
#
|
data/lib/google/freebusy.rb
CHANGED
|
@@ -16,7 +16,7 @@ module Google
|
|
|
16
16
|
# The +params+ parameter accepts
|
|
17
17
|
# * :client_id => the client ID that you received from Google after registering your application with them (https://console.developers.google.com/). REQUIRED
|
|
18
18
|
# * :client_secret => the client secret you received from Google after registering your application with them. REQUIRED
|
|
19
|
-
# * :redirect_url => the url where your users will be redirected to after they have successfully permitted access to their calendars.
|
|
19
|
+
# * :redirect_url => the url where your users will be redirected to after they have successfully permitted access to their calendars. REQUIRED
|
|
20
20
|
# * :refresh_token => if a user has already given you access to their calendars, you can specify their refresh token here and you will be 'logged on' automatically (i.e. they don't need to authorize access again). OPTIONAL
|
|
21
21
|
#
|
|
22
22
|
# See Readme.rdoc or readme_code.rb for an explication on the OAuth2 authorization process.
|
|
@@ -46,7 +46,7 @@ module Google
|
|
|
46
46
|
private
|
|
47
47
|
|
|
48
48
|
#
|
|
49
|
-
# Prepare the JSON
|
|
49
|
+
# Prepare the JSON
|
|
50
50
|
#
|
|
51
51
|
def json_for_query(calendar_ids, start_time, end_time)
|
|
52
52
|
{}.tap{ |obj|
|
|
@@ -62,10 +62,9 @@ module Google
|
|
|
62
62
|
return nil unless query_result['calendars'].is_a? Hash
|
|
63
63
|
|
|
64
64
|
query_result['calendars'].each_with_object({}) do |(calendar_id, value), result|
|
|
65
|
+
value['busy'].each { |date_times| date_times.transform_values! { |date_time| DateTime.parse(date_time) } }
|
|
65
66
|
result[calendar_id] = value['busy'] || []
|
|
66
67
|
end
|
|
67
68
|
end
|
|
68
|
-
|
|
69
69
|
end
|
|
70
|
-
|
|
71
70
|
end
|
data/readme_code.rb
CHANGED
|
@@ -12,7 +12,7 @@ require 'google_calendar'
|
|
|
12
12
|
cal = Google::Calendar.new(:client_id => YOUR_CLIENT_ID,
|
|
13
13
|
:client_secret => YOUR_SECRET,
|
|
14
14
|
:calendar => YOUR_CALENDAR_ID,
|
|
15
|
-
:redirect_url =>
|
|
15
|
+
:redirect_url => YOUR_REDIRECT_URL # this is what Google uses for 'applications'
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
puts "Do you already have a refresh token? (y/n)"
|
|
@@ -23,7 +23,7 @@ if has_token.downcase != 'y'
|
|
|
23
23
|
# A user needs to approve access in order to work with their calendars.
|
|
24
24
|
puts "Visit the following web page in your browser and approve access."
|
|
25
25
|
puts cal.authorize_url
|
|
26
|
-
puts "\nCopy the code
|
|
26
|
+
puts "\nCopy the code out of the paramters after Google redirects you to your provided redirect_url"
|
|
27
27
|
|
|
28
28
|
# Pass the ONE TIME USE access code here to login and get a refresh token that you can use for access from now on.
|
|
29
29
|
refresh_token = cal.login_with_auth_code( $stdin.gets.chomp )
|
data/test/helper.rb
CHANGED
data/test/mocks/400.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"error": {
|
|
3
|
+
"errors": [
|
|
4
|
+
{
|
|
5
|
+
"domain": "calendar",
|
|
6
|
+
"reason": "timeRangeEmpty",
|
|
7
|
+
"message": "The specified time range is empty.",
|
|
8
|
+
"locationType": "parameter",
|
|
9
|
+
"location": "timeMax",
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"code": 400,
|
|
13
|
+
"message": "The specified time range is empty."
|
|
14
|
+
}
|
|
15
|
+
}
|
data/test/mocks/401.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
2
|
+
"error": {
|
|
3
|
+
"errors": [
|
|
4
|
+
{
|
|
5
|
+
"domain": "global",
|
|
6
|
+
"reason": "authError",
|
|
7
|
+
"message": "Invalid Credentials",
|
|
8
|
+
"locationType": "header",
|
|
9
|
+
"location": "Authorization",
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"code": 401,
|
|
13
|
+
"message": "Invalid Credentials"
|
|
14
|
+
}
|
|
15
15
|
}
|
data/test/mocks/409.json
ADDED
data/test/mocks/410.json
ADDED
data/test/mocks/412.json
ADDED
data/test/mocks/500.json
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "calendar#calendar",
|
|
3
|
+
"etag": "\"W8S50vTLOjlc76YTghtSZVQwSEE/cpIguMlgGWrAb4L_lleRpa2ALCA\"",
|
|
4
|
+
"id": "gqeb0i6v737kfu5md0f35htjlg@group.calendar.google.com",
|
|
5
|
+
"summary": "Some Calendar",
|
|
6
|
+
"description": "Our work events",
|
|
7
|
+
"location": "Portland",
|
|
8
|
+
"timeZone": "America/Los_Angeles"
|
|
9
|
+
}
|