nylas 5.2.0 → 5.3.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: c6b0265bb93198dcc5494a819c68a5261703a143a4fe320a4662cc6c65aa2e94
4
- data.tar.gz: ee107c7cacfb2b7e2b099fd675c20c02700def063e1ccdd6b46923448da9e25b
3
+ metadata.gz: 8ab5c418509c447497fbd6106eb6e01fb7c23af451bf8150584b9bcf4e1ce736
4
+ data.tar.gz: 6827492459317c848f6f89c748a1cf5f5858506b83a578f53dbb4169010779ad
5
5
  SHA512:
6
- metadata.gz: 4e7aca3de25b0e2847011c4b190960405a214e8905429ba2743f9d3bd068d41e60cb36ad7365d298f685eb47979c30df0397996212d784c26e20e54f32b874aa
7
- data.tar.gz: 8fc30003aa6609694e5f2a7aedf2c949e2f191c45a0edea6045669d918c3ff88cdfc837046ec409815f67c255b7a1184586532878988166cd39865c8517f00fe
6
+ metadata.gz: 593d58ed82147ee51b00f90ed0e619eb4a6680b07cc8bae04eeba0809026e2e24ecce2565292c026bd2d164fba8a6a76f67768bf362c35c8e50bc0efbbe61da1
7
+ data.tar.gz: 10ed94be5d4e2c785ef92d32495301857f6c193e85e5087e96e8c2826b379219833f6db07c669c38fb7be573f77376748a6b323c1af46952c10853bf50e04233
data/lib/nylas.rb CHANGED
@@ -75,6 +75,19 @@ require_relative "nylas/raw_message"
75
75
  require_relative "nylas/thread"
76
76
  require_relative "nylas/webhook"
77
77
 
78
+ # Neural specific types
79
+ require_relative "nylas/neural"
80
+ require_relative "nylas/neural_sentiment_analysis"
81
+ require_relative "nylas/neural_ocr"
82
+ require_relative "nylas/neural_categorizer"
83
+ require_relative "nylas/neural_clean_conversation"
84
+ require_relative "nylas/neural_contact_link"
85
+ require_relative "nylas/neural_contact_name"
86
+ require_relative "nylas/neural_signature_contact"
87
+ require_relative "nylas/neural_signature_extraction"
88
+ require_relative "nylas/neural_message_options"
89
+ require_relative "nylas/categorize"
90
+
78
91
  require_relative "nylas/native_authentication"
79
92
 
80
93
  require_relative "nylas/http_client"
@@ -110,4 +123,9 @@ module Nylas
110
123
  Types.registry[:contact_group] = Types::ModelType.new(model: ContactGroup)
111
124
  Types.registry[:when] = Types::ModelType.new(model: When)
112
125
  Types.registry[:time_slot] = Types::ModelType.new(model: TimeSlot)
126
+ Types.registry[:neural] = Types::ModelType.new(model: Neural)
127
+ Types.registry[:categorize] = Types::ModelType.new(model: Categorize)
128
+ Types.registry[:neural_signature_contact] = Types::ModelType.new(model: NeuralSignatureContact)
129
+ Types.registry[:neural_contact_link] = Types::ModelType.new(model: NeuralContactLink)
130
+ Types.registry[:neural_contact_name] = Types::ModelType.new(model: NeuralContactName)
113
131
  end
data/lib/nylas/api.rb CHANGED
@@ -126,6 +126,11 @@ module Nylas
126
126
  @room_resources ||= Collection.new(model: RoomResource, api: self)
127
127
  end
128
128
 
129
+ # @return[Neural] A {Neural} object that provides
130
+ def neural
131
+ @neural ||= Neural.new(api: self)
132
+ end
133
+
129
134
  # Revokes access to the Nylas API for the given access token
130
135
  # @return [Boolean]
131
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/delta.rb CHANGED
@@ -15,6 +15,8 @@ module Nylas
15
15
  attribute :namespace_id, :string
16
16
  attribute :account_id, :string
17
17
 
18
+ attribute :headers, :message_headers
19
+
18
20
  attribute :date, :unix_timestamp
19
21
  attribute :metadata, :hash
20
22
  attribute :object_attributes, :hash
@@ -5,7 +5,7 @@ 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, 302].freeze
8
+ HTTP_SUCCESS_CODES = [200, 201, 302].freeze
9
9
 
10
10
  HTTP_CODE_TO_EXCEPTIONS = {
11
11
  400 => InvalidRequest,
@@ -92,7 +92,12 @@ module Nylas
92
92
  content_type = response.headers[:content_type].downcase
93
93
  end
94
94
 
95
- 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
96
101
 
97
102
  handle_failed_response(result: result, response: response)
98
103
  response
@@ -139,7 +144,7 @@ module Nylas
139
144
  "X-Nylas-Client-Id" => @app_id,
140
145
  "Nylas-API-Version" => SUPPORTED_API_VERSION,
141
146
  "User-Agent" => "Nylas Ruby SDK #{Nylas::VERSION} - #{RUBY_VERSION}",
142
- "Content-types" => "application/json"
147
+ "Content-type" => "application/json"
143
148
  }
144
149
  end
145
150
 
@@ -179,12 +184,12 @@ module Nylas
179
184
  return if HTTP_SUCCESS_CODES.include?(http_code)
180
185
 
181
186
  exception = HTTP_CODE_TO_EXCEPTIONS.fetch(http_code, APIError)
182
- parsed_response = parse_response(response)
187
+ raise exception.new(http_code, response) unless response.is_a?(Hash)
183
188
 
184
189
  raise exception.new(
185
- parsed_response[:type],
186
- parsed_response[:message],
187
- parsed_response.fetch(:server_error, nil)
190
+ response[:type],
191
+ response[:message],
192
+ response.fetch(:server_error, nil)
188
193
  )
189
194
  end
190
195
 
@@ -63,6 +63,21 @@ module Nylas
63
63
  end
64
64
  end
65
65
 
66
+ # Allows a class to inherit parent's attributes
67
+ def inherit_attributes
68
+ return if superclass.nil?
69
+
70
+ parent_attributes = superclass.attribute_definitions
71
+ parent_attributes.each do |parent_attribute|
72
+ name = parent_attribute[0]
73
+ attr = parent_attribute[1]
74
+ next if attribute_definitions.key?(name)
75
+
76
+ attribute_definitions[name] = attr
77
+ define_accessors(name)
78
+ end
79
+ end
80
+
66
81
  def attribute_definitions
67
82
  @attribute_definitions ||= Registry.new
68
83
  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
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.2.0"
4
+ VERSION = "5.3.0"
5
5
  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.2.0
4
+ version: 5.3.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-07-15 00:00:00.000000000 Z
11
+ date: 2021-08-18 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
@@ -302,6 +303,16 @@ files:
302
303
  - lib/nylas/model/list_attribute_definition.rb
303
304
  - lib/nylas/model/transferable.rb
304
305
  - lib/nylas/native_authentication.rb
306
+ - lib/nylas/neural.rb
307
+ - lib/nylas/neural_categorizer.rb
308
+ - lib/nylas/neural_clean_conversation.rb
309
+ - lib/nylas/neural_contact_link.rb
310
+ - lib/nylas/neural_contact_name.rb
311
+ - lib/nylas/neural_message_options.rb
312
+ - lib/nylas/neural_ocr.rb
313
+ - lib/nylas/neural_sentiment_analysis.rb
314
+ - lib/nylas/neural_signature_contact.rb
315
+ - lib/nylas/neural_signature_extraction.rb
305
316
  - lib/nylas/new_message.rb
306
317
  - lib/nylas/nylas_date.rb
307
318
  - lib/nylas/participant.rb