nylas_v2 5.14.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/lib/nylas_v2/account.rb +56 -0
  3. data/lib/nylas_v2/api.rb +244 -0
  4. data/lib/nylas_v2/application_details.rb +13 -0
  5. data/lib/nylas_v2/calendar.rb +46 -0
  6. data/lib/nylas_v2/calendar_collection.rb +144 -0
  7. data/lib/nylas_v2/categorize.rb +14 -0
  8. data/lib/nylas_v2/collection.rb +175 -0
  9. data/lib/nylas_v2/component.rb +35 -0
  10. data/lib/nylas_v2/component_collection.rb +10 -0
  11. data/lib/nylas_v2/constraints.rb +56 -0
  12. data/lib/nylas_v2/contact.rb +53 -0
  13. data/lib/nylas_v2/contact_group.rb +23 -0
  14. data/lib/nylas_v2/current_account.rb +23 -0
  15. data/lib/nylas_v2/delta.rb +56 -0
  16. data/lib/nylas_v2/deltas.rb +19 -0
  17. data/lib/nylas_v2/deltas_collection.rb +40 -0
  18. data/lib/nylas_v2/draft.rb +100 -0
  19. data/lib/nylas_v2/email_address.rb +12 -0
  20. data/lib/nylas_v2/errors.rb +111 -0
  21. data/lib/nylas_v2/event.rb +141 -0
  22. data/lib/nylas_v2/event_collection.rb +15 -0
  23. data/lib/nylas_v2/event_conferencing.rb +12 -0
  24. data/lib/nylas_v2/event_conferencing_autocreate.rb +10 -0
  25. data/lib/nylas_v2/event_conferencing_details.rb +14 -0
  26. data/lib/nylas_v2/event_notification.rb +17 -0
  27. data/lib/nylas_v2/file.rb +75 -0
  28. data/lib/nylas_v2/filter_attributes.rb +25 -0
  29. data/lib/nylas_v2/folder.rb +26 -0
  30. data/lib/nylas_v2/free_busy.rb +13 -0
  31. data/lib/nylas_v2/free_busy_collection.rb +48 -0
  32. data/lib/nylas_v2/http_client.rb +279 -0
  33. data/lib/nylas_v2/im_address.rb +11 -0
  34. data/lib/nylas_v2/job_status.rb +27 -0
  35. data/lib/nylas_v2/job_status_collection.rb +21 -0
  36. data/lib/nylas_v2/label.rb +27 -0
  37. data/lib/nylas_v2/logging.rb +41 -0
  38. data/lib/nylas_v2/message.rb +98 -0
  39. data/lib/nylas_v2/message_headers.rb +27 -0
  40. data/lib/nylas_v2/message_tracking.rb +13 -0
  41. data/lib/nylas_v2/model/attributable.rb +89 -0
  42. data/lib/nylas_v2/model/attribute_definition.rb +24 -0
  43. data/lib/nylas_v2/model/attributes.rb +97 -0
  44. data/lib/nylas_v2/model/list_attribute_definition.rb +39 -0
  45. data/lib/nylas_v2/model/transferable.rb +53 -0
  46. data/lib/nylas_v2/model.rb +217 -0
  47. data/lib/nylas_v2/native_authentication.rb +39 -0
  48. data/lib/nylas_v2/neural.rb +87 -0
  49. data/lib/nylas_v2/neural_categorizer.rb +29 -0
  50. data/lib/nylas_v2/neural_clean_conversation.rb +33 -0
  51. data/lib/nylas_v2/neural_contact_link.rb +11 -0
  52. data/lib/nylas_v2/neural_contact_name.rb +11 -0
  53. data/lib/nylas_v2/neural_message_options.rb +35 -0
  54. data/lib/nylas_v2/neural_ocr.rb +16 -0
  55. data/lib/nylas_v2/neural_sentiment_analysis.rb +17 -0
  56. data/lib/nylas_v2/neural_signature_contact.rb +81 -0
  57. data/lib/nylas_v2/neural_signature_extraction.rb +18 -0
  58. data/lib/nylas_v2/new_message.rb +39 -0
  59. data/lib/nylas_v2/nylas_date.rb +25 -0
  60. data/lib/nylas_v2/open_hours.rb +15 -0
  61. data/lib/nylas_v2/outbox.rb +116 -0
  62. data/lib/nylas_v2/outbox_job_status.rb +19 -0
  63. data/lib/nylas_v2/outbox_message.rb +17 -0
  64. data/lib/nylas_v2/participant.rb +13 -0
  65. data/lib/nylas_v2/phone_number.rb +11 -0
  66. data/lib/nylas_v2/physical_address.rb +17 -0
  67. data/lib/nylas_v2/raw_message.rb +25 -0
  68. data/lib/nylas_v2/recurrence.rb +11 -0
  69. data/lib/nylas_v2/registry.rb +42 -0
  70. data/lib/nylas_v2/room_resource.rb +19 -0
  71. data/lib/nylas_v2/rsvp.rb +24 -0
  72. data/lib/nylas_v2/scheduler.rb +51 -0
  73. data/lib/nylas_v2/scheduler_booking_confirmation.rb +24 -0
  74. data/lib/nylas_v2/scheduler_booking_request.rb +17 -0
  75. data/lib/nylas_v2/scheduler_collection.rb +104 -0
  76. data/lib/nylas_v2/scheduler_config.rb +20 -0
  77. data/lib/nylas_v2/scheduler_time_slot.rb +14 -0
  78. data/lib/nylas_v2/search_collection.rb +10 -0
  79. data/lib/nylas_v2/send_grid_verified_status.rb +12 -0
  80. data/lib/nylas_v2/thread.rb +66 -0
  81. data/lib/nylas_v2/time_slot.rb +16 -0
  82. data/lib/nylas_v2/time_slot_capacity.rb +13 -0
  83. data/lib/nylas_v2/timespan.rb +20 -0
  84. data/lib/nylas_v2/token_info.rb +20 -0
  85. data/lib/nylas_v2/types.rb +168 -0
  86. data/lib/nylas_v2/version.rb +5 -0
  87. data/lib/nylas_v2/web_page.rb +11 -0
  88. data/lib/nylas_v2/webhook.rb +98 -0
  89. data/lib/nylas_v2/when.rb +75 -0
  90. data/lib/nylas_v2.rb +162 -0
  91. metadata +415 -0
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ Error = Class.new(::StandardError)
5
+
6
+ class ModelActionError < Error; end
7
+ class ModelNotFilterableError < ModelActionError; end
8
+ class ModelNotCreatableError < ModelActionError; end
9
+ class ModelNotShowableError < ModelActionError; end
10
+ class ModelNotAvailableAsRawError < ModelActionError; end
11
+ class ModelNotListableError < ModelActionError; end
12
+ class ModelNotFilterableError < ModelActionError; end
13
+ class ModelNotSearchableError < ModelActionError; end
14
+ class ModelNotUpdatableError < ModelActionError; end
15
+ class ModelNotDestroyableError < ModelActionError; end
16
+
17
+ class JsonParseError < Error; end
18
+
19
+ # Raised when attempting to set a field that is not on a model with mass assignment
20
+ class ModelMissingFieldError < ModelActionError
21
+ def initialize(field, model)
22
+ super("#{field} is not a valid attribute for #{model.class.name}")
23
+ end
24
+ end
25
+
26
+ # Indicates that a given method needs an access token to work.
27
+ class NoAuthToken < Error
28
+ def initialize(method_name)
29
+ super "No access token was provided and the #{method_name} method requires one"
30
+ end
31
+ end
32
+
33
+ UnexpectedAccountAction = Class.new(Error)
34
+ UnexpectedResponse = Class.new(Error)
35
+
36
+ # Base class to inflate the standard errors returned from the Nylas API
37
+ class APIError < Error
38
+ attr_accessor :type
39
+ attr_accessor :message
40
+ attr_accessor :server_error
41
+
42
+ def initialize(type, message, server_error = nil)
43
+ super(message)
44
+ self.type = type
45
+ self.message = message
46
+ self.server_error = server_error
47
+ end
48
+
49
+ def self.parse_error_response(response)
50
+ new(
51
+ response["type"],
52
+ response["message"],
53
+ response["server_error"]
54
+ )
55
+ end
56
+ end
57
+
58
+ # Error class representing a 429 error response, with details on the rate limit
59
+ class RateLimitError < APIError
60
+ attr_accessor :rate_limit
61
+ attr_accessor :rate_limit_reset
62
+
63
+ RATE_LIMIT_LIMIT_HEADER = "x_ratelimit_limit"
64
+ RATE_LIMIT_RESET_HEADER = "x_ratelimit_reset"
65
+
66
+ def initialize(type, message, server_error = nil, rate_limit = nil, rate_limit_reset = nil)
67
+ super(type, message, server_error)
68
+ self.rate_limit = rate_limit
69
+ self.rate_limit_reset = rate_limit_reset
70
+ end
71
+
72
+ def self.parse_error_response(response)
73
+ rate_limit, rate_limit_rest = extract_rate_limit_details(response)
74
+
75
+ new(
76
+ response["type"],
77
+ response["message"],
78
+ response["server_error"],
79
+ rate_limit,
80
+ rate_limit_rest
81
+ )
82
+ end
83
+
84
+ def self.extract_rate_limit_details(response)
85
+ return nil, nil unless response.respond_to?(:headers)
86
+
87
+ rate_limit = response.headers[RATE_LIMIT_LIMIT_HEADER.to_sym].to_i
88
+ rate_limit_rest = response.headers[RATE_LIMIT_RESET_HEADER.to_sym].to_i
89
+
90
+ [rate_limit, rate_limit_rest]
91
+ end
92
+
93
+ private_class_method :extract_rate_limit_details
94
+ end
95
+
96
+ AccessDenied = Class.new(APIError)
97
+ ResourceNotFound = Class.new(APIError)
98
+ MethodNotAllowed = Class.new(APIError)
99
+ InvalidRequest = Class.new(APIError)
100
+ UnauthorizedRequest = Class.new(APIError)
101
+ ResourceRemoved = Class.new(APIError)
102
+ TeapotError = Class.new(APIError)
103
+ RequestTimedOut = Class.new(APIError)
104
+ MessageRejected = Class.new(APIError)
105
+ SendingQuotaExceeded = Class.new(RateLimitError)
106
+ ServiceUnavailable = Class.new(APIError)
107
+ BadGateway = Class.new(APIError)
108
+ InternalError = Class.new(APIError)
109
+ EndpointNotYetImplemented = Class.new(APIError)
110
+ MailProviderError = Class.new(APIError)
111
+ end
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Structure to represent a the Event Schema.
5
+ # @see https://docs.nylas.com/reference#events
6
+ class Event
7
+ include Model
8
+ self.resources_path = "/events"
9
+ self.creatable = true
10
+ self.listable = true
11
+ self.showable = true
12
+ self.filterable = true
13
+ self.updatable = true
14
+ self.destroyable = true
15
+ self.id_listable = true
16
+ self.countable = true
17
+
18
+ attribute :id, :string, read_only: true
19
+ attribute :object, :string, read_only: true
20
+ attribute :account_id, :string, read_only: true
21
+ attribute :calendar_id, :string
22
+ attribute :master_event_id, :string
23
+ attribute :message_id, :string
24
+ attribute :ical_uid, :string
25
+ attribute :event_collection_id, :string
26
+
27
+ attribute :capacity, :integer
28
+ attribute :busy, :boolean
29
+ attribute :description, :string
30
+ attribute :location, :string
31
+ attribute :owner, :string
32
+ attribute :recurrence, :recurrence
33
+ has_n_of_attribute :participants, :participant
34
+ attribute :read_only, :boolean
35
+ attribute :status, :string
36
+ attribute :title, :string
37
+ attribute :when, :when
38
+ attribute :metadata, :hash
39
+ attribute :conferencing, :event_conferencing
40
+ has_n_of_attribute :notifications, :event_notification
41
+ has_n_of_attribute :round_robin_order, :string
42
+ attribute :original_start_time, :unix_timestamp
43
+ attribute :reminder_minutes, :string
44
+ attribute :reminder_method, :string
45
+ attribute :job_status_id, :string, read_only: true
46
+ attribute :visibility, :string
47
+
48
+ attr_accessor :notify_participants
49
+
50
+ def busy?
51
+ busy
52
+ end
53
+
54
+ def read_only?
55
+ read_only
56
+ end
57
+
58
+ def save
59
+ validate
60
+ format_reminder_minutes
61
+
62
+ super
63
+ end
64
+
65
+ def rsvp(status, notify_participants:)
66
+ rsvp = Rsvp.new(api: api, status: status, notify_participants: notify_participants,
67
+ event_id: id, account_id: account_id)
68
+ rsvp.save
69
+ end
70
+
71
+ # Generate an ICS file server-side, from an Event
72
+ # @param ical_uid [String] Unique identifier used events across calendaring systems
73
+ # @param method [String] Description of invitation and response methods for attendees
74
+ # @param prodid [String] Company-specific unique product identifier
75
+ # @return [String] String for writing directly into an ICS file
76
+ def generate_ics(ical_uid: nil, method: nil, prodid: nil)
77
+ raise ArgumentError, "Cannot generate an ICS file for an event without a Calendar ID or when set" unless
78
+ calendar_id && self.when
79
+
80
+ payload = build_ics_event_payload(ical_uid, method, prodid)
81
+ response = api.execute(
82
+ method: :post,
83
+ path: "#{resources_path}/to-ics",
84
+ payload: JSON.dump(payload)
85
+ )
86
+
87
+ response[:ics]
88
+ end
89
+
90
+ private
91
+
92
+ def validate
93
+ if conferencing
94
+ body = to_h
95
+ if body.dig(:conferencing, :details) && body.dig(:conferencing, :autocreate)
96
+ raise ArgumentError, "Cannot set both 'details' and 'autocreate' in conferencing object."
97
+ end
98
+ end
99
+ return unless capacity && capacity != -1 && participants && participants.length > capacity
100
+
101
+ raise ArgumentError, "The number of participants in the event exceeds the set capacity."
102
+ end
103
+
104
+ def build_ics_event_payload(ical_uid, method, prodid)
105
+ payload = {}
106
+ if id
107
+ payload[:event_id] = id
108
+ else
109
+ payload = to_h(enforce_read_only: true)
110
+ end
111
+ ics_options = build_ics_options_payload(ical_uid, method, prodid)
112
+ payload["ics_options"] = ics_options unless ics_options.empty?
113
+ payload
114
+ end
115
+
116
+ def build_ics_options_payload(ical_uid, method, prodid)
117
+ payload = {}
118
+ payload["ical_uid"] = ical_uid if ical_uid
119
+ payload["method"] = method if method
120
+ payload["prodid"] = prodid if prodid
121
+ payload
122
+ end
123
+
124
+ # Formats the reminder minute field to match the API format: "[%d]"
125
+ def format_reminder_minutes
126
+ return if reminder_minutes.nil? || reminder_minutes.empty? || reminder_minutes.match(/\[\d+\]/)
127
+
128
+ self.reminder_minutes = "[#{reminder_minutes}]"
129
+ end
130
+
131
+ def query_params
132
+ if notify_participants.nil?
133
+ {}
134
+ else
135
+ {
136
+ notify_participants: notify_participants
137
+ }
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Syntactical sugar methods for some of the Event's filters
5
+ # @see https://docs.nylas.com/reference#get-events
6
+ class EventCollection < Collection
7
+ def expand_recurring
8
+ where(expand_recurring: true)
9
+ end
10
+
11
+ def show_cancelled
12
+ where(show_cancelled: true)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
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 NylasV2
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 NylasV2
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
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
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
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Structure to represent a the File Schema.
5
+ # @see https://docs.nylas.com/reference#events
6
+ class File
7
+ include Model
8
+ self.resources_path = "/files"
9
+ self.creatable = true
10
+ self.listable = true
11
+ self.showable = true
12
+ self.filterable = true
13
+ self.destroyable = true
14
+ self.id_listable = true
15
+ self.countable = true
16
+
17
+ attribute :id, :string
18
+ attribute :account_id, :string
19
+ attribute :content_id, :string
20
+ has_n_of_attribute :message_ids, :string
21
+
22
+ attribute :object, :string
23
+
24
+ attribute :content_type, :string
25
+ attribute :filename, :string
26
+ attribute :size, :integer
27
+ attribute :content_disposition, :string
28
+
29
+ attr_accessor :file
30
+
31
+ # Downloads and caches a local copy of the file.
32
+ # @return [Tempfile] - Local copy of the file
33
+ def download
34
+ return file if file
35
+
36
+ self.file = retrieve_file
37
+ end
38
+
39
+ # Redownloads a file even if it's been cached. Closes and unlinks the tempfile to help memory usage.
40
+ def download!
41
+ return download if file.nil?
42
+
43
+ file.close
44
+ file.unlink
45
+ self.file = nil
46
+ download
47
+ end
48
+
49
+ def create
50
+ save
51
+ end
52
+
53
+ def save
54
+ raise ModelNotUpdatableError if persisted?
55
+
56
+ response = api.execute(path: "/files", method: :post, headers: { multipart: true },
57
+ payload: { file: file })
58
+ attributes.merge(response.first)
59
+ true
60
+ end
61
+
62
+ private
63
+
64
+ def retrieve_file
65
+ response = api.get(path: "#{resource_path}/download")
66
+ filename = response.headers.fetch(:content_disposition, "").gsub("attachment; filename=", "")
67
+ # The returned filename can be longer than 256 chars which isn't supported by rb_sysopen.
68
+ # 128 chars here is more than enough given that TempFile ensure the filename will be unique.
69
+ temp_file = Tempfile.new(filename[0..127], encoding: "ascii-8bit")
70
+ temp_file.write(response.body)
71
+ temp_file.seek(0)
72
+ temp_file
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Methods to check and raise error if extra attributes are present
5
+ class FilterAttributes
6
+ def initialize(attributes:, allowed_attributes:)
7
+ @attributes = attributes
8
+ @allowed_attributes = allowed_attributes
9
+ end
10
+
11
+ def check
12
+ return if extra_attributes.empty?
13
+
14
+ raise ArgumentError, "Only #{allowed_attributes} are allowed to be sent"
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :attributes, :allowed_attributes
20
+
21
+ def extra_attributes
22
+ attributes - allowed_attributes
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Structure to represent the Folder Schema
5
+ # @see https://docs.nylas.com/reference#folders
6
+ class Folder
7
+ include Model
8
+ self.resources_path = "/folders"
9
+ self.creatable = true
10
+ self.listable = true
11
+ self.showable = true
12
+ self.filterable = false
13
+ self.updatable = true
14
+ self.destroyable = true
15
+ self.id_listable = true
16
+ self.countable = true
17
+
18
+ attribute :id, :string, read_only: true
19
+ attribute :account_id, :string, read_only: true
20
+ attribute :object, :string, read_only: true
21
+
22
+ attribute :name, :string
23
+ attribute :display_name, :string
24
+ attribute :job_status_id, :string, read_only: true
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Query free/busy information for a calendar during a certain time period
5
+ # @see https://docs.nylas.com/reference#calendars-free-busy
6
+ class FreeBusy
7
+ include Model::Attributable
8
+
9
+ attribute :email, :string
10
+ attribute :object, :string
11
+ has_n_of_attribute :time_slots, :time_slot
12
+ end
13
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Helper to get and build `FreeBusy` objects
5
+ class FreeBusyCollection
6
+ extend Forwardable
7
+ def_delegators :each, :map, :select, :reject, :to_a, :take
8
+ def_delegators :to_a, :first, :last, :[]
9
+
10
+ def initialize(emails:, start_time:, end_time:, api:)
11
+ @api = api
12
+ @emails = emails
13
+ @start_time = start_time
14
+ @end_time = end_time
15
+ end
16
+
17
+ def each
18
+ return enum_for(:each) unless block_given?
19
+
20
+ execute.each do |result|
21
+ yield(FreeBusy.new(**result))
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :api, :emails, :start_time, :end_time
28
+
29
+ PATH = "/calendars/free-busy"
30
+ private_constant :PATH
31
+
32
+ def execute
33
+ api.execute(
34
+ method: :post,
35
+ path: PATH,
36
+ payload: payload
37
+ )
38
+ end
39
+
40
+ def payload
41
+ JSON.dump(
42
+ emails: emails,
43
+ start_time: start_time,
44
+ end_time: end_time
45
+ )
46
+ end
47
+ end
48
+ end