cal-invite 0.1.5 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rdoc_options +6 -3
- data/AGENTS.md +47 -0
- data/CHANGELOG.md +35 -0
- data/CLAUDE.md +49 -0
- data/CONFIGURATION.md +536 -0
- data/README.md +18 -7
- data/SECURITY.md +21 -0
- data/gemfiles/Gemfile.rails6 +3 -0
- data/gemfiles/Gemfile.rails7 +3 -0
- data/gemfiles/Gemfile.rails8 +3 -0
- data/lib/cal_invite/event.rb +103 -9
- data/lib/cal_invite/ical_timezone.rb +132 -0
- data/lib/cal_invite/providers/base_provider.rb +188 -4
- data/lib/cal_invite/providers/google.rb +4 -0
- data/lib/cal_invite/providers/ical.rb +23 -24
- data/lib/cal_invite/providers/ics.rb +30 -18
- data/lib/cal_invite/providers/ics_content.rb +33 -22
- data/lib/cal_invite/providers/office365.rb +8 -4
- data/lib/cal_invite/providers/outlook.rb +9 -5
- data/lib/cal_invite/version.rb +1 -1
- data/lib/cal_invite.rb +4 -0
- metadata +69 -8
|
@@ -46,9 +46,15 @@ module CalInvite
|
|
|
46
46
|
"VERSION:2.0",
|
|
47
47
|
"PRODID:-//CalInvite//EN",
|
|
48
48
|
"CALSCALE:GREGORIAN",
|
|
49
|
-
"METHOD
|
|
49
|
+
"METHOD:#{method_value}"
|
|
50
50
|
]
|
|
51
51
|
|
|
52
|
+
calendar_lines << "X-WR-CALNAME:#{escape_text(event.calendar_name)}" if event.calendar_name
|
|
53
|
+
|
|
54
|
+
unless event.all_day
|
|
55
|
+
calendar_lines.concat(vtimezone_lines || [])
|
|
56
|
+
end
|
|
57
|
+
|
|
52
58
|
if event.all_day
|
|
53
59
|
calendar_lines.concat(generate_all_day_event)
|
|
54
60
|
elsif event.multi_day_sessions.any?
|
|
@@ -71,7 +77,7 @@ module CalInvite
|
|
|
71
77
|
def generate_all_day_event
|
|
72
78
|
vevent = [
|
|
73
79
|
"BEGIN:VEVENT",
|
|
74
|
-
"UID:#{
|
|
80
|
+
"UID:#{event.uid}",
|
|
75
81
|
"DTSTAMP:#{format_timestamp(Time.now.utc)}",
|
|
76
82
|
"DTSTART;VALUE=DATE:#{format_date(event.start_time)}",
|
|
77
83
|
"DTEND;VALUE=DATE:#{format_date(event.end_time)}",
|
|
@@ -90,7 +96,7 @@ module CalInvite
|
|
|
90
96
|
def generate_vevent(start_time, end_time)
|
|
91
97
|
vevent = [
|
|
92
98
|
"BEGIN:VEVENT",
|
|
93
|
-
"UID:#{
|
|
99
|
+
"UID:#{event.uid}",
|
|
94
100
|
"DTSTAMP:#{format_timestamp(Time.now.utc)}",
|
|
95
101
|
"DTSTART;TZID=#{event.timezone}:#{format_local_timestamp(start_time)}",
|
|
96
102
|
"DTEND;TZID=#{event.timezone}:#{format_local_timestamp(end_time)}",
|
|
@@ -102,7 +108,8 @@ module CalInvite
|
|
|
102
108
|
end
|
|
103
109
|
|
|
104
110
|
# Adds optional fields to the event component if they exist.
|
|
105
|
-
# Handles description, location, URL,
|
|
111
|
+
# Handles description, location, URL, geo, organizer, attendees, recurrence,
|
|
112
|
+
# visibility/busy status, and reminders.
|
|
106
113
|
#
|
|
107
114
|
# @param vevent [Array<String>] The current event lines array
|
|
108
115
|
# @return [void]
|
|
@@ -121,11 +128,23 @@ module CalInvite
|
|
|
121
128
|
vevent << "URL:#{escape_text(url)}"
|
|
122
129
|
end
|
|
123
130
|
|
|
124
|
-
if
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
131
|
+
vevent << geo_line if geo_line
|
|
132
|
+
|
|
133
|
+
if organizer = organizer_line
|
|
134
|
+
vevent << organizer
|
|
128
135
|
end
|
|
136
|
+
|
|
137
|
+
attendees_list.each { |attendee| vevent << attendee_line(attendee) }
|
|
138
|
+
|
|
139
|
+
vevent << rrule_line if rrule_line
|
|
140
|
+
vevent << "SEQUENCE:#{event.sequence}"
|
|
141
|
+
vevent << status_line
|
|
142
|
+
vevent << transp_line
|
|
143
|
+
vevent << busystatus_line
|
|
144
|
+
vevent << class_line
|
|
145
|
+
vevent.concat(importance_lines)
|
|
146
|
+
vevent << disallow_counter_line if disallow_counter_line
|
|
147
|
+
vevent.concat(valarm_lines)
|
|
129
148
|
end
|
|
130
149
|
|
|
131
150
|
# Formats a time object as an UTC timestamp in iCalendar format.
|
|
@@ -145,20 +164,13 @@ module CalInvite
|
|
|
145
164
|
end
|
|
146
165
|
|
|
147
166
|
# Formats a time object as a local timestamp in iCalendar format.
|
|
148
|
-
#
|
|
167
|
+
# Converts from UTC to the event's timezone; times are expected to be in
|
|
168
|
+
# UTC already.
|
|
149
169
|
#
|
|
150
170
|
# @param time [Time] The time to format
|
|
151
171
|
# @return [String] The formatted local time (YYYYMMDDTHHmmSS)
|
|
152
172
|
def format_local_timestamp(time)
|
|
153
|
-
time.strftime("%Y%m%dT%H%M%S")
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
# Generates a unique identifier for the calendar event.
|
|
157
|
-
# Format: timestamp-randomhex@cal-invite
|
|
158
|
-
#
|
|
159
|
-
# @return [String] The generated UID
|
|
160
|
-
def generate_uid
|
|
161
|
-
"#{Time.now.to_i}-#{SecureRandom.hex(8)}@cal-invite"
|
|
173
|
+
local_wall_time(time).strftime("%Y%m%dT%H%M%S")
|
|
162
174
|
end
|
|
163
175
|
|
|
164
176
|
# Escapes special characters in text according to iCalendar spec.
|
|
@@ -36,9 +36,11 @@ module CalInvite
|
|
|
36
36
|
"VERSION:2.0",
|
|
37
37
|
"PRODID:-//CalInvite//EN",
|
|
38
38
|
"CALSCALE:GREGORIAN",
|
|
39
|
-
"METHOD
|
|
39
|
+
"METHOD:#{method_value}"
|
|
40
40
|
]
|
|
41
41
|
|
|
42
|
+
calendar_lines << "X-WR-CALNAME:#{escape_text(event.calendar_name)}" if event.calendar_name
|
|
43
|
+
|
|
42
44
|
if event.multi_day_sessions.any?
|
|
43
45
|
event.multi_day_sessions.each do |session|
|
|
44
46
|
calendar_lines.concat(generate_vevent(session[:start_time], session[:end_time]))
|
|
@@ -61,7 +63,7 @@ module CalInvite
|
|
|
61
63
|
def generate_vevent(start_time, end_time)
|
|
62
64
|
[
|
|
63
65
|
"BEGIN:VEVENT",
|
|
64
|
-
"UID:#{
|
|
66
|
+
"UID:#{event.uid}",
|
|
65
67
|
"DTSTAMP:#{format_timestamp(Time.now.utc)}",
|
|
66
68
|
"DTSTART:#{format_timestamp(start_time)}",
|
|
67
69
|
"DTEND:#{format_timestamp(end_time)}",
|
|
@@ -69,7 +71,18 @@ module CalInvite
|
|
|
69
71
|
description_line,
|
|
70
72
|
location_line,
|
|
71
73
|
url_line,
|
|
74
|
+
geo_line,
|
|
75
|
+
organizer_line,
|
|
72
76
|
attendee_lines,
|
|
77
|
+
rrule_line,
|
|
78
|
+
"SEQUENCE:#{event.sequence}",
|
|
79
|
+
status_line,
|
|
80
|
+
transp_line,
|
|
81
|
+
busystatus_line,
|
|
82
|
+
class_line,
|
|
83
|
+
importance_lines,
|
|
84
|
+
disallow_counter_line,
|
|
85
|
+
valarm_lines,
|
|
73
86
|
"END:VEVENT"
|
|
74
87
|
].compact
|
|
75
88
|
end
|
|
@@ -82,14 +95,6 @@ module CalInvite
|
|
|
82
95
|
time.utc.strftime("%Y%m%dT%H%M%SZ")
|
|
83
96
|
end
|
|
84
97
|
|
|
85
|
-
# Generates a unique identifier for the calendar event.
|
|
86
|
-
# Format: timestamp-randomhex@cal-invite
|
|
87
|
-
#
|
|
88
|
-
# @return [String] The generated UID
|
|
89
|
-
def generate_uid
|
|
90
|
-
"#{Time.now.to_i}-#{SecureRandom.hex(8)}@cal-invite"
|
|
91
|
-
end
|
|
92
|
-
|
|
93
98
|
# Escapes special characters in text according to iCalendar spec.
|
|
94
99
|
#
|
|
95
100
|
# @param text [String, nil] The text to escape
|
|
@@ -131,8 +136,8 @@ module CalInvite
|
|
|
131
136
|
#
|
|
132
137
|
# @return [Array<String>, nil] Array of ATTENDEE lines, or nil if no attendees or not showing
|
|
133
138
|
def attendee_lines
|
|
134
|
-
return nil
|
|
135
|
-
|
|
139
|
+
return nil if attendees_list.empty?
|
|
140
|
+
attendees_list.map { |attendee| attendee_line(attendee) }
|
|
136
141
|
end
|
|
137
142
|
end
|
|
138
143
|
|
|
@@ -142,10 +147,19 @@ module CalInvite
|
|
|
142
147
|
# Generates appropriate HTTP headers for ICS file download.
|
|
143
148
|
#
|
|
144
149
|
# @param filename [String] The desired filename for the download
|
|
150
|
+
# @param method [Symbol, nil] The iCalendar METHOD used to generate the content
|
|
151
|
+
# (:publish or :request). When given, it's added as a `method` parameter on
|
|
152
|
+
# the Content-Type header — this is what lets mail clients (Gmail, Outlook,
|
|
153
|
+
# Apple Mail) recognize the attachment as a meeting invite and render RSVP
|
|
154
|
+
# actions instead of a plain file attachment. Must match the METHOD in the
|
|
155
|
+
# .ics content itself.
|
|
145
156
|
# @return [Hash] HTTP headers for the ICS file download
|
|
146
|
-
def self.headers(filename)
|
|
157
|
+
def self.headers(filename, method: nil)
|
|
158
|
+
content_type = 'text/calendar; charset=UTF-8'
|
|
159
|
+
content_type += "; method=#{method == :decline_counter ? 'DECLINECOUNTER' : method.to_s.upcase}" if method
|
|
160
|
+
|
|
147
161
|
{
|
|
148
|
-
'Content-Type' =>
|
|
162
|
+
'Content-Type' => content_type,
|
|
149
163
|
'Content-Disposition' => "attachment; filename=#{sanitize_filename(filename)}"
|
|
150
164
|
}
|
|
151
165
|
end
|
|
@@ -162,23 +176,20 @@ module CalInvite
|
|
|
162
176
|
#
|
|
163
177
|
# @param content [String] The ICS calendar content
|
|
164
178
|
# @param title [String] The event title to use in the filename
|
|
179
|
+
# @param method [Symbol, nil] The iCalendar METHOD used to generate `content`
|
|
180
|
+
# (:publish or :request); forwarded to {headers}. Must match the METHOD
|
|
181
|
+
# used when generating `content` itself.
|
|
165
182
|
# @return [Hash] Hash containing content and headers for download
|
|
166
183
|
# @example
|
|
167
184
|
# result = IcsDownload.wrap_for_download(ics_content, "team-meeting")
|
|
168
185
|
# # => { content: "BEGIN:VCALENDAR...", headers: { 'Content-Type' => '...' } }
|
|
169
|
-
def self.wrap_for_download(content, title)
|
|
186
|
+
def self.wrap_for_download(content, title, method: nil)
|
|
170
187
|
filename = sanitize_filename("#{title.downcase}_#{Time.now.strftime('%Y%m%d')}.ics")
|
|
171
188
|
{
|
|
172
189
|
content: content,
|
|
173
|
-
headers: headers(filename)
|
|
190
|
+
headers: headers(filename, method: method)
|
|
174
191
|
}
|
|
175
192
|
end
|
|
176
193
|
end
|
|
177
|
-
|
|
178
|
-
# Compatibility class aliases
|
|
179
|
-
# @api private
|
|
180
|
-
class Ics < IcsContent; end
|
|
181
|
-
# @api private
|
|
182
|
-
class Ical < IcsContent; end
|
|
183
194
|
end
|
|
184
195
|
end
|
|
@@ -52,6 +52,7 @@ module CalInvite
|
|
|
52
52
|
params = {
|
|
53
53
|
subject: url_encode(event.title),
|
|
54
54
|
path: '/calendar/action/compose',
|
|
55
|
+
rru: 'addevent',
|
|
55
56
|
allday: 'true'
|
|
56
57
|
}
|
|
57
58
|
|
|
@@ -73,7 +74,8 @@ module CalInvite
|
|
|
73
74
|
def generate_single_event
|
|
74
75
|
params = {
|
|
75
76
|
subject: url_encode(event.title),
|
|
76
|
-
path: '/calendar/action/compose'
|
|
77
|
+
path: '/calendar/action/compose',
|
|
78
|
+
rru: 'addevent'
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
raise ArgumentError, "Start time is required" unless event.start_time
|
|
@@ -115,10 +117,12 @@ module CalInvite
|
|
|
115
117
|
params[:body] = url_encode(description_parts.join("\n\n")) if description_parts.any?
|
|
116
118
|
params[:location] = url_encode(format_location) if format_location
|
|
117
119
|
|
|
118
|
-
if
|
|
119
|
-
params[:to] = url_encode(
|
|
120
|
+
if attendees_list.any?
|
|
121
|
+
params[:to] = url_encode(attendee_emails.join(';'))
|
|
120
122
|
end
|
|
121
123
|
|
|
124
|
+
params[:freebusy] = event.busy ? 'busy' : 'free' unless event.busy.nil?
|
|
125
|
+
|
|
122
126
|
params
|
|
123
127
|
end
|
|
124
128
|
|
|
@@ -128,7 +132,7 @@ module CalInvite
|
|
|
128
132
|
# @return [String] The complete Office 365 calendar URL
|
|
129
133
|
def build_url(params)
|
|
130
134
|
query = params.map { |k, v| "#{k}=#{v}" }.join('&')
|
|
131
|
-
"https://outlook.office.com/
|
|
135
|
+
"https://outlook.office.com/calendar/deeplink/compose?#{query}"
|
|
132
136
|
end
|
|
133
137
|
end
|
|
134
138
|
end
|
|
@@ -55,7 +55,8 @@ module CalInvite
|
|
|
55
55
|
# @return [String] The Outlook.com calendar URL for an all-day event
|
|
56
56
|
def generate_all_day_event
|
|
57
57
|
params = {
|
|
58
|
-
path: '/calendar/
|
|
58
|
+
path: '/calendar/action/compose',
|
|
59
|
+
rru: 'addevent',
|
|
59
60
|
subject: url_encode(event.title),
|
|
60
61
|
allday: 'true'
|
|
61
62
|
}
|
|
@@ -77,7 +78,8 @@ module CalInvite
|
|
|
77
78
|
# @raise [ArgumentError] If start_time or end_time is missing
|
|
78
79
|
def generate_single_event
|
|
79
80
|
params = {
|
|
80
|
-
path: '/calendar/
|
|
81
|
+
path: '/calendar/action/compose',
|
|
82
|
+
rru: 'addevent',
|
|
81
83
|
subject: url_encode(event.title)
|
|
82
84
|
}
|
|
83
85
|
|
|
@@ -120,10 +122,12 @@ module CalInvite
|
|
|
120
122
|
params[:body] = url_encode(description_parts.join("\n\n")) if description_parts.any?
|
|
121
123
|
params[:location] = url_encode(format_location) if format_location
|
|
122
124
|
|
|
123
|
-
if
|
|
124
|
-
params[:to] = url_encode(
|
|
125
|
+
if attendees_list.any?
|
|
126
|
+
params[:to] = url_encode(attendee_emails.join(';'))
|
|
125
127
|
end
|
|
126
128
|
|
|
129
|
+
params[:freebusy] = event.busy ? 'busy' : 'free' unless event.busy.nil?
|
|
130
|
+
|
|
127
131
|
params
|
|
128
132
|
end
|
|
129
133
|
|
|
@@ -133,7 +137,7 @@ module CalInvite
|
|
|
133
137
|
# @return [String] The complete Outlook.com calendar URL
|
|
134
138
|
def build_url(params)
|
|
135
139
|
query = params.map { |k, v| "#{k}=#{v}" }.join('&')
|
|
136
|
-
"https://outlook.live.com/calendar/
|
|
140
|
+
"https://outlook.live.com/calendar/deeplink/compose?#{query}"
|
|
137
141
|
end
|
|
138
142
|
end
|
|
139
143
|
end
|
data/lib/cal_invite/version.rb
CHANGED
data/lib/cal_invite.rb
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
# lib/cal_invite.rb
|
|
2
|
+
require 'logger'
|
|
3
|
+
require 'mutex_m'
|
|
4
|
+
require 'bigdecimal'
|
|
2
5
|
require 'active_support'
|
|
3
6
|
require 'active_support/core_ext'
|
|
4
7
|
require 'securerandom'
|
|
@@ -8,6 +11,7 @@ require 'uri'
|
|
|
8
11
|
require 'cal_invite/version'
|
|
9
12
|
require 'cal_invite/configuration'
|
|
10
13
|
require 'cal_invite/caching'
|
|
14
|
+
require 'cal_invite/ical_timezone'
|
|
11
15
|
require 'cal_invite/event'
|
|
12
16
|
require 'cal_invite/providers'
|
|
13
17
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cal-invite
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stephane Paquet
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-08-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -24,20 +24,76 @@ dependencies:
|
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '6.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: tzinfo
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.2'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.2'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: logger
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: mutex_m
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: bigdecimal
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :runtime
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
27
83
|
- !ruby/object:Gem::Dependency
|
|
28
84
|
name: rdoc
|
|
29
85
|
requirement: !ruby/object:Gem::Requirement
|
|
30
86
|
requirements:
|
|
31
87
|
- - "~>"
|
|
32
88
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
89
|
+
version: '8.0'
|
|
34
90
|
type: :development
|
|
35
91
|
prerelease: false
|
|
36
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
93
|
requirements:
|
|
38
94
|
- - "~>"
|
|
39
95
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
96
|
+
version: '8.0'
|
|
41
97
|
description: CalInvite provides a simple way to generate calendar invite URLs for
|
|
42
98
|
various providers (Google, Outlook, Yahoo) and ICS files
|
|
43
99
|
email:
|
|
@@ -49,12 +105,16 @@ files:
|
|
|
49
105
|
- ".DS_Store"
|
|
50
106
|
- ".rdoc_options"
|
|
51
107
|
- ".rubocop.yml"
|
|
108
|
+
- AGENTS.md
|
|
52
109
|
- CACHING.md
|
|
53
110
|
- CHANGELOG.md
|
|
111
|
+
- CLAUDE.md
|
|
54
112
|
- CODE_OF_CONDUCT.md
|
|
113
|
+
- CONFIGURATION.md
|
|
55
114
|
- LICENSE.txt
|
|
56
115
|
- README.md
|
|
57
116
|
- Rakefile
|
|
117
|
+
- SECURITY.md
|
|
58
118
|
- gemfiles/Gemfile.rails6
|
|
59
119
|
- gemfiles/Gemfile.rails7
|
|
60
120
|
- gemfiles/Gemfile.rails8
|
|
@@ -64,6 +124,7 @@ files:
|
|
|
64
124
|
- lib/cal_invite/caching.rb
|
|
65
125
|
- lib/cal_invite/configuration.rb
|
|
66
126
|
- lib/cal_invite/event.rb
|
|
127
|
+
- lib/cal_invite/ical_timezone.rb
|
|
67
128
|
- lib/cal_invite/providers.rb
|
|
68
129
|
- lib/cal_invite/providers/base_provider.rb
|
|
69
130
|
- lib/cal_invite/providers/google.rb
|
|
@@ -76,13 +137,13 @@ files:
|
|
|
76
137
|
- lib/cal_invite/version.rb
|
|
77
138
|
- lib/tasks/rdoc.rake
|
|
78
139
|
- sig/cal/invite.rbs
|
|
79
|
-
homepage: https://github.com/
|
|
140
|
+
homepage: https://github.com/DashAPI-ai/cal-invite
|
|
80
141
|
licenses:
|
|
81
142
|
- MIT
|
|
82
143
|
metadata:
|
|
83
|
-
homepage_uri: https://github.com/
|
|
84
|
-
source_code_uri: https://github.com/
|
|
85
|
-
changelog_uri: https://github.com/
|
|
144
|
+
homepage_uri: https://github.com/DashAPI-ai/cal-invite
|
|
145
|
+
source_code_uri: https://github.com/DashAPI-ai/cal-invite
|
|
146
|
+
changelog_uri: https://github.com/DashAPI-ai/cal-invite/blob/master/CHANGELOG.md
|
|
86
147
|
post_install_message:
|
|
87
148
|
rdoc_options:
|
|
88
149
|
- "--title"
|