googlecalendar 0.0.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,23 @@
1
+ module Googlecalendar
2
+ class Calendar
3
+ attr_accessor :product_id, :version, :scale, :method, :events
4
+
5
+ def add(event)
6
+ # create events if it doesn't exist
7
+ @events ||= []
8
+ @events.push event
9
+ end
10
+
11
+ def to_s
12
+ data = "########## calendar ##########\n"
13
+ data << 'version: ' + @version.to_s + "\n"
14
+ data << 'scale: ' + @scale.to_s + "\n"
15
+ data << 'method: ' + @method.to_s + "\n"
16
+ data << 'number of events: ' + @events.size.to_s + "\n"
17
+ @events.each do |event|
18
+ data << event.to_s
19
+ end
20
+ return data
21
+ end
22
+ end
23
+ end # module Googlecalendar
@@ -0,0 +1,52 @@
1
+ require 'net/http'
2
+ # require 'net/https'
3
+ # require 'uri'
4
+
5
+ def parse(data)
6
+ parser = Googlecalendar::ICALParser.new
7
+ parser.parse(data)
8
+ end
9
+
10
+ def scan(ical_url, base_url='www.google.com')
11
+ Net::HTTP.start(base_url, 80) do |http|
12
+ response, data = http.get(ical_url)
13
+ case response
14
+ when Net::HTTPSuccess, Net::HTTPRedirection
15
+ return data
16
+ else
17
+ response.error!
18
+ end
19
+ end
20
+ end
21
+
22
+ def scan_proxy(proxy_addr, proxy_port, ical_url, base_url='www.google.com')
23
+ Net::HTTP::Proxy(proxy_addr, proxy_port).start(base_url, 80) do |http|
24
+ response, data = http.get(ical_url)
25
+ case response
26
+ when Net::HTTPSuccess, Net::HTTPRedirection
27
+ return data
28
+ else
29
+ response.error!
30
+ end
31
+ end
32
+ end
33
+
34
+ # Builder DSL
35
+ def text(calendar, filename)
36
+ dirname = File.dirname(filename)
37
+ Dir.mkdir(dirname) unless File.exists?(dirname)
38
+ text_builder = Googlecalendar::TextBuilder.new
39
+ text_builder.calendar = calendar
40
+ text_builder.filename = filename
41
+ text_builder.export
42
+ end
43
+
44
+ def html(calendar, filename)
45
+ dirname = File.dirname(filename)
46
+ Dir.mkdir(dirname) unless File.exists?(dirname)
47
+ html_builder = Googlecalendar::HtmlBuilder.new
48
+ html_builder.calendar = calendar
49
+ html_builder.filename = filename
50
+ html_builder.date_format = "%d-%m-%y" #"%F"#"%A %B %d %Y" #"%d-%m-%Y"
51
+ html_builder.export
52
+ end
@@ -0,0 +1,32 @@
1
+ module Googlecalendar
2
+ class Event
3
+ attr_accessor :start_date, :end_date, :time_stamp, :class_name, :created, :last_modified, :status, :summary, :description, :location, :rrule
4
+
5
+ def to_s
6
+ data = "---------- event ----------\n"
7
+ data << 'start_date: ' + @start_date.to_s + "\n"
8
+ data << 'end_date: ' + @end_date.to_s + "\n"
9
+ data << 'time_stamp: ' + @time_stamp.to_s + "\n"
10
+ data << 'class_name: ' + @class_name.to_s + "\n"
11
+ data << 'created: ' + @created.to_s + "\n"
12
+ data << 'last_modified: ' + @last_modified.to_s + "\n"
13
+ data << 'status: ' + @status.to_s + "\n"
14
+ data << 'rrule: ' + @rrule.to_s + "\n"
15
+ data << 'summary: ' + @summary.to_s + "\n"
16
+ data << 'desription: ' + @desription.to_s + "\n"
17
+ data << 'location: ' + @location.to_s + "\n"
18
+ return data
19
+ end
20
+
21
+ # 'FREQ=WEEKLY;BYDAY=MO;WKST=MO'
22
+ def rrule_as_hash
23
+ array = @rrule.split(';')
24
+ hash = Hash.new
25
+ array.each do |item|
26
+ pair = item.split('=')
27
+ hash[pair[0]] = pair[1]
28
+ end
29
+ return hash
30
+ end
31
+ end # class Event
32
+ end # module Googlecalendar
@@ -0,0 +1,10 @@
1
+ module Googlecalendar
2
+ class GCalendar
3
+ attr_reader :title, :url
4
+
5
+ def initialize(title, url)
6
+ @title = title
7
+ @url = url
8
+ end
9
+ end # class GCalendar
10
+ end # module Googlecalendar
@@ -0,0 +1,200 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'uri'
4
+ require "rexml/document"
5
+
6
+ module Googlecalendar
7
+ # A ruby class to wrap calls to the Google Data API
8
+ #
9
+ # More informations
10
+ #
11
+ # Google calendar API: http://code.google.com/apis/calendar/developers_guide_protocol.html
12
+ class GData
13
+ attr_accessor :google_url
14
+
15
+ def initialize(google='www.google.com')
16
+ @calendars = []
17
+ @google_url = google
18
+ end
19
+
20
+ #Convinient method to create the conf file use in login_with_conf_file
21
+ #if you don't want to create it by hand
22
+ def self.create_conf_file(email, pwd)
23
+ p = {'email' => email, 'password' => pwd}
24
+ path = File.expand_path("~/.googlecalendar4ruby/google.yaml")
25
+ unless File.exists?(path)
26
+ puts "Creating file in #{path}"
27
+ Dir.mkdir(File.dirname(path))
28
+ end
29
+ f = File.new(path, File::CREAT|File::TRUNC|File::RDWR)
30
+ f << p.to_yaml
31
+ f.close
32
+ end
33
+
34
+ #Log into google data
35
+ #This method is basically the same as the login with user and password
36
+ #but it tries to find a ~/.googlecalendar4ruby/google.yml
37
+ #Use this if you don't want to hardcode your user/password in your .rb files
38
+ def login_with_conf_file(file='~/.googlecalendar4ruby/google.yaml')
39
+ path = File.expand_path(file)
40
+ if(File.exists?(path))
41
+ File.open(path) { |f| @yaml = YAML::load(f) }
42
+ else
43
+ GData::create_conf_file('REPLACE_WITH_YOUR_MAIL@gmail.com', 'REPLACE_WITH_YOUR_PASSWORD')
44
+ throw "Created a default file in: #{path}, you need to edit it !!"
45
+ end
46
+ email = @yaml['email']
47
+ pwd = @yaml['password']
48
+ login(email, pwd)
49
+ end # login
50
+
51
+ #Log into google data, this method needs to be call once before using other methods of the class
52
+ #* Email The user's email address.
53
+ #* Passwd The user's password.
54
+ #* source Identifies your client application. Should take the form companyName-applicationName-versionID
55
+ #*Warning* Replace the default value with something like:
56
+ #+companyName-applicationName-versionID+
57
+ def login(email, pwd, source='googlecalendar.rubyforge.org-googlecalendar-default')
58
+ # service The string cl, which is the service name for Google Calendar.
59
+ @user_id = email
60
+ response = Net::HTTPS.post_form(URI.parse("https://#{@google_url}/accounts/ClientLogin"),
61
+ { 'Email' => email,
62
+ 'Passwd' => pwd,
63
+ 'source' => source,
64
+ 'accountType' => 'HOSTED_OR_GOOGLE',
65
+ 'service' => 'cl'})
66
+ response.error! unless response.kind_of? Net::HTTPSuccess
67
+ @token = response.body.split(/=/).last
68
+ @headers = {
69
+ 'Authorization' => "GoogleLogin auth=#{@token}",
70
+ 'Content-Type' => 'application/atom+xml'
71
+ }
72
+ return @token
73
+ end # login
74
+
75
+ # Reset reminders
76
+ def reset_reminders(event)
77
+ event[:reminders] = ""
78
+ end
79
+
80
+ # Add a reminder to the event hash
81
+ #* reminderMinutes
82
+ #* reminderMethod [email, alert, sms, none]
83
+ def add_reminder(event, reminderMinutes, reminderMethod)
84
+ event[:reminders] = event[:reminders].to_s +
85
+ "<gd:reminder minutes='#{reminderMinutes}' method='#{reminderMethod}' />\n"
86
+ end
87
+
88
+ # Create a quick add event
89
+ #
90
+ # <tt>text = 'Tennis with John April 11 3pm-3:30pm'</tt>
91
+ #
92
+ # http://code.google.com/apis/calendar/developers_guide_protocol.html#CreatingQuickAdd
93
+ def quick_add(text)
94
+ content = <<EOF
95
+ <entry xmlns='http://www.w3.org/2005/Atom' xmlns:gCal='http://schemas.google.com/gCal/2005'>
96
+ <content type="html">#{text}</content>
97
+ <gCal:quickadd value="true"/>
98
+ </entry>
99
+ EOF
100
+ post_event(content)
101
+ end # quick_add
102
+
103
+ #'event' param is a hash containing
104
+ #* :title
105
+ #* :content
106
+ #* :author
107
+ #* :email
108
+ #* :where
109
+ #* :startTime '2007-06-06T15:00:00.000Z'
110
+ #* :endTime '2007-06-06T17:00:00.000Z'
111
+ #
112
+ # Use add_reminder(event, reminderMinutes, reminderMethod) method to add reminders
113
+ def new_event(event={},calendar = nil)
114
+ new_event = template(event)
115
+ post_event(new_event, calendar)
116
+ end
117
+
118
+ def post_event(xml, calendar = nil)
119
+ #Get calendar url
120
+ calendar_url = if calendar
121
+ get_calendars
122
+ find_calendar(calendar).url
123
+ else
124
+ # We will use user'default calendar in this case
125
+ '/calendar/feeds/default/private/full'
126
+ end
127
+
128
+ http = Net::HTTP.new(@google_url, 80)
129
+ response, data = http.post(calendar_url, xml, @headers)
130
+ case response
131
+ when Net::HTTPSuccess, Net::HTTPRedirection
132
+ redirect_response, redirect_data = http.post(response['location'], xml, @headers)
133
+ case response
134
+ when Net::HTTPSuccess, Net::HTTPRedirection
135
+ return redirect_response
136
+ else
137
+ response.error!
138
+ end
139
+ else
140
+ response.error!
141
+ end
142
+ end # post_event
143
+
144
+ # Retreive user's calendar urls.
145
+ def get_calendars
146
+ http = Net::HTTP.new(@google_url, 80)
147
+ response, data = http.get("http://#{@google_url}/calendar/feeds/" + @user_id, @headers)
148
+ case response
149
+ when Net::HTTPSuccess, Net::HTTPRedirection
150
+ redirect_response, redirect_data = http.get(response['location'], @headers)
151
+ case response
152
+ when Net::HTTPSuccess, Net::HTTPRedirection
153
+ doc = REXML::Document.new redirect_data
154
+ doc.elements.each('//entry')do |e|
155
+ title = e.elements['title'].text
156
+ url = e.elements['link'].attributes['href']
157
+ @calendars << GCalendar.new(title, url.sub!("http://#{@google_url}",''))
158
+ end
159
+ return redirect_response
160
+ else
161
+ response.error!
162
+ end
163
+ else
164
+ response.error!
165
+ end
166
+ end # get_calendars
167
+
168
+ def find_calendar(x)
169
+ @calendars.find {|c| c.title.match x}
170
+ end
171
+
172
+ # The atom event template to submit a new event
173
+ def template(event={})
174
+ content = <<EOF
175
+ <?xml version="1.0"?>
176
+ <entry xmlns='http://www.w3.org/2005/Atom'
177
+ xmlns:gd='http://schemas.google.com/g/2005'>
178
+ <category scheme='http://schemas.google.com/g/2005#kind'
179
+ term='http://schemas.google.com/g/2005#event'></category>
180
+ <title type='text'>#{event[:title]}</title>
181
+ <content type='text'>#{event[:content]}</content>
182
+ <author>
183
+ <name>#{event[:author]}</name>
184
+ <email>#{event[:email]}</email>
185
+ </author>
186
+ <gd:transparency
187
+ value='http://schemas.google.com/g/2005#event.opaque'>
188
+ </gd:transparency>
189
+ <gd:eventStatus
190
+ value='http://schemas.google.com/g/2005#event.confirmed'>
191
+ </gd:eventStatus>
192
+ <gd:where valueString='#{event[:where]}'></gd:where>
193
+ <gd:when startTime='#{event[:startTime]}' endTime='#{event[:endTime]}'>
194
+ #{event[:reminders]}
195
+ </gd:when>
196
+ </entry>
197
+ EOF
198
+ end # template
199
+ end # GData class
200
+ end # module Googlecalendar
@@ -0,0 +1,126 @@
1
+ module Googlecalendar
2
+ class ICALParser
3
+ attr_reader :calendar
4
+
5
+ def parse(data)
6
+ lines = data.split("\n")
7
+
8
+ reset_prefix
9
+ lines.each do |line|
10
+ handle_element(line)
11
+ end
12
+
13
+ return @calendar
14
+ end
15
+
16
+ # An ICal line consist of 2 part XXX: YYYY
17
+ # Get the first part of the line and after a small transformation call the appropriate method
18
+ # example:
19
+ # line is: VCALENDAR:BEGIN
20
+ # VERSION:VALUE
21
+ # method call: handle_vcalendar_version
22
+ # kind of work like a sax parser...
23
+ def handle_element(line)
24
+ pair = line.split(':', 2) # avoid problems when summary contains ':'
25
+ name = pair[0]
26
+ value = pair[1]
27
+ handler_method = @method_prefix + name.split(';')[0].tr('-', '_').downcase
28
+ if self.respond_to? handler_method
29
+ self.send(handler_method, value.chomp)
30
+ end
31
+ end
32
+
33
+ def reset_prefix
34
+ @method_prefix = "handle_"
35
+ end
36
+
37
+ def handle_begin(value)
38
+ if value == "VCALENDAR"
39
+ handle_vcalendar_begin(value)
40
+ elsif value == "VEVENT"
41
+ handle_vevent_begin(value)
42
+ end
43
+ end
44
+
45
+ def handle_vcalendar_end(value)
46
+ reset_prefix
47
+ end
48
+
49
+ def handle_vcalendar_begin(value)
50
+ @calendar = Calendar.new
51
+ @method_prefix = @method_prefix + value.downcase + "_"
52
+ end
53
+
54
+ # def handle_vcalendar_prodid(value)
55
+ # @calendar.product_id = value
56
+ # end
57
+
58
+ def handle_vcalendar_version(value)
59
+ @calendar.version = value
60
+ end
61
+
62
+ def handle_vcalendar_calscale(value)
63
+ @calendar.scale = value
64
+ end
65
+
66
+ def handle_vcalendar_method(value)
67
+ @calendar.method = value
68
+ # FIXME don't like to do this!
69
+ reset_prefix
70
+ end
71
+
72
+ def handle_vevent_begin(value)
73
+ event = Event.new
74
+ @calendar.add event
75
+ @method_prefix = @method_prefix + value.downcase + "_"
76
+ end
77
+
78
+ def handle_vevent_end(value)
79
+ reset_prefix
80
+ end
81
+
82
+ def handle_vevent_dtstart(value)
83
+ @calendar.events.last.start_date = Date.parse(value)
84
+ end
85
+
86
+ def handle_vevent_dtend(value)
87
+ @calendar.events.last.end_date = Date.parse(value)
88
+ end
89
+
90
+ def handle_vevent_dtstamp(value)
91
+ @calendar.events.last.time_stamp = DateTime.parse(value)
92
+ end
93
+
94
+ def handle_vevent_class(value)
95
+ @calendar.events.last.class_name = value
96
+ end
97
+
98
+ def handle_vevent_created(value)
99
+ @calendar.events.last.created = DateTime.parse(value)
100
+ end
101
+
102
+ def handle_vevent_last_modified(value)
103
+ @calendar.events.last.last_modified = DateTime.parse(value)
104
+ end
105
+
106
+ def handle_vevent_status(value)
107
+ @calendar.events.last.status = value
108
+ end
109
+
110
+ def handle_vevent_summary(value)
111
+ @calendar.events.last.summary = value
112
+ end
113
+
114
+ def handle_vevent_rrule(value)
115
+ @calendar.events.last.rrule = value
116
+ end
117
+
118
+ def handle_vevent_description(value)
119
+ @calendar.events.last.description = value
120
+ end
121
+
122
+ def handle_vevent_location(value)
123
+ @calendar.events.last.location = value
124
+ end
125
+ end # class ICALParser
126
+ end # module Googlecalendar