googlecalendar 0.0.6 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{CHANGELOG → History.txt} +12 -0
- data/Manifest.txt +20 -0
- data/PostInstall.txt +14 -0
- data/README.rdoc +55 -0
- data/README.txt +55 -0
- data/Rakefile +4 -0
- data/bin/googlecalendar4ruby +44 -0
- data/html/scripts.js +9 -0
- data/html/styles.css +11 -0
- data/lib/builders.rb +2 -95
- data/lib/googlecalendar.rb +10 -384
- data/lib/googlecalendar/calendar.rb +23 -0
- data/lib/googlecalendar/dsl.rb +52 -0
- data/lib/googlecalendar/event.rb +32 -0
- data/lib/googlecalendar/gcalendar.rb +10 -0
- data/lib/googlecalendar/gdata.rb +200 -0
- data/lib/googlecalendar/ical.rb +126 -0
- data/lib/googlecalendar/net.rb +14 -0
- data/lib/googlecalendar/version.rb +10 -0
- data/lib/googlecalendar_builders.rb +85 -0
- data/test/test_event.rb +12 -0
- data/test/test_googlecalendar.rb +11 -0
- data/test/test_helper.rb +4 -0
- data/test/test_ical.rb +16 -0
- metadata +93 -38
- data/README +0 -14
data/{CHANGELOG → History.txt}
RENAMED
@@ -1,9 +1,21 @@
|
|
1
1
|
= Versions
|
2
|
+
=== 1.0.0 (Nov 18th, 2008)
|
3
|
+
* New svn repository layout (with trunk, branches and tags)
|
4
|
+
* Using newgen for project maintenance and website generation
|
5
|
+
* Old website http://benjamin.francisoud.googlepages.com/googlecalendar is DEPRECATED
|
6
|
+
* New website http://googlecalendar.rubyforge.org
|
7
|
+
* Changed from Apache License to MIT License - no big deal, googlecalendar for ruby is still free to use,modify, extend and will ever be ;)s
|
8
|
+
* Fixed a bug when parsing a calendar summary with ':' in it
|
9
|
+
Thanks to Gregor Schmidt for his contribution :)
|
10
|
+
* dsl methods html and text create output dir if missing
|
11
|
+
|
12
|
+
|
2
13
|
=== 0.0.6 (Dec 03rd, 2007)
|
3
14
|
* Added add_reminder and reset_reminders to GData (see examples/ruby_standalone/gdata_new_event_reminder.rb)
|
4
15
|
Contribution: Nicolas Fouché
|
5
16
|
* Added "Quick Add" (see examples/ruby_standalone/gdata_quick_add.rb)
|
6
17
|
Contribution: Levi Kennedy
|
18
|
+
* Fixed white space in '@ location.to_s'
|
7
19
|
|
8
20
|
=== 0.0.5 (Sept 24th, 2007)
|
9
21
|
* You can now set a different google url in GData class (default value is www.google.com)
|
data/Manifest.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
PostInstall.txt
|
4
|
+
README.rdoc
|
5
|
+
README.txt
|
6
|
+
Rakefile
|
7
|
+
bin/googlecalendar4ruby
|
8
|
+
html/scripts.js
|
9
|
+
html/styles.css
|
10
|
+
lib/builders.rb
|
11
|
+
lib/googlecalendar.rb
|
12
|
+
lib/googlecalendar/calendar.rb
|
13
|
+
lib/googlecalendar/dsl.rb
|
14
|
+
lib/googlecalendar/event.rb
|
15
|
+
lib/googlecalendar/gcalendar.rb
|
16
|
+
lib/googlecalendar/gdata.rb
|
17
|
+
lib/googlecalendar/ical.rb
|
18
|
+
lib/googlecalendar/net.rb
|
19
|
+
lib/googlecalendar/version.rb
|
20
|
+
lib/googlecalendar_builders.rb
|
data/PostInstall.txt
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Thanks a lot for installing googlecalendar for ruby ;)
|
2
|
+
|
3
|
+
If you are migrating from version 0.0.x to 1.0.0, you will need to add:
|
4
|
+
|
5
|
+
require 'googlecalendar'
|
6
|
+
** include Googlecalendar **
|
7
|
+
|
8
|
+
If you where using the 'builders' with:
|
9
|
+
require 'builders' # DEPRECATED
|
10
|
+
is replaced by
|
11
|
+
require 'googlecalendar_builders'
|
12
|
+
|
13
|
+
For more information on googlecalendar, see http://googlecalendar.rubyforge.org
|
14
|
+
|
data/README.rdoc
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
= Google Calendar
|
2
|
+
|
3
|
+
* Website (http://googlecalendar.rubyforge.org/)
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
The Google Calendar project provides
|
8
|
+
* Ruby api's to connect to google calendars (standalone, without rails)
|
9
|
+
* A plugin for Ruby On Rails
|
10
|
+
* Export features (text file or simple html page)
|
11
|
+
|
12
|
+
== FEATURES:
|
13
|
+
|
14
|
+
* api to connect ot google calendars
|
15
|
+
* log into your calendar account
|
16
|
+
* list calendars
|
17
|
+
* compatible with google apps accounts
|
18
|
+
* add events, reminders
|
19
|
+
* browse events
|
20
|
+
* export to text file
|
21
|
+
* export to html
|
22
|
+
* and many more...
|
23
|
+
|
24
|
+
== INSTALL:
|
25
|
+
|
26
|
+
* sudo gem install googlecalendar
|
27
|
+
|
28
|
+
== Author
|
29
|
+
|
30
|
+
Benjamin Francisoud - http://rubyscube.blogspot.com
|
31
|
+
|
32
|
+
== LICENSE:
|
33
|
+
|
34
|
+
(The MIT License)
|
35
|
+
|
36
|
+
Copyright (c) 2008 Benjamin Francisoud
|
37
|
+
|
38
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
39
|
+
a copy of this software and associated documentation files (the
|
40
|
+
'Software'), to deal in the Software without restriction, including
|
41
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
42
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
43
|
+
permit persons to whom the Software is furnished to do so, subject to
|
44
|
+
the following conditions:
|
45
|
+
|
46
|
+
The above copyright notice and this permission notice shall be
|
47
|
+
included in all copies or substantial portions of the Software.
|
48
|
+
|
49
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
50
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
51
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
52
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
53
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
54
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
55
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.txt
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
= Google Calendar
|
2
|
+
|
3
|
+
* Website (http://googlecalendar.rubyforge.org/)
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
The Google Calendar project provides
|
8
|
+
* Ruby api's to connect to google calendars (standalone, without rails)
|
9
|
+
* A plugin for Ruby On Rails
|
10
|
+
* Export features (text file or simple html page)
|
11
|
+
|
12
|
+
== FEATURES:
|
13
|
+
|
14
|
+
* api to connect ot google calendars
|
15
|
+
* log into your calendar account
|
16
|
+
* list calendars
|
17
|
+
* compatible with google apps accounts
|
18
|
+
* add events, reminders
|
19
|
+
* browse events
|
20
|
+
* export to text file
|
21
|
+
* export to html
|
22
|
+
* and many more...
|
23
|
+
|
24
|
+
== INSTALL:
|
25
|
+
|
26
|
+
* sudo gem install googlecalendar
|
27
|
+
|
28
|
+
== Author
|
29
|
+
|
30
|
+
Benjamin Francisoud - http://rubyscube.blogspot.com
|
31
|
+
|
32
|
+
== LICENSE:
|
33
|
+
|
34
|
+
(The MIT License)
|
35
|
+
|
36
|
+
Copyright (c) 2008 Benjamin Francisoud
|
37
|
+
|
38
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
39
|
+
a copy of this software and associated documentation files (the
|
40
|
+
'Software'), to deal in the Software without restriction, including
|
41
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
42
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
43
|
+
permit persons to whom the Software is furnished to do so, subject to
|
44
|
+
the following conditions:
|
45
|
+
|
46
|
+
The above copyright notice and this permission notice shall be
|
47
|
+
included in all copies or substantial portions of the Software.
|
48
|
+
|
49
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
50
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
51
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
52
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
53
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
54
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
55
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Created by Benjamin Francisoud on 2008-10-18.
|
4
|
+
# Copyright (c) 2008. All rights reserved.
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'rubygems'
|
8
|
+
rescue LoadError
|
9
|
+
# no rubygems to load, so we fail silently
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'optparse'
|
13
|
+
|
14
|
+
# NOTE: the option -p/--path= is given as an example, and should probably be replaced in your application.
|
15
|
+
|
16
|
+
OPTIONS = {
|
17
|
+
:path => '~'
|
18
|
+
}
|
19
|
+
MANDATORY_OPTIONS = %w( )
|
20
|
+
|
21
|
+
parser = OptionParser.new do |opts|
|
22
|
+
opts.banner = <<BANNER
|
23
|
+
This application is wonderful because...
|
24
|
+
|
25
|
+
Usage: #{File.basename($0)} [options]
|
26
|
+
|
27
|
+
Options are:
|
28
|
+
BANNER
|
29
|
+
opts.separator ""
|
30
|
+
opts.on("-p", "--path=PATH", String,
|
31
|
+
"The root path for selecting files",
|
32
|
+
"Default: ~") { |OPTIONS[:path]| }
|
33
|
+
opts.on("-h", "--help",
|
34
|
+
"Show this help message.") { puts opts; exit }
|
35
|
+
opts.parse!(ARGV)
|
36
|
+
|
37
|
+
if MANDATORY_OPTIONS && MANDATORY_OPTIONS.find { |option| OPTIONS[option.to_sym].nil? }
|
38
|
+
puts opts; exit
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
path = OPTIONS[:path]
|
43
|
+
|
44
|
+
# do stuff
|
data/html/scripts.js
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
<script language="javascript">
|
2
|
+
function displayHideSection(labelSection) {
|
3
|
+
if ((document.getElementById(labelSection).style.display == "") || (document.getElementById(labelSection).style.display == "none")) {
|
4
|
+
document.getElementById(labelSection).style.display = "block";
|
5
|
+
} else if (document.getElementById(labelSection).style.display == "block") {
|
6
|
+
document.getElementById(labelSection).style.display = "none";
|
7
|
+
}
|
8
|
+
}
|
9
|
+
</script>
|
data/html/styles.css
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
<style type="text/css">
|
2
|
+
body{background:#ffffff;color:#000000;font:0.9em "Trebuchet MS",Trebuchet,Verdana,Sans-Serif;}
|
3
|
+
a:hover{color: #ff6835;}
|
4
|
+
a:visited {color: #c63200;}
|
5
|
+
h1,h2,h3,h4,h5,h6{padding:0px;margin:0px;}
|
6
|
+
h1 a:link{text-decoration:none;color:#FFFAFA;}
|
7
|
+
h1 a:visited{text-decoration:none;color:#FFFAFA;}
|
8
|
+
h1{padding:18px 0px 10px 5%;margin:0px 0px 8px 0px;border-top:solid 9px #FF7F50;border-bottom:solid 1px #DEB887;color:#FFFAFA;background:#8e2400;font:bold 266% Verdana,Sans-Serif;}
|
9
|
+
h2{margin:0px 0px 10px 0px;padding:2px 0px 2px 5px;border-right:solid 1px #f5f5f5;border-bottom:solid 1px #dddddd;border-top:solid 1px #f5f5f5;border-left:solid 1px #f5f5f5;color:#555555;background:#eeeeee;font:bold 110% Verdana,Sans-Serif;}
|
10
|
+
.details{margin:10px 10px 10px 10px;padding:2px 2px 2px 2px;display:none}
|
11
|
+
</style>
|
data/lib/builders.rb
CHANGED
@@ -1,96 +1,3 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/
|
1
|
+
require File.dirname(__FILE__) + '/googlecalendar_builders'
|
2
2
|
|
3
|
-
|
4
|
-
attr_accessor :calendar, :filename
|
5
|
-
|
6
|
-
def export
|
7
|
-
begin
|
8
|
-
File.delete(@filename)
|
9
|
-
rescue
|
10
|
-
# if doesn't exist
|
11
|
-
end
|
12
|
-
File.open(@filename, File::CREAT|File::RDWR) do |file|
|
13
|
-
file << calendar.to_s
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def text(calendar, filename)
|
19
|
-
text_builder = TextBuilder.new
|
20
|
-
text_builder.calendar = calendar
|
21
|
-
text_builder.filename = filename
|
22
|
-
text_builder.export
|
23
|
-
end
|
24
|
-
|
25
|
-
class HtmlBuilder
|
26
|
-
attr_accessor :calendar, :filename, :date_format
|
27
|
-
|
28
|
-
def export
|
29
|
-
begin
|
30
|
-
File.delete(@filename)
|
31
|
-
rescue
|
32
|
-
# if doesn't exist
|
33
|
-
end
|
34
|
-
File.open(@filename, File::CREAT|File::RDWR) do |file|
|
35
|
-
file << "<html><head>\n"
|
36
|
-
file << "<title>Calendar</tilte>\n"
|
37
|
-
IO.foreach("html/styles.css") { |line| file << line }
|
38
|
-
file << "\n"
|
39
|
-
IO.foreach("html/scripts.js") { |line| file << line }
|
40
|
-
file << "\n</head>\n<body>"
|
41
|
-
file << summary
|
42
|
-
event_number = 0
|
43
|
-
@calendar.events.each do |event|
|
44
|
-
file << "<p class=\"event\">"
|
45
|
-
file << "<h2>Event [" + event.start_date.to_s + "]</h2>"
|
46
|
-
file << "<div><b>From: </b>" + event.start_date.to_s + "<b> -> To:</b> " + event.end_date.to_s + "</div>"
|
47
|
-
file << div(event, 'summary')
|
48
|
-
file << details(event, event_number)
|
49
|
-
file << "</p>\n"
|
50
|
-
event_number += 1
|
51
|
-
end
|
52
|
-
file << "</body></html>"
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def format(date)
|
57
|
-
Date.strptime(date, @date_format)
|
58
|
-
end
|
59
|
-
|
60
|
-
def summary
|
61
|
-
data = "<p class=\"calendar\">"
|
62
|
-
data << "<h1>Calendar</h1>"
|
63
|
-
data << div(@calendar, 'version')
|
64
|
-
data << div(@calendar, 'scale')
|
65
|
-
data << div(@calendar, 'method')
|
66
|
-
data << "<div><b>number of events: </b>" + @calendar.events.size.to_s + "</div>"
|
67
|
-
data << "</p>\n"
|
68
|
-
return data
|
69
|
-
end
|
70
|
-
|
71
|
-
def details(event, number)
|
72
|
-
details = "<a href=\"javascript:displayHideSection('details" + number.to_s + "');\">Display details</a>"
|
73
|
-
details << "<div id=\"details" + number.to_s + "\" class=\"details\">"
|
74
|
-
details << div(event, 'start_date')
|
75
|
-
details << div(event, 'end_date')
|
76
|
-
details << div(event, 'time_stamp')
|
77
|
-
details << div(event, 'created')
|
78
|
-
details << div(event, 'last_modified')
|
79
|
-
details << div(event, 'status')
|
80
|
-
details << div(event, 'rrule')
|
81
|
-
details << div(event, 'class_name')
|
82
|
-
details << "</div>"
|
83
|
-
end
|
84
|
-
|
85
|
-
def div(object, field)
|
86
|
-
"<div><b>" + field.capitalize + ": </b>" + object.send(field).to_s + "</div>\n"
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def html(calendar, filename)
|
91
|
-
html_builder = HtmlBuilder.new
|
92
|
-
html_builder.calendar = calendar
|
93
|
-
html_builder.filename = filename
|
94
|
-
html_builder.date_format = "%d-%m-%y" #"%F"#"%A %B %d %Y" #"%d-%m-%Y"
|
95
|
-
html_builder.export
|
96
|
-
end
|
3
|
+
puts "Warning: [googlecalendar] require 'builders' is DEPRECATED use require 'googlecalendar_builders' instead ! Will be remove in next versions..."
|
data/lib/googlecalendar.rb
CHANGED
@@ -1,384 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@events ||= []
|
12
|
-
@events.push event
|
13
|
-
end
|
14
|
-
|
15
|
-
def to_s
|
16
|
-
data = "########## calendar ##########\n"
|
17
|
-
data << 'version: ' + @version.to_s + "\n"
|
18
|
-
data << 'scale: ' + @scale.to_s + "\n"
|
19
|
-
data << 'method: ' + @method.to_s + "\n"
|
20
|
-
data << 'number of events: ' + @events.size.to_s + "\n"
|
21
|
-
@events.each do |event|
|
22
|
-
data << event.to_s
|
23
|
-
end
|
24
|
-
return data
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
class GCalendar
|
29
|
-
attr_reader :title, :url
|
30
|
-
|
31
|
-
def initialize(title, url)
|
32
|
-
@title = title
|
33
|
-
@url = url
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
class Event
|
38
|
-
attr_accessor :start_date, :end_date, :time_stamp, :class_name, :created, :last_modified, :status, :summary, :description, :location, :rrule
|
39
|
-
|
40
|
-
def to_s
|
41
|
-
data = "---------- event ----------\n"
|
42
|
-
data << 'start_date: ' + @start_date.to_s + "\n"
|
43
|
-
data << 'end_date: ' + @end_date.to_s + "\n"
|
44
|
-
data << 'time_stamp: ' + @time_stamp.to_s + "\n"
|
45
|
-
data << 'class_name: ' + @class_name.to_s + "\n"
|
46
|
-
data << 'created: ' + @created.to_s + "\n"
|
47
|
-
data << 'last_modified: ' + @last_modified.to_s + "\n"
|
48
|
-
data << 'status: ' + @status.to_s + "\n"
|
49
|
-
data << 'rrule: ' + @rrule.to_s + "\n"
|
50
|
-
data << 'summary: ' + @summary.to_s + "\n"
|
51
|
-
data << 'desription: ' + @desription.to_s + "\n"
|
52
|
-
data << 'location: ' + @location.to_s + "\n"
|
53
|
-
return data
|
54
|
-
end
|
55
|
-
|
56
|
-
# 'FREQ=WEEKLY;BYDAY=MO;WKST=MO'
|
57
|
-
def rrule_as_hash
|
58
|
-
array = @rrule.split(';')
|
59
|
-
hash = Hash.new
|
60
|
-
array.each do |item|
|
61
|
-
pair = item.split('=')
|
62
|
-
hash[pair[0]] = pair[1]
|
63
|
-
end
|
64
|
-
return hash
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
#
|
69
|
-
# Make it east to use some of the convenience methods using https
|
70
|
-
#
|
71
|
-
module Net
|
72
|
-
class HTTPS < HTTP
|
73
|
-
def initialize(address, port = nil)
|
74
|
-
super(address, port)
|
75
|
-
self.use_ssl = true
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
# A ruby class to wrap calls to the Google Data API
|
81
|
-
#
|
82
|
-
# More informations
|
83
|
-
#
|
84
|
-
# Google calendar API: http://code.google.com/apis/calendar/developers_guide_protocol.html
|
85
|
-
class GData
|
86
|
-
attr_accessor :google_url
|
87
|
-
|
88
|
-
def initialize(google='www.google.com')
|
89
|
-
@calendars = []
|
90
|
-
@google_url = google
|
91
|
-
end
|
92
|
-
|
93
|
-
#Log into google data, this method needs to be call once before using other methods of the class
|
94
|
-
#* Email The user's email address.
|
95
|
-
#* Passwd The user's password.
|
96
|
-
#* source Identifies your client application. Should take the form companyName-applicationName-versionID
|
97
|
-
#*Warning* Replace the default value with something like:
|
98
|
-
#+companyName-applicationName-versionID+
|
99
|
-
def login(email, pwd, source='googlecalendar.rubyforge.org-googlecalendar-default')
|
100
|
-
# service The string cl, which is the service name for Google Calendar.
|
101
|
-
@user_id = email
|
102
|
-
response = Net::HTTPS.post_form(URI.parse("https://#{@google_url}/accounts/ClientLogin"),
|
103
|
-
{ 'Email' => email,
|
104
|
-
'Passwd' => pwd,
|
105
|
-
'source' => source,
|
106
|
-
'accountType' => 'HOSTED_OR_GOOGLE',
|
107
|
-
'service' => 'cl'})
|
108
|
-
response.error! unless response.kind_of? Net::HTTPSuccess
|
109
|
-
@token = response.body.split(/=/).last
|
110
|
-
@headers = {
|
111
|
-
'Authorization' => "GoogleLogin auth=#{@token}",
|
112
|
-
'Content-Type' => 'application/atom+xml'
|
113
|
-
}
|
114
|
-
return @token
|
115
|
-
end
|
116
|
-
|
117
|
-
# Reset reminders
|
118
|
-
def reset_reminders(event)
|
119
|
-
event[:reminders] = ""
|
120
|
-
end
|
121
|
-
|
122
|
-
# Add a reminder to the event hash
|
123
|
-
#* reminderMinutes
|
124
|
-
#* reminderMethod [email, alert, sms, none]
|
125
|
-
def add_reminder(event, reminderMinutes, reminderMethod)
|
126
|
-
event[:reminders] = event[:reminders].to_s +
|
127
|
-
"<gd:reminder minutes='#{reminderMinutes}' method='#{reminderMethod}' />\n"
|
128
|
-
end
|
129
|
-
|
130
|
-
# Create a quick add event
|
131
|
-
#
|
132
|
-
# <tt>text = 'Tennis with John April 11 3pm-3:30pm'</tt>
|
133
|
-
#
|
134
|
-
# http://code.google.com/apis/calendar/developers_guide_protocol.html#CreatingQuickAdd
|
135
|
-
def quick_add(text)
|
136
|
-
content = <<EOF
|
137
|
-
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gCal='http://schemas.google.com/gCal/2005'>
|
138
|
-
<content type="html">#{text}</content>
|
139
|
-
<gCal:quickadd value="true"/>
|
140
|
-
</entry>
|
141
|
-
EOF
|
142
|
-
post_event(content)
|
143
|
-
end
|
144
|
-
|
145
|
-
#'event' param is a hash containing
|
146
|
-
#* :title
|
147
|
-
#* :content
|
148
|
-
#* :author
|
149
|
-
#* :email
|
150
|
-
#* :where
|
151
|
-
#* :startTime '2007-06-06T15:00:00.000Z'
|
152
|
-
#* :endTime '2007-06-06T17:00:00.000Z'
|
153
|
-
#
|
154
|
-
# Use add_reminder(event, reminderMinutes, reminderMethod) method to add reminders
|
155
|
-
def new_event(event={},calendar = nil)
|
156
|
-
new_event = template(event)
|
157
|
-
post_event(new_event, calendar)
|
158
|
-
end
|
159
|
-
|
160
|
-
def post_event(xml, calendar = nil)
|
161
|
-
#Get calendar url
|
162
|
-
calendar_url = if calendar
|
163
|
-
get_calendars
|
164
|
-
find_calendar(calendar).url
|
165
|
-
else
|
166
|
-
# We will use user'default calendar in this case
|
167
|
-
'/calendar/feeds/default/private/full'
|
168
|
-
end
|
169
|
-
|
170
|
-
http = Net::HTTP.new(@google_url, 80)
|
171
|
-
response, data = http.post(calendar_url, xml, @headers)
|
172
|
-
case response
|
173
|
-
when Net::HTTPSuccess, Net::HTTPRedirection
|
174
|
-
redirect_response, redirect_data = http.post(response['location'], xml, @headers)
|
175
|
-
case response
|
176
|
-
when Net::HTTPSuccess, Net::HTTPRedirection
|
177
|
-
return redirect_response
|
178
|
-
else
|
179
|
-
response.error!
|
180
|
-
end
|
181
|
-
else
|
182
|
-
response.error!
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
# Retreive user's calendar urls.
|
187
|
-
def get_calendars
|
188
|
-
http = Net::HTTP.new(@google_url, 80)
|
189
|
-
response, data = http.get("http://#{@google_url}/calendar/feeds/" + @user_id, @headers)
|
190
|
-
case response
|
191
|
-
when Net::HTTPSuccess, Net::HTTPRedirection
|
192
|
-
redirect_response, redirect_data = http.get(response['location'], @headers)
|
193
|
-
case response
|
194
|
-
when Net::HTTPSuccess, Net::HTTPRedirection
|
195
|
-
doc = REXML::Document.new redirect_data
|
196
|
-
doc.elements.each('//entry')do |e|
|
197
|
-
title = e.elements['title'].text
|
198
|
-
url = e.elements['link'].attributes['href']
|
199
|
-
@calendars << GCalendar.new(title, url.sub!("http://#{@google_url}",''))
|
200
|
-
end
|
201
|
-
return redirect_response
|
202
|
-
else
|
203
|
-
response.error!
|
204
|
-
end
|
205
|
-
else
|
206
|
-
response.error!
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
def find_calendar(x)
|
211
|
-
@calendars.find {|c| c.title.match x}
|
212
|
-
end
|
213
|
-
|
214
|
-
# The atom event template to submit a new event
|
215
|
-
def template(event={})
|
216
|
-
content = <<EOF
|
217
|
-
<?xml version="1.0"?>
|
218
|
-
<entry xmlns='http://www.w3.org/2005/Atom'
|
219
|
-
xmlns:gd='http://schemas.google.com/g/2005'>
|
220
|
-
<category scheme='http://schemas.google.com/g/2005#kind'
|
221
|
-
term='http://schemas.google.com/g/2005#event'></category>
|
222
|
-
<title type='text'>#{event[:title]}</title>
|
223
|
-
<content type='text'>#{event[:content]}</content>
|
224
|
-
<author>
|
225
|
-
<name>#{event[:author]}</name>
|
226
|
-
<email>#{event[:email]}</email>
|
227
|
-
</author>
|
228
|
-
<gd:transparency
|
229
|
-
value='http://schemas.google.com/g/2005#event.opaque'>
|
230
|
-
</gd:transparency>
|
231
|
-
<gd:eventStatus
|
232
|
-
value='http://schemas.google.com/g/2005#event.confirmed'>
|
233
|
-
</gd:eventStatus>
|
234
|
-
<gd:where valueString='#{event[:where]}'></gd:where>
|
235
|
-
<gd:when startTime='#{event[:startTime]}' endTime='#{event[:endTime]}'>
|
236
|
-
#{event[:reminders]}
|
237
|
-
</gd:when>
|
238
|
-
</entry>
|
239
|
-
EOF
|
240
|
-
end
|
241
|
-
end # GData class
|
242
|
-
|
243
|
-
class ICALParser
|
244
|
-
attr_reader :calendar
|
245
|
-
|
246
|
-
def parse(data)
|
247
|
-
lines = data.split("\n")
|
248
|
-
|
249
|
-
reset_prefix
|
250
|
-
lines.each do |line|
|
251
|
-
handle_element(line)
|
252
|
-
end
|
253
|
-
|
254
|
-
return @calendar
|
255
|
-
end
|
256
|
-
|
257
|
-
def handle_element(line)
|
258
|
-
pair = line.split(':')
|
259
|
-
name = pair[0]
|
260
|
-
value = pair[1]
|
261
|
-
handler_method = @method_prefix + name.split(';')[0].tr('-', '_').downcase
|
262
|
-
if self.respond_to? handler_method
|
263
|
-
self.send(handler_method, value.chomp)
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
267
|
-
def reset_prefix
|
268
|
-
@method_prefix = "handle_"
|
269
|
-
end
|
270
|
-
|
271
|
-
def handle_begin(value)
|
272
|
-
if value == "VCALENDAR"
|
273
|
-
handle_vcalendar_begin(value)
|
274
|
-
elsif value == "VEVENT"
|
275
|
-
handle_vevent_begin(value)
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
def handle_vcalendar_end(value)
|
280
|
-
reset_prefix
|
281
|
-
end
|
282
|
-
|
283
|
-
def handle_vcalendar_begin(value)
|
284
|
-
@calendar = Calendar.new
|
285
|
-
@method_prefix = @method_prefix + value.downcase + "_"
|
286
|
-
end
|
287
|
-
|
288
|
-
def handle_vcalendar_version(value)
|
289
|
-
@calendar.version = value
|
290
|
-
end
|
291
|
-
|
292
|
-
def handle_vcalendar_calscale(value)
|
293
|
-
@calendar.scale = value
|
294
|
-
end
|
295
|
-
|
296
|
-
def handle_vcalendar_method(value)
|
297
|
-
@calendar.method = value
|
298
|
-
# FIXME don't like to do this!
|
299
|
-
reset_prefix
|
300
|
-
end
|
301
|
-
|
302
|
-
def handle_vevent_begin(value)
|
303
|
-
event = Event.new
|
304
|
-
@calendar.add event
|
305
|
-
@method_prefix = @method_prefix + value.downcase + "_"
|
306
|
-
end
|
307
|
-
|
308
|
-
def handle_vevent_end(value)
|
309
|
-
reset_prefix
|
310
|
-
end
|
311
|
-
|
312
|
-
def handle_vevent_dtstart(value)
|
313
|
-
@calendar.events.last.start_date = Date.parse(value)
|
314
|
-
end
|
315
|
-
|
316
|
-
def handle_vevent_dtend(value)
|
317
|
-
@calendar.events.last.end_date = Date.parse(value)
|
318
|
-
end
|
319
|
-
|
320
|
-
def handle_vevent_dtstamp(value)
|
321
|
-
@calendar.events.last.time_stamp = DateTime.parse(value)
|
322
|
-
end
|
323
|
-
|
324
|
-
def handle_vevent_class(value)
|
325
|
-
@calendar.events.last.class_name = value
|
326
|
-
end
|
327
|
-
|
328
|
-
def handle_vevent_created(value)
|
329
|
-
@calendar.events.last.created = DateTime.parse(value)
|
330
|
-
end
|
331
|
-
|
332
|
-
def handle_vevent_last_modified(value)
|
333
|
-
@calendar.events.last.last_modified = DateTime.parse(value)
|
334
|
-
end
|
335
|
-
|
336
|
-
def handle_vevent_status(value)
|
337
|
-
@calendar.events.last.status = value
|
338
|
-
end
|
339
|
-
|
340
|
-
def handle_vevent_summary(value)
|
341
|
-
@calendar.events.last.summary = value
|
342
|
-
end
|
343
|
-
|
344
|
-
def handle_vevent_rrule(value)
|
345
|
-
@calendar.events.last.rrule = value
|
346
|
-
end
|
347
|
-
|
348
|
-
def handle_vevent_description(value)
|
349
|
-
@calendar.events.last.description = value
|
350
|
-
end
|
351
|
-
|
352
|
-
def handle_vevent_location(value)
|
353
|
-
@calendar.events.last.location = value
|
354
|
-
end
|
355
|
-
end
|
356
|
-
|
357
|
-
def parse(data)
|
358
|
-
parser = ICALParser.new
|
359
|
-
parser.parse(data)
|
360
|
-
end
|
361
|
-
|
362
|
-
def scan(ical_url, base_url='www.google.com')
|
363
|
-
Net::HTTP.start(base_url, 80) do |http|
|
364
|
-
response, data = http.get(ical_url)
|
365
|
-
case response
|
366
|
-
when Net::HTTPSuccess, Net::HTTPRedirection
|
367
|
-
return data
|
368
|
-
else
|
369
|
-
response.error!
|
370
|
-
end
|
371
|
-
end
|
372
|
-
end
|
373
|
-
|
374
|
-
def scan_proxy(proxy_addr, proxy_port, ical_url, base_url='www.google.com')
|
375
|
-
Net::HTTP::Proxy(proxy_addr, proxy_port).start(base_url, 80) do |http|
|
376
|
-
response, data = http.get(ical_url)
|
377
|
-
case response
|
378
|
-
when Net::HTTPSuccess, Net::HTTPRedirection
|
379
|
-
return data
|
380
|
-
else
|
381
|
-
response.error!
|
382
|
-
end
|
383
|
-
end
|
384
|
-
end
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
module Googlecalendar
|
5
|
+
# List of lib files to include
|
6
|
+
FILES = %w{calendar.rb dsl.rb event.rb gcalendar.rb gdata.rb ical.rb net.rb version.rb}
|
7
|
+
end
|
8
|
+
|
9
|
+
# Add all FILES as require
|
10
|
+
Googlecalendar::FILES.each { |f| require "googlecalendar/#{f}"}
|