calendav 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/calendav/calendar.rb +23 -15
- data/lib/calendav/clients/events_client.rb +1 -1
- data/lib/calendav/endpoint.rb +1 -1
- data/lib/calendav/event.rb +18 -7
- data/lib/calendav/parsers/sync_xml.rb +13 -1
- data/lib/calendav/sync_collection.rb +7 -2
- data/spec/acceptance/google_spec.rb +23 -15
- data/spec/acceptance/shared.rb +5 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 605ae687dccd58f74c2c2ec01b44bf27b2cc71de6f5453d26c398b7828325d40
|
4
|
+
data.tar.gz: '08c0253e9cc5479f1370a2acb5973901a4d9079078a9f51aba2ac28fccf75b9d'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 20d4fefd21bdf9d58a2c76e557b80be9a6f62c0a4c38667ab806f91e9081e34179941ad9238ca25007db41525a9ac21ec1fe2ce84ac311418e50458af55a413a
|
7
|
+
data.tar.gz: e3584378cea92199c918f81df44394ccac34b20b2f963abd72d2488d0356dd2108e06ec038ea68e511e2548f9ee48684b3584950cd737d431530479d57430ae2
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
...
|
4
4
|
|
5
|
+
## 0.2.0 - 2021-07-07
|
6
|
+
|
7
|
+
* Improve serialisation of Event and Calendar objects (easily converted to/from hashes).
|
8
|
+
* Add `more?` to sync collection objects, indicating whether there are further changes available.
|
9
|
+
|
5
10
|
## 0.1.1 - 2021-06-28
|
6
11
|
|
7
12
|
* Fix reports lists to just the relevant calendar.
|
data/lib/calendav/calendar.rb
CHANGED
@@ -5,27 +5,35 @@ require_relative "./parsers/calendar_xml"
|
|
5
5
|
|
6
6
|
module Calendav
|
7
7
|
class Calendar
|
8
|
-
|
9
|
-
|
8
|
+
ATTRIBUTES = %i[
|
9
|
+
url display_name description ctag etag time_zone color components reports
|
10
|
+
sync_token
|
11
|
+
].freeze
|
10
12
|
|
11
13
|
def self.from_xml(host, node)
|
12
14
|
new(
|
13
|
-
|
14
|
-
|
15
|
+
{
|
16
|
+
url: ContextualURL.call(host, node.xpath("./dav:href").text)
|
17
|
+
}.merge(
|
18
|
+
Parsers::CalendarXML.call(node)
|
19
|
+
)
|
15
20
|
)
|
16
21
|
end
|
17
22
|
|
18
|
-
def initialize(
|
19
|
-
@
|
20
|
-
@display_name = attributes[:display_name]
|
21
|
-
@description = attributes[:description]
|
22
|
-
@ctag = attributes[:ctag]
|
23
|
-
@etag = attributes[:etag]
|
24
|
-
@time_zone = attributes[:time_zone]
|
25
|
-
@color = attributes[:color]
|
26
|
-
@components = attributes[:components]
|
27
|
-
@reports = attributes[:reports]
|
28
|
-
@sync_token = attributes[:sync_token]
|
23
|
+
def initialize(attributes = {})
|
24
|
+
@attributes = attributes
|
29
25
|
end
|
26
|
+
|
27
|
+
ATTRIBUTES.each do |attribute|
|
28
|
+
define_method(attribute) { attributes[attribute] }
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_h
|
32
|
+
attributes.dup
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_reader :attributes
|
30
38
|
end
|
31
39
|
end
|
data/lib/calendav/endpoint.rb
CHANGED
data/lib/calendav/event.rb
CHANGED
@@ -5,19 +5,28 @@ require_relative "./parsers/event_xml"
|
|
5
5
|
|
6
6
|
module Calendav
|
7
7
|
class Event
|
8
|
-
|
8
|
+
ATTRIBUTES = %i[url calendar_data etag].freeze
|
9
9
|
|
10
10
|
def self.from_xml(host, node)
|
11
11
|
new(
|
12
|
-
|
13
|
-
|
12
|
+
{
|
13
|
+
url: ContextualURL.call(host, node.xpath("./dav:href").text)
|
14
|
+
}.merge(
|
15
|
+
Parsers::EventXML.call(node)
|
16
|
+
)
|
14
17
|
)
|
15
18
|
end
|
16
19
|
|
17
|
-
def initialize(
|
18
|
-
@
|
19
|
-
|
20
|
-
|
20
|
+
def initialize(attributes = {})
|
21
|
+
@attributes = attributes
|
22
|
+
end
|
23
|
+
|
24
|
+
ATTRIBUTES.each do |attribute|
|
25
|
+
define_method(attribute) { attributes[attribute] }
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_h
|
29
|
+
attributes.dup
|
21
30
|
end
|
22
31
|
|
23
32
|
def summary
|
@@ -38,6 +47,8 @@ module Calendav
|
|
38
47
|
|
39
48
|
private
|
40
49
|
|
50
|
+
attr_reader :attributes
|
51
|
+
|
41
52
|
def inner_calendar
|
42
53
|
Icalendar::Calendar.parse(calendar_data).first
|
43
54
|
end
|
@@ -17,7 +17,7 @@ module Calendav
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def call
|
20
|
-
SyncCollection.new(events, deleted_urls, token)
|
20
|
+
SyncCollection.new(events, deleted_urls, token, more?)
|
21
21
|
end
|
22
22
|
|
23
23
|
private
|
@@ -40,11 +40,23 @@ module Calendav
|
|
40
40
|
@calendar_path ||= URI(calendar_url).path
|
41
41
|
end
|
42
42
|
|
43
|
+
def calendar_response
|
44
|
+
multi_response
|
45
|
+
.detect { |node| node.xpath("./dav:href").text == calendar_path }
|
46
|
+
end
|
47
|
+
|
43
48
|
def individual_responses
|
44
49
|
multi_response
|
45
50
|
.reject { |node| node.xpath("./dav:href").text == calendar_path }
|
46
51
|
end
|
47
52
|
|
53
|
+
def more?
|
54
|
+
return false if calendar_response.nil?
|
55
|
+
|
56
|
+
status = calendar_response.xpath("./dav:propstat/dav:status").text
|
57
|
+
!status["507 Insufficient Storage"].nil?
|
58
|
+
end
|
59
|
+
|
48
60
|
def token
|
49
61
|
multi_response.xpath("/dav:multistatus/dav:sync-token").text
|
50
62
|
end
|
@@ -2,12 +2,17 @@
|
|
2
2
|
|
3
3
|
module Calendav
|
4
4
|
class SyncCollection
|
5
|
-
attr_reader :changes, :deletions, :sync_token
|
5
|
+
attr_reader :changes, :deletions, :sync_token, :more
|
6
6
|
|
7
|
-
def initialize(changes, deletions, sync_token)
|
7
|
+
def initialize(changes, deletions, sync_token, more)
|
8
8
|
@changes = changes
|
9
9
|
@deletions = deletions
|
10
10
|
@sync_token = sync_token
|
11
|
+
@more = more
|
12
|
+
end
|
13
|
+
|
14
|
+
def more?
|
15
|
+
more
|
11
16
|
end
|
12
17
|
end
|
13
18
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "google/apis/calendar_v3"
|
3
4
|
require "googleauth"
|
4
5
|
require "icalendar"
|
5
6
|
require "securerandom"
|
@@ -12,20 +13,22 @@ RSpec.describe "Google" do
|
|
12
13
|
let(:username) { ENV.fetch("GOOGLE_USERNAME") }
|
13
14
|
let(:access_token) { @access_token }
|
14
15
|
let(:credentials) { Calendav.credentials(provider, username, access_token) }
|
16
|
+
let(:google_auth) { @google_auth }
|
15
17
|
|
16
18
|
subject { Calendav.client(credentials) }
|
17
19
|
|
18
20
|
before :context do
|
21
|
+
@google_auth = Google::Auth::UserRefreshCredentials.new(
|
22
|
+
client_id: ENV.fetch("GOOGLE_CLIENT_ID"),
|
23
|
+
scope: [],
|
24
|
+
client_secret: ENV.fetch("GOOGLE_CLIENT_SECRET"),
|
25
|
+
refresh_token: ENV.fetch("GOOGLE_REFRESH_TOKEN"),
|
26
|
+
additional_parameters: { "access_type" => "offline" }
|
27
|
+
)
|
28
|
+
|
19
29
|
@access_token = begin
|
20
|
-
|
21
|
-
|
22
|
-
scope: [],
|
23
|
-
client_secret: ENV.fetch("GOOGLE_CLIENT_SECRET"),
|
24
|
-
refresh_token: ENV.fetch("GOOGLE_REFRESH_TOKEN"),
|
25
|
-
additional_parameters: { "access_type" => "offline" }
|
26
|
-
)
|
27
|
-
credentials.fetch_access_token!
|
28
|
-
credentials.access_token
|
30
|
+
@google_auth.fetch_access_token!
|
31
|
+
@google_auth.access_token
|
29
32
|
end
|
30
33
|
end
|
31
34
|
|
@@ -61,15 +64,20 @@ RSpec.describe "Google" do
|
|
61
64
|
|
62
65
|
context "with a calendar" do
|
63
66
|
let(:calendars) { subject.calendars.list }
|
64
|
-
let(:calendar)
|
65
|
-
|
67
|
+
let(:calendar) { calendars.detect { |cal| cal.display_name == name } }
|
68
|
+
let(:name) { "Calendav Test #{Time.now.to_i}" }
|
69
|
+
let(:service) { Google::Apis::CalendarV3::CalendarService.new }
|
70
|
+
let(:entry) { Google::Apis::CalendarV3::Calendar.new(summary: name) }
|
71
|
+
|
72
|
+
before :each do
|
73
|
+
service.authorization = google_auth
|
74
|
+
|
75
|
+
result = service.insert_calendar entry
|
76
|
+
entry.update!(**result.to_h)
|
66
77
|
end
|
67
78
|
|
68
79
|
after :each do
|
69
|
-
|
70
|
-
.events
|
71
|
-
.list(calendar.url)
|
72
|
-
.each { |event| subject.events.delete(event.url) }
|
80
|
+
service.delete_calendar entry.id
|
73
81
|
end
|
74
82
|
|
75
83
|
it_behaves_like "supporting event management"
|
data/spec/acceptance/shared.rb
CHANGED
@@ -105,6 +105,9 @@ RSpec.shared_examples "supporting event management" do
|
|
105
105
|
|
106
106
|
expect(subject.events.find(event_url).summary).to eq("Coffee")
|
107
107
|
|
108
|
+
# Wait for server to catch up
|
109
|
+
sleep 1
|
110
|
+
|
108
111
|
# Updating with the old etag should fail
|
109
112
|
expect(
|
110
113
|
subject.events.update(
|
@@ -139,6 +142,7 @@ RSpec.shared_examples "supporting event management" do
|
|
139
142
|
.to match_encoded_urls([first_url, second_url])
|
140
143
|
|
141
144
|
expect(collection.deletions).to be_empty
|
145
|
+
expect(collection.more?).to eq(false)
|
142
146
|
|
143
147
|
subject.events.update(first_url, update_summary(first, "Brunch"))
|
144
148
|
subject.events.delete(second_url)
|
@@ -150,6 +154,7 @@ RSpec.shared_examples "supporting event management" do
|
|
150
154
|
|
151
155
|
expect(collection.deletions.length).to eq(1)
|
152
156
|
expect(collection.deletions.first).to eq_encoded_url(second_url)
|
157
|
+
expect(collection.more?).to eq(false)
|
153
158
|
|
154
159
|
subject.events.delete(first_url)
|
155
160
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: calendav
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pat Allan
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: google-api-client
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: googleauth
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|