railsware-gcal4ruby 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,273 @@
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
+
19
+ class Time
20
+ #Returns a ISO 8601 complete formatted string of the time
21
+ def complete
22
+ self.utc.strftime("%Y%m%dT%H%M%S")
23
+ end
24
+
25
+ def self.parse_complete(value)
26
+ d, h = value.split("T")
27
+ return Time.parse(d+" "+h.gsub("Z", ""))
28
+ end
29
+ end
30
+
31
+ module GCal4Ruby
32
+ #The Recurrence class stores information on an Event's recurrence. The class implements
33
+ #the RFC 2445 iCalendar recurrence description.
34
+ class Recurrence
35
+ #The event start date/time
36
+ attr_reader :start_time
37
+ #The event end date/time
38
+ attr_reader :end_time
39
+ #the event reference
40
+ attr_reader :event
41
+ #The date until which the event will be repeated
42
+ attr_reader :repeat_until
43
+ #The event frequency
44
+ attr_reader :frequency
45
+ #True if the event is all day (i.e. no start/end time)
46
+ attr_accessor :all_day
47
+
48
+ #Accepts an optional attributes hash or a string containing a properly formatted ISO 8601 recurrence rule. Returns a new Recurrence object
49
+ def initialize(vars = {})
50
+ if vars.is_a? Hash
51
+ vars.each do |key, value|
52
+ self.send("#{key}=", value)
53
+ end
54
+ elsif vars.is_a? String
55
+ self.load(vars)
56
+ end
57
+ @all_day ||= false
58
+ end
59
+
60
+ #Accepts a string containing a properly formatted ISO 8601 recurrence rule and loads it into the recurrence object
61
+ def load(rec)
62
+ attrs = rec.split("\n")
63
+ attrs.each do |val|
64
+ key, value = val.split(":")
65
+ case key
66
+ when 'DTSTART'
67
+ @start_time = Time.parse_complete(value)
68
+ when 'DTSTART;VALUE=DATE'
69
+ @start_time = Time.parse(value)
70
+ @all_day = true
71
+ when 'DTSTART;VALUE=DATE-TIME'
72
+ @start_time = Time.parse_complete(value)
73
+ when 'DTEND'
74
+ @end_time = Time.parse_complete(value)
75
+ when 'DTEND;VALUE=DATE'
76
+ @end_time = Time.parse(value)
77
+ when 'DTEND;VALUE=DATE-TIME'
78
+ @end_time = Time.parse_complete(value)
79
+ when 'RRULE'
80
+ vals = value.split(";")
81
+ key = ''
82
+ by = ''
83
+ int = nil
84
+ vals.each do |rr|
85
+ a, h = rr.split("=")
86
+ case a
87
+ when 'FREQ'
88
+ key = h.downcase.capitalize
89
+ when 'INTERVAL'
90
+ int = h
91
+ when 'UNTIL'
92
+ @repeat_until = Time.parse(value)
93
+ else
94
+ by = h.split(",")
95
+ end
96
+ end
97
+ @frequency = {key => by}
98
+ @frequency.merge({'interval' => int}) if int
99
+ end
100
+ end
101
+ end
102
+
103
+ def to_s
104
+ output = ''
105
+ if @frequency
106
+ f = ''
107
+ i = ''
108
+ by = ''
109
+ @frequency.each do |key, v|
110
+ if v.is_a?(Array)
111
+ if v.size > 0
112
+ value = v.join(",")
113
+ else
114
+ value = nil
115
+ end
116
+ else
117
+ value = v
118
+ end
119
+ f += "#{key.downcase} " if key != 'interval'
120
+ case key.downcase
121
+ when "secondly"
122
+ by += "every #{value} second"
123
+ when "minutely"
124
+ by += "every #{value} minute"
125
+ when "hourly"
126
+ by += "every #{value} hour"
127
+ when "weekly"
128
+ by += "on #{value}" if value
129
+ when "monthly"
130
+ by += "on #{value}"
131
+ when "yearly"
132
+ by += "on the #{value} day of the year"
133
+ when 'interval'
134
+ i += "for #{value} times"
135
+ end
136
+ end
137
+ output += f+i+by
138
+ end
139
+ if @repeat_until
140
+ output += " and repeats until #{@repeat_until.strftime("%m/%d/%Y")}"
141
+ end
142
+ output
143
+ end
144
+
145
+ #Returns a string with the correctly formatted ISO 8601 recurrence rule
146
+ def to_recurrence_string
147
+
148
+ output = ''
149
+ if @all_day
150
+ output += "DTSTART;VALUE=DATE:#{@start_time.utc.strftime("%Y%m%d")}\n"
151
+ else
152
+ output += "DTSTART;VALUE=DATE-TIME:#{@start_time.complete}\n"
153
+ end
154
+ if @all_day
155
+ output += "DTEND;VALUE=DATE:#{@end_time.utc.strftime("%Y%m%d")}\n"
156
+ else
157
+ output += "DTEND;VALUE=DATE-TIME:#{@end_time.complete}\n"
158
+ end
159
+ output += "RRULE:"
160
+ if @frequency
161
+ f = 'FREQ='
162
+ i = ''
163
+ by = ''
164
+ @frequency.each do |key, v|
165
+ if v.is_a?(Array)
166
+ if v.size > 0
167
+ value = v.join(",")
168
+ else
169
+ value = nil
170
+ end
171
+ else
172
+ value = v
173
+ end
174
+ f += "#{key.upcase};" if key != 'interval'
175
+ case key.downcase
176
+ when "secondly"
177
+ by += "BYSECOND=#{value};"
178
+ when "minutely"
179
+ by += "BYMINUTE=#{value};"
180
+ when "hourly"
181
+ by += "BYHOUR=#{value};"
182
+ when "weekly"
183
+ by += "BYDAY=#{value};" if value
184
+ when "monthly"
185
+ by += "BYDAY=#{value};"
186
+ when "yearly"
187
+ by += "BYYEARDAY=#{value};"
188
+ when 'interval'
189
+ i += "INTERVAL=#{value};"
190
+ end
191
+ end
192
+ output += f+i+by
193
+ end
194
+ if @repeat_until
195
+ output += "UNTIL=#{@repeat_until.strftime("%Y%m%d")}"
196
+ end
197
+
198
+ output += "\n"
199
+ end
200
+
201
+ #Sets the start date/time. Must be a Time object.
202
+ def start_time=(s)
203
+ if not s.is_a?(Time)
204
+ raise RecurrenceValueError, "Start must be a date or a time"
205
+ else
206
+ @start_time = s
207
+ end
208
+ end
209
+
210
+ #Sets the end Date/Time. Must be a Time object.
211
+ def end_time=(e)
212
+ if not e.is_a?(Time)
213
+ raise RecurrenceValueError, "End must be a date or a time"
214
+ else
215
+ @end_time = e
216
+ end
217
+ end
218
+
219
+ #Sets the parent event reference
220
+ def event=(e)
221
+ if not e.is_a?(Event)
222
+ raise RecurrenceValueError, "Event must be an event"
223
+ else
224
+ @event = e
225
+ end
226
+ end
227
+
228
+ #Sets the end date for the recurrence
229
+ def repeat_until=(r)
230
+ if not r.is_a?(Date)
231
+ raise RecurrenceValueError, "Repeat_until must be a date"
232
+ else
233
+ @repeat_until = r
234
+ end
235
+ end
236
+
237
+ #Sets the frequency of the recurrence. Should be a hash with one of
238
+ #"SECONDLY", "MINUTELY", "HOURLY", "DAILY", "WEEKLY", "MONTHLY", "YEARLY" as the key,
239
+ #and as the value, an array containing zero to n of the following:
240
+ #- *Secondly*: A value between 0 and 59. Causes the event to repeat on that second of each minut.
241
+ #- *Minutely*: A value between 0 and 59. Causes the event to repeat on that minute of every hour.
242
+ #- *Hourly*: A value between 0 and 23. Causes the even to repeat on that hour of every day.
243
+ #- *Daily*: No value needed - will cause the event to repeat every day until the repeat_until date.
244
+ #- *Weekly*: A value of the first two letters of a day of the week. Causes the event to repeat on that day.
245
+ #- *Monthly*: A value of a positive or negative integer (i.e. +1) prepended to a day-of-week string ('TU') to indicate the position of the day within the month. E.g. +1TU would be the first tuesday of the month.
246
+ #- *Yearly*: A value of 1 to 366 indicating the day of the year. May be negative to indicate counting down from the last day of the year.
247
+ #
248
+ #Optionally, you may specific a second hash pair to set the interval the event repeats:
249
+ # "interval" => '2'
250
+ #If the interval is missing, it is assumed to be 1.
251
+ #
252
+ #===Examples
253
+ #Repeat event every Tuesday:
254
+ # frequency = {"Weekly" => ["TU"]}
255
+ #
256
+ #Repeat every first and third Monday of the month
257
+ # frequency = {"Monthly" => ["+1MO", "+3MO"]}
258
+ #
259
+ #Repeat on the last day of every year
260
+ # frequency = {"Yearly" => [366]}
261
+ #
262
+ #Repeat every other week on Friday
263
+ # frequency = {"Weekly" => ["FR"], "interval" => "2"}
264
+
265
+ def frequency=(f)
266
+ if f.is_a?(Hash)
267
+ @frequency = f
268
+ else
269
+ raise RecurrenceValueError, "Frequency must be a hash (see documentation)"
270
+ end
271
+ end
272
+ end
273
+ end
@@ -0,0 +1,160 @@
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 < GData4Ruby::Service
42
+ CALENDAR_LIST_FEED = 'http://www.google.com/calendar/feeds/default/allcalendars/full'
43
+
44
+ #Convenience attribute contains the currently authenticated account name
45
+ attr_reader :account
46
+
47
+ # The token returned by the Google servers, used to authorize all subsequent messages
48
+ attr_reader :auth_token
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 = {})
57
+ super(attributes)
58
+ attributes.each do |key, value|
59
+ self.send("#{key}=", value)
60
+ end
61
+ @check_public ||= true
62
+ end
63
+
64
+ def default_event_feed
65
+ return "http://www.google.com/calendar/feeds/#{@account}/private/full"
66
+ end
67
+
68
+ # The authenticate method passes the username and password to google servers.
69
+ # If authentication succeeds, returns true, otherwise raises the AuthenticationFailed error.
70
+ def authenticate(username, password, service='cl')
71
+ super(username, password, service)
72
+ end
73
+
74
+ #Helper function to reauthenticate to a new Google service without having to re-set credentials.
75
+ def reauthenticate(service='cl')
76
+ authenticate(@account, @password, service)
77
+ end
78
+
79
+ #Returns an array of Calendar objects for each calendar associated with
80
+ #the authenticated account.
81
+ def calendars
82
+ if not @auth_token
83
+ raise NotAuthenticated
84
+ end
85
+ ret = send_request(GData4Ruby::Request.new(:get, CALENDAR_LIST_FEED, nil, {"max-results" => "10000"}))
86
+ cals = []
87
+ REXML::Document.new(ret.body).root.elements.each("entry"){}.map do |entry|
88
+ entry = GData4Ruby::Utils.add_namespaces(entry)
89
+ cal = Calendar.new(self)
90
+ cal.load(entry.to_s)
91
+ cals << cal
92
+ end
93
+ return cals
94
+ end
95
+
96
+ #Returns an array of Event objects for each event in this account
97
+ def events
98
+ if not @auth_token
99
+ raise NotAuthenticated
100
+ end
101
+ ret = send_request(GData4Ruby::Request.new(:get, default_event_feed, nil, {"max-results" => "10000"}))
102
+ events = []
103
+ REXML::Document.new(ret.body).root.elements.each("entry"){}.map do |entry|
104
+ entry = GData4Ruby::Utils.add_namespaces(entry)
105
+ event = Event.new(self)
106
+ event.load(entry.to_s)
107
+ events << event
108
+ end
109
+ return events
110
+ end
111
+
112
+ #Helper function to return a formatted iframe embedded google calendar. Parameters are:
113
+ #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
114
+ #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:
115
+ # height:: the height of the embedded calendar in pixels
116
+ # width:: the width of the embedded calendar in pixels
117
+ # title:: the title to display
118
+ # bgcolor:: the background color. Limited choices, see google docs for allowable values.
119
+ # showTitle:: set to '0' to hide the title
120
+ # showDate:: set to '0' to hide the current date
121
+ # showNav:: set to '0 to hide the navigation tools
122
+ # showPrint:: set to '0' to hide the print icon
123
+ # showTabs:: set to '0' to hide the tabs
124
+ # showCalendars:: set to '0' to hide the calendars selection drop down
125
+ # showTz:: set to '0' to hide the timezone selection
126
+ # border:: the border width in pixels
127
+ # dates:: a range of dates to display in the format of 'yyyymmdd/yyyymmdd'. Example: 20090820/20091001
128
+ # privateKey:: use to display a private calendar. You can find this key under the calendar settings pane of the Google Calendar website.
129
+ # ctz:: The timezone to convert event times to
130
+ #3. *colors*: a hash of calendar ids as key and color values as associated hash values. Example: {'test@gmail.com' => '#7A367A'}
131
+ def to_iframe(cals, params = {}, colors = {})
132
+ params[:height] ||= "600"
133
+ params[:width] ||= "600"
134
+ params[:title] ||= (self.account ? self.account : '')
135
+ params[:bgcolor] ||= "#FFFFFF"
136
+ params[:border] ||= "0"
137
+ params.each{|key, value| params[key] = CGI::escape(value)}
138
+ output = "#{params.to_a.collect{|a| a.join("=")}.join("&")}&"
139
+
140
+ if cals.is_a?(Array)
141
+ for c in cals
142
+ output += "src=#{c}&"
143
+ if colors and colors[c]
144
+ output += "color=%23#{colors[c].gsub("#", "")}&"
145
+ end
146
+ end
147
+ elsif cals == :all
148
+ cal_list = calendars()
149
+ for c in cal_list
150
+ output += "src=#{c.id}&"
151
+ end
152
+ elsif cals == :first
153
+ cal_list = calendars()
154
+ output += "src=#{cal_list[0].id}&"
155
+ end
156
+
157
+ "<iframe src='http://www.google.com/calendar/embed?#{output}' style='#{params[:border]} px solid;' width='#{params[:width]}' height='#{params[:height]}' frameborder='#{params[:border]}' scrolling='no'></iframe>"
158
+ end
159
+ end
160
+ end
data/lib/gcal4ruby.rb ADDED
@@ -0,0 +1 @@
1
+ require "gcal4ruby/service"
data/test/unit.rb ADDED
@@ -0,0 +1,182 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'rubygems'
4
+ require 'gcal4ruby'
5
+ include GCal4Ruby
6
+
7
+ @service = Service.new
8
+ @username = nil
9
+ @password = nil
10
+
11
+ def tester
12
+ if ARGV.include?("-d")
13
+ @service.debug = true
14
+ end
15
+ ARGV.each do |ar|
16
+ if ar.match("username=")
17
+ @username = ar.gsub("username=", "")
18
+ end
19
+ if ar.match("password=")
20
+ @password = ar.gsub("password=", "")
21
+ end
22
+ end
23
+ service_test
24
+ calendar_test
25
+ event_test
26
+ event_recurrence_test
27
+ end
28
+
29
+ def service_test
30
+ puts "---Starting Service Test---"
31
+ puts "1. Authenticate"
32
+ if @service.authenticate(@username, @password)
33
+ successful
34
+ else
35
+ failed
36
+ end
37
+
38
+ puts "2. Calendar List"
39
+ cals = @service.calendars
40
+ if cals
41
+ successful "Calendars for this Account:"
42
+ cals.each do |cal|
43
+ puts cal.title
44
+ end
45
+ else
46
+ failed
47
+ end
48
+ end
49
+
50
+ def calendar_test
51
+ puts "---Starting Calendar Test---"
52
+
53
+ puts "1. Create Calendar"
54
+ cal = Calendar.new(@service)
55
+ cal.title = "test calendar"+Time.now.to_s
56
+ puts "Calender exists = "+cal.exists?.to_s
57
+ if cal.save
58
+ successful cal.to_xml
59
+ else
60
+ failed
61
+ end
62
+
63
+ puts "2. Edit Calendar"
64
+ cal.title = "renamed title"
65
+ if cal.save
66
+ successful cal.to_xml
67
+ else
68
+ puts "Test 2 Failed"
69
+ end
70
+
71
+ puts "3. Find Calendar by ID"
72
+ c = Calendar.find(@service, {:id => cal.id})
73
+ if c.title == cal.title
74
+ successful
75
+ else
76
+ failed "#{c.title} not equal to #{cal.title}"
77
+ end
78
+
79
+ puts "4. Delete Calendar"
80
+ if cal.delete and not cal.exists?
81
+ successful
82
+ else
83
+ failed
84
+ end
85
+ end
86
+
87
+ def event_test
88
+ puts "---Starting Event Test---"
89
+
90
+ puts "1. Create Event"
91
+ event = Event.new(@service)
92
+ event.calendar = @service.calendars[0]
93
+ event.title = "Test Event"
94
+ event.content = "Test event content"
95
+ event.start_time = Time.now+1800
96
+ event.end_time = Time.now+5400
97
+ if event.save
98
+ successful event.to_xml
99
+ else
100
+ failed
101
+ end
102
+
103
+ puts "2. Edit Event"
104
+ event.title = "Edited title"
105
+ if event.save
106
+ successful event.to_xml
107
+ else
108
+ failed
109
+ end
110
+
111
+ puts "3. Reload Event"
112
+ if event.reload
113
+ successful
114
+ end
115
+
116
+ puts "4. Find Event by id"
117
+ e = Event.find(@service, {:id => event.id})
118
+ if e.title == event.title
119
+ successful
120
+ else
121
+ failed "Found event doesn't match existing event"
122
+ end
123
+
124
+ puts "5. Delete Event"
125
+ if event.delete
126
+ successful
127
+ else
128
+ failed
129
+ end
130
+ end
131
+
132
+ def event_recurrence_test
133
+ puts "---Starting Event Recurrence Test---"
134
+
135
+ @first_start = Time.now
136
+ @first_end = Time.now+3600
137
+ @first_freq = {'weekly' => ['TU']}
138
+ @second_start = Time.now+86000
139
+ @second_end = Time.now+89600
140
+ @second_freq = {'weekly' => ['SA']}
141
+
142
+ puts "1. Create Recurring Event"
143
+ event = Event.new(@service)
144
+ event.calendar = @service.calendars[0]
145
+ event.title = "Test Recurring Event"
146
+ event.content = "Test event content"
147
+ event.recurrence = Recurrence.new({:start_time => @first_start, :end_time => @first_end, :frequency => @first_freq})
148
+ if event.save
149
+ successful event.to_xml
150
+ else
151
+ failed("recurrence = "+event.recurrence.to_s)
152
+ end
153
+
154
+ puts "2. Edit Recurrence"
155
+ event.title = "Edited recurring title"
156
+ event.recurrence = Recurrence.new({:start_time => @second_start, :end_time => @second_end, :frequency => @second_freq})
157
+ if event.save
158
+ successful event.to_xml
159
+ else
160
+ failed
161
+ end
162
+
163
+ puts "3. Delete Event"
164
+ if event.delete
165
+ successful
166
+ else
167
+ failed
168
+ end
169
+ end
170
+
171
+ def failed(m = nil)
172
+ puts "Test Failed"
173
+ puts m if m
174
+ exit()
175
+ end
176
+
177
+ def successful(m = nil)
178
+ puts "Test Successful"
179
+ puts m if m
180
+ end
181
+
182
+ tester
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: railsware-gcal4ruby
3
+ version: !ruby/object:Gem::Version
4
+ hash: 1
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 5
9
+ - 5
10
+ version: 0.5.5
11
+ platform: ruby
12
+ authors:
13
+ - Mike Reich
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-07-08 00:00:00 +03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: gdata4ruby
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 25
30
+ segments:
31
+ - 0
32
+ - 1
33
+ - 1
34
+ version: 0.1.1
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description: "GCal4Ruby is a Ruby Gem that can be used to interact with the current version of the Google Calendar API. GCal4Ruby provides the following features: Create and edit calendar events, Add and invite users to events, Set reminders, Make recurring events."
38
+ email: mike@seabourneconsulting.com
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - README
47
+ - CHANGELOG
48
+ - lib/gcal4ruby.rb
49
+ - lib/gcal4ruby/service.rb
50
+ - lib/gcal4ruby/calendar.rb
51
+ - lib/gcal4ruby/event.rb
52
+ - lib/gcal4ruby/recurrence.rb
53
+ - test/unit.rb
54
+ has_rdoc: true
55
+ homepage: http://cookingandcoding.com/gcal4ruby/
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options: []
60
+
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ requirements: []
82
+
83
+ rubyforge_project: gcal4ruby
84
+ rubygems_version: 1.3.7
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: A full featured wrapper for interacting with the Google Calendar API
88
+ test_files:
89
+ - test/unit.rb