agcaldav 0.2.2 → 0.2.3.beta
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +89 -26
- data/agcaldav.gemspec +0 -2
- data/lib/agcaldav/client.rb +106 -33
- data/lib/agcaldav/version.rb +1 -1
- data/lib/agcaldav.rb +1 -1
- metadata +5 -5
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#Ruby CalDAV library named "agcaldav"
|
2
2
|
**agcaldav is a CalDAV library based on martinpovolny/ruby-caldav and 4fthawaiian/ruby-caldav and collectiveidea/caldav**
|
3
3
|
|
4
|
-
##Usage
|
4
|
+
##Usage Events
|
5
5
|
|
6
6
|
First, you've to install the gem
|
7
7
|
|
@@ -20,54 +20,117 @@ Now you can e.g. create a new AgCalDAV-Client:
|
|
20
20
|
|
21
21
|
Alternatively, the proxy parameters can be specified:
|
22
22
|
|
23
|
-
cal = AgCalDAV::Client.new(:uri => "http://localhost:5232/user/calendar",:user => "user" , :password => "password, :proxy_uri => "http://my-proxy.com:8080")
|
23
|
+
cal = AgCalDAV::Client.new(:uri => "http://localhost:5232/user/calendar",:user => "user" , :password => "password", :proxy_uri => "http://my-proxy.com:8080")
|
24
24
|
|
25
25
|
|
26
|
-
####Create an Event
|
26
|
+
####Create an Event
|
27
27
|
|
28
|
-
result = cal.create_event(:start => "2012-12-29 10:00", :end => "2012-12-30 12:00", :title => "12345", :description => "
|
28
|
+
result = cal.create_event(:start => "2012-12-29 10:00", :end => "2012-12-30 12:00", :title => "12345", :description => "12345 12345")
|
29
29
|
|
30
30
|
Analyze result:
|
31
|
-
|
31
|
+
|
32
|
+
>> result
|
33
|
+
=> #<Icalendar::Event:0x007ff653b47520 @name="VEVENT", @components={}, @properties={"sequence"=>0, "dtstamp"=>#<DateTime: 2012-12-30T19:59:04+00:00 (26527957193/10800,0/1,2299161)>, "description"=>"sdkvjsdf sdkf sdkfj sdkf dsfj", "dtend"=>#<DateTime: 2012-12-30T12:00:00+00:00 (2456292/1,0/1,2299161)>, "dtstart"=>#<DateTime: 2012-12-29T10:00:00+00:00 (29475491/12,0/1,2299161)>, "summary"=>"12345", "uid"=>"e795c480-34e0-0130-7d1d-109add70606c", "x-radicale_name"=>"e795c480-34e0-0130-7d1d-109add70606c.ics"}>
|
34
|
+
|
32
35
|
>> result.class
|
33
|
-
=> Icalendar::
|
36
|
+
=> Icalendar::Event
|
34
37
|
|
35
|
-
>> result.
|
38
|
+
>> result.count
|
36
39
|
=> 1
|
37
40
|
|
38
|
-
|
39
|
-
=> #<Icalendar::Event:0x007ff653b47520 @name="VEVENT", @components={}, @properties={"sequence"=>0, "dtstamp"=>#<DateTime: 2012-12-30T19:59:04+00:00 (26527957193/10800,0/1,2299161)>, "description"=>"sdkvjsdf sdkf sdkfj sdkf dsfj", "dtend"=>#<DateTime: 2012-12-30T12:00:00+00:00 (2456292/1,0/1,2299161)>, "dtstart"=>#<DateTime: 2012-12-29T10:00:00+00:00 (29475491/12,0/1,2299161)>, "summary"=>"12345", "uid"=>"e795c480-34e0-0130-7d1d-109add70606c", "x-radicale_name"=>"e795c480-34e0-0130-7d1d-109add70606c.ics"}>
|
40
|
-
|
41
|
+
|
41
42
|
get UID of this Event:
|
42
|
-
|
43
|
+
|
44
|
+
>> result.uid
|
43
45
|
=> "e795c480-34e0-0130-7d1d-109add70606c"
|
44
46
|
|
45
47
|
|
46
|
-
Find Event
|
47
|
-
|
48
|
-
|
48
|
+
####Find an Event (via UUID)
|
49
|
+
|
50
|
+
result = cal.find_event("e795c480-34e0-0130-7d1d-109add70606c")
|
49
51
|
|
50
52
|
>> result.class
|
51
|
-
=> Icalendar::
|
53
|
+
=> Icalendar::Event
|
52
54
|
|
53
55
|
|
54
|
-
Find Events within time interval
|
56
|
+
####Find Events within time interval
|
55
57
|
|
56
58
|
result = cal.find_events(:start => "2012-10-01 08:00", :end => "2013-01-01")
|
57
59
|
|
60
|
+
>> result
|
61
|
+
=> [#<Icalendar::Event:0x007f8ad11cfdf0 @name="VEVENT", @components={}, @properties={"sequence"=>0, "dtstamp"=>#<DateTime: 2012-12-31T13:44:10+00:00 (4244474429/1728,0/1,2299161)>, "description"=>"sdkvjsdf sdkf sdkfj sdkf dsfj", "dtend"=>#<DateTime: 2012-12-30T12:00:00+00:00 (2456292/1,0/1,2299161)>, "dtstart"=>#<DateTime: 2012-12-29T10:00:00+00:00 (29475491/12,0/1,2299161)>, "summary"=>"12345", "uid"=>"b2c45e20-3575-0130-7d2e-109add70606c", "x-radicale_name"=>"b2c45e20-3575-0130-7d2e-109add70606c.ics"}>, #<Icalendar::Event:0x007f8ad10d7dd0 @name="VEVENT", @components={}, @properties={"sequence"=>0, "dtstamp"=>#<DateTime: 2012-12-31T13:44:10+00:00 (4244474429/1728,0/1,2299161)>, "uid"=>"b2c45e20-3575-0130-7d2e-109add70606c", "x-radicale_name"=>"b2c45e20-3575-0130-7d2e-109add70606c.ics"}>]
|
62
|
+
|
63
|
+
>> result.class
|
64
|
+
=> Array
|
65
|
+
|
66
|
+
>> result.count
|
67
|
+
=> 2
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
####Update Event
|
72
|
+
|
73
|
+
event = {:start => "2012-12-29 10:00", :end => "2012-12-30 12:00", :title => "12345", :description => "sdkvjsdf sdkf sdkfj sdkf dsfj"}
|
74
|
+
c = cal.update_event("e795c480-34e0-0130-7d1d-109add70606c", event)
|
75
|
+
|
76
|
+
# not nice ...
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
####Delete Event
|
81
|
+
|
82
|
+
cal.delete_event("e795c480-34e0-0130-7d1d-109add70606c")
|
83
|
+
|
84
|
+
|
58
85
|
|
59
|
-
####TODO's
|
60
86
|
|
61
|
-
|
62
|
-
# #
|
63
|
-
# TODO : #
|
64
|
-
# 1. find and notify if overlapping events #
|
65
|
-
# 2. "create_event" check for UUID is really unique #
|
66
|
-
# 3. errorhandling & code cleanup #
|
67
|
-
# #
|
68
|
-
###############################################################
|
87
|
+
##Usage ToDo
|
69
88
|
|
89
|
+
####not finished ATM
|
90
|
+
Have a look tomorrow...
|
70
91
|
|
92
|
+
|
93
|
+
|
94
|
+
####Work to be done ...
|
95
|
+
|
96
|
+
1. find and notify if overlapping events
|
97
|
+
2. code cleanup -> more ActiveRecord style
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
####Testing
|
103
|
+
|
104
|
+
agcaldav will use RSpec for its test coverage. Inside the gem
|
105
|
+
directory, you can run the specs for RoR 3.x with:
|
106
|
+
|
107
|
+
rake spec
|
108
|
+
(will be implemented in > v0.2.5)
|
109
|
+
|
110
|
+
|
111
|
+
|
71
112
|
####Licence
|
72
113
|
|
73
|
-
|
114
|
+
MIT
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
####Contributors
|
119
|
+
|
120
|
+
[Check all contributors][c]
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
Contributing
|
125
|
+
------------
|
126
|
+
|
127
|
+
1. Fork it.
|
128
|
+
2. Create a branch (`git checkout -b my_feature_branch`)
|
129
|
+
3. Commit your changes (`git commit -am "bugfixed abc..."`)
|
130
|
+
4. Push to the branch (`git push origin my_feature_branch`)
|
131
|
+
5. Open a [Pull Request][1]
|
132
|
+
6. Enjoy a refreshing Club Mate and wait
|
133
|
+
|
134
|
+
[c]: https://github.com/agilastic/agcaldav/contributors
|
135
|
+
[1]: https://github.com/agilastic/agcaldav/pull/
|
136
|
+
|
data/agcaldav.gemspec
CHANGED
@@ -21,9 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.add_runtime_dependency 'icalendar'
|
22
22
|
s.add_runtime_dependency 'uuid'
|
23
23
|
s.add_runtime_dependency 'builder'
|
24
|
-
#s.add_dependency "json"
|
25
24
|
s.add_development_dependency "rspec"
|
26
|
-
# sorry for no tests atm :-/
|
27
25
|
|
28
26
|
s.files = `git ls-files`.split("\n")
|
29
27
|
s.require_paths = ["lib"]
|
data/lib/agcaldav/client.rb
CHANGED
@@ -48,16 +48,13 @@ module AgCalDAV
|
|
48
48
|
req.body = AgCalDAV::Request::ReportVEVENT.new(DateTime.parse(data[:start]).strftime("%Y%m%dT%H%M"),
|
49
49
|
DateTime.parse(data[:end]).strftime("%Y%m%dT%H%M") ).to_xml
|
50
50
|
res = http.request(req)
|
51
|
-
|
51
|
+
}
|
52
|
+
errorhandling res
|
52
53
|
result = ""
|
53
|
-
xml = REXML::Document.new(
|
54
|
+
xml = REXML::Document.new(res.body)
|
54
55
|
REXML::XPath.each( xml, '//c:calendar-data/', {"c"=>"urn:ietf:params:xml:ns:caldav"} ){|c| result << c.text}
|
55
56
|
r = Icalendar.parse(result)
|
56
|
-
r.first
|
57
|
-
|
58
|
-
}
|
59
|
-
|
60
|
-
|
57
|
+
r.first.events
|
61
58
|
end
|
62
59
|
|
63
60
|
def find_event uuid
|
@@ -66,26 +63,33 @@ module AgCalDAV
|
|
66
63
|
req = Net::HTTP::Get.new("#{@url}/#{uuid}.ics")
|
67
64
|
req.basic_auth @user, @password
|
68
65
|
res = http.request( req )
|
69
|
-
}
|
70
|
-
|
71
|
-
|
72
|
-
r
|
73
|
-
r.first
|
66
|
+
}
|
67
|
+
errorhandling res
|
68
|
+
r = Icalendar.parse(res.body)
|
69
|
+
r.first.events.first
|
74
70
|
end
|
75
71
|
|
76
72
|
def delete_event uuid
|
73
|
+
res = nil
|
77
74
|
__create_http.start {|http|
|
78
75
|
req = Net::HTTP::Delete.new("#{@url}/#{uuid}.ics")
|
79
76
|
req.basic_auth @user, @password
|
80
77
|
res = http.request( req )
|
81
78
|
}
|
79
|
+
errorhandling res
|
80
|
+
if res.code.to_i == 200
|
81
|
+
return true
|
82
|
+
else
|
83
|
+
return false
|
84
|
+
end
|
82
85
|
end
|
83
86
|
|
84
87
|
def create_event event
|
85
88
|
c = Calendar.new
|
86
89
|
uuid = UUID.new.generate
|
90
|
+
raise DuplicateError if entry_with_uuid_exists?(uuid)
|
87
91
|
c.event do
|
88
|
-
uid uuid
|
92
|
+
uid uuid
|
89
93
|
dtstart DateTime.parse(event[:start])
|
90
94
|
dtend DateTime.parse(event[:end])
|
91
95
|
duration event[:duration]
|
@@ -96,7 +100,6 @@ module AgCalDAV
|
|
96
100
|
geo_location event[:geo_location]
|
97
101
|
status event[:status]
|
98
102
|
end
|
99
|
-
c.publish
|
100
103
|
c.event.uid = uuid
|
101
104
|
cstring = c.to_ical
|
102
105
|
res = nil
|
@@ -108,54 +111,124 @@ module AgCalDAV
|
|
108
111
|
req.body = cstring
|
109
112
|
res = http.request( req )
|
110
113
|
}
|
111
|
-
|
112
|
-
raise APIError if res.code.to_i >= 500
|
114
|
+
errorhandling res
|
113
115
|
find_event uuid
|
114
|
-
|
116
|
+
end
|
117
|
+
|
118
|
+
def update_event uuid, event
|
119
|
+
#TODO... fix me
|
120
|
+
if delete_event uuid
|
121
|
+
create_event event
|
122
|
+
else
|
123
|
+
return false
|
124
|
+
end
|
115
125
|
end
|
116
126
|
|
117
127
|
def add_alarm tevent, altCal="Calendar"
|
118
|
-
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
|
119
132
|
|
120
|
-
# TODO
|
121
133
|
|
122
134
|
|
123
135
|
|
124
136
|
|
137
|
+
|
138
|
+
|
139
|
+
def find_todo uuid
|
140
|
+
res = nil
|
141
|
+
__create_http.start {|http|
|
142
|
+
req = Net::HTTP::Get.new("#{@url}/#{uuid}.ics")
|
143
|
+
req.basic_auth @user, @password
|
144
|
+
res = http.request( req )
|
145
|
+
}
|
146
|
+
errorhandling res
|
147
|
+
r = Icalendar.parse(res.body)
|
148
|
+
r.first.todos.first
|
125
149
|
end
|
126
150
|
|
127
|
-
def update event
|
128
|
-
# FIXME old one not neat
|
129
151
|
|
130
|
-
|
152
|
+
|
153
|
+
|
154
|
+
|
155
|
+
def create_todo todo
|
156
|
+
c = Calendar.new
|
157
|
+
uuid = UUID.new.generate
|
158
|
+
raise DuplicateError if entry_with_uuid_exists?(uuid)
|
159
|
+
c.todo do
|
160
|
+
uid uuid
|
161
|
+
start DateTime.parse(todo[:start])
|
162
|
+
duration todo[:duration]
|
163
|
+
summary todo[:title]
|
164
|
+
description todo[:description]
|
165
|
+
klass todo[:accessibility] #PUBLIC, PRIVATE, CONFIDENTIAL
|
166
|
+
location todo[:location]
|
167
|
+
percent todo[:percent]
|
168
|
+
priority todo[:priority]
|
169
|
+
url todo[:url]
|
170
|
+
geo todo[:geo_location]
|
171
|
+
status todo[:status]
|
172
|
+
end
|
173
|
+
c.todo.uid = uuid
|
174
|
+
cstring = c.to_ical
|
175
|
+
res = nil
|
176
|
+
http = Net::HTTP.new(@host, @port)
|
177
|
+
__create_http.start { |http|
|
178
|
+
req = Net::HTTP::Put.new("#{@url}/#{uuid}.ics")
|
179
|
+
req['Content-Type'] = 'text/calendar'
|
180
|
+
req.basic_auth @user, @password
|
181
|
+
req.body = cstring
|
182
|
+
res = http.request( req )
|
183
|
+
}
|
184
|
+
errorhandling res
|
185
|
+
find_todo uuid
|
131
186
|
end
|
132
187
|
|
133
|
-
def
|
188
|
+
def create_todo
|
134
189
|
res = nil
|
190
|
+
raise DuplicateError if entry_with_uuid_exists?(uuid)
|
191
|
+
|
135
192
|
__create_http.start {|http|
|
136
193
|
req = Net::HTTP::Report.new(@url, initheader = {'Content-Type'=>'application/xml'} )
|
137
194
|
req.basic_auth @user, @password
|
138
195
|
req.body = AgCalDAV::Request::ReportVTODO.new.to_xml
|
139
196
|
res = http.request( req )
|
140
197
|
}
|
141
|
-
|
198
|
+
errorhandling res
|
142
199
|
format.parse_todo( res.body )
|
143
200
|
end
|
144
201
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
}
|
153
|
-
|
202
|
+
private
|
203
|
+
def entry_with_uuid_exists? uuid
|
204
|
+
res = nil
|
205
|
+
__create_http.start {|http|
|
206
|
+
req = Net::HTTP::Get.new("#{@url}/#{uuid}.ics")
|
207
|
+
req.basic_auth @user, @password
|
208
|
+
res = http.request( req )
|
209
|
+
}
|
210
|
+
if res.body.empty?
|
211
|
+
return false
|
212
|
+
else
|
213
|
+
return true
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def errorhandling response
|
218
|
+
raise AuthenticationError if response.code.to_i == 401
|
219
|
+
raise NotExistError if response.code.to_i == 410
|
220
|
+
raise APIError if response.code.to_i >= 500
|
154
221
|
end
|
155
222
|
end
|
156
223
|
|
224
|
+
|
225
|
+
|
226
|
+
|
227
|
+
|
157
228
|
class AgCalDAVError < StandardError
|
158
229
|
end
|
159
230
|
class AuthenticationError < AgCalDAVError; end
|
231
|
+
class DuplicateError < AgCalDAVError; end
|
160
232
|
class APIError < AgCalDAVError; end
|
233
|
+
class NotExistError < AgCalDAVError; end
|
161
234
|
end
|
data/lib/agcaldav/version.rb
CHANGED
data/lib/agcaldav.rb
CHANGED
@@ -6,6 +6,6 @@ require 'icalendar'
|
|
6
6
|
require 'time'
|
7
7
|
require 'date'
|
8
8
|
|
9
|
-
['client.rb', 'request.rb', 'net.rb', 'query.rb', 'filter.rb', 'event.rb', 'format.rb'].each do |f|
|
9
|
+
['client.rb', 'request.rb', 'net.rb', 'query.rb', 'filter.rb', 'event.rb', 'todo.rb', 'format.rb'].each do |f|
|
10
10
|
require File.join( File.dirname(__FILE__), 'agcaldav', f )
|
11
11
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: agcaldav
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
5
|
-
prerelease:
|
4
|
+
version: 0.2.3.beta
|
5
|
+
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Alex Ebeling-Hoppe
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: icalendar
|
@@ -109,9 +109,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
109
109
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
110
|
none: false
|
111
111
|
requirements:
|
112
|
-
- - ! '
|
112
|
+
- - ! '>'
|
113
113
|
- !ruby/object:Gem::Version
|
114
|
-
version:
|
114
|
+
version: 1.3.1
|
115
115
|
requirements: []
|
116
116
|
rubyforge_project:
|
117
117
|
rubygems_version: 1.8.24
|