edave-gcal4ruby 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.
@@ -0,0 +1,196 @@
1
+ # Author:: Mike Reich (mike@seabourneconsulting.com)
2
+ # Copyright:: Copyright (C) 2010 Mike Reich
3
+ # License:: GPL v2
4
+ #--
5
+ # Licensed under the General Public License (GPL), Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ #
15
+ # Feel free to use and update, but be sure to contribute your
16
+ # code back to the project and attribute as required by the license.
17
+ #++
18
+ require 'gdata4ruby'
19
+ require 'gdata4ruby/gdata_object'
20
+ require 'gdata4ruby/utils/utils'
21
+ require 'gdata4ruby/acl/access_rule'
22
+ require 'gcal4ruby/calendar'
23
+ require 'gcal4ruby/event'
24
+ require 'gcal4ruby/recurrence'
25
+ require 'rexml/document'
26
+
27
+ module GCal4Ruby
28
+ #The service class is the main handler for all direct interactions with the
29
+ #Google Calendar API. A service represents a single user account. Each user
30
+ #account can have multiple calendars, so you'll need to find the calendar you
31
+ #want from the service, using the Calendar#find class method.
32
+ #=Usage
33
+ #
34
+ #1. Authenticate
35
+ # service = Service.new
36
+ # service.authenticate("user@gmail.com", "password")
37
+ #
38
+ #2. Get Calendar List
39
+ # calendars = service.calendars
40
+ #
41
+ class Service
42
+ @@calendar_list_feed = 'www.google.com/calendar/feeds/default/owncalendars/full'
43
+
44
+ # The type of GData4Ruby service we want to use
45
+ attr_accessor :gdata_service
46
+
47
+ # Convenience attribute contains the currently authenticated account name
48
+ attr_accessor :account
49
+
50
+ # Determines whether GCal4Ruby ensures a calendar is public. Setting this to false can increase speeds by
51
+ # 50% but can cause errors if you try to do something to a calendar that is not public and you don't have
52
+ # adequate permissions
53
+ attr_accessor :check_public
54
+
55
+ #Accepts an optional attributes hash for initialization values
56
+ def initialize(attributes = {}, service = nil)
57
+ # If the user has specified the type of GData4Ruby class they want, instantiate it
58
+ if(service != nil)
59
+ @gdata_service = GData4Ruby.const_get(service).new(attributes)
60
+ end
61
+ # Otherwise use the default service
62
+ @gdata_service ||= GData4Ruby::Service.new(attributes)
63
+ attributes.each do |key, value|
64
+ if self.respond_to?("#{key}=")
65
+ self.send("#{key}=", value)
66
+ end
67
+ end
68
+ @check_public ||= true
69
+ @account ||= "default"
70
+ @debug ||= false
71
+ log("Check Public: #{check_public}")
72
+ end
73
+
74
+ def debug
75
+ return @debug
76
+ end
77
+
78
+ def debug=(value)
79
+ @debug=value
80
+ @gdata_service.debug = value
81
+ end
82
+
83
+ def log(string)
84
+ puts string if debug
85
+ end
86
+
87
+ def default_event_feed
88
+ return create_url("www.google.com/calendar/feeds/#{@account}/private/full")
89
+ end
90
+
91
+ # The authenticate method passes an for the service to use to access Google's servers
92
+ # If authentication succeeds, returns true, otherwise raises the AuthenticationFailed error.
93
+ def authenticate(options = {})
94
+ if not options.has_key?(:service)
95
+ options[:service] = 'cl'
96
+ end
97
+ @gdata_service.authenticate(options)
98
+ end
99
+
100
+ #Helper function to reauthenticate to a new Google service without having to re-set credentials.
101
+ def reauthenticate(options = {})
102
+ if not options.has_key?(:service)
103
+ options[:service] = 'cl'
104
+ end
105
+ @gdata_service.reauthenticate(options)
106
+ end
107
+
108
+ # Passes a request along from a GData4Ruby GDataObject to a GData4Ruby Base (Service) to be invoked
109
+ def send_request(request)
110
+ if not @gdata_service.authenticated?
111
+ raise GData4Ruby::NotAuthenticated
112
+ end
113
+ @gdata_service.send_request(request)
114
+ end
115
+
116
+ #Returns an array of Calendar objects for each calendar associated with
117
+ #the authenticated account.
118
+ def calendars
119
+ ret = send_request(GData4Ruby::Request.new(:get, create_url(@@calendar_list_feed + "?fields=entry(@gd:*,id,title)"), nil, {"max-results" => "10000"}))
120
+ cals = []
121
+ REXML::Document.new(ret.body).root.elements.each("entry"){}.map do |entry|
122
+ entry = GData4Ruby::Utils.add_namespaces(entry)
123
+ cal = Calendar.new(self, {:debug => debug})
124
+ cal.load(entry.to_s)
125
+ cals << cal
126
+ end
127
+ return cals
128
+ end
129
+
130
+ #Returns an array of Event objects for each event in this account
131
+ def events
132
+ ret = send_request(GData4Ruby::Request.new(:get, default_event_feed, nil, {"max-results" => "10000"}))
133
+ events = []
134
+ REXML::Document.new(ret.body).root.elements.each("entry"){}.map do |entry|
135
+ entry = GData4Ruby::Utils.add_namespaces(entry)
136
+ event = Event.new(self, {:debug => debug})
137
+ event.load(entry.to_s)
138
+ events << event
139
+ end
140
+ return events
141
+ end
142
+
143
+ # Builds a URL
144
+ def create_url(path)
145
+ return @gdata_service.create_url(path)
146
+ end
147
+
148
+ #Helper function to return a formatted iframe embedded google calendar. Parameters are:
149
+ #1. *cals*: either an array of calendar ids, or <em>:all</em> for all calendars, or <em>:first</em> for the first (usally default) calendar
150
+ #2. *params*: a hash of parameters that affect the display of the embedded calendar. Accepts any parameter that the google iframe recognizes. Here are the most common:
151
+ # height:: the height of the embedded calendar in pixels
152
+ # width:: the width of the embedded calendar in pixels
153
+ # title:: the title to display
154
+ # bgcolor:: the background color. Limited choices, see google docs for allowable values.
155
+ # showTitle:: set to '0' to hide the title
156
+ # showDate:: set to '0' to hide the current date
157
+ # showNav:: set to '0 to hide the navigation tools
158
+ # showPrint:: set to '0' to hide the print icon
159
+ # showTabs:: set to '0' to hide the tabs
160
+ # showCalendars:: set to '0' to hide the calendars selection drop down
161
+ # showTz:: set to '0' to hide the timezone selection
162
+ # border:: the border width in pixels
163
+ # dates:: a range of dates to display in the format of 'yyyymmdd/yyyymmdd'. Example: 20090820/20091001
164
+ # privateKey:: use to display a private calendar. You can find this key under the calendar settings pane of the Google Calendar website.
165
+ # ctz:: The timezone to convert event times to
166
+ #3. *colors*: a hash of calendar ids as key and color values as associated hash values. Example: {'test@gmail.com' => '#7A367A'}
167
+ def to_iframe(cals, params = {}, colors = {})
168
+ params[:height] ||= "600"
169
+ params[:width] ||= "600"
170
+ params[:title] ||= (self.account ? self.account : '')
171
+ params[:bgcolor] ||= "#FFFFFF"
172
+ params[:border] ||= "0"
173
+ params.each{|key, value| params[key] = CGI::escape(value)}
174
+ output = "#{params.to_a.collect{|a| a.join("=")}.join("&")}&"
175
+
176
+ if cals.is_a?(Array)
177
+ for c in cals
178
+ output += "src=#{c}&"
179
+ if colors and colors[c]
180
+ output += "color=%23#{colors[c].gsub("#", "")}&"
181
+ end
182
+ end
183
+ elsif cals == :all
184
+ cal_list = calendars()
185
+ for c in cal_list
186
+ output += "src=#{c.id}&"
187
+ end
188
+ elsif cals == :first
189
+ cal_list = calendars()
190
+ output += "src=#{cal_list[0].id}&"
191
+ end
192
+
193
+ "<iframe src='#{create_url("www.google.com/calendar/embed?"+output)}' style='#{params[:border]} px solid;' width='#{params[:width]}' height='#{params[:height]}' frameborder='#{params[:border]}' scrolling='no'></iframe>"
194
+ end
195
+ end
196
+ end
data/test/unit.rb ADDED
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # Prefix LOAD_PATH with lib sub-directory to ensure we're
4
+ # testing the intended version.
5
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
6
+
7
+ require 'rubygems'
8
+ require 'gcal4ruby'
9
+ include GCal4Ruby
10
+
11
+ @service = Service.new
12
+ @username = nil
13
+ @password = nil
14
+
15
+ def tester
16
+ if ARGV.include?("-d")
17
+ @service.debug = true
18
+ end
19
+ ARGV.each do |ar|
20
+ if ar.match("username=")
21
+ @username = ar.gsub("username=", "")
22
+ end
23
+ if ar.match("password=")
24
+ @password = ar.gsub("password=", "")
25
+ end
26
+ end
27
+ service_test
28
+ calendar_test
29
+ event_test
30
+ event_recurrence_test
31
+ all_day_recurrence_test
32
+ end
33
+
34
+ def service_test
35
+ puts "---Starting Service Test---"
36
+ puts "1. Authenticate"
37
+ if @service.authenticate(@username, @password)
38
+ successful
39
+ else
40
+ failed
41
+ end
42
+
43
+ puts "2. Calendar List"
44
+ cals = @service.calendars
45
+ if cals
46
+ successful "Calendars for this Account:"
47
+ cals.each do |cal|
48
+ puts cal.title
49
+ end
50
+ else
51
+ failed
52
+ end
53
+ end
54
+
55
+ def calendar_test
56
+ puts "---Starting Calendar Test---"
57
+
58
+ puts "1. Create Calendar"
59
+ cal = Calendar.new(@service)
60
+ cal.title = "test calendar"+Time.now.to_s
61
+ puts "Calender exists = "+cal.exists?.to_s
62
+ if cal.save
63
+ successful cal.to_xml
64
+ else
65
+ failed
66
+ end
67
+
68
+ puts "2. Edit Calendar"
69
+ cal.title = "renamed title"
70
+ if cal.save
71
+ successful cal.to_xml
72
+ else
73
+ puts "Test 2 Failed"
74
+ end
75
+
76
+ puts "3. Find Calendar by ID"
77
+ c = Calendar.find(@service, {:id => cal.id})
78
+ if c.title == cal.title
79
+ successful
80
+ else
81
+ failed "#{c.title} not equal to #{cal.title}"
82
+ end
83
+
84
+ puts "4. Delete Calendar"
85
+ if cal.delete and not cal.exists?
86
+ successful
87
+ else
88
+ failed
89
+ end
90
+ end
91
+
92
+ def event_test
93
+ puts "---Starting Event Test---"
94
+
95
+ puts "1. Create Event"
96
+ event = Event.new(@service)
97
+ event.calendar = @service.calendars[0]
98
+ event.title = "Test Event"
99
+ event.content = "Test event content"
100
+ event.start_time = Time.now+1800
101
+ event.end_time = Time.now+5400
102
+ if event.save
103
+ successful event.to_xml
104
+ else
105
+ failed
106
+ end
107
+
108
+ puts "2. Edit Event"
109
+ event.title = "Edited title"
110
+ if event.save
111
+ successful event.to_xml
112
+ else
113
+ failed
114
+ end
115
+
116
+ puts "3. Reload Event"
117
+ if event.reload
118
+ successful
119
+ end
120
+
121
+ puts "4. Find Event by id"
122
+ e = Event.find(@service, {:id => event.id})
123
+ if e.title == event.title
124
+ successful
125
+ else
126
+ failed "Found event doesn't match existing event"
127
+ end
128
+
129
+ puts "5. Delete Event"
130
+ if event.delete
131
+ successful
132
+ else
133
+ failed
134
+ end
135
+ end
136
+
137
+ def event_recurrence_test
138
+ puts "---Starting Event Recurrence Test---"
139
+
140
+ @first_start = Time.now
141
+ @first_end = Time.now+3600
142
+ @first_freq = {'weekly' => ['TU']}
143
+ @second_start = Time.now+86000
144
+ @second_end = Time.now+89600
145
+ @second_freq = {'weekly' => ['SA']}
146
+
147
+ puts "1. Create Recurring Event"
148
+ event = Event.new(@service)
149
+ event.calendar = @service.calendars[0]
150
+ event.title = "Test Recurring Event"
151
+ event.content = "Test event content"
152
+ event.recurrence = Recurrence.new({:start_time => @first_start, :end_time => @first_end, :frequency => @first_freq})
153
+ if event.save
154
+ successful event.to_xml
155
+ else
156
+ failed("recurrence = "+event.recurrence.to_s)
157
+ end
158
+
159
+ puts "2. Edit Recurrence"
160
+ event.title = "Edited recurring title"
161
+ event.recurrence = Recurrence.new({:start_time => @second_start, :end_time => @second_end, :frequency => @second_freq})
162
+ if event.save
163
+ successful event.to_xml
164
+ else
165
+ failed
166
+ end
167
+
168
+ puts "3. Delete Event"
169
+ if event.delete
170
+ successful
171
+ else
172
+ failed
173
+ end
174
+ end
175
+
176
+ def all_day_recurrence_test
177
+ puts "---Starting All Day Recurrence Test---"
178
+
179
+ start_time = Time.now
180
+ end_time = start_time + 60*60*24
181
+ freq = {'weekly' => ['MO','TU']}
182
+
183
+ puts "1. Create All Day Recurring Event"
184
+ event = Event.new(@service)
185
+ event.calendar = @service.calendars[0]
186
+ event.title = "Test All Day Recurring Event"
187
+ event.content = "Test all day event content"
188
+ event.recurrence = Recurrence.new({:start_time => start_time, :end_time => end_time, :frequency => freq, :all_day => true})
189
+ if event.save
190
+ successful event.to_xml
191
+ else
192
+ failed("recurrence = "+event.recurrence.to_s)
193
+ end
194
+
195
+ puts "2. Validate returned event is an all day event"
196
+ if event.recurrence.all_day
197
+ successful
198
+ else
199
+ failed("recurrence = "+event.recurrence.to_s)
200
+ end
201
+
202
+ puts "3. Validate frequency of event"
203
+ if event.recurrence.frequency['weekly'] == ['MO','TU']
204
+ successful
205
+ else
206
+ failed("recurrence = "+event.recurrence.to_s)
207
+ end
208
+
209
+ puts "4. Delete Event"
210
+ if event.delete
211
+ successful
212
+ else
213
+ failed
214
+ end
215
+ end
216
+
217
+ def failed(m = nil)
218
+ puts "Test Failed"
219
+ puts m if m
220
+ exit()
221
+ end
222
+
223
+ def successful(m = nil)
224
+ puts "Test Successful"
225
+ puts m if m
226
+ end
227
+
228
+ tester
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: edave-gcal4ruby
3
+ version: !ruby/object:Gem::Version
4
+ hash: 7
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
11
+ platform: ruby
12
+ authors:
13
+ - Mike Reich
14
+ - Anthony Underwood
15
+ - David Pitman
16
+ autorequire:
17
+ bindir: bin
18
+ cert_chain: []
19
+
20
+ date: 2011-01-11 00:00:00 -05:00
21
+ default_executable:
22
+ dependencies:
23
+ - !ruby/object:Gem::Dependency
24
+ name: edave-gdata4ruby
25
+ prerelease: false
26
+ requirement: &id001 !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ hash: 23
32
+ segments:
33
+ - 0
34
+ - 2
35
+ - 0
36
+ version: 0.2.0
37
+ type: :runtime
38
+ version_requirements: *id001
39
+ description:
40
+ email:
41
+ - mike@seabourneconsulting.com
42
+ - email2ants@gmail.com
43
+ - ui-design@vestaldesign.com
44
+ executables: []
45
+
46
+ extensions: []
47
+
48
+ extra_rdoc_files:
49
+ - README
50
+ files:
51
+ - CHANGELOG
52
+ - README
53
+ - lib/gcal4ruby.rb
54
+ - lib/gcal4ruby/calendar.rb
55
+ - lib/gcal4ruby/event.rb
56
+ - lib/gcal4ruby/recurrence.rb
57
+ - lib/gcal4ruby/service.rb
58
+ - test/unit.rb
59
+ has_rdoc: true
60
+ homepage: https://github.com/edave/GData4Ruby
61
+ licenses: []
62
+
63
+ post_install_message:
64
+ rdoc_options: []
65
+
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ hash: 3
83
+ segments:
84
+ - 0
85
+ version: "0"
86
+ requirements: []
87
+
88
+ rubyforge_project:
89
+ rubygems_version: 1.4.1
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: A full featured wrapper for interacting with the Google Calendar API
93
+ test_files:
94
+ - test/unit.rb