rufus-google 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.txt +98 -0
- data/lib/rufus-google.rb +3 -0
- data/lib/rufus/ahttp.rb +64 -0
- data/lib/rufus/gcal.rb +208 -0
- data/lib/rufus/google.rb +228 -0
- data/lib/rufus/gversion.rb +42 -0
- data/test/t0.rb +31 -0
- data/test/t_0_cal.rb +39 -0
- data/test/test.rb +3 -0
- metadata +82 -0
data/README.txt
ADDED
@@ -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
|
+
|
data/lib/rufus-google.rb
ADDED
data/lib/rufus/ahttp.rb
ADDED
@@ -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
|
+
|
data/lib/rufus/gcal.rb
ADDED
@@ -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
|
+
|
data/lib/rufus/google.rb
ADDED
@@ -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
|
+
|
data/test/t0.rb
ADDED
@@ -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
|
+
|
data/test/t_0_cal.rb
ADDED
@@ -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
|
+
|
data/test/test.rb
ADDED
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
|