nylas 5.4.1 → 5.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29f07de83f9f9129d2604b28ad5efd02d21cdc81075e92b16129d6ebfb3509fc
4
- data.tar.gz: f1259c4907de58f04082c6c2e0a80a7d2d50b99a13efc70714f7370ead25d420
3
+ metadata.gz: 4d8d9639941076724b3e9ae95b85a2e4a48c8f663a35b03f5f26473c5c87b208
4
+ data.tar.gz: 4b2733e86538a6dd7ac3069dc5738997ea8db1b7be13b1a8de9bef5c868ec1d5
5
5
  SHA512:
6
- metadata.gz: 9117a61ff796ee58ee596d2ce7f1d41874a0f79f452d678f66dc768e8cf7db59580085f069946e4d4a634b47a85ebd4696f59b59960ecdec805c0244575bbc7a
7
- data.tar.gz: b53cedb0c8c2334da1f6e092819eea787ec4c856eafdb606ce29713605eed834044e780dfd6ed6fafc0ee47c6c1bfd48d947237dc4dd9a6d84d531c4c5cc1daf
6
+ metadata.gz: 56b9216d9e5f37a0c449d999891a76a06e1ed8dd8925efe5186d8d59d16105da76ea3b8a5599d88a9e8e83bd2862bc71cc7491957ac8c8da8718a825af2a2a2a
7
+ data.tar.gz: 5fa04ae09e9692f0c954926ae8e7d541388597a12a154dd8bf82b78c40e91b7b9b73508c5d39b6a2c604ed5d53f5eec86379687dc9b79da81b4a8571d0500460
data/lib/nylas/account.rb CHANGED
@@ -7,15 +7,18 @@ module Nylas
7
7
  include Model
8
8
  self.listable = true
9
9
  self.showable = true
10
+ self.updatable = true
11
+ self.destroyable = true
10
12
 
11
- attribute :id, :string
12
- attribute :account_id, :string
13
- attribute :billing_state, :string
14
- attribute :sync_state, :string
15
- attribute :provider, :string
13
+ attribute :id, :string, read_only: true
14
+ attribute :account_id, :string, read_only: true
15
+ attribute :billing_state, :string, read_only: true
16
+ attribute :sync_state, :string, read_only: true
17
+ attribute :provider, :string, read_only: true
16
18
 
17
- attribute :email, :string
18
- attribute :trial, :boolean
19
+ attribute :email, :string, read_only: true
20
+ attribute :trial, :boolean, read_only: true
21
+ attribute :metadata, :hash
19
22
 
20
23
  def upgrade
21
24
  response = execute(method: :post, path: "#{resource_path}/upgrade")
@@ -34,6 +37,15 @@ module Nylas
34
37
  response[:success]
35
38
  end
36
39
 
40
+ # Return information about an account's access token
41
+ # @param access_token [String] The access token to inquire about
42
+ # @return [TokenInfo] The access token information
43
+ def token_info(access_token)
44
+ payload = JSON.dump(access_token: access_token)
45
+ response = execute(method: :post, path: "#{resource_path}/token-info", payload: payload)
46
+ TokenInfo.new(**response)
47
+ end
48
+
37
49
  def self.resources_path(api:)
38
50
  "/a/#{api.app_id}/accounts"
39
51
  end
data/lib/nylas/api.rb CHANGED
@@ -48,7 +48,11 @@ module Nylas
48
48
  "#{api_server}/oauth/authorize?#{URI.encode_www_form(params)}"
49
49
  end
50
50
 
51
- def exchange_code_for_token(code)
51
+ # Exchanges an authorization code for an access token
52
+ # @param code [String] The authorization code to exchange
53
+ # @param return_full_response [Boolean] If true, returns the full response body instead of just the token
54
+ # @return [String | Hash] Returns just the access token as a string, or the full response as a hash
55
+ def exchange_code_for_token(code, return_full_response: false)
52
56
  data = {
53
57
  "client_id" => app_id,
54
58
  "client_secret" => client.app_secret,
@@ -56,8 +60,8 @@ module Nylas
56
60
  "code" => code
57
61
  }
58
62
 
59
- response_json = execute(method: :post, path: "/oauth/token", payload: data)
60
- response_json[:access_token]
63
+ response = execute(method: :post, path: "/oauth/token", payload: data)
64
+ return_full_response ? response : response[:access_token]
61
65
  end
62
66
 
63
67
  # @return [Collection<Contact>] A queryable collection of Contacts
@@ -81,9 +85,9 @@ module Nylas
81
85
  @accounts ||= Collection.new(model: Account, api: as(client.app_secret))
82
86
  end
83
87
 
84
- # @return [Collection<Calendar>] A queryable collection of {Calendar}s
88
+ # @return [CalendarCollection<Calendar>] A queryable collection of {Calendar}s
85
89
  def calendars
86
- @calendars ||= Collection.new(model: Calendar, api: self)
90
+ @calendars ||= CalendarCollection.new(model: Calendar, api: self)
87
91
  end
88
92
 
89
93
  # @return [DeltasCollection<Delta>] A queryable collection of Deltas, which are themselves a collection.
@@ -96,7 +100,7 @@ module Nylas
96
100
  @drafts ||= Collection.new(model: Draft, api: self)
97
101
  end
98
102
 
99
- # @return [Collection<Event>] A queryable collection of {Event}s
103
+ # @return [EventCollection<Event>] A queryable collection of {Event}s
100
104
  def events
101
105
  @events ||= EventCollection.new(model: Event, api: self)
102
106
  end
@@ -126,11 +130,29 @@ module Nylas
126
130
  @room_resources ||= Collection.new(model: RoomResource, api: self)
127
131
  end
128
132
 
133
+ # @return[Collection<JobStatus>] A queryable collection of {JobStatus} objects
134
+ def job_statuses
135
+ @job_statuses ||= Collection.new(model: JobStatus, api: self)
136
+ end
137
+
138
+ # @return[SchedulerCollection<Scheduler>] A queryable collection of {Scheduler} objects
139
+ def scheduler
140
+ # Make a deep copy of the API as the scheduler API uses a different base URL
141
+ scheduler_api = Marshal.load(Marshal.dump(self))
142
+ scheduler_api.client.api_server = "https://api.schedule.nylas.com"
143
+ @scheduler ||= SchedulerCollection.new(model: Scheduler, api: scheduler_api)
144
+ end
145
+
129
146
  # @return[Neural] A {Neural} object that provides
130
147
  def neural
131
148
  @neural ||= Neural.new(api: self)
132
149
  end
133
150
 
151
+ # @return [Collection<Component>] A queryable collection of {Component}s
152
+ def components
153
+ @components ||= ComponentCollection.new(model: Component, api: as(client.app_secret))
154
+ end
155
+
134
156
  # Revokes access to the Nylas API for the given access token
135
157
  # @return [Boolean]
136
158
  def revoke(access_token)
@@ -138,6 +160,25 @@ module Nylas
138
160
  response.code == 200 && response.empty?
139
161
  end
140
162
 
163
+ # Returns the application details
164
+ # @return [ApplicationDetail] The application details
165
+ def application_details
166
+ response = client.as(client.app_secret).execute(method: :get, path: "/a/#{app_id}")
167
+ ApplicationDetail.new(**response)
168
+ end
169
+
170
+ # Updates the application details
171
+ # @param application_details [ApplicationDetail] The updated application details
172
+ # @return [ApplicationDetails] The updated application details, returned from the server
173
+ def update_application_details(application_details)
174
+ response = client.as(client.app_secret).execute(
175
+ method: :put,
176
+ path: "/a/#{app_id}",
177
+ payload: JSON.dump(application_details.to_h)
178
+ )
179
+ ApplicationDetail.new(**response)
180
+ end
181
+
141
182
  # Returns list of IP addresses
142
183
  # @return [Hash]
143
184
  # hash has keys of :updated_at (unix timestamp) and :ip_addresses (array of strings)
@@ -155,7 +196,7 @@ module Nylas
155
196
  end
156
197
 
157
198
  # Allows you to get an API that acts as a different user but otherwise has the same settings
158
- # @param [String] Oauth Access token or app secret used to authenticate with the API
199
+ # @param access_token [String] Oauth Access token or app secret used to authenticate with the API
159
200
  # @return [API]
160
201
  def as(access_token)
161
202
  API.new(client: client.as(access_token))
@@ -171,6 +212,7 @@ module Nylas
171
212
  @webhooks ||= Collection.new(model: Webhook, api: as(client.app_secret))
172
213
  end
173
214
 
215
+ # TODO: Move this into calendar collection
174
216
  def free_busy(emails:, start_time:, end_time:)
175
217
  FreeBusyCollection.new(
176
218
  api: self,
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent a Nylas Application Detail object.
5
+ # @see https://developer.nylas.com/docs/api/#get/a/client_id
6
+ class ApplicationDetail
7
+ include Model::Attributable
8
+
9
+ attribute :application_name, :string
10
+ attribute :icon_url, :string
11
+ has_n_of_attribute :redirect_uris, :string
12
+ end
13
+ end
@@ -6,7 +6,8 @@ module Nylas
6
6
  class Calendar
7
7
  include Model
8
8
  self.resources_path = "/calendars"
9
- allows_operations(listable: true, filterable: true, showable: true)
9
+ allows_operations(creatable: true, listable: true, filterable: true, showable: true, updatable: true,
10
+ destroyable: true)
10
11
 
11
12
  attribute :id, :string
12
13
  attribute :account_id, :string
@@ -20,6 +21,8 @@ module Nylas
20
21
  attribute :timezone, :string
21
22
 
22
23
  attribute :read_only, :boolean
24
+ attribute :metadata, :hash
25
+ attribute :job_status_id, :string, read_only: true
23
26
 
24
27
  def read_only?
25
28
  read_only == true
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Additional methods for some of Calendar's other functionality
5
+ # @see https://developer.nylas.com/docs/connectivity/calendar
6
+ class CalendarCollection < Collection
7
+ def availability(duration_minutes:,
8
+ interval:,
9
+ start_time:,
10
+ end_time:,
11
+ emails:,
12
+ buffer: nil,
13
+ round_robin: nil,
14
+ free_busy: [],
15
+ open_hours: [])
16
+ validate_open_hours(emails, free_busy, open_hours) unless open_hours.empty?
17
+
18
+ execute_availability("/calendars/availability",
19
+ duration_minutes: duration_minutes,
20
+ interval: interval,
21
+ start_time: start_time,
22
+ end_time: end_time,
23
+ emails: emails,
24
+ buffer: buffer,
25
+ round_robin: round_robin,
26
+ free_busy: free_busy,
27
+ open_hours: open_hours)
28
+ end
29
+
30
+ def consecutive_availability(duration_minutes:,
31
+ interval:,
32
+ start_time:,
33
+ end_time:,
34
+ emails:,
35
+ buffer: nil,
36
+ free_busy: [],
37
+ open_hours: [])
38
+ validate_open_hours(emails, free_busy, open_hours) unless open_hours.empty?
39
+
40
+ execute_availability("/calendars/availability/consecutive",
41
+ duration_minutes: duration_minutes,
42
+ interval: interval,
43
+ start_time: start_time,
44
+ end_time: end_time,
45
+ emails: emails,
46
+ buffer: buffer,
47
+ free_busy: free_busy,
48
+ open_hours: open_hours)
49
+ end
50
+
51
+ private
52
+
53
+ def execute_availability(path, **payload)
54
+ api.execute(
55
+ method: :post,
56
+ path: path,
57
+ payload: JSON.dump(payload)
58
+ )
59
+ end
60
+
61
+ def validate_open_hours(emails, free_busy, open_hours)
62
+ raise TypeError, "open_hours' must be an array." unless open_hours.is_a?(Array)
63
+
64
+ open_hours_emails = map_open_hours_emails(open_hours)
65
+ free_busy_emails = map_free_busy_emails(free_busy)
66
+ emails = merge_arrays(emails) if emails[0].is_a?(Array)
67
+
68
+ open_hours_emails.each do |email|
69
+ next if emails.include?(email) || free_busy_emails.include?(email)
70
+
71
+ raise ArgumentError, "Open Hours cannot contain an email not present in the main email list or
72
+ the free busy email list."
73
+ end
74
+ end
75
+
76
+ def map_open_hours_emails(open_hours)
77
+ open_hours_emails = []
78
+ open_hours.map do |oh|
79
+ open_hours_emails += oh.emails
80
+ end
81
+ open_hours_emails
82
+ end
83
+
84
+ def map_free_busy_emails(free_busy)
85
+ free_busy_emails = []
86
+ free_busy.map do |fb|
87
+ free_busy_emails.append(fb.email)
88
+ end
89
+ free_busy_emails
90
+ end
91
+
92
+ def merge_arrays(array)
93
+ list = []
94
+ array.each do |x|
95
+ list += x
96
+ end
97
+ list
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent a the Component Schema.
5
+ class Component
6
+ include Model
7
+ allows_operations(creatable: true, listable: true, filterable: true, showable: true, updatable: true,
8
+ destroyable: true)
9
+
10
+ attribute :id, :string, read_only: true
11
+ attribute :account_id, :string
12
+ attribute :name, :string
13
+ attribute :type, :string
14
+ attribute :action, :integer
15
+ attribute :active, :boolean
16
+ attribute :settings, :hash
17
+ attribute :public_account_id, :string
18
+ attribute :public_token_id, :string
19
+ attribute :public_application_id, :string, read_only: true
20
+ attribute :access_token, :string
21
+ attribute :created_at, :date, read_only: true
22
+ attribute :updated_at, :date, read_only: true
23
+
24
+ has_n_of_attribute :allowed_domains, :string
25
+
26
+ def resources_path(*)
27
+ "/component/#{api.client.app_id}"
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Additional configuration for the Component CRUD API
5
+ class ComponentCollection < Collection
6
+ def resources_path
7
+ "/component/#{api.client.app_id}"
8
+ end
9
+ end
10
+ end
data/lib/nylas/contact.rb CHANGED
@@ -30,6 +30,7 @@ module Nylas
30
30
  attribute :office_location, :string
31
31
  attribute :notes, :string
32
32
  attribute :source, :string
33
+ attribute :job_status_id, :string, read_only: true
33
34
 
34
35
  has_n_of_attribute :groups, :contact_group
35
36
  has_n_of_attribute :emails, :email_address
data/lib/nylas/draft.rb CHANGED
@@ -27,6 +27,7 @@ module Nylas
27
27
  attribute :body, :string
28
28
  attribute :starred, :boolean
29
29
  attribute :unread, :boolean
30
+ attribute :metadata, :hash
30
31
 
31
32
  has_n_of_attribute :events, :event
32
33
  has_n_of_attribute :files, :file, read_only: true
@@ -35,6 +36,7 @@ module Nylas
35
36
  has_n_of_attribute :labels, :label
36
37
 
37
38
  attribute :tracking, :message_tracking
39
+ attribute :job_status_id, :string, read_only: true
38
40
 
39
41
  transfer :api, to: %i[events files folder labels]
40
42
 
@@ -75,18 +77,18 @@ module Nylas
75
77
  execute(method: :delete, path: resource_path, payload: attributes.serialize_for_api(keys: [:version]))
76
78
  end
77
79
 
78
- private
79
-
80
- def save_call
80
+ def save
81
81
  extract_file_ids!
82
82
 
83
83
  super
84
84
  end
85
85
 
86
+ private
87
+
86
88
  def extract_file_ids!
87
89
  files = self.files || []
88
90
 
89
- self.file_ids = files.map(&:id)
91
+ self.file_ids ||= files.map(&:id)
90
92
  end
91
93
  end
92
94
  end
data/lib/nylas/event.rb CHANGED
@@ -29,7 +29,9 @@ module Nylas
29
29
  attribute :when, :when
30
30
  attribute :metadata, :hash
31
31
  attribute :conferencing, :event_conferencing
32
+ has_n_of_attribute :notifications, :event_notification
32
33
  attribute :original_start_time, :unix_timestamp
34
+ attribute :job_status_id, :string, read_only: true
33
35
 
34
36
  attr_accessor :notify_participants
35
37
 
@@ -58,8 +60,47 @@ module Nylas
58
60
  rsvp.save
59
61
  end
60
62
 
63
+ # Generate an ICS file server-side, from an Event
64
+ # @param ical_uid [String] Unique identifier used events across calendaring systems
65
+ # @param method [String] Description of invitation and response methods for attendees
66
+ # @param prodid [String] Company-specific unique product identifier
67
+ # @return [String] String for writing directly into an ICS file
68
+ def generate_ics(ical_uid: nil, method: nil, prodid: nil)
69
+ raise ArgumentError, "Cannot generate an ICS file for an event without a Calendar ID or when set" unless
70
+ calendar_id && self.when
71
+
72
+ payload = build_ics_event_payload(ical_uid, method, prodid)
73
+ response = api.execute(
74
+ method: :post,
75
+ path: "#{resources_path}/to-ics",
76
+ payload: JSON.dump(payload)
77
+ )
78
+
79
+ response[:ics]
80
+ end
81
+
61
82
  private
62
83
 
84
+ def build_ics_event_payload(ical_uid, method, prodid)
85
+ payload = {}
86
+ if id
87
+ payload[:event_id] = id
88
+ else
89
+ payload = to_h(enforce_read_only: true)
90
+ end
91
+ ics_options = build_ics_options_payload(ical_uid, method, prodid)
92
+ payload["ics_options"] = ics_options unless ics_options.empty?
93
+ payload
94
+ end
95
+
96
+ def build_ics_options_payload(ical_uid, method, prodid)
97
+ payload = {}
98
+ payload["ical_uid"] = ical_uid if ical_uid
99
+ payload["method"] = method if method
100
+ payload["prodid"] = prodid if prodid
101
+ payload
102
+ end
103
+
63
104
  def query_params
64
105
  if notify_participants.nil?
65
106
  {}
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent the Event Notification object
5
+ # @see https://developer.nylas.com/docs/connectivity/calendar/event-notifications
6
+ class EventNotification
7
+ include Model::Attributable
8
+
9
+ attribute :type, :string
10
+ attribute :minutes_before_event, :integer
11
+ attribute :url, :string
12
+ attribute :payload, :string
13
+ attribute :subject, :string
14
+ attribute :body, :string
15
+ attribute :message, :string
16
+ end
17
+ end
data/lib/nylas/file.rb CHANGED
@@ -6,7 +6,7 @@ module Nylas
6
6
  class File
7
7
  include Model
8
8
  self.resources_path = "/files"
9
- allows_operations(listable: true, showable: true, filterable: true, creatable: true)
9
+ allows_operations(listable: true, showable: true, filterable: true, creatable: true, destroyable: true)
10
10
 
11
11
  attribute :id, :string
12
12
  attribute :account_id, :string
data/lib/nylas/folder.rb CHANGED
@@ -13,12 +13,12 @@ module Nylas
13
13
  self.updatable = true
14
14
  self.destroyable = true
15
15
 
16
- attribute :id, :string
17
- attribute :account_id, :string
18
-
19
- attribute :object, :string
16
+ attribute :id, :string, read_only: true
17
+ attribute :account_id, :string, read_only: true
18
+ attribute :object, :string, read_only: true
20
19
 
21
20
  attribute :name, :string
22
21
  attribute :display_name, :string
22
+ attribute :job_status_id, :string, read_only: true
23
23
  end
24
24
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Ruby representation of a Nylas Job Status object
5
+ # @see https://developer.nylas.com/docs/api/#tag--Job-Status
6
+ class JobStatus
7
+ include Model
8
+ self.resources_path = "/job-statuses"
9
+ allows_operations(listable: true)
10
+
11
+ attribute :id, :string, read_only: true
12
+ attribute :account_id, :string, read_only: true
13
+ attribute :job_status_id, :string, read_only: true
14
+ attribute :action, :string, read_only: true
15
+ attribute :object, :string, read_only: true
16
+ attribute :status, :string, read_only: true
17
+ attribute :created_at, :unix_timestamp, read_only: true
18
+ attribute :original_data, :message, read_only: true
19
+
20
+ # Returns the status of a job as a boolean
21
+ # @return [Boolean] If the job was successful
22
+ def successful?
23
+ status == "successful"
24
+ end
25
+ end
26
+ end
data/lib/nylas/label.rb CHANGED
@@ -20,5 +20,6 @@ module Nylas
20
20
 
21
21
  attribute :name, :string
22
22
  attribute :display_name, :string
23
+ attribute :job_status_id, :string, read_only: true
23
24
  end
24
25
  end
data/lib/nylas/message.rb CHANGED
@@ -8,7 +8,7 @@ module Nylas
8
8
  self.raw_mime_type = "message/rfc822"
9
9
  self.resources_path = "/messages"
10
10
  allows_operations(showable: true, listable: true, filterable: true, searchable: true, updatable: true)
11
- UPDATABLE_ATTRIBUTES = %i[label_ids folder_id starred unread].freeze
11
+ UPDATABLE_ATTRIBUTES = %i[label_ids folder_id starred unread metadata].freeze
12
12
 
13
13
  attribute :id, :string
14
14
  attribute :object, :string
@@ -36,6 +36,8 @@ module Nylas
36
36
  has_n_of_attribute :files, :file
37
37
  attribute :folder, :folder
38
38
  attribute :folder_id, :string
39
+ attribute :metadata, :hash
40
+ attribute :job_status_id, :string, read_only: true
39
41
 
40
42
  has_n_of_attribute :labels, :label, read_only: true
41
43
  has_n_of_attribute :label_ids, :string
@@ -72,14 +74,10 @@ module Nylas
72
74
  self
73
75
  end
74
76
 
75
- def save_call
77
+ def save
76
78
  handle_folder
77
79
 
78
- execute(
79
- method: :put,
80
- payload: attributes.serialize_for_api,
81
- path: resource_path
82
- )
80
+ super
83
81
  end
84
82
 
85
83
  def handle_folder
@@ -17,8 +17,8 @@ module Nylas
17
17
  end
18
18
 
19
19
  # @return [Hash] Representation of the model with values serialized into primitives based on their Type
20
- def to_h
21
- attributes.to_h
20
+ def to_h(enforce_read_only: false)
21
+ attributes.to_h(enforce_read_only: enforce_read_only)
22
22
  end
23
23
 
24
24
  protected
@@ -5,7 +5,7 @@ module Nylas
5
5
  # Define a particular attribute for a given model
6
6
  class AttributeDefinition
7
7
  extend Forwardable
8
- def_delegators :type, :cast, :serialize
8
+ def_delegators :type, :cast, :serialize, :serialize_for_api
9
9
  attr_accessor :type_name, :read_only, :default
10
10
 
11
11
  def initialize(type_name:, read_only:, default:)
@@ -28,23 +28,34 @@ module Nylas
28
28
  end
29
29
  end
30
30
 
31
- def to_h(keys: attribute_definitions.keys)
32
- keys.each_with_object({}) do |key, casted_data|
33
- value = attribute_definitions[key].serialize(self[key])
31
+ # Convert the object to hash
32
+ # @param keys [Array<String>] The keys included
33
+ # @param enforce_read_only [Boolean] Whether to enforce read_only property (serializing for API)
34
+ # @return [Hash] The hash representation of the object
35
+ def to_h(keys: attribute_definitions.keys, enforce_read_only: false)
36
+ casted_data = {}
37
+ keys.each do |key|
38
+ value = attribute_to_hash(key, enforce_read_only)
34
39
  # If the value is an empty hash but we specify that it is valid (via default value), serialize it
35
40
  casted_data[key] = value unless value.nil? || (value.respond_to?(:empty?) && value.empty? &&
36
41
  !(attribute_definitions[key].default == value && value.is_a?(Hash)))
37
42
  end
43
+ casted_data
38
44
  end
39
45
 
40
- def serialize(keys: attribute_definitions.keys)
41
- JSON.dump(to_h(keys: keys))
46
+ # Serialize the object
47
+ # @param keys [Array<String>] The keys included
48
+ # @param enforce_read_only [Boolean] Whether to enforce read_only property (serializing for API)
49
+ # @return [String] The serialized object as a JSON string
50
+ def serialize(keys: attribute_definitions.keys, enforce_read_only: false)
51
+ JSON.dump(to_h(keys: keys, enforce_read_only: enforce_read_only))
42
52
  end
43
53
 
54
+ # Serialize the object to an API-compatible JSON string
55
+ # @param keys [Array<String>] The keys included
56
+ # @return [String] The serialized object as a JSON string
44
57
  def serialize_for_api(keys: attribute_definitions.keys)
45
- api_keys = keys.delete_if { |key| attribute_definitions[key].read_only == true }
46
-
47
- serialize(keys: api_keys)
58
+ serialize(keys: keys, enforce_read_only: true)
48
59
  end
49
60
 
50
61
  def serialize_all_for_api(keys: attribute_definitions.keys)
@@ -68,6 +79,19 @@ module Nylas
68
79
  def default_attributes
69
80
  attribute_definitions.keys.zip([]).to_h
70
81
  end
82
+
83
+ # Convert the attribute value as a hash
84
+ # @param key [String] The attribute's key
85
+ # @param enforce_read_only [Boolean] Whether to enforce read_only property (serializing for API)
86
+ # @return [nil | Hash] The appropriately serialized value
87
+ def attribute_to_hash(key, enforce_read_only)
88
+ attribute_definition = attribute_definitions[key]
89
+ if enforce_read_only
90
+ attribute_definition.read_only == true ? nil : attribute_definition.serialize_for_api(self[key])
91
+ else
92
+ attribute_definition.serialize(self[key])
93
+ end
94
+ end
71
95
  end
72
96
  end
73
97
  end
@@ -18,9 +18,17 @@ module Nylas
18
18
  list.map { |item| type.cast(item) }
19
19
  end
20
20
 
21
- def serialize(list)
21
+ def serialize(list, enforce_read_only: false)
22
22
  list = default if list.nil? || list.empty?
23
- list.map { |item| type.serialize(item) }
23
+ if enforce_read_only
24
+ list.map { |item| type.serialize_for_api(item) }
25
+ else
26
+ list.map { |item| type.serialize(item) }
27
+ end
28
+ end
29
+
30
+ def serialize_for_api(list)
31
+ serialize(list, enforce_read_only: true)
24
32
  end
25
33
 
26
34
  def type
data/lib/nylas/model.rb CHANGED
@@ -28,7 +28,7 @@ module Nylas
28
28
  result = if persisted?
29
29
  raise ModelNotUpdatableError, self unless updatable?
30
30
 
31
- save_call
31
+ update_call(attributes.serialize_for_api)
32
32
  else
33
33
  create
34
34
  end
@@ -120,14 +120,6 @@ module Nylas
120
120
 
121
121
  private
122
122
 
123
- def save_call
124
- execute(
125
- method: :put,
126
- payload: attributes.serialize_for_api,
127
- path: resource_path
128
- )
129
- end
130
-
131
123
  def update_call(payload)
132
124
  result = execute(
133
125
  method: :put,
@@ -20,6 +20,7 @@ module Nylas
20
20
  attribute :subject, :string
21
21
  attribute :body, :string
22
22
  attribute :reply_to_message_id, :string
23
+ attribute :metadata, :hash
23
24
 
24
25
  has_n_of_attribute :file_ids, :string
25
26
 
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Additional times email accounts are available
5
+ # @see https://developer.nylas.com/docs/api/#post/calendars/availability
6
+ class OpenHours
7
+ include Model::Attributable
8
+
9
+ attribute :timezone, :string
10
+ attribute :start, :string
11
+ attribute :end, :string
12
+ has_n_of_attribute :emails, :string
13
+ has_n_of_attribute :days, :integer
14
+ end
15
+ end
@@ -7,6 +7,6 @@ module Nylas
7
7
  attribute :name, :string
8
8
  attribute :email, :string
9
9
  attribute :comment, :string
10
- attribute :status, :string
10
+ attribute :status, :string, read_only: true
11
11
  end
12
12
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Ruby representation of a the Nylas Scheduler API
5
+ # @see https://developer.nylas.com/docs/api/scheduler/#overview
6
+ class Scheduler
7
+ include Model
8
+ self.resources_path = "/manage/pages"
9
+ allows_operations(creatable: true, listable: true, filterable: true, showable: true, updatable: true,
10
+ destroyable: true)
11
+
12
+ attribute :id, :integer, read_only: true
13
+ attribute :app_client_id, :string
14
+ attribute :app_organization_id, :integer
15
+ attribute :config, :scheduler_config
16
+ attribute :edit_token, :string
17
+ attribute :name, :string
18
+ attribute :slug, :string
19
+ attribute :created_at, :date
20
+ attribute :modified_at, :date
21
+
22
+ has_n_of_attribute :access_tokens, :string
23
+
24
+ def get_available_calendars
25
+ raise ArgumentError, "Cannot get calendars for a page without an ID." if id.nil?
26
+
27
+ api.execute(
28
+ method: :get,
29
+ path: "/manage/pages/#{id}/calendars"
30
+ )
31
+ end
32
+
33
+ def upload_image(content_type:, object_name:)
34
+ raise ArgumentError, "Cannot upload an image to a page without an ID." if id.nil?
35
+
36
+ payload = {
37
+ contentType: content_type,
38
+ objectName: object_name
39
+ }
40
+ api.execute(
41
+ method: :put,
42
+ path: "/manage/pages/#{id}/upload-image",
43
+ payload: JSON.dump(payload)
44
+ )
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent the booking response returned from the Scheduler API
5
+ class SchedulerBookingConfirmation
6
+ include Model::Attributable
7
+ attribute :id, :integer
8
+ attribute :account_id, :string
9
+ attribute :calendar_event_id, :string
10
+ attribute :calendar_id, :string
11
+ attribute :edit_hash, :string
12
+ attribute :location, :string
13
+ attribute :title, :string
14
+ attribute :recipient_email, :string
15
+ attribute :recipient_locale, :string
16
+ attribute :recipient_name, :string
17
+ attribute :recipient_tz, :string
18
+ attribute :additional_field_values, :hash
19
+ attribute :is_confirmed, :boolean
20
+ attribute :start_time, :unix_timestamp
21
+ attribute :end_time, :unix_timestamp
22
+ has_n_of_attribute :additional_emails, :string
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent the booking request used for the Scheduler API
5
+ class SchedulerBookingRequest
6
+ include Model::Attributable
7
+ attribute :additional_values, :hash
8
+ attribute :email, :string
9
+ attribute :locale, :string
10
+ attribute :name, :string
11
+ attribute :page_hostname, :string
12
+ attribute :replaces_booking_hash, :string
13
+ attribute :timezone, :string
14
+ attribute :slot, :scheduler_time_slot
15
+ has_n_of_attribute :additional_emails, :string
16
+ end
17
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Additional methods for some of Scheduler's other functionality
5
+ # @see https://developer.nylas.com/docs/api/scheduler#overview
6
+ class SchedulerCollection < Collection
7
+ # Retrieve Google availability
8
+ # @return [Hash] Returns the availability
9
+ def get_google_availability
10
+ execute_provider_availability("google")
11
+ end
12
+
13
+ # Retrieve Office 365 availability
14
+ # @return [Hash] Returns the availability
15
+ def get_office_365_availability
16
+ execute_provider_availability("o365")
17
+ end
18
+
19
+ # Retrieve public config for a scheduling page
20
+ # @param slug [String] The Scheduler page slug
21
+ # @return [Scheduler] Returns the Scheduler object representing the page configuration
22
+ def get_page_slug(slug)
23
+ page_response = api.execute(
24
+ method: :get,
25
+ path: "/schedule/#{slug}/info"
26
+ )
27
+
28
+ Scheduler.new(**page_response.merge(api: api))
29
+ end
30
+
31
+ # Retrieve available time slots
32
+ # @param slug [String] The Scheduler page slug
33
+ # @return [Array<SchedulerTimeSlot>] Returns the list of available timeslots
34
+ def get_available_time_slots(slug)
35
+ response = api.execute(
36
+ method: :get,
37
+ path: "/schedule/#{slug}/timeslots"
38
+ )
39
+
40
+ timeslots = []
41
+ response.each do |available_slot|
42
+ timeslots.push(SchedulerTimeSlot.new(**available_slot.merge(api: api)))
43
+ end
44
+ timeslots
45
+ end
46
+
47
+ # Book a time slot
48
+ # @param slug [String] The Scheduler page slug
49
+ # @param timeslot [SchedulerBookingRequest] The time slot booking request
50
+ # @return [SchedulerBookingConfirmation] Returns the booking confirmation
51
+ def book_time_slot(slug, timeslot)
52
+ payload = timeslot.to_h
53
+ # The booking endpoint requires additional_values and additional_emails
54
+ # to exist regardless if they are empty or not
55
+ payload[:additional_values] = {} unless payload[:additional_values]
56
+ payload[:additional_emails] = [] unless payload[:additional_emails]
57
+ booking_response = api.execute(
58
+ method: :post,
59
+ path: "/schedule/#{slug}/timeslots",
60
+ payload: JSON.dump(payload)
61
+ )
62
+
63
+ SchedulerBookingConfirmation.new(**booking_response.merge(api: api))
64
+ end
65
+
66
+ # Cancel a booking
67
+ # @param slug [String] The Scheduler page slug
68
+ # @param edit_hash [String] The token used for editing the booked time slot
69
+ # @param reason [String] The reason for cancelling the booking
70
+ # @return [Hash] Returns a hash of a boolean representing success of cancellation
71
+ def cancel_booking(slug, edit_hash, reason)
72
+ api.execute(
73
+ method: :post,
74
+ path: "/schedule/#{slug}/#{edit_hash}/cancel",
75
+ payload: JSON.dump(reason: reason)
76
+ )
77
+ end
78
+
79
+ # Confirm a booking
80
+ # @param slug [String] The Scheduler page slug
81
+ # @param edit_hash [String] The token used for editing the booked time slot
82
+ # @return [SchedulerBookingConfirmation] Returns the confirmed booking confirmation
83
+ def confirm_booking(slug, edit_hash)
84
+ booking_response = api.execute(
85
+ method: :post,
86
+ path: "/schedule/#{slug}/#{edit_hash}/confirm",
87
+ payload: {}
88
+ )
89
+
90
+ SchedulerBookingConfirmation.new(**booking_response.merge(api: api))
91
+ end
92
+
93
+ private
94
+
95
+ # Retrieve provider availability
96
+ # @return [Hash] Returns the availability
97
+ def execute_provider_availability(provider)
98
+ api.execute(
99
+ method: :get,
100
+ path: "/schedule/availability/#{provider}"
101
+ )
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Configuration settings for a Scheduler page
5
+ # @see https://developer.nylas.com/docs/api/scheduler
6
+ class SchedulerConfig
7
+ include Model::Attributable
8
+
9
+ attribute :appearance, :hash
10
+ attribute :booking, :hash
11
+ attribute :calendar_ids, :hash
12
+ attribute :event, :hash
13
+ attribute :expire_after, :hash
14
+ attribute :locale, :string
15
+ attribute :locale_for_guests, :string
16
+ attribute :timezone, :string
17
+
18
+ has_n_of_attribute :reminders, :hash
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent the time slot object from the Scheduler API
5
+ class SchedulerTimeSlot
6
+ include Model::Attributable
7
+ attribute :account_id, :string
8
+ attribute :calendar_id, :string
9
+ attribute :host_name, :string
10
+ attribute :start, :unix_timestamp
11
+ attribute :end, :unix_timestamp
12
+ has_n_of_attribute :emails, :string
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent information about a Nylas access token.
5
+ # @see https://developer.nylas.com/docs/api/#post/a/client_id/accounts/id/token-info
6
+ class TokenInfo
7
+ include Model::Attributable
8
+
9
+ attribute :scopes, :string
10
+ attribute :state, :string
11
+ attribute :created_at, :unix_timestamp
12
+ attribute :updated_at, :unix_timestamp
13
+
14
+ # Returns the state of the token as a boolean
15
+ # @return [Boolean] If the token is active
16
+ def valid?
17
+ state == "valid"
18
+ end
19
+ end
20
+ end
data/lib/nylas/types.rb CHANGED
@@ -7,8 +7,27 @@ module Nylas
7
7
  @registry ||= Registry.new
8
8
  end
9
9
 
10
+ # Base type for attributes
11
+ class ValueType
12
+ def cast(object)
13
+ object
14
+ end
15
+
16
+ def serialize(object)
17
+ object
18
+ end
19
+
20
+ def deseralize(object)
21
+ object
22
+ end
23
+
24
+ def serialize_for_api(object)
25
+ serialize(object)
26
+ end
27
+ end
28
+
10
29
  # Casts/Serializes data that is persisted and used natively as a Hash
11
- class HashType
30
+ class HashType < ValueType
12
31
  def serialize(object)
13
32
  object.to_h
14
33
  end
@@ -22,10 +41,11 @@ module Nylas
22
41
 
23
42
  # Type for attributes that are persisted in the API as a hash but exposed in ruby as a particular
24
43
  # {Model} or Model-like thing.
25
- class ModelType
44
+ class ModelType < ValueType
26
45
  attr_accessor :model
27
46
 
28
47
  def initialize(model:)
48
+ super()
29
49
  self.model = model
30
50
  end
31
51
 
@@ -33,6 +53,10 @@ module Nylas
33
53
  object.to_h
34
54
  end
35
55
 
56
+ def serialize_for_api(object)
57
+ object&.to_h(enforce_read_only: true)
58
+ end
59
+
36
60
  def cast(value)
37
61
  return model.new if value.nil?
38
62
  return value if already_cast?(value)
@@ -56,23 +80,8 @@ module Nylas
56
80
  end
57
81
  end
58
82
 
59
- # Type for attributes that do not require casting/serializing/deserializing.
60
- class ValueType
61
- def cast(object)
62
- object
63
- end
64
-
65
- def serialize(object)
66
- object
67
- end
68
-
69
- def deseralize(object)
70
- object
71
- end
72
- end
73
-
74
83
  # Type for attributes represented as a unix timestamp in the API and Time in Ruby
75
- class UnixTimestampType
84
+ class UnixTimestampType < ValueType
76
85
  def cast(object)
77
86
  return object if object.is_a?(Time) || object.nil?
78
87
  return Time.at(object.to_i) if object.is_a?(String)
data/lib/nylas/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nylas
4
- VERSION = "5.4.1"
4
+ VERSION = "5.7.0"
5
5
  end
data/lib/nylas.rb CHANGED
@@ -35,7 +35,6 @@ require_relative "nylas/model"
35
35
  # Attribute types supported by the API
36
36
  require_relative "nylas/email_address"
37
37
  require_relative "nylas/event"
38
- require_relative "nylas/event_collection"
39
38
  require_relative "nylas/file"
40
39
  require_relative "nylas/folder"
41
40
  require_relative "nylas/im_address"
@@ -53,14 +52,21 @@ require_relative "nylas/nylas_date"
53
52
  require_relative "nylas/when"
54
53
  require_relative "nylas/free_busy"
55
54
  require_relative "nylas/time_slot"
55
+ require_relative "nylas/open_hours"
56
56
  require_relative "nylas/event_conferencing"
57
57
  require_relative "nylas/event_conferencing_details"
58
58
  require_relative "nylas/event_conferencing_autocreate"
59
+ require_relative "nylas/event_notification"
60
+ require_relative "nylas/component"
59
61
 
60
62
  # Custom collection types
63
+ require_relative "nylas/event_collection"
61
64
  require_relative "nylas/search_collection"
62
65
  require_relative "nylas/deltas_collection"
63
66
  require_relative "nylas/free_busy_collection"
67
+ require_relative "nylas/calendar_collection"
68
+ require_relative "nylas/component_collection"
69
+ require_relative "nylas/scheduler_collection"
64
70
 
65
71
  # Models supported by the API
66
72
  require_relative "nylas/account"
@@ -77,6 +83,10 @@ require_relative "nylas/new_message"
77
83
  require_relative "nylas/raw_message"
78
84
  require_relative "nylas/thread"
79
85
  require_relative "nylas/webhook"
86
+ require_relative "nylas/scheduler"
87
+ require_relative "nylas/job_status"
88
+ require_relative "nylas/token_info"
89
+ require_relative "nylas/application_details"
80
90
 
81
91
  # Neural specific types
82
92
  require_relative "nylas/neural"
@@ -90,6 +100,10 @@ require_relative "nylas/neural_signature_contact"
90
100
  require_relative "nylas/neural_signature_extraction"
91
101
  require_relative "nylas/neural_message_options"
92
102
  require_relative "nylas/categorize"
103
+ require_relative "nylas/scheduler_config"
104
+ require_relative "nylas/scheduler_time_slot"
105
+ require_relative "nylas/scheduler_booking_request"
106
+ require_relative "nylas/scheduler_booking_confirmation"
93
107
 
94
108
  require_relative "nylas/native_authentication"
95
109
 
@@ -129,9 +143,13 @@ module Nylas
129
143
  Types.registry[:event_conferencing] = Types::ModelType.new(model: EventConferencing)
130
144
  Types.registry[:event_conferencing_details] = Types::ModelType.new(model: EventConferencingDetails)
131
145
  Types.registry[:event_conferencing_autocreate] = Types::ModelType.new(model: EventConferencingAutocreate)
146
+ Types.registry[:event_notification] = Types::ModelType.new(model: EventNotification)
132
147
  Types.registry[:neural] = Types::ModelType.new(model: Neural)
133
148
  Types.registry[:categorize] = Types::ModelType.new(model: Categorize)
134
149
  Types.registry[:neural_signature_contact] = Types::ModelType.new(model: NeuralSignatureContact)
135
150
  Types.registry[:neural_contact_link] = Types::ModelType.new(model: NeuralContactLink)
136
151
  Types.registry[:neural_contact_name] = Types::ModelType.new(model: NeuralContactName)
152
+ Types.registry[:scheduler_config] = Types::ModelType.new(model: SchedulerConfig)
153
+ Types.registry[:scheduler_time_slot] = Types::ModelType.new(model: SchedulerTimeSlot)
154
+ Types.registry[:job_status] = Types::ModelType.new(model: JobStatus)
137
155
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nylas
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.4.1
4
+ version: 5.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nylas, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-27 00:00:00.000000000 Z
11
+ date: 2022-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -58,28 +58,28 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.52.0
61
+ version: 1.24.1
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.52.0
68
+ version: 1.24.1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rubocop-rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 1.20.1
75
+ version: 2.7.0
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 1.20.1
82
+ version: 2.7.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: overcommit
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -269,9 +269,13 @@ files:
269
269
  - lib/nylas.rb
270
270
  - lib/nylas/account.rb
271
271
  - lib/nylas/api.rb
272
+ - lib/nylas/application_details.rb
272
273
  - lib/nylas/calendar.rb
274
+ - lib/nylas/calendar_collection.rb
273
275
  - lib/nylas/categorize.rb
274
276
  - lib/nylas/collection.rb
277
+ - lib/nylas/component.rb
278
+ - lib/nylas/component_collection.rb
275
279
  - lib/nylas/constraints.rb
276
280
  - lib/nylas/contact.rb
277
281
  - lib/nylas/contact_group.rb
@@ -287,6 +291,7 @@ files:
287
291
  - lib/nylas/event_conferencing.rb
288
292
  - lib/nylas/event_conferencing_autocreate.rb
289
293
  - lib/nylas/event_conferencing_details.rb
294
+ - lib/nylas/event_notification.rb
290
295
  - lib/nylas/file.rb
291
296
  - lib/nylas/filter_attributes.rb
292
297
  - lib/nylas/folder.rb
@@ -294,6 +299,7 @@ files:
294
299
  - lib/nylas/free_busy_collection.rb
295
300
  - lib/nylas/http_client.rb
296
301
  - lib/nylas/im_address.rb
302
+ - lib/nylas/job_status.rb
297
303
  - lib/nylas/label.rb
298
304
  - lib/nylas/logging.rb
299
305
  - lib/nylas/message.rb
@@ -318,6 +324,7 @@ files:
318
324
  - lib/nylas/neural_signature_extraction.rb
319
325
  - lib/nylas/new_message.rb
320
326
  - lib/nylas/nylas_date.rb
327
+ - lib/nylas/open_hours.rb
321
328
  - lib/nylas/participant.rb
322
329
  - lib/nylas/phone_number.rb
323
330
  - lib/nylas/physical_address.rb
@@ -326,10 +333,17 @@ files:
326
333
  - lib/nylas/registry.rb
327
334
  - lib/nylas/room_resource.rb
328
335
  - lib/nylas/rsvp.rb
336
+ - lib/nylas/scheduler.rb
337
+ - lib/nylas/scheduler_booking_confirmation.rb
338
+ - lib/nylas/scheduler_booking_request.rb
339
+ - lib/nylas/scheduler_collection.rb
340
+ - lib/nylas/scheduler_config.rb
341
+ - lib/nylas/scheduler_time_slot.rb
329
342
  - lib/nylas/search_collection.rb
330
343
  - lib/nylas/thread.rb
331
344
  - lib/nylas/time_slot.rb
332
345
  - lib/nylas/timespan.rb
346
+ - lib/nylas/token_info.rb
333
347
  - lib/nylas/types.rb
334
348
  - lib/nylas/version.rb
335
349
  - lib/nylas/web_page.rb
@@ -360,7 +374,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
360
374
  - !ruby/object:Gem::Version
361
375
  version: '0'
362
376
  requirements: []
363
- rubygems_version: 3.1.6
377
+ rubygems_version: 3.2.17
364
378
  signing_key:
365
379
  specification_version: 4
366
380
  summary: Gem for interacting with the Nylas API