nylas 5.0.0 → 5.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82a2a7e6af812dd58557c604deb553e18d586c373ee8c308b1eddc8492a44c28
4
- data.tar.gz: 43b9a7943a854c10f2257d49220fc420ff4e3b022b76a527ba772041600d24dd
3
+ metadata.gz: 9e585c607f124440a448e29f36d010eff7ac9b2023000b82256874830338f327
4
+ data.tar.gz: 0c0d882e1831a5367f4eaa69701482c6b452cf129e205a136def8f64310b695e
5
5
  SHA512:
6
- metadata.gz: 6c005ca3d6e0f61bc25ebdab118cc0dda5dd366c24b8ad1519b78a5bb32bd0de976b1070fb6dc35dfbd81ffd4540c636956c38f1248e412e80441cf12fb788d0
7
- data.tar.gz: 05e47ffa2fb00e66adf7483b7eb7a0bd870c85dbff006dee3cfa7b968589173634d77d74519bc04e657d214efdfd17b1bc8ef492da0880edef5552fb012ac466
6
+ metadata.gz: 2cf81593d36344ca0f18e734688fa6276acc86be3ffa0436bc0e02aa126414f920e7295ab0de1ce8f90538505073ae180ce1e94bcb1255c37aa471c06aad63cd
7
+ data.tar.gz: 47d5ebabda297aeca2d455536ce12eb7292c895a4865b815173f4852f24d131583709127c5549b15ca1d3a1999582090198be23ea72a9fdd41fe5bac9d675509
data/lib/nylas/api.rb CHANGED
@@ -16,13 +16,11 @@ module Nylas
16
16
  # @param access_token [String] (Optional) Your users access token.
17
17
  # @param api_server [String] (Optional) Which Nylas API Server to connect to. Only change this if
18
18
  # you're using a self-hosted Nylas instance.
19
- # @param service_domain [String] (Optional) Host you are authenticating OAuth against.
20
19
  # @return [Nylas::API]
21
20
  def initialize(client: nil, app_id: nil, app_secret: nil, access_token: nil,
22
- api_server: "https://api.nylas.com", service_domain: "api.nylas.com")
21
+ api_server: "https://api.nylas.com")
23
22
  self.client = client || HttpClient.new(app_id: app_id, app_secret: app_secret,
24
- access_token: access_token, api_server: api_server,
25
- service_domain: service_domain)
23
+ access_token: access_token, api_server: api_server)
26
24
  end
27
25
 
28
26
  # @return [String] A Nylas access token for that particular user.
@@ -123,6 +121,16 @@ module Nylas
123
121
  @messages ||= Collection.new(model: Message, api: self)
124
122
  end
125
123
 
124
+ # @return[Collection<RoomResource>] A queryable collection of {RoomResource} objects
125
+ def room_resources
126
+ @room_resources ||= Collection.new(model: RoomResource, api: self)
127
+ end
128
+
129
+ # @return[Neural] A {Neural} object that provides
130
+ def neural
131
+ @neural ||= Neural.new(api: self)
132
+ end
133
+
126
134
  # Revokes access to the Nylas API for the given access token
127
135
  # @return [Boolean]
128
136
  def revoke(access_token)
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent the Neural Categorize object.
5
+ # @see https://developer.nylas.com/docs/intelligence/categorizer/#categorize-message-response
6
+ class Categorize
7
+ include Model::Attributable
8
+
9
+ attribute :category, :string
10
+ attribute :categorized_at, :unix_timestamp
11
+ attribute :model_version, :string
12
+ has_n_of_attribute :subcategories, :string
13
+ end
14
+ end
data/lib/nylas/contact.rb CHANGED
@@ -13,9 +13,9 @@ module Nylas
13
13
  self.updatable = true
14
14
  self.destroyable = true
15
15
 
16
- attribute :id, :string, exclude_when: %i[creating updating]
16
+ attribute :id, :string, read_only: true
17
17
  attribute :object, :string, default: "contact"
18
- attribute :account_id, :string, exclude_when: %i[creating updating]
18
+ attribute :account_id, :string, read_only: true
19
19
 
20
20
  attribute :given_name, :string
21
21
  attribute :middle_name, :string
data/lib/nylas/delta.rb CHANGED
@@ -6,6 +6,7 @@ module Nylas
6
6
  # @see https://docs.nylas.com/reference#deltas
7
7
  class Delta
8
8
  include Model::Attributable
9
+
9
10
  attribute :id, :string
10
11
  attribute :type, :string
11
12
  attribute :object, :string
@@ -14,6 +15,8 @@ module Nylas
14
15
  attribute :namespace_id, :string
15
16
  attribute :account_id, :string
16
17
 
18
+ attribute :headers, :message_headers
19
+
17
20
  attribute :date, :unix_timestamp
18
21
  attribute :metadata, :hash
19
22
  attribute :object_attributes, :hash
@@ -24,6 +27,8 @@ module Nylas
24
27
  @model ||= Types.registry[object.to_sym].cast(object_attributes_with_ids)
25
28
  end
26
29
 
30
+ private
31
+
27
32
  def object_attributes_with_ids
28
33
  (object_attributes || {}).merge(id: id, account_id: account_id)
29
34
  end
@@ -42,8 +47,10 @@ module Nylas
42
47
  else
43
48
  data
44
49
  end
50
+
51
+ data = data.merge(data[:attributes]) if data[:attributes]
45
52
  data[:object_attributes] = data.delete(:attributes)
46
- super(data)
53
+ super(**data)
47
54
  end
48
55
  end
49
56
  end
data/lib/nylas/deltas.rb CHANGED
@@ -14,6 +14,6 @@ module Nylas
14
14
  attribute :cursor_end, :string
15
15
 
16
16
  extend Forwardable
17
- def_delegators :deltas, :count, :length, :each, :map, :first, :to_a, :empty?
17
+ def_delegators :deltas, :count, :length, :each, :map, :first, :last, :to_a, :empty?
18
18
  end
19
19
  end
data/lib/nylas/draft.rb CHANGED
@@ -29,7 +29,8 @@ module Nylas
29
29
  attribute :unread, :boolean
30
30
 
31
31
  has_n_of_attribute :events, :event
32
- has_n_of_attribute :files, :file
32
+ has_n_of_attribute :files, :file, read_only: true
33
+ has_n_of_attribute :file_ids, :string
33
34
  attribute :folder, :folder
34
35
  has_n_of_attribute :labels, :label
35
36
 
@@ -37,10 +38,26 @@ module Nylas
37
38
 
38
39
  transfer :api, to: %i[events files folder labels]
39
40
 
41
+ def update(**data)
42
+ # If files are provided, replace files with file IDs
43
+ self.files = data[:files] if data[:files]
44
+ extract_file_ids!
45
+ data[:file_ids] = file_ids
46
+ # If version is not provided, add version or request will fail
47
+ data[:version] = version unless data[:version]
48
+
49
+ super
50
+ end
51
+
52
+ def create
53
+ extract_file_ids!
54
+
55
+ super
56
+ end
57
+
40
58
  def send!
41
- return execute(method: :post, path: "/send", payload: to_json) if tracking
59
+ return execute(method: :post, path: "/send", payload: to_json) if tracking || !id
42
60
 
43
- save
44
61
  execute(method: :post, path: "/send", payload: JSON.dump(draft_id: id, version: version))
45
62
  end
46
63
 
@@ -53,7 +70,21 @@ module Nylas
53
70
  end
54
71
 
55
72
  def destroy
56
- execute(method: :delete, path: resource_path, payload: attributes.serialize(keys: [:version]))
73
+ execute(method: :delete, path: resource_path, payload: attributes.serialize_for_api(keys: [:version]))
74
+ end
75
+
76
+ private
77
+
78
+ def save_call
79
+ extract_file_ids!
80
+
81
+ super
82
+ end
83
+
84
+ def extract_file_ids!
85
+ files = self.files || []
86
+
87
+ self.file_ids = files.map(&:id)
57
88
  end
58
89
  end
59
90
  end
data/lib/nylas/event.rb CHANGED
@@ -9,9 +9,9 @@ module Nylas
9
9
  allows_operations(creatable: true, listable: true, filterable: true, showable: true, updatable: true,
10
10
  destroyable: true)
11
11
 
12
- attribute :id, :string, exclude_when: %i[saving]
13
- attribute :object, :string, exclude_when: %i[saving]
14
- attribute :account_id, :string, exclude_when: %i[saving]
12
+ attribute :id, :string, read_only: true
13
+ attribute :object, :string, read_only: true
14
+ attribute :account_id, :string, read_only: true
15
15
  attribute :calendar_id, :string
16
16
  attribute :master_event_id, :string
17
17
  attribute :message_id, :string
@@ -27,6 +27,8 @@ module Nylas
27
27
  attribute :status, :string
28
28
  attribute :title, :string
29
29
  attribute :when, :when
30
+ attribute :metadata, :hash
31
+ attribute :conferencing, :event_conferencing
30
32
  attribute :original_start_time, :unix_timestamp
31
33
 
32
34
  attr_accessor :notify_participants
@@ -39,6 +41,17 @@ module Nylas
39
41
  read_only
40
42
  end
41
43
 
44
+ def save
45
+ if conferencing
46
+ body = to_h
47
+ if body.dig(:conferencing, :details) && body.dig(:conferencing, :autocreate)
48
+ raise ArgumentError, "Cannot set both 'details' and 'autocreate' in conferencing object."
49
+ end
50
+ end
51
+
52
+ super
53
+ end
54
+
42
55
  def rsvp(status, notify_participants:)
43
56
  rsvp = Rsvp.new(api: api, status: status, notify_participants: notify_participants,
44
57
  event_id: id, account_id: account_id)
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent the Event Conferencing object
5
+ # @see https://developer.nylas.com/docs/connectivity/calendar/conference-sync-beta
6
+ class EventConferencing
7
+ include Model::Attributable
8
+ attribute :provider, :string
9
+ attribute :details, :event_conferencing_details
10
+ attribute :autocreate, :event_conferencing_autocreate
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent the autocreate object within the Event Conferencing object
5
+ # @see https://developer.nylas.com/docs/connectivity/calendar/conference-sync-beta
6
+ class EventConferencingAutocreate
7
+ include Model::Attributable
8
+ attribute :settings, :hash, default: {}
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent the details object within the Event Conferencing object
5
+ # @see https://developer.nylas.com/docs/connectivity/calendar/conference-sync-beta
6
+ class EventConferencingDetails
7
+ include Model::Attributable
8
+ attribute :meeting_code, :string
9
+ attribute :password, :string
10
+ attribute :pin, :string
11
+ attribute :url, :string
12
+ has_n_of_attribute :phone, :string
13
+ end
14
+ end
@@ -5,6 +5,8 @@ module Nylas
5
5
 
6
6
  # Plain HTTP client that can be used to interact with the Nylas API sans any type casting.
7
7
  class HttpClient # rubocop:disable Metrics/ClassLength
8
+ HTTP_SUCCESS_CODES = [200, 201, 302].freeze
9
+
8
10
  HTTP_CODE_TO_EXCEPTIONS = {
9
11
  400 => InvalidRequest,
10
12
  401 => UnauthorizedRequest,
@@ -34,7 +36,7 @@ module Nylas
34
36
  SUPPORTED_API_VERSION = "2.2"
35
37
 
36
38
  include Logging
37
- attr_accessor :api_server, :service_domain
39
+ attr_accessor :api_server
38
40
  attr_writer :default_headers
39
41
  attr_reader :access_token
40
42
  attr_reader :app_id
@@ -45,10 +47,8 @@ module Nylas
45
47
  # @param access_token [String] (Optional) Your users access token.
46
48
  # @param api_server [String] (Optional) Which Nylas API Server to connect to. Only change this if
47
49
  # you're using a self-hosted Nylas instance.
48
- # @param service_domain [String] (Optional) Host you are authenticating OAuth against.
49
50
  # @return [Nylas::HttpClient]
50
- def initialize(app_id:, app_secret:, access_token: nil, api_server: "https://api.nylas.com",
51
- service_domain: "api.nylas.com")
51
+ def initialize(app_id:, app_secret:, access_token: nil, api_server: "https://api.nylas.com")
52
52
  unless api_server.include?("://")
53
53
  raise "When overriding the Nylas API server address, you must include https://"
54
54
  end
@@ -57,13 +57,12 @@ module Nylas
57
57
  @access_token = access_token
58
58
  @app_secret = app_secret
59
59
  @app_id = app_id
60
- @service_domain = service_domain
61
60
  end
62
61
 
63
62
  # @return [Nylas::HttpClient[]
64
63
  def as(access_token)
65
64
  HttpClient.new(app_id: app_id, access_token: access_token,
66
- app_secret: app_secret, api_server: api_server, service_domain: service_domain)
65
+ app_secret: app_secret, api_server: api_server)
67
66
  end
68
67
 
69
68
  # Sends a request to the Nylas API and rai
@@ -93,7 +92,12 @@ module Nylas
93
92
  content_type = response.headers[:content_type].downcase
94
93
  end
95
94
 
96
- response = parse_response(response) if content_type == "application/json"
95
+ begin
96
+ response = parse_response(response) if content_type == "application/json"
97
+ rescue Nylas::JsonParseError
98
+ handle_failed_response(result: result, response: response)
99
+ raise
100
+ end
97
101
 
98
102
  handle_failed_response(result: result, response: response)
99
103
  response
@@ -104,8 +108,8 @@ module Nylas
104
108
  also_log: { result: true, values: %i[method url path headers query payload] }
105
109
 
106
110
  def build_request(method:, path: nil, headers: {}, query: {}, payload: nil, timeout: nil)
107
- headers[:params] = query
108
111
  url ||= url_for_path(path)
112
+ url = add_query_params_to_url(url, query)
109
113
  resulting_headers = default_headers.merge(headers)
110
114
  { method: method, url: url, payload: payload, headers: resulting_headers, timeout: timeout }
111
115
  end
@@ -140,7 +144,7 @@ module Nylas
140
144
  "X-Nylas-Client-Id" => @app_id,
141
145
  "Nylas-API-Version" => SUPPORTED_API_VERSION,
142
146
  "User-Agent" => "Nylas Ruby SDK #{Nylas::VERSION} - #{RUBY_VERSION}",
143
- "Content-types" => "application/json"
147
+ "Content-type" => "application/json"
144
148
  }
145
149
  end
146
150
 
@@ -177,11 +181,40 @@ module Nylas
177
181
  end
178
182
 
179
183
  def handle_anticipated_failure_mode(http_code:, response:)
180
- return if http_code == 200
181
- return unless response.is_a?(Hash)
184
+ return if HTTP_SUCCESS_CODES.include?(http_code)
182
185
 
183
186
  exception = HTTP_CODE_TO_EXCEPTIONS.fetch(http_code, APIError)
184
- raise exception.new(response[:type], response[:message], response.fetch(:server_error, nil))
187
+ raise exception.new(http_code, response) unless response.is_a?(Hash)
188
+
189
+ raise exception.new(
190
+ response[:type],
191
+ response[:message],
192
+ response.fetch(:server_error, nil)
193
+ )
194
+ end
195
+
196
+ def add_query_params_to_url(url, query)
197
+ unless query.empty?
198
+ uri = URI.parse(url)
199
+ query = custom_params(query)
200
+ params = URI.decode_www_form(uri.query || "") + query.to_a
201
+ uri.query = URI.encode_www_form(params)
202
+ url = uri.to_s
203
+ end
204
+
205
+ url
206
+ end
207
+
208
+ def custom_params(query)
209
+ # Convert hash to "<key>:<value>" form for metadata_pair query
210
+ if query.key?(:metadata_pair)
211
+ pairs = query[:metadata_pair].map do |key, value|
212
+ "#{key}:#{value}"
213
+ end
214
+ query[:metadata_pair] = pairs
215
+ end
216
+
217
+ query
185
218
  end
186
219
  end
187
220
  end
data/lib/nylas/message.rb CHANGED
@@ -37,7 +37,7 @@ module Nylas
37
37
  attribute :folder, :folder
38
38
  attribute :folder_id, :string
39
39
 
40
- has_n_of_attribute :labels, :label, exclude_when: [:saving]
40
+ has_n_of_attribute :labels, :label, read_only: true
41
41
  has_n_of_attribute :label_ids, :string
42
42
 
43
43
  transfer :api, to: %i[events files folder labels]
@@ -67,6 +67,8 @@ module Nylas
67
67
  return self unless headers.nil?
68
68
 
69
69
  assign(**api.execute(method: :get, path: resource_path, query: { view: "expanded" }))
70
+ # Transfer reference to the API to attributes that need it
71
+ transfer_attributes
70
72
  self
71
73
  end
72
74
 
@@ -75,7 +77,7 @@ module Nylas
75
77
 
76
78
  execute(
77
79
  method: :put,
78
- payload: attributes.serialize(keys: allowed_keys_for_save),
80
+ payload: attributes.serialize_for_api,
79
81
  path: resource_path
80
82
  )
81
83
  end
@@ -25,6 +25,8 @@ module Nylas
25
25
 
26
26
  def assign(**data)
27
27
  data.each do |attribute_name, value|
28
+ next if value.nil?
29
+
28
30
  if respond_to?(:"#{attribute_name}=")
29
31
  send(:"#{attribute_name}=", value)
30
32
  end
@@ -34,17 +36,22 @@ module Nylas
34
36
  # Methods to call when tweaking Attributable classes
35
37
  module ClassMethods
36
38
  # rubocop:disable Naming/PredicateName
37
- def has_n_of_attribute(name, type_name, exclude_when: [], default: [])
38
- attribute_definitions[name] = ListAttributeDefinition.new(type_name: type_name,
39
- exclude_when: exclude_when,
40
- default: default)
39
+ def has_n_of_attribute(name, type_name, read_only: false, default: [])
40
+ attribute_definitions[name] = ListAttributeDefinition.new(
41
+ type_name: type_name,
42
+ read_only: read_only,
43
+ default: default
44
+ )
41
45
  define_accessors(name)
42
46
  end
43
47
  # rubocop:enable Naming/PredicateName
44
48
 
45
- def attribute(name, type_name, exclude_when: [], default: nil)
46
- attribute_definitions[name] = AttributeDefinition.new(type_name: type_name,
47
- exclude_when: exclude_when, default: default)
49
+ def attribute(name, type_name, read_only: false, default: nil)
50
+ attribute_definitions[name] = AttributeDefinition.new(
51
+ type_name: type_name,
52
+ read_only: read_only,
53
+ default: default
54
+ )
48
55
  define_accessors(name)
49
56
  end
50
57
 
@@ -58,6 +65,21 @@ module Nylas
58
65
  end
59
66
  end
60
67
 
68
+ # Allows a class to inherit parent's attributes
69
+ def inherit_attributes
70
+ return if superclass.nil?
71
+
72
+ parent_attributes = superclass.attribute_definitions
73
+ parent_attributes.each do |parent_attribute|
74
+ name = parent_attribute[0]
75
+ attr = parent_attribute[1]
76
+ next if attribute_definitions.key?(name)
77
+
78
+ attribute_definitions[name] = attr
79
+ define_accessors(name)
80
+ end
81
+ end
82
+
61
83
  def attribute_definitions
62
84
  @attribute_definitions ||= Registry.new
63
85
  end
@@ -6,11 +6,11 @@ module Nylas
6
6
  class AttributeDefinition
7
7
  extend Forwardable
8
8
  def_delegators :type, :cast, :serialize
9
- attr_accessor :type_name, :exclude_when, :default
9
+ attr_accessor :type_name, :read_only, :default
10
10
 
11
- def initialize(type_name:, exclude_when:, default:)
11
+ def initialize(type_name:, read_only:, default:)
12
12
  self.type_name = type_name
13
- self.exclude_when = exclude_when
13
+ self.read_only = read_only
14
14
  self.default = default
15
15
  end
16
16
 
@@ -31,7 +31,9 @@ module Nylas
31
31
  def to_h(keys: attribute_definitions.keys)
32
32
  keys.each_with_object({}) do |key, casted_data|
33
33
  value = attribute_definitions[key].serialize(self[key])
34
- casted_data[key] = value unless value.nil? || (value.respond_to?(:empty?) && value.empty?)
34
+ # If the value is an empty hash but we specify that it is valid (via default value), serialize it
35
+ casted_data[key] = value unless value.nil? || (value.respond_to?(:empty?) && value.empty? &&
36
+ !(attribute_definitions[key].default == value && value.is_a?(Hash)))
35
37
  end
36
38
  end
37
39
 
@@ -39,6 +41,22 @@ module Nylas
39
41
  JSON.dump(to_h(keys: keys))
40
42
  end
41
43
 
44
+ 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)
48
+ end
49
+
50
+ def serialize_all_for_api(keys: attribute_definitions.keys)
51
+ api_keys = keys.delete_if { |key| attribute_definitions[key].read_only == true }
52
+
53
+ JSON.dump(
54
+ api_keys.each_with_object({}) do |key, casted_data|
55
+ casted_data[key] = attribute_definitions[key].serialize(self[key])
56
+ end
57
+ )
58
+ end
59
+
42
60
  private
43
61
 
44
62
  def cast(key, value)
@@ -4,11 +4,11 @@ module Nylas
4
4
  module Model
5
5
  # Allows models to have an attribute which is a lists of another type of thing
6
6
  class ListAttributeDefinition
7
- attr_accessor :type_name, :exclude_when, :default
7
+ attr_accessor :type_name, :read_only, :default
8
8
 
9
- def initialize(type_name:, exclude_when:, default:)
9
+ def initialize(type_name:, read_only:, default:)
10
10
  self.type_name = type_name
11
- self.exclude_when = exclude_when
11
+ self.read_only = read_only
12
12
  self.default = default
13
13
  end
14
14
 
data/lib/nylas/model.rb CHANGED
@@ -48,7 +48,7 @@ module Nylas
48
48
 
49
49
  execute(
50
50
  method: :post,
51
- payload: attributes.serialize,
51
+ payload: attributes.serialize_for_api,
52
52
  path: resources_path,
53
53
  query: query_params
54
54
  )
@@ -58,12 +58,37 @@ module Nylas
58
58
  raise ModelNotUpdatableError, model_class unless updatable?
59
59
 
60
60
  attributes.merge(**data)
61
- execute(
62
- method: :put,
63
- payload: attributes.serialize(keys: data.keys),
64
- path: resource_path,
65
- query: query_params
66
- )
61
+ payload = attributes.serialize_for_api(keys: data.keys)
62
+ update_call(payload)
63
+
64
+ true
65
+ rescue Registry::MissingKeyError => e
66
+ raise ModelMissingFieldError.new(e.key, self)
67
+ end
68
+
69
+ def save_all_attributes
70
+ result = if persisted?
71
+ raise ModelNotUpdatableError, self unless updatable?
72
+
73
+ execute(
74
+ method: :put,
75
+ payload: attributes.serialize_all_for_api,
76
+ path: resource_path
77
+ )
78
+ else
79
+ create
80
+ end
81
+
82
+ attributes.merge(result)
83
+ end
84
+
85
+ def update_all_attributes(**data)
86
+ raise ModelNotUpdatableError, model_class unless updatable?
87
+
88
+ attributes.merge(**data)
89
+ payload = attributes.serialize_all_for_api(keys: data.keys)
90
+ update_call(payload)
91
+
67
92
  true
68
93
  rescue Registry::MissingKeyError => e
69
94
  raise ModelMissingFieldError.new(e.key, self)
@@ -95,20 +120,24 @@ module Nylas
95
120
 
96
121
  private
97
122
 
98
- def allowed_keys_for_save
99
- attributes.attribute_definitions.to_h.reject do |_k, v|
100
- v.exclude_when.include?(:saving)
101
- end.keys
102
- end
103
-
104
123
  def save_call
105
124
  execute(
106
125
  method: :put,
107
- payload: attributes.serialize(keys: allowed_keys_for_save),
126
+ payload: attributes.serialize_for_api,
108
127
  path: resource_path
109
128
  )
110
129
  end
111
130
 
131
+ def update_call(payload)
132
+ result = execute(
133
+ method: :put,
134
+ payload: payload,
135
+ path: resource_path,
136
+ query: query_params
137
+ )
138
+ attributes.merge(result) if result
139
+ end
140
+
112
141
  def query_params
113
142
  {}
114
143
  end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Class containing methods for accessing Neural API features.
5
+ # @see https://developer.nylas.com/docs/intelligence/
6
+ class Neural
7
+ attr_accessor :api
8
+
9
+ def initialize(api:)
10
+ self.api = api
11
+ end
12
+
13
+ def sentiment_analysis_message(message_ids)
14
+ body = { message_id: message_ids }
15
+ response = request(NeuralSentimentAnalysis.resources_path, body)
16
+
17
+ collection = []
18
+ response.each do |sentiment|
19
+ collection.push(NeuralSentimentAnalysis.new(**sentiment.merge(api: api)))
20
+ end
21
+ collection
22
+ end
23
+
24
+ def sentiment_analysis_text(text)
25
+ body = { text: text }
26
+ NeuralSentimentAnalysis.new(**request(NeuralSentimentAnalysis.resources_path, body).merge(api: api))
27
+ end
28
+
29
+ def extract_signature(message_ids, options = nil)
30
+ body = { message_id: message_ids }
31
+ body = body.merge(options) unless options.nil?
32
+ response = request(NeuralSignatureExtraction.resources_path, body)
33
+
34
+ collection = []
35
+ response.each do |signature|
36
+ collection.push(NeuralSignatureExtraction.new(**signature.merge(api: api)))
37
+ end
38
+ collection
39
+ end
40
+
41
+ def ocr_request(file_id, pages = nil)
42
+ body = { file_id: file_id }
43
+ body[:pages] = pages unless pages.nil?
44
+
45
+ NeuralOcr.new(**request(NeuralOcr.resources_path, body).merge(api: api))
46
+ end
47
+
48
+ def categorize(message_ids)
49
+ body = { message_id: message_ids }
50
+ response = request(NeuralCategorizer.resources_path, body)
51
+
52
+ collection = []
53
+ response.each do |categorize|
54
+ collection.push(NeuralCategorizer.new(**categorize.merge(api: api)))
55
+ end
56
+ collection
57
+ end
58
+
59
+ def clean_conversation(message_ids, options = nil)
60
+ body = { message_id: message_ids }
61
+ body = body.merge(delete_from_hash(options.to_hash, :parse_contact)) unless options.nil?
62
+
63
+ response = request(NeuralCleanConversation.resources_path, body)
64
+ collection = []
65
+ response.each do |conversation|
66
+ collection.push(NeuralCleanConversation.new(**conversation.merge(api: api)))
67
+ end
68
+ collection
69
+ end
70
+
71
+ private
72
+
73
+ def request(path, body)
74
+ api.execute(
75
+ method: :put,
76
+ path: path,
77
+ payload: JSON.dump(body)
78
+ )
79
+ end
80
+
81
+ # For Ruby < 3.0 support, as it doesn't support Hash.except
82
+ def delete_from_hash(hash, to_delete)
83
+ hash.delete(to_delete)
84
+ hash
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent a the Neural Categorizer object.
5
+ # @see https://developer.nylas.com/docs/intelligence/categorizer/#categorize-message-response
6
+ class NeuralCategorizer < Message
7
+ include Model
8
+ self.resources_path = "/neural/categorize"
9
+ allows_operations(listable: true)
10
+
11
+ attribute :categorizer, :categorize
12
+ # Overrides Message's label attribute as currently categorize returns
13
+ # list of strings for labels instead of label object types
14
+ has_n_of_attribute :labels, :string
15
+
16
+ inherit_attributes
17
+
18
+ def recategorize(category)
19
+ body = { message_id: id, category: category }
20
+ api.execute(
21
+ method: :post,
22
+ path: "#{resources_path}/feedback",
23
+ payload: JSON.dump(body)
24
+ )
25
+ list = api.neural.categorize([id])
26
+ list[0]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent a the Neural Clean Conversations object.
5
+ # @see https://developer.nylas.com/docs/intelligence/clean-conversations/#clean-conversation-response
6
+ class NeuralCleanConversation < Message
7
+ include Model
8
+ self.resources_path = "/neural/conversation"
9
+ allows_operations(listable: true)
10
+ IMAGE_REGEX = /[(']cid:(.*?)[)']/.freeze
11
+
12
+ attribute :conversation, :string
13
+ attribute :model_version, :string
14
+
15
+ inherit_attributes
16
+
17
+ # Parses image file IDs found in the clean conversation object and returns
18
+ # an array of File objects returned from the File API
19
+ def extract_images
20
+ return if conversation.nil?
21
+
22
+ files = []
23
+ matches = conversation.scan(IMAGE_REGEX)
24
+ matches.each do |match|
25
+ # After applying the regex, if there are IDs found they would be
26
+ # in the form of => 'cid:xxxx' (including apostrophes), so we discard
27
+ # everything before and after the file ID (denoted as xxxx above)
28
+ files.push(api.files.find(match))
29
+ end
30
+ files
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent the "Link" object in the Neural API's Signature Extraction Contact object
5
+ # @see https://developer.nylas.com/docs/intelligence/signature-extraction/#parse-signature-response
6
+ class NeuralContactLink
7
+ include Model::Attributable
8
+ attribute :description, :string
9
+ attribute :url, :string
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent the "Name" object in the Neural API's Signature Extraction Contact object
5
+ # @see https://developer.nylas.com/docs/intelligence/signature-extraction/#parse-signature-response
6
+ class NeuralContactName
7
+ include Model::Attributable
8
+ attribute :first_name, :string
9
+ attribute :last_name, :string
10
+ end
11
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent a the Neural Optical Character Recognition object.
5
+ # @see https://developer.nylas.com/docs/intelligence/optical-charecter-recognition/#ocr-response
6
+ class NeuralMessageOptions
7
+ attr_accessor :ignore_links, :ignore_images, :ignore_tables, :remove_conclusion_phrases,
8
+ :images_as_markdown, :parse_contact
9
+
10
+ def initialize(ignore_links: nil,
11
+ ignore_images: nil,
12
+ ignore_tables: nil,
13
+ remove_conclusion_phrases: nil,
14
+ images_as_markdown: nil,
15
+ parse_contact: nil)
16
+ @ignore_links = ignore_links
17
+ @ignore_images = ignore_images
18
+ @ignore_tables = ignore_tables
19
+ @remove_conclusion_phrases = remove_conclusion_phrases
20
+ @images_as_markdown = images_as_markdown
21
+ @parse_contact = parse_contact
22
+ end
23
+
24
+ def to_hash
25
+ hash = {}
26
+ hash[:ignore_links] = @ignore_links unless @ignore_links.nil?
27
+ hash[:ignore_images] = @ignore_images unless @ignore_images.nil?
28
+ hash[:ignore_tables] = @ignore_tables unless @ignore_tables.nil?
29
+ hash[:remove_conclusion_phrases] = @remove_conclusion_phrases unless @remove_conclusion_phrases.nil?
30
+ hash[:images_as_markdown] = @images_as_markdown unless @images_as_markdown.nil?
31
+ hash[:parse_contact] = @parse_contact unless @parse_contact.nil?
32
+ hash
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent a the Neural Optical Character Recognition object.
5
+ # @see https://developer.nylas.com/docs/intelligence/optical-charecter-recognition/#ocr-response
6
+ class NeuralOcr < File
7
+ include Model
8
+ self.resources_path = "/neural/ocr"
9
+ allows_operations(listable: true)
10
+
11
+ has_n_of_attribute :ocr, :string
12
+ attribute :processed_pages, :integer
13
+
14
+ inherit_attributes
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent a the Neural Sentiment Analysis object.
5
+ # @see https://developer.nylas.com/docs/intelligence/sentiment-analysis/#sentiment-analysis-response-message
6
+ class NeuralSentimentAnalysis
7
+ include Model
8
+ self.resources_path = "/neural/sentiment"
9
+ allows_operations(listable: true)
10
+
11
+ attribute :account_id, :string
12
+ attribute :sentiment, :string
13
+ attribute :sentiment_score, :float
14
+ attribute :processed_length, :integer
15
+ attribute :text, :string
16
+ end
17
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent the Neural API's Signature Extraction Contact object
5
+ # @see https://developer.nylas.com/docs/intelligence/signature-extraction/#parse-signature-response
6
+ class NeuralSignatureContact
7
+ include Model::Attributable
8
+ has_n_of_attribute :job_titles, :string
9
+ has_n_of_attribute :links, :neural_contact_link
10
+ has_n_of_attribute :phone_numbers, :string
11
+ has_n_of_attribute :emails, :string
12
+ has_n_of_attribute :names, :neural_contact_name
13
+
14
+ attr_accessor :api
15
+
16
+ # Creates a Nylas contact object compatible with the contact endpoints.
17
+ # Please note if multiple names or multiple job titles were parsed only
18
+ # the first set are used.
19
+ def to_contact_object
20
+ contact = merge_multiple_hashes([convert_names, convert_emails, convert_phone_numbers, convert_links])
21
+ contact[:job_title] = job_titles[0] unless job_titles.nil?
22
+ Contact.new(**contact.merge(api: api))
23
+ end
24
+
25
+ private
26
+
27
+ def convert_names
28
+ return {} if names.empty?
29
+
30
+ contact = {}
31
+ contact[:given_name] = names[0].first_name if names[0].first_name
32
+ contact[:surname] = names[0].last_name if names[0].last_name
33
+ contact
34
+ end
35
+
36
+ def convert_emails
37
+ return {} if emails.empty?
38
+
39
+ contact = {}
40
+ contact[:emails] = []
41
+ emails.each do |e|
42
+ contact[:emails].push(type: "personal", email: e)
43
+ end
44
+ contact
45
+ end
46
+
47
+ def convert_phone_numbers
48
+ return {} if phone_numbers.empty?
49
+
50
+ contact = {}
51
+ contact[:phone_numbers] = []
52
+ phone_numbers.each do |number|
53
+ contact[:phone_numbers].push(type: "mobile", number: number)
54
+ end
55
+ contact
56
+ end
57
+
58
+ def convert_links
59
+ return {} if links.empty?
60
+
61
+ contact = {}
62
+ contact[:web_pages] = []
63
+ links.each do |link|
64
+ type = "homepage"
65
+ type = link.description unless link.description.empty?
66
+ contact[:web_pages].push(type: type, url: link.url)
67
+ end
68
+ contact
69
+ end
70
+
71
+ # For Ruby 2.5 support as it doesn't support multiple hashes to merge at once
72
+ def merge_multiple_hashes(hashes_to_merge)
73
+ hash = {}
74
+ hashes_to_merge.each do |new_hash|
75
+ hash = hash.merge(new_hash)
76
+ end
77
+
78
+ hash
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Structure to represent a the Signature Extraction Schema.
5
+ # @see https://developer.nylas.com/docs/intelligence/signature-extraction/#signature-feedback-response
6
+ class NeuralSignatureExtraction < Message
7
+ include Model
8
+ self.resources_path = "/neural/signature"
9
+
10
+ attribute :signature, :string
11
+ attribute :model_version, :string
12
+ attribute :contacts, :neural_signature_contact
13
+
14
+ inherit_attributes
15
+
16
+ transfer :api, to: %i[contacts]
17
+ end
18
+ end
@@ -26,7 +26,7 @@ module Nylas
26
26
  attribute :tracking, :message_tracking
27
27
 
28
28
  def send!
29
- Message.new(api.execute(method: :post, path: "/send", payload: to_json).merge(api: api))
29
+ Message.new(**api.execute(method: :post, path: "/send", payload: to_json).merge(api: api))
30
30
  end
31
31
  end
32
32
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nylas
4
+ # Ruby representation of a Nylas Room Resource object
5
+ # @see https://developer.nylas.com/docs/api/#tag--Room-Resources
6
+ class RoomResource
7
+ include Model
8
+ self.resources_path = "/resources"
9
+ allows_operations(listable: true)
10
+
11
+ attribute :object, :string, read_only: true
12
+ attribute :email, :string, read_only: true
13
+ attribute :name, :string, read_only: true
14
+ attribute :capacity, :string, read_only: true
15
+ attribute :building, :string, read_only: true
16
+ attribute :floor_name, :string, read_only: true
17
+ attribute :floor_number, :string, read_only: true
18
+ end
19
+ end
data/lib/nylas/rsvp.rb CHANGED
@@ -13,8 +13,12 @@ module Nylas
13
13
  attr_accessor :notify_participants
14
14
 
15
15
  def save
16
- api.execute(method: :post, path: "/send-rsvp", payload: attributes.serialize,
17
- query: { notify_participants: notify_participants })
16
+ api.execute(
17
+ method: :post,
18
+ path: "/send-rsvp",
19
+ payload: attributes.serialize_for_api,
20
+ query: { notify_participants: notify_participants }
21
+ )
18
22
  end
19
23
  end
20
24
  end
data/lib/nylas/thread.rb CHANGED
@@ -23,6 +23,7 @@ module Nylas
23
23
  has_n_of_attribute :labels, :label
24
24
  has_n_of_attribute :folders, :folder
25
25
  has_n_of_attribute :message_ids, :string
26
+ has_n_of_attribute :messages, :message
26
27
  has_n_of_attribute :participants, :participant
27
28
  attribute :snippet, :string
28
29
  attribute :starred, :boolean
data/lib/nylas/types.rb CHANGED
@@ -144,5 +144,16 @@ module Nylas
144
144
  end
145
145
  end
146
146
  Types.registry[:boolean] = BooleanType.new
147
+
148
+ # Type for attributes represented as floats.
149
+ class FloatType < ValueType
150
+ # @param value [Object] Strictly casts the passed in value to a boolean (must be true, not "" or 1)
151
+ def cast(value)
152
+ return nil if value.nil?
153
+
154
+ value.to_f
155
+ end
156
+ end
157
+ Types.registry[:float] = FloatType.new
147
158
  end
148
159
  end
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.0.0"
4
+ VERSION = "5.4.0"
5
5
  end
data/lib/nylas/when.rb CHANGED
@@ -8,7 +8,7 @@ module Nylas
8
8
 
9
9
  include Model::Attributable
10
10
 
11
- attribute :object, :string
11
+ attribute :object, :string, read_only: true
12
12
 
13
13
  # when object == 'date'
14
14
  attribute :date, :date
data/lib/nylas.rb CHANGED
@@ -53,6 +53,9 @@ require_relative "nylas/nylas_date"
53
53
  require_relative "nylas/when"
54
54
  require_relative "nylas/free_busy"
55
55
  require_relative "nylas/time_slot"
56
+ require_relative "nylas/event_conferencing"
57
+ require_relative "nylas/event_conferencing_details"
58
+ require_relative "nylas/event_conferencing_autocreate"
56
59
 
57
60
  # Custom collection types
58
61
  require_relative "nylas/search_collection"
@@ -69,11 +72,25 @@ require_relative "nylas/deltas"
69
72
  require_relative "nylas/delta"
70
73
  require_relative "nylas/draft"
71
74
  require_relative "nylas/message"
75
+ require_relative "nylas/room_resource"
72
76
  require_relative "nylas/new_message"
73
77
  require_relative "nylas/raw_message"
74
78
  require_relative "nylas/thread"
75
79
  require_relative "nylas/webhook"
76
80
 
81
+ # Neural specific types
82
+ require_relative "nylas/neural"
83
+ require_relative "nylas/neural_sentiment_analysis"
84
+ require_relative "nylas/neural_ocr"
85
+ require_relative "nylas/neural_categorizer"
86
+ require_relative "nylas/neural_clean_conversation"
87
+ require_relative "nylas/neural_contact_link"
88
+ require_relative "nylas/neural_contact_name"
89
+ require_relative "nylas/neural_signature_contact"
90
+ require_relative "nylas/neural_signature_extraction"
91
+ require_relative "nylas/neural_message_options"
92
+ require_relative "nylas/categorize"
93
+
77
94
  require_relative "nylas/native_authentication"
78
95
 
79
96
  require_relative "nylas/http_client"
@@ -94,6 +111,7 @@ module Nylas
94
111
  Types.registry[:folder] = Types::ModelType.new(model: Folder)
95
112
  Types.registry[:im_address] = Types::ModelType.new(model: IMAddress)
96
113
  Types.registry[:label] = Types::ModelType.new(model: Label)
114
+ Types.registry[:room_resource] = Types::ModelType.new(model: RoomResource)
97
115
  Types.registry[:message] = Types::ModelType.new(model: Message)
98
116
  Types.registry[:message_headers] = MessageHeadersType.new
99
117
  Types.registry[:message_tracking] = Types::ModelType.new(model: MessageTracking)
@@ -108,4 +126,12 @@ module Nylas
108
126
  Types.registry[:contact_group] = Types::ModelType.new(model: ContactGroup)
109
127
  Types.registry[:when] = Types::ModelType.new(model: When)
110
128
  Types.registry[:time_slot] = Types::ModelType.new(model: TimeSlot)
129
+ Types.registry[:event_conferencing] = Types::ModelType.new(model: EventConferencing)
130
+ Types.registry[:event_conferencing_details] = Types::ModelType.new(model: EventConferencingDetails)
131
+ Types.registry[:event_conferencing_autocreate] = Types::ModelType.new(model: EventConferencingAutocreate)
132
+ Types.registry[:neural] = Types::ModelType.new(model: Neural)
133
+ Types.registry[:categorize] = Types::ModelType.new(model: Categorize)
134
+ Types.registry[:neural_signature_contact] = Types::ModelType.new(model: NeuralSignatureContact)
135
+ Types.registry[:neural_contact_link] = Types::ModelType.new(model: NeuralContactLink)
136
+ Types.registry[:neural_contact_name] = Types::ModelType.new(model: NeuralContactName)
111
137
  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.0.0
4
+ version: 5.4.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-05-07 00:00:00.000000000 Z
11
+ date: 2021-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -270,6 +270,7 @@ files:
270
270
  - lib/nylas/account.rb
271
271
  - lib/nylas/api.rb
272
272
  - lib/nylas/calendar.rb
273
+ - lib/nylas/categorize.rb
273
274
  - lib/nylas/collection.rb
274
275
  - lib/nylas/constraints.rb
275
276
  - lib/nylas/contact.rb
@@ -283,6 +284,9 @@ files:
283
284
  - lib/nylas/errors.rb
284
285
  - lib/nylas/event.rb
285
286
  - lib/nylas/event_collection.rb
287
+ - lib/nylas/event_conferencing.rb
288
+ - lib/nylas/event_conferencing_autocreate.rb
289
+ - lib/nylas/event_conferencing_details.rb
286
290
  - lib/nylas/file.rb
287
291
  - lib/nylas/filter_attributes.rb
288
292
  - lib/nylas/folder.rb
@@ -302,6 +306,16 @@ files:
302
306
  - lib/nylas/model/list_attribute_definition.rb
303
307
  - lib/nylas/model/transferable.rb
304
308
  - lib/nylas/native_authentication.rb
309
+ - lib/nylas/neural.rb
310
+ - lib/nylas/neural_categorizer.rb
311
+ - lib/nylas/neural_clean_conversation.rb
312
+ - lib/nylas/neural_contact_link.rb
313
+ - lib/nylas/neural_contact_name.rb
314
+ - lib/nylas/neural_message_options.rb
315
+ - lib/nylas/neural_ocr.rb
316
+ - lib/nylas/neural_sentiment_analysis.rb
317
+ - lib/nylas/neural_signature_contact.rb
318
+ - lib/nylas/neural_signature_extraction.rb
305
319
  - lib/nylas/new_message.rb
306
320
  - lib/nylas/nylas_date.rb
307
321
  - lib/nylas/participant.rb
@@ -310,6 +324,7 @@ files:
310
324
  - lib/nylas/raw_message.rb
311
325
  - lib/nylas/recurrence.rb
312
326
  - lib/nylas/registry.rb
327
+ - lib/nylas/room_resource.rb
313
328
  - lib/nylas/rsvp.rb
314
329
  - lib/nylas/search_collection.rb
315
330
  - lib/nylas/thread.rb
@@ -345,7 +360,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
345
360
  - !ruby/object:Gem::Version
346
361
  version: '0'
347
362
  requirements: []
348
- rubygems_version: 3.1.2
363
+ rubygems_version: 3.2.17
349
364
  signing_key:
350
365
  specification_version: 4
351
366
  summary: Gem for interacting with the Nylas API