google_calendar 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -10
- data/.travis.yml +1 -1
- data/Gemfile +2 -12
- data/Gemfile.lock +81 -24
- data/Guardfile +7 -0
- data/README.rdoc +60 -8
- data/VERSION +1 -1
- data/google_calendar.gemspec +19 -29
- data/lib/google/calendar.rb +149 -118
- data/lib/google/connection.rb +114 -79
- data/lib/google/errors.rb +2 -1
- data/lib/google/event.rb +191 -94
- data/lib/google_calendar.rb +5 -5
- data/readme_code.rb +72 -0
- data/test/helper.rb +12 -5
- data/test/mocks/401.json +15 -0
- data/test/mocks/403.json +12 -0
- data/test/mocks/404.json +13 -0
- data/test/mocks/create_event.json +31 -0
- data/test/mocks/create_quickadd_event.json +30 -0
- data/test/mocks/empty_events.json +12 -0
- data/test/mocks/events.json +117 -0
- data/test/mocks/find_event_by_id.json +31 -0
- data/test/mocks/login_with_auth_code_fail.json +4 -0
- data/test/mocks/login_with_auth_code_success.json +6 -0
- data/test/mocks/login_with_refresh_token_success.json +5 -0
- data/test/mocks/query_events.json +44 -0
- data/test/mocks/repeating_events.json +48 -0
- data/test/mocks/successful_login.json +6 -0
- data/test/test_google_calendar.rb +167 -139
- metadata +167 -53
- data/lib/google/net/https.rb +0 -19
- data/test/mocks/create_event.xml +0 -31
- data/test/mocks/create_quickadd_event.xml +0 -31
- data/test/mocks/events.xml +0 -119
- data/test/mocks/find_event_by_id.xml +0 -33
- data/test/mocks/list_calendars.xml +0 -89
- data/test/mocks/query_events.xml +0 -55
- data/test/mocks/successful_login.txt +0 -3
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c0abc20ca5bb465a9042cad4e9941fbaa0397888
|
4
|
+
data.tar.gz: 21d702bee56ff9ae28582efc993f9765015b6ee7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1c881f0d97bab2f853c863f7e58b1d1385001b2b1b2bd101cb91f113d3ef5d599dc80b5bc53fd453b566e147ba24b14681364c405fe9a927e3fa25cc052dac68
|
7
|
+
data.tar.gz: 4c56297fdd70294df8b274651ad3bc28b3cf9e1025ccbb5fab8dfd3a046f7707797a44a94be0ef08fad496c2ebc3da80490d841a208057f80b0d2ed1e93a01c1
|
data/.gitignore
CHANGED
@@ -1,19 +1,14 @@
|
|
1
1
|
# rcov generated
|
2
2
|
coverage
|
3
|
-
|
4
3
|
# rdoc generated
|
5
4
|
rdoc
|
6
|
-
|
7
5
|
# yard generated
|
8
6
|
doc
|
9
7
|
.yardoc
|
10
|
-
|
11
8
|
# bundler
|
12
9
|
.bundle
|
13
|
-
|
14
10
|
# jeweler generated
|
15
11
|
pkg
|
16
|
-
|
17
12
|
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
18
13
|
#
|
19
14
|
# * Create a file at ~/.gitignore
|
@@ -25,17 +20,12 @@ pkg
|
|
25
20
|
#
|
26
21
|
# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
|
27
22
|
#
|
28
|
-
|
29
23
|
# For MacOS:
|
30
24
|
#
|
31
25
|
.DS_Store
|
32
|
-
|
33
|
-
|
34
26
|
# For TextMate
|
35
27
|
*.tmproj
|
36
28
|
tmtags
|
37
|
-
|
38
|
-
|
39
29
|
# For emacs:
|
40
30
|
#*~
|
41
31
|
#\#*
|
@@ -43,3 +33,5 @@ tmtags
|
|
43
33
|
#
|
44
34
|
# For vim:
|
45
35
|
#*.swp
|
36
|
+
notes.md
|
37
|
+
test_harness.rb
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -1,14 +1,4 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
|
-
#
|
4
|
-
|
5
|
-
gem "addressable", ">= 2.2.2"
|
6
|
-
|
7
|
-
# Gem development dependencies.
|
8
|
-
group :development do
|
9
|
-
gem "shoulda", ">= 0"
|
10
|
-
gem "bundler", ">= 1.0.0"
|
11
|
-
gem "mocha", ">= 0"
|
12
|
-
gem "rake", "> 10"
|
13
|
-
gem "rdoc", "> 3"
|
14
|
-
end
|
3
|
+
# Using google_calendar to manage dependencies
|
4
|
+
gemspec
|
data/Gemfile.lock
CHANGED
@@ -1,37 +1,94 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
google_calendar (0.4.0)
|
5
|
+
addressable (>= 2.2.2)
|
6
|
+
signet (>= 0.5.1)
|
7
|
+
|
1
8
|
GEM
|
2
9
|
remote: http://rubygems.org/
|
3
10
|
specs:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
addressable (2.3.6)
|
12
|
+
ansi (1.4.3)
|
13
|
+
builder (3.2.2)
|
14
|
+
celluloid (0.16.0)
|
15
|
+
timers (~> 4.0.0)
|
16
|
+
coderay (1.1.0)
|
17
|
+
docile (1.1.5)
|
18
|
+
faraday (0.9.0)
|
19
|
+
multipart-post (>= 1.2, < 3)
|
20
|
+
ffi (1.9.6)
|
21
|
+
formatador (0.2.5)
|
22
|
+
guard (2.8.2)
|
23
|
+
formatador (>= 0.2.4)
|
24
|
+
listen (~> 2.7)
|
25
|
+
lumberjack (~> 1.0)
|
26
|
+
pry (>= 0.9.12)
|
27
|
+
thor (>= 0.18.1)
|
28
|
+
guard-minitest (2.3.2)
|
29
|
+
guard (~> 2.0)
|
30
|
+
minitest (>= 3.0)
|
31
|
+
hitimes (1.2.2)
|
32
|
+
json (1.8.1)
|
33
|
+
jwt (1.0.0)
|
34
|
+
listen (2.8.0)
|
35
|
+
celluloid (>= 0.15.2)
|
36
|
+
rb-fsevent (>= 0.9.3)
|
37
|
+
rb-inotify (>= 0.9)
|
38
|
+
lumberjack (1.0.9)
|
39
|
+
metaclass (0.0.4)
|
40
|
+
method_source (0.8.2)
|
41
|
+
minitest (5.4.3)
|
42
|
+
minitest-reporters (1.0.7)
|
43
|
+
ansi
|
44
|
+
builder
|
45
|
+
minitest (>= 5.0)
|
46
|
+
ruby-progressbar
|
47
|
+
mocha (1.1.0)
|
13
48
|
metaclass (~> 0.0.1)
|
14
|
-
multi_json (1.
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
49
|
+
multi_json (1.10.1)
|
50
|
+
multipart-post (2.0.0)
|
51
|
+
pry (0.10.1)
|
52
|
+
coderay (~> 1.1.0)
|
53
|
+
method_source (~> 0.8.1)
|
54
|
+
slop (~> 3.4)
|
55
|
+
rake (10.3.2)
|
56
|
+
rb-fsevent (0.9.4)
|
57
|
+
rb-inotify (0.9.5)
|
58
|
+
ffi (>= 0.5.0)
|
59
|
+
rdoc (4.1.2)
|
19
60
|
json (~> 1.4)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
61
|
+
ruby-progressbar (1.7.0)
|
62
|
+
shoulda-context (1.2.1)
|
63
|
+
signet (0.5.1)
|
64
|
+
addressable (>= 2.2.3)
|
65
|
+
faraday (>= 0.9.0.rc5)
|
66
|
+
jwt (>= 0.1.5)
|
67
|
+
multi_json (>= 1.0.0)
|
68
|
+
simplecov (0.9.1)
|
69
|
+
docile (~> 1.1.0)
|
70
|
+
multi_json (~> 1.0)
|
71
|
+
simplecov-html (~> 0.8.0)
|
72
|
+
simplecov-html (0.8.0)
|
73
|
+
slop (3.6.0)
|
74
|
+
terminal-notifier-guard (1.6.4)
|
75
|
+
thor (0.19.1)
|
76
|
+
timers (4.0.1)
|
77
|
+
hitimes
|
26
78
|
|
27
79
|
PLATFORMS
|
28
80
|
ruby
|
29
81
|
|
30
82
|
DEPENDENCIES
|
31
|
-
addressable (>= 2.2.2)
|
32
83
|
bundler (>= 1.0.0)
|
84
|
+
google_calendar!
|
85
|
+
guard-minitest
|
86
|
+
minitest (~> 5.1)
|
87
|
+
minitest-reporters
|
33
88
|
mocha
|
34
|
-
nokogiri (>= 1.4.4)
|
35
89
|
rake (> 10)
|
36
|
-
|
37
|
-
|
90
|
+
rb-fsevent
|
91
|
+
rdoc (>= 3)
|
92
|
+
shoulda-context
|
93
|
+
simplecov (~> 0.9.0)
|
94
|
+
terminal-notifier-guard
|
data/Guardfile
ADDED
data/README.rdoc
CHANGED
@@ -3,20 +3,71 @@
|
|
3
3
|
|
4
4
|
A fast lightweight and minimalist wrapper around the google calendar api.
|
5
5
|
|
6
|
-
{<img src="https://travis-ci.org/northworld/google_calendar.png?branch=master" alt="Build Status" />}[https://travis-ci.org/northworld/google_calendar] {<img src="https://gemnasium.com/northworld/google_calendar.png" alt="Dependency Status" />}[https://gemnasium.com/northworld/google_calendar] {<img src="https://codeclimate.com/github/northworld/google_calendar.
|
7
|
-
|
6
|
+
{<img src="https://travis-ci.org/northworld/google_calendar.png?branch=master" alt="Build Status" />}[https://travis-ci.org/northworld/google_calendar] {<img src="https://gemnasium.com/northworld/google_calendar.png" alt="Dependency Status" />}[https://gemnasium.com/northworld/google_calendar] {<img src="https://codeclimate.com/github/northworld/google_calendar/badges/gpa.svg" />}[https://codeclimate.com/github/northworld/google_calendar]
|
8
7
|
== Install
|
9
8
|
[sudo] gem install 'google_calendar'
|
10
9
|
|
11
|
-
|
10
|
+
== Setup
|
11
|
+
|
12
|
+
Obtain a Client ID and Secret from Google
|
13
|
+
|
14
|
+
Go to the {Google Developers Console}[https://console.developers.google.com/].
|
15
|
+
Select a project, or create a new one.
|
16
|
+
In the sidebar on the left, expand APIs & auth. Next, click APIs. In the list of APIs, make sure the status is ON for the Calendar API.
|
17
|
+
In the sidebar on the left, select Credentials.
|
18
|
+
In either case, you end up on the Credentials page and can create your project's credentials from here.
|
19
|
+
|
20
|
+
If you haven't done so already, create your OAuth 2.0 credentials by clicking Create new Client ID under the OAuth heading. Next, look for your application's client ID and client secret in the relevant table. You may also create and edit redirect URIs from this page.
|
21
|
+
|
22
|
+
Take note of the Client ID as you'll need to add it to your code later.
|
23
|
+
|
24
|
+
=== How to find your calendar ID
|
25
|
+
Visit Google calendar in your web browser.
|
26
|
+
In the calendar list on the left, click the down-arrow button next to the appropriate calendar, then select Calendar settings.
|
27
|
+
In the Calendar Address section, locate the Calendar ID listed next to the XML, ICAL and HTML buttons.
|
28
|
+
Copy the Calendar ID.
|
12
29
|
|
13
30
|
== Usage
|
14
31
|
require 'rubygems'
|
15
32
|
require 'google_calendar'
|
16
33
|
|
17
|
-
|
18
|
-
|
19
|
-
|
34
|
+
YOUR_CLIENT_ID = ""
|
35
|
+
YOUR_SECRET = ""
|
36
|
+
YOUR_CALENDAR_ID = ""
|
37
|
+
|
38
|
+
# Create an instance of the calendar.
|
39
|
+
cal = Google::Calendar.new(:client_id => YOUR_CLIENT_ID,
|
40
|
+
:client_secret => YOUR_SECRET,
|
41
|
+
:calendar => YOUR_CALENDAR_ID,
|
42
|
+
:redirect_url => "urn:ietf:wg:oauth:2.0:oob" # this is what Google uses for 'applications'
|
43
|
+
)
|
44
|
+
|
45
|
+
puts "Do you already have a refresh token? (y/n)"
|
46
|
+
has_token = $stdin.gets.chomp
|
47
|
+
|
48
|
+
if has_token.downcase != 'y'
|
49
|
+
|
50
|
+
# A user needs to approve access in order to work with their calendars.
|
51
|
+
puts "Visit the following web page in your browser and approve access."
|
52
|
+
puts cal.authorize_url
|
53
|
+
puts "\nCopy the code that Google returned and paste it here:"
|
54
|
+
|
55
|
+
# Pass the ONE TIME USE access code here to login and get a refresh token that you can use for access from now on.
|
56
|
+
refresh_token = cal.login_with_auth_code( $stdin.gets.chomp )
|
57
|
+
|
58
|
+
puts "\nMake sure you SAVE YOUR REFRESH TOKEN so you don't have to prompt the user to approve access again."
|
59
|
+
puts "your refresh token is:\n\t#{refresh_token}\n"
|
60
|
+
puts "Press return to continue"
|
61
|
+
$stdin.gets.chomp
|
62
|
+
|
63
|
+
else
|
64
|
+
puts "Enter your refresh token"
|
65
|
+
refresh_token = $stdin.gets.chomp
|
66
|
+
cal.login_with_refresh_token(refresh_token)
|
67
|
+
|
68
|
+
# Note: You can also pass your refresh_token to the constructor and it will login at that time.
|
69
|
+
|
70
|
+
end
|
20
71
|
|
21
72
|
event = cal.create_event do |e|
|
22
73
|
e.title = 'A Cool Event'
|
@@ -37,8 +88,9 @@ Note: Google requests that you set the name of your application so they can bett
|
|
37
88
|
puts cal.events
|
38
89
|
|
39
90
|
# Query events
|
40
|
-
puts cal.find_events('
|
91
|
+
puts cal.find_events('your search string')
|
41
92
|
|
93
|
+
This sample code is located in readme_code.rb in the root folder.
|
42
94
|
|
43
95
|
Note: This is not a complete implementation of the calendar api, it just includes the features we needed to support our internal calendar integration.
|
44
96
|
|
@@ -54,4 +106,4 @@ Note: This is not a complete implementation of the calendar api, it just include
|
|
54
106
|
|
55
107
|
== Copyright
|
56
108
|
|
57
|
-
Copyright (c) 2010 Steve Zich. See LICENSE.txt for further details.
|
109
|
+
Copyright (c) 2010 Steve Zich. See LICENSE.txt for further details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/google_calendar.gemspec
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "google_calendar"
|
5
|
-
s.version = "0.
|
6
|
-
s.date = "
|
5
|
+
s.version = "0.4.0"
|
6
|
+
s.date = "2014-11-17"
|
7
7
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
9
9
|
|
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.email = "steve.zich@gmail.com"
|
12
12
|
|
13
13
|
s.summary = "A lightweight google calendar API wrapper"
|
14
|
-
s.description = "A minimal wrapper around the google calendar API
|
14
|
+
s.description = "A minimal wrapper around the google calendar API"
|
15
15
|
s.homepage = "http://github.com/northworld/google_calendar"
|
16
16
|
s.licenses = ["MIT"]
|
17
17
|
|
@@ -26,29 +26,19 @@ Gem::Specification.new do |s|
|
|
26
26
|
s.require_paths = ["lib"]
|
27
27
|
s.rubygems_version = "1.8.24"
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
46
|
-
else
|
47
|
-
s.add_dependency(%q<nokogiri>, [">= 1.4.4"])
|
48
|
-
s.add_dependency(%q<addressable>, [">= 2.2.2"])
|
49
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
50
|
-
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
51
|
-
s.add_dependency(%q<mocha>, [">= 0"])
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
29
|
+
s.add_runtime_dependency(%q<signet>, [">= 0.5.1"])
|
30
|
+
s.add_runtime_dependency(%q<addressable>, [">= 2.2.2"])
|
31
|
+
|
32
|
+
s.add_development_dependency(%q<terminal-notifier-guard>, [">= 0"])
|
33
|
+
s.add_development_dependency(%q<rb-fsevent>, [">= 0"])
|
34
|
+
s.add_development_dependency(%q<guard-minitest>, [">= 0"])
|
35
|
+
s.add_development_dependency(%q<minitest>, ["~> 5.1"])
|
36
|
+
s.add_development_dependency(%q<minitest-reporters>, [">=0"])
|
37
|
+
s.add_development_dependency(%q<shoulda-context>, [">= 0"])
|
38
|
+
s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
|
39
|
+
s.add_development_dependency(%q<mocha>, [">= 0"])
|
40
|
+
s.add_development_dependency(%q<rake>, ["> 10"])
|
41
|
+
s.add_development_dependency(%q<rdoc>, [">= 3"])
|
42
|
+
s.add_development_dependency(%q<simplecov>, ["~> 0.9.0"])
|
43
|
+
|
44
|
+
end
|
data/lib/google/calendar.rb
CHANGED
@@ -1,102 +1,157 @@
|
|
1
|
-
require 'nokogiri'
|
2
|
-
|
3
1
|
module Google
|
4
2
|
|
3
|
+
#
|
5
4
|
# Calendar is the main object you use to interact with events.
|
6
5
|
# use it to find, create, update and delete them.
|
7
6
|
#
|
8
7
|
class Calendar
|
9
8
|
|
10
|
-
|
9
|
+
attr_reader :connection
|
10
|
+
|
11
|
+
#
|
12
|
+
# Setup and connect to the specified Google Calendar.
|
11
13
|
# the +params+ paramater accepts
|
12
|
-
# * :
|
13
|
-
# * :
|
14
|
-
# * :
|
15
|
-
# * :
|
16
|
-
# * :
|
14
|
+
# * :client_id => the client ID that you received from Google after registering your application with them (https://console.developers.google.com/). REQUIRED
|
15
|
+
# * :client_secret => the client secret you received from Google after registering your application with them. REQUIRED
|
16
|
+
# * :redirect_url => the url where your users will be redirected to after they have successfully permitted access to their calendars. Use 'urn:ietf:wg:oauth:2.0:oob' if you are using an 'application'" REQUIRED
|
17
|
+
# * :calendar_id => the id of the calendar you would like to work with (see Readme.rdoc for instructions on how to find yours)
|
18
|
+
# * :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
|
17
19
|
#
|
18
|
-
#
|
20
|
+
# See Readme.rdoc or readme_code.rb for an explication on the OAuth2 authorization process.
|
19
21
|
#
|
20
|
-
# ====
|
21
|
-
#
|
22
|
-
#
|
22
|
+
# ==== Example
|
23
|
+
# Google::Calendar.new(:client_id => YOUR_CLIENT_ID,
|
24
|
+
# :client_secret => YOUR_SECRET,
|
25
|
+
# :calendar => YOUR_CALENDAR_ID,
|
26
|
+
# :redirect_url => "urn:ietf:wg:oauth:2.0:oob" # this is what Google uses for 'applications'
|
27
|
+
# )
|
23
28
|
#
|
24
|
-
|
25
|
-
|
29
|
+
def initialize(params={})
|
30
|
+
options = {
|
31
|
+
:client_id => params[:client_id],
|
32
|
+
:client_secret => params[:client_secret],
|
33
|
+
:refresh_token => params[:refresh_token],
|
34
|
+
:redirect_url => params[:redirect_url],
|
35
|
+
:calendar_id => params[:calendar]
|
36
|
+
}
|
37
|
+
|
38
|
+
@connection = Connection.new options
|
39
|
+
end
|
40
|
+
|
26
41
|
#
|
27
|
-
#
|
28
|
-
# Calendar.new(:username => 'some.guy@gmail.com', :password => 'ilovepie!', :app_name => 'mycompany.com-googlecalendar-integration')
|
42
|
+
# The URL you need to send a user in order to let them grant you access to their calendars.
|
29
43
|
#
|
44
|
+
def authorize_url
|
45
|
+
@connection.authorize_url
|
46
|
+
end
|
30
47
|
|
31
|
-
#
|
32
|
-
|
48
|
+
#
|
49
|
+
# The single use auth code that google uses during the auth process.
|
50
|
+
#
|
51
|
+
def auth_code
|
52
|
+
@connection.auth_code
|
53
|
+
end
|
33
54
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
55
|
+
#
|
56
|
+
# The current access token. Used during a session, typically expires in a hour.
|
57
|
+
#
|
58
|
+
def access_token
|
59
|
+
@connection.access_token
|
60
|
+
end
|
40
61
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
62
|
+
#
|
63
|
+
# The refresh token is used to obtain a new access token. It remains valid until a user revokes access.
|
64
|
+
#
|
65
|
+
def refresh_token
|
66
|
+
@connection.refresh_token
|
45
67
|
end
|
46
68
|
|
69
|
+
#
|
70
|
+
# Convenience method used to streamline the process of logging in with a auth code.
|
71
|
+
#
|
72
|
+
def login_with_auth_code(auth_code)
|
73
|
+
@connection.login_with_auth_code(auth_code)
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# Convenience method used to streamline the process of logging in with a refresh token.
|
78
|
+
#
|
79
|
+
def login_with_refresh_token(refresh_token)
|
80
|
+
@connection.login_with_refresh_token(refresh_token)
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
47
84
|
# Find all of the events associated with this calendar.
|
48
85
|
# Returns:
|
49
|
-
#
|
50
|
-
#
|
86
|
+
# an empty array if nothing found.
|
87
|
+
# an array with one element if only one found.
|
51
88
|
# an array of events if many found.
|
52
89
|
#
|
53
90
|
def events
|
54
91
|
event_lookup()
|
55
92
|
end
|
56
93
|
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
94
|
+
#
|
95
|
+
# This is equivalent to running a search in the Google calendar web application.
|
96
|
+
# Google does not provide a way to specify what attributes you would like to
|
97
|
+
# search (i.e. title), by default it searches everything.
|
60
98
|
# If you would like to find specific attribute value (i.e. title=Picnic), run a query
|
61
99
|
# and parse the results.
|
62
100
|
# Returns:
|
63
|
-
#
|
64
|
-
#
|
101
|
+
# an empty array if nothing found.
|
102
|
+
# an array with one element if only one found.
|
65
103
|
# an array of events if many found.
|
66
104
|
#
|
67
105
|
def find_events(query)
|
68
106
|
event_lookup("?q=#{query}")
|
69
107
|
end
|
70
108
|
|
109
|
+
#
|
71
110
|
# Find all of the events associated with this calendar that start in the given time frame.
|
72
111
|
# The lower bound is inclusive, whereas the upper bound is exclusive.
|
73
112
|
# Events that overlap the range are included.
|
113
|
+
#
|
114
|
+
# the +options+ parameter accepts
|
115
|
+
# :max_results => the maximum number of results to return defaults to 25 the largest number Google accepts is 2500
|
116
|
+
# :order_by => how you would like the results ordered, can be either 'startTime' or 'updated'. Defaults to 'startTime'. Note: it must be 'updated' if expand_recurring_events is set to false.
|
117
|
+
# :expand_recurring_events => When set to true each instance of a recurring event is returned. Defaults to true.
|
118
|
+
#
|
74
119
|
# Returns:
|
75
|
-
#
|
76
|
-
#
|
120
|
+
# an empty array if nothing found.
|
121
|
+
# an array with one element if only one found.
|
77
122
|
# an array of events if many found.
|
78
123
|
#
|
79
|
-
def find_events_in_range(start_min, start_max,options = {})
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
formatted_start_max = start_max.strftime("%Y-%m-%dT%H:%M:%S")
|
84
|
-
query = "?start-min=#{formatted_start_min}&start-max=#{formatted_start_max}&recurrence-expansion-start=#{formatted_start_min}&recurrence-expansion-end=#{formatted_start_max}"
|
85
|
-
query = "#{query}&orderby=#{options[:order_by]}&max-results=#{options[:max_results]}"
|
124
|
+
def find_events_in_range(start_min, start_max, options = {})
|
125
|
+
formatted_start_min = encode_time(start_min)
|
126
|
+
formatted_start_max = encode_time(start_max)
|
127
|
+
query = "?timeMin=#{formatted_start_min}&timeMax=#{formatted_start_max}#{parse_options(options)}"
|
86
128
|
event_lookup(query)
|
87
129
|
end
|
88
130
|
|
131
|
+
#
|
132
|
+
# Find all events that are occurring at the time the method is run or later.
|
133
|
+
#
|
134
|
+
# the +options+ parameter accepts
|
135
|
+
# :max_results => the maximum number of results to return defaults to 25 the largest number Google accepts is 2500
|
136
|
+
# :order_by => how you would like the results ordered, can be either 'startTime' or 'updated'. Defaults to 'startTime'. Note: it must be 'updated' if expand_recurring_events is set to false.
|
137
|
+
# :expand_recurring_events => When set to true each instance of a recurring event is returned. Defaults to true.
|
138
|
+
#
|
139
|
+
# Returns:
|
140
|
+
# an empty array if nothing found.
|
141
|
+
# an array with one element if only one found.
|
142
|
+
# an array of events if many found.
|
143
|
+
#
|
89
144
|
def find_future_events(options={})
|
90
|
-
|
91
|
-
|
92
|
-
query = "?futureevents=true&orderby=#{options[:order_by]}&max-results=#{options[:max_results]}"
|
145
|
+
formatted_start_min = encode_time(DateTime.now)
|
146
|
+
query = "?timeMin=#{formatted_start_min}#{parse_options(options)}"
|
93
147
|
event_lookup(query)
|
94
148
|
end
|
95
149
|
|
150
|
+
#
|
96
151
|
# Attempts to find the event specified by the id
|
97
152
|
# Returns:
|
98
|
-
#
|
99
|
-
#
|
153
|
+
# an empty array if nothing found.
|
154
|
+
# an array with one element if only one found.
|
100
155
|
# an array of events if many found.
|
101
156
|
#
|
102
157
|
def find_event_by_id(id)
|
@@ -104,8 +159,9 @@ module Google
|
|
104
159
|
event_lookup("/#{id}")
|
105
160
|
end
|
106
161
|
|
107
|
-
#
|
108
|
-
#
|
162
|
+
#
|
163
|
+
# Creates a new event and immediately saves it.
|
164
|
+
# Returns the event
|
109
165
|
#
|
110
166
|
# ==== Examples
|
111
167
|
# # Use a block
|
@@ -114,7 +170,7 @@ module Google
|
|
114
170
|
# e.where = "Room 101"
|
115
171
|
# end
|
116
172
|
#
|
117
|
-
# # Don't use a block (need to call save
|
173
|
+
# # Don't use a block (need to call save manually)
|
118
174
|
# event = cal.create_event
|
119
175
|
# event.title = "A New Event"
|
120
176
|
# event.where = "Room 101"
|
@@ -124,108 +180,83 @@ module Google
|
|
124
180
|
setup_event(Event.new, &blk)
|
125
181
|
end
|
126
182
|
|
127
|
-
#
|
183
|
+
#
|
184
|
+
# Looks for the specified event id.
|
128
185
|
# If it is found it, updates it's vales and returns it.
|
129
186
|
# If the event is no longer on the server it creates a new one with the specified values.
|
130
187
|
# Works like the create_event method.
|
131
188
|
#
|
132
189
|
def find_or_create_event_by_id(id, &blk)
|
133
|
-
setup_event(find_event_by_id(id) || Event.new, &blk)
|
190
|
+
setup_event(find_event_by_id(id)[0] || Event.new, &blk)
|
134
191
|
end
|
135
192
|
|
193
|
+
#
|
136
194
|
# Saves the specified event.
|
137
195
|
# This is a callback used by the Event class.
|
138
196
|
#
|
139
197
|
def save_event(event)
|
140
|
-
method =
|
141
|
-
|
142
|
-
|
198
|
+
method = event.new_event? ? :post : :put
|
199
|
+
body = event.use_quickadd? ? nil : event.to_json
|
200
|
+
|
201
|
+
query_string = if event.use_quickadd?
|
202
|
+
"/quickAdd?text=#{ Addressable::URI.encode_component(event.quickadd)}"
|
203
|
+
elsif event.new_event?
|
204
|
+
''
|
205
|
+
else # update existing event.
|
206
|
+
"/#{event.id}"
|
207
|
+
end
|
208
|
+
|
209
|
+
@connection.send_events_request(query_string, method, body)
|
143
210
|
end
|
144
211
|
|
212
|
+
#
|
145
213
|
# Deletes the specified event.
|
146
214
|
# This is a callback used by the Event class.
|
147
215
|
#
|
148
216
|
def delete_event(event)
|
149
|
-
@connection.
|
217
|
+
@connection.send_events_request("/#{event.id}", :delete)
|
150
218
|
end
|
151
219
|
|
152
|
-
|
220
|
+
protected
|
221
|
+
|
153
222
|
#
|
154
|
-
#
|
155
|
-
# class User
|
156
|
-
# def calendar
|
157
|
-
# @calendar ||= Google::Calendar.new :username => "foo@gmail.com", :password => "bar"
|
158
|
-
# end
|
159
|
-
# end
|
160
|
-
# user = User.new
|
161
|
-
# 2.times { user.calendar } #only one HTTP authentication request to google
|
162
|
-
# user.calendar.reload #new HTTP authentication request to google
|
223
|
+
# Utility method used to centralize the parsing of common query parameters.
|
163
224
|
#
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
:auth_url => auth_url)
|
170
|
-
self
|
171
|
-
end
|
172
|
-
|
173
|
-
def display_color
|
174
|
-
calendar_data.xpath("//entry[title='#{@calendar}']/color/@value").first.value
|
225
|
+
def parse_options(options) # :nodoc
|
226
|
+
options[:max_results] ||= 25
|
227
|
+
options[:order_by] ||= 'startTime' # other option is 'updated'
|
228
|
+
options[:expand_recurring_events] ||= true
|
229
|
+
"&orderBy=#{options[:order_by]}&maxResults=#{options[:max_results]}&singleEvents=#{options[:expand_recurring_events]}"
|
175
230
|
end
|
176
231
|
|
177
|
-
|
232
|
+
#
|
233
|
+
# Utility method to centralize time encoding.
|
234
|
+
#
|
235
|
+
def encode_time(time) #:nodoc:
|
236
|
+
Addressable::URI.encode_component(time.strftime("%FT%T%:z"), Addressable::URI::CharacterClasses::UNRESERVED)
|
237
|
+
end
|
178
238
|
|
239
|
+
#
|
240
|
+
# Utility method used to centralize event lookup.
|
241
|
+
#
|
179
242
|
def event_lookup(query_string = '') #:nodoc:
|
180
243
|
begin
|
181
|
-
|
182
|
-
|
183
|
-
|
244
|
+
response = @connection.send_events_request(query_string, :get)
|
245
|
+
events = Event.build_from_google_feed( JSON.parse(response.body) , self) || []
|
246
|
+
return events if events.empty?
|
247
|
+
events.length > 1 ? events : [events[0]]
|
184
248
|
rescue Google::HTTPNotFound
|
185
249
|
return nil
|
186
250
|
end
|
187
251
|
end
|
188
252
|
|
189
|
-
def calendar_id #:nodoc:
|
190
|
-
@calendar || "default"
|
191
|
-
end
|
192
|
-
|
193
|
-
# Initialize the events URL given String attribute @calendar value :
|
194
253
|
#
|
195
|
-
#
|
196
|
-
# does not contain '@' : fetch user's all calendars (http://code.google.com/apis/calendar/data/2.0/developers_guide_protocol.html#RetrievingAllCalendars)
|
197
|
-
# and return feed url matching @calendar.
|
198
|
-
# nil : default feed url.
|
254
|
+
# Utility method used to centralize event setup
|
199
255
|
#
|
200
|
-
# Returns:
|
201
|
-
# a String url for a calendar feeds.
|
202
|
-
# raise a Google::InvalidCalendar error if @calendar is invalid.
|
203
|
-
#
|
204
|
-
def events_url
|
205
|
-
if @calendar and !@calendar.include?("@")
|
206
|
-
link = calendar_data.xpath("//entry[title='#{@calendar}']/link[contains(@rel, '#eventFeed')]/@href").to_s
|
207
|
-
link.empty? ? raise(Google::InvalidCalendar) : link
|
208
|
-
else
|
209
|
-
"https://www.google.com/calendar/feeds/#{calendar_id}/private/full"
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
def calendar_data
|
214
|
-
unless @calendar_data
|
215
|
-
xml = @connection.send(Addressable::URI.parse("https://www.google.com/calendar/feeds/default/allcalendars/full"), :get)
|
216
|
-
@calendar_data = Nokogiri::XML(xml.body)
|
217
|
-
@calendar_data.remove_namespaces!
|
218
|
-
end
|
219
|
-
@calendar_data
|
220
|
-
end
|
221
|
-
|
222
256
|
def setup_event(event) #:nodoc:
|
223
257
|
event.calendar = self
|
224
258
|
if block_given?
|
225
|
-
|
226
|
-
event.title = event.title.encode(:xml => :text) if event.title
|
227
|
-
event.content = event.content.encode(:xml => :text) if event.content
|
228
|
-
event.where = event.where.encode(:xml => :text) if event.where
|
259
|
+
yield(event)
|
229
260
|
end
|
230
261
|
event.save
|
231
262
|
event
|