rufus-google 0.0.1

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,98 @@
1
+
2
+ = rufus-google
3
+
4
+ rufus-google should probably be named "rufus-gcal" for now, as only google calendar stuff is implemented.
5
+
6
+ This gem leverages 'atom-tools' to play with Google Data APIs.
7
+
8
+ The only authentication mechanism implemented for now is "ClientLogin".
9
+
10
+ (There is a one way synchronization tool for ical to gcal at
11
+
12
+ http://github.com/jmettraux/rufus-google/tree/master/tools/itog.rb
13
+
14
+ work in progress...)
15
+
16
+
17
+ == getting it
18
+
19
+ sudo gem install rufus-google
20
+
21
+ or at
22
+
23
+ http://rubyforge.org/frs/?group_id=4812
24
+
25
+
26
+ == usage
27
+
28
+ Using Google Calendar :
29
+
30
+ require 'rubygems'
31
+ require 'rufus/gcal'
32
+
33
+ calendars = Rufus::Google::Calendar.get_calendars(
34
+ :account => ENV['GUSER'], :password => ENV['GPASS'])
35
+
36
+ #calendars.values.each { |c| p [ c.name, c.href ] }
37
+
38
+ cal = calendars['gwork']
39
+
40
+ event_id = cal.post_quick!('Tennis with John November 13 3pm-4:30pm')
41
+
42
+ cal.events(:q => 'tennis').each do |e|
43
+ puts
44
+ puts e.to_s
45
+ end
46
+
47
+ cal.delete!(event_id)
48
+
49
+ puts "#{cal.events(:q => 'tennis').size} tennis events"
50
+
51
+
52
+ Other Google APIs will be covered later, if the need arise.
53
+
54
+
55
+ == dependencies
56
+
57
+ the 'rufus-verbs' and the 'atom-tools' gems.
58
+
59
+
60
+ == mailing list
61
+
62
+ On the rufus-ruby list[http://groups.google.com/group/rufus-ruby] :
63
+
64
+ http://groups.google.com/group/rufus-ruby
65
+
66
+
67
+ == issue tracker
68
+
69
+ http://rubyforge.org/tracker/?atid=18584&group_id=4812&func=browse
70
+
71
+
72
+ == irc
73
+
74
+ irc.freenode.net #ruote
75
+
76
+
77
+ == source
78
+
79
+ http://github.com/jmettraux/rufus-google
80
+
81
+ git clone git://github.com/jmettraux/rufus-google.git
82
+
83
+
84
+ == author
85
+
86
+ John Mettraux, jmettraux@gmail.com
87
+ http://jmettraux.wordpress.com
88
+
89
+
90
+ == the rest of Rufus
91
+
92
+ http://rufus.rubyforge.org
93
+
94
+
95
+ == license
96
+
97
+ MIT
98
+
@@ -0,0 +1,3 @@
1
+
2
+ require 'rufus/gcal'
3
+
@@ -0,0 +1,64 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2008, John Mettraux, jmettraux@gmail.com
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+ #
23
+ # (MIT license)
24
+ #++
25
+ #
26
+
27
+ #
28
+ # John Mettraux
29
+ #
30
+ # Made in Japan
31
+ #
32
+ # Tue Nov 11 22:18:23 JST 2008
33
+ #
34
+
35
+ require 'atom/http'
36
+
37
+ module Rufus
38
+ module Google
39
+
40
+ class Http < Atom::HTTP
41
+
42
+ def initialize (auth_token)
43
+
44
+ @auth_token = auth_token
45
+
46
+ super(nil)
47
+ #super({})
48
+
49
+ @allow_all_redirects = true
50
+ end
51
+
52
+ def http_request (
53
+ url_s, method, body=nil, headers={}, www_a=nil, redir_limit=5)
54
+
55
+ headers['Authorization'] = "GoogleLogin auth=#{@auth_token}"
56
+ headers['GData-Version'] = GDATA_VERSION
57
+
58
+ super(url_s, method, body, headers, www_a, redir_limit)
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+
@@ -0,0 +1,208 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2008, John Mettraux, jmettraux@gmail.com
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+ #
23
+ # (MIT license)
24
+ #++
25
+ #
26
+
27
+ #
28
+ # John Mettraux
29
+ #
30
+ # "Made in Japan" as opposed to "Swiss Made"
31
+ #
32
+ # Wed Nov 12 09:14:09 JST 2008
33
+ #
34
+
35
+ require 'rexml/element'
36
+ require 'rufus/google'
37
+
38
+
39
+ module Rufus
40
+ module Google
41
+
42
+ class Calendar
43
+
44
+ include CollectionMixin
45
+
46
+ #
47
+ # Returns all the events in the calendar.
48
+ #
49
+ # The query hash can be used to 'query' those events. It currently
50
+ # accepts :q, :start_min and :start_max as keys.
51
+ #
52
+ def events (query={})
53
+
54
+ q = query.inject([]) { |a, (k, v)|
55
+ a << "#{k.to_s.gsub(/\_/, '-')}=#{v}"
56
+ }.join("&")
57
+
58
+ q = "?#{q}" if q.length > 0
59
+
60
+ feed = Rufus::Google.feed_for("#{href}#{q}", @token)
61
+ feed.update!
62
+
63
+ feed.entries.collect { |e| Event.new(e) }
64
+ end
65
+
66
+ #
67
+ # Posts (creates) a QuickAdd event
68
+ # in this calendar.
69
+ #
70
+ # http://code.google.com/apis/calendar/developers_guide_protocol.html#CreatingQuickAdd
71
+ #
72
+ def post_quick! (event_text)
73
+
74
+ post!(Event.create_quick(event_text))
75
+ end
76
+
77
+ #
78
+ # Returns a hash calendar_name => calendar
79
+ #
80
+ # an example :
81
+ #
82
+ # calendars = Rufus::Google::Calendar.get_calendars(
83
+ # :account => ENV['GUSER'], :password => env['GPASS'])
84
+ # calendars.values.each { |c| p [ c.name, c.href ] }
85
+ #
86
+ def self.get_calendars (options)
87
+
88
+ options[:service] = :cl
89
+
90
+ feed = Rufus::Google.feed_for(
91
+ 'https://www.google.com/calendar/feeds/default', options)
92
+
93
+ feed.update! # fetch the data over the net
94
+
95
+ feed.entries.inject({}) { |h, e|
96
+ c = Calendar.new(options[:auth], e)
97
+ h[c.name] = c
98
+ h
99
+ }
100
+ end
101
+ end
102
+
103
+ #
104
+ # A google calendar event.
105
+ #
106
+ class Event
107
+
108
+ include EntryMixin
109
+
110
+ def start_time
111
+ evalue('when', 'startTime', :time => true)
112
+ end
113
+
114
+ def end_time
115
+ evalue('when', 'endTime', :time => true)
116
+ end
117
+
118
+ def where
119
+ evalue('where', 'valueString')
120
+ end
121
+
122
+ # TODO : add method for recurrence
123
+
124
+ def to_s
125
+ {
126
+ :id => @entry.id,
127
+ :etag => etag,
128
+ :title => @entry.title.to_s,
129
+ :start_time => start_time,
130
+ :end_time => end_time,
131
+ :where => where,
132
+ :author => "#{author.name} #{author.email}"
133
+ }.inspect
134
+ end
135
+
136
+ def self.create (opts)
137
+
138
+ e = Atom::Entry.new
139
+ e.title = opts[:title]
140
+ e.updated!
141
+
142
+ if c = opts[:content]
143
+ e.content = c
144
+ e.content['type'] = opts[:type] || 'text'
145
+ end
146
+
147
+ if st = opts[:start_time]
148
+
149
+ st = st.is_a?(DateTime) ? st : DateTime.parse(st)
150
+ st = st.to_s
151
+ st = st[0, 10] if opts[:all_day]
152
+
153
+ w = REXML::Element.new('gd:when')
154
+ w.add_attribute('startTime', st)
155
+
156
+ if et = opts[:end_time]
157
+
158
+ et = et.is_a?(DateTime) ? et : DateTime.parse(et)
159
+ et = et.to_s
160
+ et = et[0, 10] if opts[:all_day]
161
+
162
+ w.add_attribute('endTime', et)
163
+ end
164
+
165
+ e.extensions << w
166
+ end
167
+
168
+ if rc = opts[:recurrence]
169
+
170
+ r = REXML::Element.new('gd:recurrence')
171
+ r.text = rc
172
+
173
+ e.extensions << r
174
+ end
175
+
176
+ e.extensions.attributes['xmlns:gd'] =
177
+ 'http://schemas.google.com/g/2005'
178
+ e.extensions.attributes['xmlns:gCal'] =
179
+ 'http://schemas.google.com/gCal/2005'
180
+
181
+ #p e.to_xml.to_s
182
+
183
+ Event.new(e)
184
+ end
185
+
186
+ #
187
+ # Creates a QuickAdd event.
188
+ #
189
+ # http://code.google.com/apis/calendar/developers_guide_protocol.html#CreatingQuickAdd
190
+ #
191
+ def self.create_quick (text)
192
+
193
+ e = create(
194
+ :title => 'nada',
195
+ :type => 'html',
196
+ :content => text)
197
+
198
+ qa = REXML::Element.new('gCal:quickadd')
199
+ qa.add_attribute('value', 'true')
200
+ e.entry.extensions << qa
201
+
202
+ e
203
+ end
204
+ end
205
+
206
+ end
207
+ end
208
+
@@ -0,0 +1,228 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2008, John Mettraux, jmettraux@gmail.com
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+ #
23
+ # (MIT license)
24
+ #++
25
+ #
26
+
27
+ #
28
+ # John Mettraux
29
+ #
30
+ # Made in Japan
31
+ #
32
+ # Tue Nov 11 15:21:44 JST 2008
33
+ #
34
+
35
+ require 'cgi'
36
+ require 'uri'
37
+ require 'time'
38
+ require 'rufus/verbs'
39
+ require 'atom/feed'
40
+ #require 'atom/service'
41
+ require 'atom/collection'
42
+ require 'rufus/ahttp'
43
+
44
+ module Rufus
45
+ module Google
46
+
47
+ GDATA_VERSION = '2'
48
+
49
+ #
50
+ # Gets an auth token via the Google ClientLogin facility
51
+ #
52
+ def self.get_auth_tokens (options)
53
+
54
+ account = options[:account]
55
+ account_type = options[:account_type] || 'GOOGLE'
56
+ password = options[:password]
57
+ service = options[:service] || :cl
58
+ source = options[:source] || "rufus.rubyforge.org-rufus_google-#{VERSION}"
59
+
60
+ account = "#{account}@gmail.com" unless account.index('@')
61
+
62
+ password = CGI.escape(password)
63
+
64
+ data = ''
65
+ data << "accountType=#{account_type}&"
66
+ data << "Email=#{account}&"
67
+ data << "Passwd=#{password}&"
68
+ data << "service=#{service}&"
69
+ data << "source=#{source}"
70
+
71
+ headers = { 'Content-type' => 'application/x-www-form-urlencoded' }
72
+ headers['GData-Version'] = GDATA_VERSION
73
+
74
+ r = Rufus::Verbs.post(
75
+ 'https://www.google.com/accounts/ClientLogin',
76
+ :headers => headers,
77
+ :data => data)
78
+
79
+ code = r.code.to_i
80
+
81
+ raise r.body if code == 403
82
+ raise "not a 200 OK reply : #{code} : #{r.body}" unless code == 200
83
+
84
+ tokens = r.body.split.inject({}) { |h, l|
85
+ md = l.match(/^(.*)=(.*$)/)
86
+ h[md[1].downcase.to_sym] = md[2]
87
+ h
88
+ }
89
+
90
+ options.merge!(tokens)
91
+
92
+ tokens
93
+ end
94
+
95
+ #
96
+ # Returns the auth token for a google account.
97
+ #
98
+ def self.get_auth_token (options)
99
+
100
+ return options if options.is_a?(String)
101
+
102
+ options[:auth] || get_auth_tokens(options)[:auth]
103
+ end
104
+
105
+ #
106
+ # A small method for getting an atom-tools Feed instance.
107
+ # The options hash is a get_auth_token() hash.
108
+ #
109
+ def self.feed_for (feed_uri, options)
110
+
111
+ token = get_auth_token(options)
112
+
113
+ Atom::Feed.new(feed_uri, Rufus::Google::Http.new(token))
114
+ end
115
+
116
+ module CollectionMixin
117
+
118
+ attr_reader :name, :href
119
+
120
+ def initialize (auth_token, entry)
121
+
122
+ @token = auth_token
123
+ @name = entry.title.to_s
124
+ @href = entry.links.find { |l| l.rel == 'alternate' }.href
125
+ end
126
+
127
+ #
128
+ # Posts (creates) an object
129
+ #
130
+ # Returns the URI of the created resource.
131
+ #
132
+ def post! (o)
133
+
134
+ r = collection.post!(o.entry)
135
+
136
+ raise "posting object of class #{o.class} failed : #{r.body}" \
137
+ unless r.code.to_i == 201
138
+
139
+ r['Location']
140
+ end
141
+
142
+ #
143
+ # Removes an object from the collection
144
+ #
145
+ def delete! (entry)
146
+
147
+ uri = entry.entry.edit_url
148
+
149
+ #r = collection.delete!(nil, uri)
150
+ r = collection.http.delete(uri, nil, { 'If-Match' => entry.etag })
151
+
152
+ raise "failed to delete entry (#{r.code}): #{r.body}" \
153
+ unless r.code.to_i == 200
154
+
155
+ r
156
+ end
157
+
158
+ protected
159
+
160
+ #
161
+ # returns the Atom::Collection instance
162
+ #
163
+ def collection
164
+
165
+ return @collection if @collection
166
+
167
+ @collection = Atom::Collection.new(
168
+ href, Rufus::Google::Http.new(@token))
169
+ end
170
+ end
171
+
172
+ #
173
+ # A mixin for entry based objects (like cal events for example)
174
+ #
175
+ module EntryMixin
176
+
177
+ attr_reader :entry
178
+
179
+ #
180
+ # Creates a google calendar event based on the info found in an
181
+ # atom-tools Entry instance.
182
+ #
183
+ def initialize (entry)
184
+ @entry = entry
185
+ end
186
+
187
+ def title
188
+ @entry.title.to_s
189
+ end
190
+
191
+ def author
192
+ @entry.authors.first
193
+ end
194
+
195
+ def authors
196
+ @entry.authors
197
+ end
198
+
199
+ def etag
200
+ @entry.extensions.attributes['gd:etag']
201
+ end
202
+
203
+ protected
204
+
205
+ #
206
+ # fetches a value in the extension part of the entry
207
+ #
208
+ # :time => true will attempt to parse the value to a Time instance
209
+ #
210
+ def evalue (elt_name, att_name, options={})
211
+
212
+ v = @entry.extensions.find { |e|
213
+ e.name == elt_name
214
+ }
215
+
216
+ return nil unless v
217
+
218
+ v = v.attribute(att_name)
219
+
220
+ v = Time.parse(v.value) if options[:time] == true
221
+
222
+ v
223
+ end
224
+ end
225
+
226
+ end
227
+ end
228
+
@@ -0,0 +1,42 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2008, John Mettraux, jmettraux@gmail.com
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+ #
23
+ # (MIT license)
24
+ #++
25
+ #
26
+
27
+ #
28
+ # John Mettraux
29
+ #
30
+ # Made in Japan
31
+ #
32
+ # Wed Nov 12 20:08:24 JST 2008
33
+ #
34
+
35
+ module Rufus
36
+ module Google
37
+
38
+ VERSION = '0.0.1'
39
+
40
+ end
41
+ end
42
+
@@ -0,0 +1,31 @@
1
+
2
+ require 'rubygems'
3
+ require 'rufus/gcal'
4
+
5
+ calendars = Rufus::Google::Calendar.get_calendars(
6
+ :account => ENV['GUSER'], :password => ENV['GPASS'])
7
+
8
+ #calendars.values.each { |c| p [ c.name, c.href ] }
9
+
10
+ cal = calendars['gtest']
11
+
12
+ #id = cal.post_quick!('Tennis with John November 13 3pm-4:30pm')
13
+ #t = Time.now
14
+ #id = cal.post!(Rufus::Google::Event.create(
15
+ # :title => 'drink Tequila at the Tennis club',
16
+ # :start_time => t,
17
+ # :end_time => t + 3600))
18
+
19
+ #cal.events(:q => 'tennis').each do |e|
20
+ cal.events().each do |e|
21
+ puts
22
+ puts e.to_s
23
+ #puts e.entry.to_s.gsub(/</, "\n<")
24
+ #puts e.entry.inspect
25
+ #p e.entry.extensions.attributes
26
+ #cal.delete!(e)
27
+ end
28
+ #cal.delete!(id)
29
+
30
+ #puts "#{cal.events(:q => 'tennis').size} tennis events"
31
+
@@ -0,0 +1,39 @@
1
+
2
+ #
3
+ # Testing rufus-google
4
+ #
5
+ # Wed Nov 12 20:59:36 JST 2008
6
+ #
7
+
8
+ require 'test/unit'
9
+ require 'rubygems'
10
+ require 'rufus/gcal'
11
+
12
+ class Test0Cal < Test::Unit::TestCase
13
+
14
+ def test_0
15
+
16
+ calendars = Rufus::Google::Calendar.get_calendars(
17
+ :account => ENV['GUSER'], :password => ENV['GPASS'])
18
+
19
+ cal = calendars['gtest']
20
+
21
+ #cal.events(:q => 'zorglub').each { |e| puts e.entry.to_s }
22
+ #cal.events(:q => 'zorglub').each { |e| puts e.to_s }
23
+ #return
24
+ cal.events(:q => 'zorglub').each { |e| cal.delete!(e) }
25
+
26
+ event_id = cal.post_quick!('Tennis with Zorglub November 13 3pm-4:30pm')
27
+
28
+ evts = cal.events(:q => 'zorglub')
29
+
30
+ assert_equal 1, evts.size
31
+ assert_equal 'Tennis with Zorglub', evts.first.title
32
+
33
+ cal.delete!(evts.first)
34
+
35
+ assert_equal [], cal.events(:q => 'zorglub')
36
+ end
37
+
38
+ end
39
+
@@ -0,0 +1,3 @@
1
+
2
+ require 't_0_cal.rb'
3
+
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rufus-google
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - John Mettraux
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-03 00:00:00 +09:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rufus-verbs
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: atom-tools
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description:
36
+ email: john at gmail dot com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.txt
43
+ files:
44
+ - lib/rufus
45
+ - lib/rufus/ahttp.rb
46
+ - lib/rufus/gcal.rb
47
+ - lib/rufus/google.rb
48
+ - lib/rufus/gversion.rb
49
+ - lib/rufus-google.rb
50
+ - test/t0.rb
51
+ - test/t_0_cal.rb
52
+ - test/test.rb
53
+ - README.txt
54
+ has_rdoc: true
55
+ homepage: http://rufus.rubyforge.org/rufus-google
56
+ post_install_message:
57
+ rdoc_options: []
58
+
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ requirements:
74
+ - rufus-verbs
75
+ - atom-tools
76
+ rubyforge_project: rufus
77
+ rubygems_version: 1.3.1
78
+ signing_key:
79
+ specification_version: 2
80
+ summary: snippets of Ruby code for accessing Google stuff
81
+ test_files:
82
+ - test/test.rb