inbox 0.18.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +54 -54
- data/lib/account.rb +1 -1
- data/lib/api_account.rb +21 -0
- data/lib/draft.rb +1 -1
- data/lib/event.rb +1 -1
- data/lib/inbox.rb +228 -11
- data/lib/message.rb +2 -2
- data/lib/nylas.rb +228 -11
- data/lib/restful_model.rb +4 -4
- data/lib/restful_model_collection.rb +3 -5
- data/lib/version.rb +1 -1
- metadata +3 -3
- data/lib/namespace.rb +0 -210
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4572727f15af142648617ef23c2d02cfbaeb829a
|
4
|
+
data.tar.gz: 11dc0cb420be765146e33679ca143f4ccd798a16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37b247c67eeff634a5f215810ea8b60e54a59c49282e0bbab16302b28fd1ac1d808e760891e208f4fd6e35a23228db5a26bf1addbb9c0d0a5c208eaf77dd386c
|
7
|
+
data.tar.gz: 573a0525f28d8c219be3df6863846f29b8ee4148b87c7ef9c4f47be79768abb65928c8e9d986b9234c234ec29ece20b608b8a9cf0fc6ec0451bb54544f2222fe
|
data/README.md
CHANGED
@@ -55,7 +55,7 @@ Generally, you should store your App ID and Secret into environment variables to
|
|
55
55
|
|
56
56
|
### Authentication
|
57
57
|
|
58
|
-
The Nylas REST API uses server-side (three-legged) OAuth, and the Ruby gem provides convenience methods that simplify the OAuth process. For more information about authenticating with Nylas, visit the [Developer Documentation](https://
|
58
|
+
The Nylas REST API uses server-side (three-legged) OAuth, and the Ruby gem provides convenience methods that simplify the OAuth process. For more information about authenticating with Nylas, visit the [Developer Documentation](https://nylas.com/docs/platform#authentication).
|
59
59
|
|
60
60
|
**Step 1: Redirect the user to Nylas:**
|
61
61
|
|
@@ -113,12 +113,9 @@ If you're using the open-source version of the Nylas Sync Engine or have fewer t
|
|
113
113
|
```ruby
|
114
114
|
nylas = Nylas::API.new(config.nylas_app_id, config.nylas_app_secret, nylas_token)
|
115
115
|
|
116
|
-
# Get the first namespace
|
117
|
-
namespace = nylas.namespaces.first
|
118
|
-
|
119
116
|
# Print out the email address and provider (Gmail, Exchange)
|
120
|
-
puts
|
121
|
-
puts
|
117
|
+
puts nylas.account.email_address
|
118
|
+
puts nylas.account.provider
|
122
119
|
```
|
123
120
|
|
124
121
|
|
@@ -126,36 +123,36 @@ puts namespace.provider
|
|
126
123
|
|
127
124
|
```ruby
|
128
125
|
# Fetch the first thread
|
129
|
-
thread =
|
126
|
+
thread = nylas.threads.first
|
130
127
|
|
131
128
|
# Fetch a specific thread
|
132
|
-
thread =
|
129
|
+
thread = nylas.threads.find('ac123acd123ef123')
|
133
130
|
|
134
131
|
# List all threads tagged `inbox`
|
135
132
|
# (paginating 50 at a time until no more are returned.)
|
136
|
-
|
133
|
+
nylas.threads.where(:tag => 'inbox').each do |thread|
|
137
134
|
puts thread.subject
|
138
135
|
end
|
139
136
|
|
140
137
|
# List the 5 most recent unread threads
|
141
|
-
|
138
|
+
nylas.threads.where(:tag => 'unread').range(0,4).each do |thread|
|
142
139
|
puts thread.subject
|
143
140
|
end
|
144
141
|
|
145
142
|
# List all threads with 'ben@nylas.com'
|
146
|
-
|
143
|
+
nylas.threads.where(:any_email => 'ben@nylas.com').each do |thread|
|
147
144
|
puts thread.subject
|
148
145
|
end
|
149
146
|
|
150
147
|
# Get number of all threads
|
151
|
-
count =
|
148
|
+
count = nylas.threads.count
|
152
149
|
|
153
150
|
# Get number of threads with 'ben@inboxapp.com'
|
154
|
-
count =
|
151
|
+
count = nylas.threads.where(:any_email => 'ben@inboxapp.com').count
|
155
152
|
|
156
153
|
# Collect all threads with 'ben@nylas.com' into an array.
|
157
154
|
# Note: for large numbers of threads, this is not advised.
|
158
|
-
threads =
|
155
|
+
threads = nylas.threads.where(:any_email => 'ben@nylas.com').all
|
159
156
|
```
|
160
157
|
|
161
158
|
|
@@ -181,13 +178,13 @@ thread.update_tags!(tagsToAdd, tagsToRemove)
|
|
181
178
|
# Add a new label to a message
|
182
179
|
|
183
180
|
important = nil
|
184
|
-
|
181
|
+
nylas.labels.each do |label|
|
185
182
|
if label.display_name == 'Important'
|
186
183
|
important = label
|
187
184
|
end
|
188
185
|
end
|
189
186
|
|
190
|
-
thread =
|
187
|
+
thread = nylas.threads.where(:from => "helena@nylas.com").first
|
191
188
|
thread.labels.push(important)
|
192
189
|
thread.save!
|
193
190
|
|
@@ -202,41 +199,41 @@ end
|
|
202
199
|
|
203
200
|
```ruby
|
204
201
|
# List files
|
205
|
-
|
202
|
+
nylas.files.each do |file|
|
206
203
|
puts file.filename
|
207
204
|
end
|
208
205
|
|
209
206
|
# Create a new file
|
210
|
-
file =
|
207
|
+
file = nylas.files.build(:file => File.new("./public/favicon.ico", 'rb'))
|
211
208
|
file.save!
|
212
209
|
```
|
213
210
|
|
214
|
-
### Working with Labels/
|
211
|
+
### Working with Labels/Folders
|
215
212
|
|
216
213
|
The new folders and labels API replaces the now deprecated Tags API. It allows you to apply Gmail labels to whole threads or individual messages and, for providers other than Gmail, to move threads and messages between folders.
|
217
214
|
|
218
215
|
```ruby
|
219
216
|
|
220
217
|
# List labels
|
221
|
-
|
218
|
+
nylas.labels.each do |label|
|
222
219
|
puts label.display_name, label.id
|
223
220
|
end
|
224
221
|
|
225
222
|
# Create a label
|
226
|
-
label =
|
223
|
+
label = nylas.folders.build(:display_name => 'Test label', :name => 'test name')
|
227
224
|
label.save!
|
228
225
|
|
229
226
|
# Create a folder
|
230
227
|
#
|
231
228
|
# Note that Folders and Labels are absolutely identical from the standpoint of the SDK.
|
232
229
|
# The only difference is that a message can have many labels but only a single folder.
|
233
|
-
fld =
|
230
|
+
fld = nylas.folders.build(:display_name => 'Test folder', :name => 'test name')
|
234
231
|
fld.save!
|
235
232
|
|
236
233
|
# Rename a folder
|
237
234
|
#
|
238
235
|
# Note that you can not rename folders like INBOX, Trash, etc.
|
239
|
-
fld =
|
236
|
+
fld = nylas.folders.first
|
240
237
|
fld.display_name = 'Renamed folder'
|
241
238
|
fld.save!
|
242
239
|
|
@@ -247,10 +244,10 @@ fld.save!
|
|
247
244
|
Each of the primary collections (contacts, messages, etc.) behave the same way as `threads`. For example, finding messages with a filter is similar to finding threads:
|
248
245
|
|
249
246
|
```ruby
|
250
|
-
messages =
|
247
|
+
messages = nylas.messages.where(:to => 'ben@nylas.com`).all
|
251
248
|
```
|
252
249
|
|
253
|
-
The `where` method accepts a hash of filters, as documented in the [Filters Documentation](https://
|
250
|
+
The `where` method accepts a hash of filters, as documented in the [Filters Documentation](https://nylas.com/docs/platform#filters).
|
254
251
|
|
255
252
|
### Getting the raw contents of a message
|
256
253
|
|
@@ -265,7 +262,7 @@ raw_contents = message.raw
|
|
265
262
|
|
266
263
|
```ruby
|
267
264
|
# Create a new draft
|
268
|
-
draft =
|
265
|
+
draft = nylas.drafts.build(
|
269
266
|
:to => [{:name => 'Ben Gotow', :email => 'ben@nylas.com'}],
|
270
267
|
:subject => "Sent by Ruby",
|
271
268
|
:body => "Hi there!<strong>This is HTML</strong>"
|
@@ -288,8 +285,8 @@ draft.send!
|
|
288
285
|
|
289
286
|
````ruby
|
290
287
|
# Every event is attached to a calendar -- get the id of the first calendar
|
291
|
-
calendar_id =
|
292
|
-
new_event =
|
288
|
+
calendar_id = nylas.calendars.first.id
|
289
|
+
new_event = nylas.events.build(:calendar_id => calendar_id, :title => 'Coffee?')
|
293
290
|
|
294
291
|
# Modify attributes as necessary
|
295
292
|
new_event.location = "L'excelsior"
|
@@ -310,17 +307,16 @@ emailed_invite.rsvp!(status='yes', comment='I will come')
|
|
310
307
|
|
311
308
|
## Using the Delta sync API
|
312
309
|
|
313
|
-
The delta sync API allows fetching all the changes that occured
|
310
|
+
The delta sync API allows fetching all the changes that occured after a specific time. [Read this](https://nylas.com/docs/platform/#deltas) for more details about the API.
|
314
311
|
|
315
312
|
````ruby
|
316
|
-
# Get
|
317
|
-
#
|
318
|
-
#
|
319
|
-
|
320
|
-
cursor = nylas.namespaces.first.get_cursor(1407543195)
|
313
|
+
# Get an API cursor. Cursors are API objects identifying an individual change.
|
314
|
+
# The latest cursor is the id of the latest change which was applied
|
315
|
+
# to an API object (e.g: a message got read, an event got created, etc.)
|
316
|
+
cursor = nylas.latest_cursor
|
321
317
|
|
322
318
|
last_cursor = nil
|
323
|
-
nylas.
|
319
|
+
nylas.deltas(cursor) do |event, object|
|
324
320
|
if event == "create" or event == "modify"
|
325
321
|
if object.is_a?(Nylas::Contact)
|
326
322
|
puts "#{object.name} - #{object.email}"
|
@@ -346,14 +342,10 @@ save_to_db(last_cursor)
|
|
346
342
|
The streaming API will receive deltas in real time, without needing to repeatedly poll. It uses EventMachine for async IO.
|
347
343
|
|
348
344
|
````ruby
|
349
|
-
|
350
|
-
#
|
351
|
-
# we first need to get a cursor object a cursor is simply the id of
|
352
|
-
# an individual change.
|
353
|
-
cursor = inbox.namespaces.first.get_cursor(1407543195)
|
345
|
+
cursor = nylas.latest_cursor
|
354
346
|
|
355
347
|
last_cursor = nil
|
356
|
-
|
348
|
+
nylas.delta_stream(cursor) do |event, object|
|
357
349
|
if event == "create" or event == "modify"
|
358
350
|
if object.is_a?(Inbox::Contact)
|
359
351
|
puts "#{object.name} - #{object.email}"
|
@@ -376,11 +368,11 @@ end
|
|
376
368
|
|
377
369
|
### Exclude changes from a specific type --- get only messages
|
378
370
|
````ruby
|
379
|
-
nylas.
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
371
|
+
nylas.deltas(cursor, exclude=[Nylas::Contact,
|
372
|
+
Nylas::Event,
|
373
|
+
Nylas::File,
|
374
|
+
Nylas::Tag,
|
375
|
+
Nylas::Thread]) do |event, object|
|
384
376
|
if event == 'create' or event == 'modify'
|
385
377
|
puts object.subject
|
386
378
|
end
|
@@ -410,11 +402,19 @@ Code | Error Type | Description
|
|
410
402
|
|
411
403
|
## Open-Source Sync Engine
|
412
404
|
|
413
|
-
The [Nylas Sync Engine](http://github.com/nylas/sync-engine) is open source, and you can also use the Ruby gem with the open source API. Since the open source API provides no authentication or security, connecting to it is simple. When you instantiate the Nylas object, provide `nil` for the App ID
|
405
|
+
The [Nylas Sync Engine](http://github.com/nylas/sync-engine) is open source, and you can also use the Ruby gem with the open source API. Since the open source API provides no authentication or security, connecting to it is simple. When you instantiate the Nylas object, provide `nil` for the App ID and App Secret, and set the API Token to the id of the account you're going to access. Finally, don't forget to pass the fully-qualified address to your copy of the sync engine:
|
414
406
|
|
415
407
|
```ruby
|
416
|
-
require '
|
417
|
-
|
408
|
+
require 'nylas'
|
409
|
+
nylas = Nylas::API.new(nil, nil, nil, 'http://localhost:5555/')
|
410
|
+
|
411
|
+
# Get the id of the first account -- this is the access token we're
|
412
|
+
# going to use.
|
413
|
+
account_id = nylas.accounts.first.id
|
414
|
+
|
415
|
+
# Display the contents of the first message for the first account
|
416
|
+
nylas = Nylas::API.new(nil, nil, account_id, 'http://localhost:5555/')
|
417
|
+
puts nylas.messages.first.contents
|
418
418
|
```
|
419
419
|
|
420
420
|
|
@@ -443,10 +443,10 @@ Test your new version (found in `pkg/`) locally, and then release with:
|
|
443
443
|
|
444
444
|
If it's your first time updating the ruby gems, you may be prompted for the username/password for rubygems.org. Members of the Nylas team can find that by doing `fetch-password rubygems`.
|
445
445
|
|
446
|
-
##
|
447
|
-
|
448
|
-
Because it's very important that we don't break OAuth, we require releasers to run the OAuth self-test before releasing a version of the gem. The self-test is a small sinatra program which will ask you to click on a couple URLs. You need to make sure that following the URLs returns a working token.
|
446
|
+
## API self-tests
|
449
447
|
|
450
|
-
To set up
|
448
|
+
Because it's critical that we don't break the SDK for our customers, we require releasers to run some tests before releasing a new version of the gem. The test programs are located in the test/ directory. To set up them up, you'll need to copy `tests/credentials.rb.templates` as `test/credentials.rb` and edit the `APP_ID` and `APP_SECRET` with a working Nylas API app id and secret. You also need to set up a `/callback` URL in the Nylas admin panel.
|
451
449
|
|
452
|
-
You can
|
450
|
+
You can run the programs like this:
|
451
|
+
`cd tests && ruby -I../lib auth.rb`
|
452
|
+
`cd tests && ruby -I../lib system.rb`
|
data/lib/account.rb
CHANGED
@@ -12,7 +12,7 @@ module Inbox
|
|
12
12
|
def _perform_account_action!(action)
|
13
13
|
raise UnexpectedAccountAction.new unless action == "upgrade" || action == "downgrade"
|
14
14
|
|
15
|
-
collection = ManagementModelCollection.new(Account, @_api,
|
15
|
+
collection = ManagementModelCollection.new(Account, @_api, {:account_id=>@account_id})
|
16
16
|
::RestClient.post("#{collection.url}/#{@account_id}/#{action}",{}) do |response, request, result|
|
17
17
|
# Throw any exceptions
|
18
18
|
json = Inbox.interpret_response(result, response, :expected_class => Object)
|
data/lib/api_account.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# api_account.rb --- functions related to the /account endpoint.
|
2
|
+
# not to be confused with account.rb which is used by the hosted API
|
3
|
+
# account management endpoint.
|
4
|
+
require 'restful_model'
|
5
|
+
|
6
|
+
module Inbox
|
7
|
+
class APIAccount < RestfulModel
|
8
|
+
|
9
|
+
parameter :account_id
|
10
|
+
parameter :email_address
|
11
|
+
parameter :id
|
12
|
+
parameter :name
|
13
|
+
parameter :object
|
14
|
+
parameter :organization_unit
|
15
|
+
parameter :provider
|
16
|
+
|
17
|
+
def self.collection_name
|
18
|
+
"accounts"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/draft.rb
CHANGED
data/lib/event.rb
CHANGED
@@ -31,7 +31,7 @@ module Inbox
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def rsvp!(status, comment)
|
34
|
-
url = @_api.url_for_path("/
|
34
|
+
url = @_api.url_for_path("/send-rsvp")
|
35
35
|
data = {:event_id => @id, :status => status, :comment => comment}
|
36
36
|
|
37
37
|
::RestClient.post(url, data.to_json, :content_type => :json) do |response, request, result|
|
data/lib/inbox.rb
CHANGED
@@ -1,9 +1,26 @@
|
|
1
|
-
require 'version'
|
2
|
-
require 'rest-client'
|
3
|
-
require 'restful_model_collection'
|
4
1
|
require 'json'
|
5
|
-
require '
|
2
|
+
require 'rest-client'
|
3
|
+
require 'yajl'
|
4
|
+
require 'em-http'
|
5
|
+
require 'ostruct'
|
6
|
+
|
7
|
+
require 'account'
|
8
|
+
require 'api_account'
|
9
|
+
require 'api_thread'
|
10
|
+
require 'calendar'
|
6
11
|
require 'account'
|
12
|
+
require 'tag'
|
13
|
+
require 'message'
|
14
|
+
require 'draft'
|
15
|
+
require 'contact'
|
16
|
+
require 'file'
|
17
|
+
require 'calendar'
|
18
|
+
require 'event'
|
19
|
+
require 'folder'
|
20
|
+
require 'restful_model'
|
21
|
+
require 'restful_model_collection'
|
22
|
+
require 'version'
|
23
|
+
|
7
24
|
|
8
25
|
module Inbox
|
9
26
|
|
@@ -122,18 +139,218 @@ module Inbox
|
|
122
139
|
end
|
123
140
|
end
|
124
141
|
|
125
|
-
#
|
142
|
+
# API Methods
|
143
|
+
def threads
|
144
|
+
@threads ||= RestfulModelCollection.new(Thread, self)
|
145
|
+
end
|
126
146
|
|
127
|
-
def
|
128
|
-
@
|
129
|
-
@namespaces
|
147
|
+
def tags
|
148
|
+
@tags ||= RestfulModelCollection.new(Tag, self)
|
130
149
|
end
|
131
150
|
|
132
|
-
|
151
|
+
def messages
|
152
|
+
@messages ||= RestfulModelCollection.new(Message, self)
|
153
|
+
end
|
154
|
+
|
155
|
+
def files
|
156
|
+
@files ||= RestfulModelCollection.new(File, self)
|
157
|
+
end
|
158
|
+
|
159
|
+
def drafts
|
160
|
+
@drafts ||= RestfulModelCollection.new(Draft, self)
|
161
|
+
end
|
162
|
+
|
163
|
+
def contacts
|
164
|
+
@contacts ||= RestfulModelCollection.new(Contact, self)
|
165
|
+
end
|
166
|
+
|
167
|
+
def calendars
|
168
|
+
@calendars ||= RestfulModelCollection.new(Calendar, self)
|
169
|
+
end
|
170
|
+
|
171
|
+
def events
|
172
|
+
@events ||= RestfulModelCollection.new(Event, self)
|
173
|
+
end
|
174
|
+
|
175
|
+
def folders
|
176
|
+
@folders ||= RestfulModelCollection.new(Folder, self)
|
177
|
+
end
|
178
|
+
|
179
|
+
def labels
|
180
|
+
@labels ||= RestfulModelCollection.new(Label, self)
|
181
|
+
end
|
182
|
+
|
183
|
+
def account
|
184
|
+
path = self.url_for_path("/account")
|
185
|
+
|
186
|
+
RestClient.get(path, {}) do |response,request,result|
|
187
|
+
json = Inbox.interpret_response(result, response, {:expected_class => Object})
|
188
|
+
model = APIAccount.new(self)
|
189
|
+
model.inflate(json)
|
190
|
+
model
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def using_hosted_api?
|
195
|
+
return !@app_id.nil?
|
196
|
+
end
|
133
197
|
|
134
198
|
def accounts
|
135
|
-
|
136
|
-
|
199
|
+
if self.using_hosted_api?
|
200
|
+
@accounts ||= ManagementModelCollection.new(Account, self)
|
201
|
+
else
|
202
|
+
@accounts ||= RestfulModelCollection.new(APIAccount, self)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def get_cursor(timestamp)
|
207
|
+
# Get the cursor corresponding to a specific timestamp.
|
208
|
+
warn "Nylas#get_cursor is deprecated. Use Nylas#latest_cursor instead."
|
209
|
+
|
210
|
+
path = self.url_for_path("/delta/generate_cursor")
|
211
|
+
data = { :start => timestamp }
|
212
|
+
|
213
|
+
cursor = nil
|
214
|
+
|
215
|
+
RestClient.post(path, data.to_json, :content_type => :json) do |response,request,result|
|
216
|
+
json = Inbox.interpret_response(result, response, {:expected_class => Object})
|
217
|
+
cursor = json["cursor"]
|
218
|
+
end
|
219
|
+
|
220
|
+
cursor
|
221
|
+
end
|
222
|
+
|
223
|
+
def latest_cursor
|
224
|
+
# Get the cursor corresponding to a specific timestamp.
|
225
|
+
path = self.url_for_path("/delta/latest_cursor")
|
226
|
+
|
227
|
+
cursor = nil
|
228
|
+
|
229
|
+
RestClient.post(path, :content_type => :json) do |response,request,result|
|
230
|
+
json = Inbox.interpret_response(result, response, {:expected_class => Object})
|
231
|
+
cursor = json["cursor"]
|
232
|
+
end
|
233
|
+
|
234
|
+
cursor
|
235
|
+
end
|
236
|
+
|
237
|
+
OBJECTS_TABLE = {
|
238
|
+
"account" => Inbox::Account,
|
239
|
+
"calendar" => Inbox::Calendar,
|
240
|
+
"draft" => Inbox::Draft,
|
241
|
+
"thread" => Inbox::Thread,
|
242
|
+
"contact" => Inbox::Contact,
|
243
|
+
"event" => Inbox::Event,
|
244
|
+
"file" => Inbox::File,
|
245
|
+
"message" => Inbox::Message,
|
246
|
+
"tag" => Inbox::Tag,
|
247
|
+
"folder" => Inbox::Folder,
|
248
|
+
"label" => Inbox::Label,
|
249
|
+
}
|
250
|
+
|
251
|
+
def _build_exclude_types(exclude_types)
|
252
|
+
exclude_string = "&exclude_types="
|
253
|
+
|
254
|
+
exclude_types.each do |value|
|
255
|
+
count = 0
|
256
|
+
if OBJECTS_TABLE.has_value?(value)
|
257
|
+
param_name = OBJECTS_TABLE.key(value)
|
258
|
+
exclude_string += "#{param_name},"
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
exclude_string = exclude_string[0..-2]
|
263
|
+
end
|
264
|
+
|
265
|
+
def deltas(cursor, exclude_types=[])
|
266
|
+
raise 'Please provide a block for receiving the delta objects' if !block_given?
|
267
|
+
exclude_string = ""
|
268
|
+
|
269
|
+
if exclude_types.any?
|
270
|
+
exclude_string = _build_exclude_types(exclude_types)
|
271
|
+
end
|
272
|
+
|
273
|
+
# loop and yield deltas until we've come to the end.
|
274
|
+
loop do
|
275
|
+
path = self.url_for_path("/delta?cursor=#{cursor}#{exclude_string}")
|
276
|
+
json = nil
|
277
|
+
|
278
|
+
RestClient.get(path) do |response,request,result|
|
279
|
+
json = Inbox.interpret_response(result, response, {:expected_class => Object})
|
280
|
+
end
|
281
|
+
|
282
|
+
start_cursor = json["cursor_start"]
|
283
|
+
end_cursor = json["cursor_end"]
|
284
|
+
|
285
|
+
json["deltas"].each do |delta|
|
286
|
+
if not OBJECTS_TABLE.has_key?(delta['object'])
|
287
|
+
next
|
288
|
+
end
|
289
|
+
|
290
|
+
cls = OBJECTS_TABLE[delta['object']]
|
291
|
+
obj = cls.new(self)
|
292
|
+
|
293
|
+
case delta["event"]
|
294
|
+
when 'create', 'modify'
|
295
|
+
obj.inflate(delta['attributes'])
|
296
|
+
obj.cursor = delta["cursor"]
|
297
|
+
yield delta["event"], obj
|
298
|
+
when 'delete'
|
299
|
+
obj.id = delta["id"]
|
300
|
+
obj.cursor = delta["cursor"]
|
301
|
+
yield delta["event"], obj
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
break if start_cursor == end_cursor
|
306
|
+
cursor = end_cursor
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
def delta_stream(cursor, exclude_types=[], timeout=0)
|
311
|
+
raise 'Please provide a block for receiving the delta objects' if !block_given?
|
312
|
+
|
313
|
+
exclude_string = ""
|
314
|
+
|
315
|
+
if exclude_types.any?
|
316
|
+
exclude_string = _build_exclude_types(exclude_types)
|
317
|
+
end
|
318
|
+
|
319
|
+
# loop and yield deltas indefinitely.
|
320
|
+
path = self.url_for_path("/delta/streaming?cursor=#{cursor}#{exclude_string}")
|
321
|
+
|
322
|
+
parser = Yajl::Parser.new(:symbolize_keys => false)
|
323
|
+
parser.on_parse_complete = proc do |data|
|
324
|
+
delta = Inbox.interpret_response(OpenStruct.new(:code => '200'), data, {:expected_class => Object, :result_parsed => true})
|
325
|
+
|
326
|
+
if not OBJECTS_TABLE.has_key?(delta['object'])
|
327
|
+
next
|
328
|
+
end
|
329
|
+
|
330
|
+
cls = OBJECTS_TABLE[delta['object']]
|
331
|
+
obj = cls.new(self)
|
332
|
+
|
333
|
+
case delta["event"]
|
334
|
+
when 'create', 'modify'
|
335
|
+
obj.inflate(delta['attributes'])
|
336
|
+
obj.cursor = delta["cursor"]
|
337
|
+
yield delta["event"], obj
|
338
|
+
when 'delete'
|
339
|
+
obj.id = delta["id"]
|
340
|
+
obj.cursor = delta["cursor"]
|
341
|
+
yield delta["event"], obj
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
EventMachine.run do
|
346
|
+
http = EventMachine::HttpRequest.new(path, :connect_timeout => 0, :inactivity_timeout => timeout).get(:keepalive => true)
|
347
|
+
http.stream do |chunk|
|
348
|
+
parser << chunk
|
349
|
+
end
|
350
|
+
http.errback do
|
351
|
+
raise UnexpectedResponse.new http.error
|
352
|
+
end
|
353
|
+
end
|
137
354
|
end
|
138
355
|
end
|
139
356
|
end
|
data/lib/message.rb
CHANGED
@@ -68,12 +68,12 @@ module Inbox
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def files
|
71
|
-
@files ||= RestfulModelCollection.new(File, @_api,
|
71
|
+
@files ||= RestfulModelCollection.new(File, @_api, {:message_id=>@id})
|
72
72
|
end
|
73
73
|
|
74
74
|
def raw
|
75
75
|
model = nil
|
76
|
-
collection = RestfulModelCollection.new(Message, @_api,
|
76
|
+
collection = RestfulModelCollection.new(Message, @_api, {:message_id=>@id})
|
77
77
|
RestClient.get("#{collection.url}/#{id}/", :accept => 'message/rfc822'){ |response,request,result|
|
78
78
|
response
|
79
79
|
}
|
data/lib/nylas.rb
CHANGED
@@ -1,9 +1,26 @@
|
|
1
|
-
require 'version'
|
2
|
-
require 'rest-client'
|
3
|
-
require 'restful_model_collection'
|
4
1
|
require 'json'
|
5
|
-
require '
|
2
|
+
require 'rest-client'
|
3
|
+
require 'yajl'
|
4
|
+
require 'em-http'
|
5
|
+
require 'ostruct'
|
6
|
+
|
7
|
+
require 'account'
|
8
|
+
require 'api_account'
|
9
|
+
require 'api_thread'
|
10
|
+
require 'calendar'
|
6
11
|
require 'account'
|
12
|
+
require 'tag'
|
13
|
+
require 'message'
|
14
|
+
require 'draft'
|
15
|
+
require 'contact'
|
16
|
+
require 'file'
|
17
|
+
require 'calendar'
|
18
|
+
require 'event'
|
19
|
+
require 'folder'
|
20
|
+
require 'restful_model'
|
21
|
+
require 'restful_model_collection'
|
22
|
+
require 'version'
|
23
|
+
|
7
24
|
|
8
25
|
module Inbox
|
9
26
|
|
@@ -122,18 +139,218 @@ module Inbox
|
|
122
139
|
end
|
123
140
|
end
|
124
141
|
|
125
|
-
#
|
142
|
+
# API Methods
|
143
|
+
def threads
|
144
|
+
@threads ||= RestfulModelCollection.new(Thread, self)
|
145
|
+
end
|
126
146
|
|
127
|
-
def
|
128
|
-
@
|
129
|
-
@namespaces
|
147
|
+
def tags
|
148
|
+
@tags ||= RestfulModelCollection.new(Tag, self)
|
130
149
|
end
|
131
150
|
|
132
|
-
|
151
|
+
def messages
|
152
|
+
@messages ||= RestfulModelCollection.new(Message, self)
|
153
|
+
end
|
154
|
+
|
155
|
+
def files
|
156
|
+
@files ||= RestfulModelCollection.new(File, self)
|
157
|
+
end
|
158
|
+
|
159
|
+
def drafts
|
160
|
+
@drafts ||= RestfulModelCollection.new(Draft, self)
|
161
|
+
end
|
162
|
+
|
163
|
+
def contacts
|
164
|
+
@contacts ||= RestfulModelCollection.new(Contact, self)
|
165
|
+
end
|
166
|
+
|
167
|
+
def calendars
|
168
|
+
@calendars ||= RestfulModelCollection.new(Calendar, self)
|
169
|
+
end
|
170
|
+
|
171
|
+
def events
|
172
|
+
@events ||= RestfulModelCollection.new(Event, self)
|
173
|
+
end
|
174
|
+
|
175
|
+
def folders
|
176
|
+
@folders ||= RestfulModelCollection.new(Folder, self)
|
177
|
+
end
|
178
|
+
|
179
|
+
def labels
|
180
|
+
@labels ||= RestfulModelCollection.new(Label, self)
|
181
|
+
end
|
182
|
+
|
183
|
+
def account
|
184
|
+
path = self.url_for_path("/account")
|
185
|
+
|
186
|
+
RestClient.get(path, {}) do |response,request,result|
|
187
|
+
json = Inbox.interpret_response(result, response, {:expected_class => Object})
|
188
|
+
model = APIAccount.new(self)
|
189
|
+
model.inflate(json)
|
190
|
+
model
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def using_hosted_api?
|
195
|
+
return !@app_id.nil?
|
196
|
+
end
|
133
197
|
|
134
198
|
def accounts
|
135
|
-
|
136
|
-
|
199
|
+
if self.using_hosted_api?
|
200
|
+
@accounts ||= ManagementModelCollection.new(Account, self)
|
201
|
+
else
|
202
|
+
@accounts ||= RestfulModelCollection.new(APIAccount, self)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def get_cursor(timestamp)
|
207
|
+
# Get the cursor corresponding to a specific timestamp.
|
208
|
+
warn "Nylas#get_cursor is deprecated. Use Nylas#latest_cursor instead."
|
209
|
+
|
210
|
+
path = self.url_for_path("/delta/generate_cursor")
|
211
|
+
data = { :start => timestamp }
|
212
|
+
|
213
|
+
cursor = nil
|
214
|
+
|
215
|
+
RestClient.post(path, data.to_json, :content_type => :json) do |response,request,result|
|
216
|
+
json = Inbox.interpret_response(result, response, {:expected_class => Object})
|
217
|
+
cursor = json["cursor"]
|
218
|
+
end
|
219
|
+
|
220
|
+
cursor
|
221
|
+
end
|
222
|
+
|
223
|
+
def latest_cursor
|
224
|
+
# Get the cursor corresponding to a specific timestamp.
|
225
|
+
path = self.url_for_path("/delta/latest_cursor")
|
226
|
+
|
227
|
+
cursor = nil
|
228
|
+
|
229
|
+
RestClient.post(path, :content_type => :json) do |response,request,result|
|
230
|
+
json = Inbox.interpret_response(result, response, {:expected_class => Object})
|
231
|
+
cursor = json["cursor"]
|
232
|
+
end
|
233
|
+
|
234
|
+
cursor
|
235
|
+
end
|
236
|
+
|
237
|
+
OBJECTS_TABLE = {
|
238
|
+
"account" => Inbox::Account,
|
239
|
+
"calendar" => Inbox::Calendar,
|
240
|
+
"draft" => Inbox::Draft,
|
241
|
+
"thread" => Inbox::Thread,
|
242
|
+
"contact" => Inbox::Contact,
|
243
|
+
"event" => Inbox::Event,
|
244
|
+
"file" => Inbox::File,
|
245
|
+
"message" => Inbox::Message,
|
246
|
+
"tag" => Inbox::Tag,
|
247
|
+
"folder" => Inbox::Folder,
|
248
|
+
"label" => Inbox::Label,
|
249
|
+
}
|
250
|
+
|
251
|
+
def _build_exclude_types(exclude_types)
|
252
|
+
exclude_string = "&exclude_types="
|
253
|
+
|
254
|
+
exclude_types.each do |value|
|
255
|
+
count = 0
|
256
|
+
if OBJECTS_TABLE.has_value?(value)
|
257
|
+
param_name = OBJECTS_TABLE.key(value)
|
258
|
+
exclude_string += "#{param_name},"
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
exclude_string = exclude_string[0..-2]
|
263
|
+
end
|
264
|
+
|
265
|
+
def deltas(cursor, exclude_types=[])
|
266
|
+
raise 'Please provide a block for receiving the delta objects' if !block_given?
|
267
|
+
exclude_string = ""
|
268
|
+
|
269
|
+
if exclude_types.any?
|
270
|
+
exclude_string = _build_exclude_types(exclude_types)
|
271
|
+
end
|
272
|
+
|
273
|
+
# loop and yield deltas until we've come to the end.
|
274
|
+
loop do
|
275
|
+
path = self.url_for_path("/delta?cursor=#{cursor}#{exclude_string}")
|
276
|
+
json = nil
|
277
|
+
|
278
|
+
RestClient.get(path) do |response,request,result|
|
279
|
+
json = Inbox.interpret_response(result, response, {:expected_class => Object})
|
280
|
+
end
|
281
|
+
|
282
|
+
start_cursor = json["cursor_start"]
|
283
|
+
end_cursor = json["cursor_end"]
|
284
|
+
|
285
|
+
json["deltas"].each do |delta|
|
286
|
+
if not OBJECTS_TABLE.has_key?(delta['object'])
|
287
|
+
next
|
288
|
+
end
|
289
|
+
|
290
|
+
cls = OBJECTS_TABLE[delta['object']]
|
291
|
+
obj = cls.new(self)
|
292
|
+
|
293
|
+
case delta["event"]
|
294
|
+
when 'create', 'modify'
|
295
|
+
obj.inflate(delta['attributes'])
|
296
|
+
obj.cursor = delta["cursor"]
|
297
|
+
yield delta["event"], obj
|
298
|
+
when 'delete'
|
299
|
+
obj.id = delta["id"]
|
300
|
+
obj.cursor = delta["cursor"]
|
301
|
+
yield delta["event"], obj
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
break if start_cursor == end_cursor
|
306
|
+
cursor = end_cursor
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
def delta_stream(cursor, exclude_types=[], timeout=0)
|
311
|
+
raise 'Please provide a block for receiving the delta objects' if !block_given?
|
312
|
+
|
313
|
+
exclude_string = ""
|
314
|
+
|
315
|
+
if exclude_types.any?
|
316
|
+
exclude_string = _build_exclude_types(exclude_types)
|
317
|
+
end
|
318
|
+
|
319
|
+
# loop and yield deltas indefinitely.
|
320
|
+
path = self.url_for_path("/delta/streaming?cursor=#{cursor}#{exclude_string}")
|
321
|
+
|
322
|
+
parser = Yajl::Parser.new(:symbolize_keys => false)
|
323
|
+
parser.on_parse_complete = proc do |data|
|
324
|
+
delta = Inbox.interpret_response(OpenStruct.new(:code => '200'), data, {:expected_class => Object, :result_parsed => true})
|
325
|
+
|
326
|
+
if not OBJECTS_TABLE.has_key?(delta['object'])
|
327
|
+
next
|
328
|
+
end
|
329
|
+
|
330
|
+
cls = OBJECTS_TABLE[delta['object']]
|
331
|
+
obj = cls.new(self)
|
332
|
+
|
333
|
+
case delta["event"]
|
334
|
+
when 'create', 'modify'
|
335
|
+
obj.inflate(delta['attributes'])
|
336
|
+
obj.cursor = delta["cursor"]
|
337
|
+
yield delta["event"], obj
|
338
|
+
when 'delete'
|
339
|
+
obj.id = delta["id"]
|
340
|
+
obj.cursor = delta["cursor"]
|
341
|
+
yield delta["event"], obj
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
EventMachine.run do
|
346
|
+
http = EventMachine::HttpRequest.new(path, :connect_timeout => 0, :inactivity_timeout => timeout).get(:keepalive => true)
|
347
|
+
http.stream do |chunk|
|
348
|
+
parser << chunk
|
349
|
+
end
|
350
|
+
http.errback do
|
351
|
+
raise UnexpectedResponse.new http.error
|
352
|
+
end
|
353
|
+
end
|
137
354
|
end
|
138
355
|
end
|
139
356
|
end
|
data/lib/restful_model.rb
CHANGED
@@ -7,7 +7,7 @@ module Inbox
|
|
7
7
|
include Inbox::Parameters
|
8
8
|
|
9
9
|
parameter :id
|
10
|
-
parameter :
|
10
|
+
parameter :account_id
|
11
11
|
parameter :cursor # Only used by the delta sync API
|
12
12
|
time_attr_accessor :created_at
|
13
13
|
|
@@ -15,9 +15,9 @@ module Inbox
|
|
15
15
|
"#{self.to_s.downcase}s".split('::').last
|
16
16
|
end
|
17
17
|
|
18
|
-
def initialize(api,
|
18
|
+
def initialize(api, account_id = nil)
|
19
19
|
raise StandardError.new unless api.class <= Inbox::API
|
20
|
-
@
|
20
|
+
@account_id = account_id
|
21
21
|
@_api = api
|
22
22
|
end
|
23
23
|
|
@@ -41,7 +41,7 @@ module Inbox
|
|
41
41
|
|
42
42
|
def url(action = "")
|
43
43
|
action = "/#{action}" unless action.empty?
|
44
|
-
@_api.url_for_path("
|
44
|
+
@_api.url_for_path("/#{self.class.collection_name}/#{id}#{action}")
|
45
45
|
end
|
46
46
|
|
47
47
|
def as_json(options = {})
|
@@ -5,11 +5,10 @@ module Inbox
|
|
5
5
|
|
6
6
|
attr_accessor :filters
|
7
7
|
|
8
|
-
def initialize(model_class, api,
|
8
|
+
def initialize(model_class, api, filters = {})
|
9
9
|
raise StandardError.new unless api.class <= Inbox::API
|
10
10
|
@model_class = model_class
|
11
11
|
@filters = filters
|
12
|
-
@namespace_id = namespace_id
|
13
12
|
@_api = api
|
14
13
|
end
|
15
14
|
|
@@ -93,7 +92,7 @@ module Inbox
|
|
93
92
|
for key in args.keys
|
94
93
|
args[key.to_s] = args[key]
|
95
94
|
end
|
96
|
-
model = @model_class.new(@_api
|
95
|
+
model = @model_class.new(@_api)
|
97
96
|
model.inflate(args)
|
98
97
|
model
|
99
98
|
end
|
@@ -115,8 +114,7 @@ module Inbox
|
|
115
114
|
end
|
116
115
|
|
117
116
|
def url
|
118
|
-
|
119
|
-
@_api.url_for_path("#{prefix}/#{@model_class.collection_name}")
|
117
|
+
@_api.url_for_path("/#{@model_class.collection_name}")
|
120
118
|
end
|
121
119
|
|
122
120
|
private
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inbox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Gotow
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2015-08-
|
13
|
+
date: 2015-08-26 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rest-client
|
@@ -203,6 +203,7 @@ extra_rdoc_files:
|
|
203
203
|
- README.md
|
204
204
|
files:
|
205
205
|
- lib/account.rb
|
206
|
+
- lib/api_account.rb
|
206
207
|
- lib/api_thread.rb
|
207
208
|
- lib/calendar.rb
|
208
209
|
- lib/contact.rb
|
@@ -213,7 +214,6 @@ files:
|
|
213
214
|
- lib/inbox.rb
|
214
215
|
- lib/label.rb
|
215
216
|
- lib/message.rb
|
216
|
-
- lib/namespace.rb
|
217
217
|
- lib/nylas.rb
|
218
218
|
- lib/parameters.rb
|
219
219
|
- lib/restful_model.rb
|
data/lib/namespace.rb
DELETED
@@ -1,210 +0,0 @@
|
|
1
|
-
require 'restful_model'
|
2
|
-
require 'account'
|
3
|
-
require 'tag'
|
4
|
-
require 'message'
|
5
|
-
require 'draft'
|
6
|
-
require 'contact'
|
7
|
-
require 'file'
|
8
|
-
require 'calendar'
|
9
|
-
require 'event'
|
10
|
-
require 'folder'
|
11
|
-
require 'yajl'
|
12
|
-
require 'em-http'
|
13
|
-
require 'ostruct'
|
14
|
-
|
15
|
-
# Rather than saying require 'thread', we need to explicitly force
|
16
|
-
# the thread model to load. Otherwise, we can't reference it below.
|
17
|
-
# Thread still refers to the built-in Thread type, and Inbox::Thread
|
18
|
-
# is undefined.
|
19
|
-
load "api_thread.rb"
|
20
|
-
|
21
|
-
module Inbox
|
22
|
-
|
23
|
-
class Namespace < RestfulModel
|
24
|
-
|
25
|
-
parameter :account_id
|
26
|
-
parameter :name
|
27
|
-
parameter :email_address
|
28
|
-
parameter :provider
|
29
|
-
|
30
|
-
def self.collection_name
|
31
|
-
"n"
|
32
|
-
end
|
33
|
-
|
34
|
-
def threads
|
35
|
-
@threads ||= RestfulModelCollection.new(Thread, @_api, @id)
|
36
|
-
end
|
37
|
-
|
38
|
-
def tags
|
39
|
-
@tags ||= RestfulModelCollection.new(Tag, @_api, @id)
|
40
|
-
end
|
41
|
-
|
42
|
-
def messages
|
43
|
-
@messages ||= RestfulModelCollection.new(Message, @_api, @id)
|
44
|
-
end
|
45
|
-
|
46
|
-
def files
|
47
|
-
@files ||= RestfulModelCollection.new(File, @_api, @id)
|
48
|
-
end
|
49
|
-
|
50
|
-
def drafts
|
51
|
-
@drafts ||= RestfulModelCollection.new(Draft, @_api, @id)
|
52
|
-
end
|
53
|
-
|
54
|
-
def contacts
|
55
|
-
@contacts ||= RestfulModelCollection.new(Contact, @_api, @id)
|
56
|
-
end
|
57
|
-
|
58
|
-
def calendars
|
59
|
-
@calendars ||= RestfulModelCollection.new(Calendar, @_api, @id)
|
60
|
-
end
|
61
|
-
|
62
|
-
def events
|
63
|
-
@events ||= RestfulModelCollection.new(Event, @_api, @id)
|
64
|
-
end
|
65
|
-
|
66
|
-
def folders
|
67
|
-
@folders ||= RestfulModelCollection.new(Folder, @_api, @id)
|
68
|
-
end
|
69
|
-
|
70
|
-
def labels
|
71
|
-
@labels ||= RestfulModelCollection.new(Label, @_api, @id)
|
72
|
-
end
|
73
|
-
|
74
|
-
def get_cursor(timestamp)
|
75
|
-
# Get the cursor corresponding to a specific timestamp.
|
76
|
-
path = @_api.url_for_path("/n/#{@namespace_id}/delta/generate_cursor")
|
77
|
-
data = { :start => timestamp }
|
78
|
-
|
79
|
-
cursor = nil
|
80
|
-
|
81
|
-
RestClient.post(path, data.to_json, :content_type => :json) do |response,request,result|
|
82
|
-
json = Inbox.interpret_response(result, response, {:expected_class => Object})
|
83
|
-
cursor = json["cursor"]
|
84
|
-
end
|
85
|
-
|
86
|
-
cursor
|
87
|
-
end
|
88
|
-
|
89
|
-
OBJECTS_TABLE = {
|
90
|
-
"account" => Inbox::Account,
|
91
|
-
"calendar" => Inbox::Calendar,
|
92
|
-
"draft" => Inbox::Draft,
|
93
|
-
"thread" => Inbox::Thread,
|
94
|
-
"contact" => Inbox::Contact,
|
95
|
-
"event" => Inbox::Event,
|
96
|
-
"file" => Inbox::File,
|
97
|
-
"message" => Inbox::Message,
|
98
|
-
"namespace" => Inbox::Namespace,
|
99
|
-
"tag" => Inbox::Tag,
|
100
|
-
"folder" => Inbox::Folder,
|
101
|
-
"label" => Inbox::Label,
|
102
|
-
}
|
103
|
-
|
104
|
-
def _build_exclude_types(exclude_types)
|
105
|
-
exclude_string = "&exclude_types="
|
106
|
-
|
107
|
-
exclude_types.each do |value|
|
108
|
-
count = 0
|
109
|
-
if OBJECTS_TABLE.has_value?(value)
|
110
|
-
param_name = OBJECTS_TABLE.key(value)
|
111
|
-
exclude_string += "#{param_name},"
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
exclude_string = exclude_string[0..-2]
|
116
|
-
end
|
117
|
-
|
118
|
-
def deltas(cursor, exclude_types=[])
|
119
|
-
raise 'Please provide a block for receiving the delta objects' if !block_given?
|
120
|
-
exclude_string = ""
|
121
|
-
|
122
|
-
if exclude_types.any?
|
123
|
-
exclude_string = _build_exclude_types(exclude_types)
|
124
|
-
end
|
125
|
-
|
126
|
-
# loop and yield deltas until we've come to the end.
|
127
|
-
loop do
|
128
|
-
path = @_api.url_for_path("/n/#{@namespace_id}/delta?cursor=#{cursor}#{exclude_string}")
|
129
|
-
json = nil
|
130
|
-
|
131
|
-
RestClient.get(path) do |response,request,result|
|
132
|
-
json = Inbox.interpret_response(result, response, {:expected_class => Object})
|
133
|
-
end
|
134
|
-
|
135
|
-
start_cursor = json["cursor_start"]
|
136
|
-
end_cursor = json["cursor_end"]
|
137
|
-
|
138
|
-
json["deltas"].each do |delta|
|
139
|
-
if not OBJECTS_TABLE.has_key?(delta['object'])
|
140
|
-
next
|
141
|
-
end
|
142
|
-
|
143
|
-
cls = OBJECTS_TABLE[delta['object']]
|
144
|
-
obj = cls.new(@_api, @namespace_id)
|
145
|
-
|
146
|
-
case delta["event"]
|
147
|
-
when 'create', 'modify'
|
148
|
-
obj.inflate(delta['attributes'])
|
149
|
-
obj.cursor = delta["cursor"]
|
150
|
-
yield delta["event"], obj
|
151
|
-
when 'delete'
|
152
|
-
obj.id = delta["id"]
|
153
|
-
obj.cursor = delta["cursor"]
|
154
|
-
yield delta["event"], obj
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
break if start_cursor == end_cursor
|
159
|
-
cursor = end_cursor
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
def delta_stream(cursor, exclude_types=[], timeout=0)
|
164
|
-
raise 'Please provide a block for receiving the delta objects' if !block_given?
|
165
|
-
|
166
|
-
exclude_string = ""
|
167
|
-
|
168
|
-
if exclude_types.any?
|
169
|
-
exclude_string = _build_exclude_types(exclude_types)
|
170
|
-
end
|
171
|
-
|
172
|
-
# loop and yield deltas indefinitely.
|
173
|
-
path = @_api.url_for_path("/n/#{@namespace_id}/delta/streaming?cursor=#{cursor}#{exclude_string}")
|
174
|
-
|
175
|
-
parser = Yajl::Parser.new(:symbolize_keys => false)
|
176
|
-
parser.on_parse_complete = proc do |data|
|
177
|
-
delta = Inbox.interpret_response(OpenStruct.new(:code => '200'), data, {:expected_class => Object, :result_parsed => true})
|
178
|
-
|
179
|
-
if not OBJECTS_TABLE.has_key?(delta['object'])
|
180
|
-
next
|
181
|
-
end
|
182
|
-
|
183
|
-
cls = OBJECTS_TABLE[delta['object']]
|
184
|
-
obj = cls.new(@_api, @namespace_id)
|
185
|
-
|
186
|
-
case delta["event"]
|
187
|
-
when 'create', 'modify'
|
188
|
-
obj.inflate(delta['attributes'])
|
189
|
-
obj.cursor = delta["cursor"]
|
190
|
-
yield delta["event"], obj
|
191
|
-
when 'delete'
|
192
|
-
obj.id = delta["id"]
|
193
|
-
obj.cursor = delta["cursor"]
|
194
|
-
yield delta["event"], obj
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
EventMachine.run do
|
199
|
-
http = EventMachine::HttpRequest.new(path, :connect_timeout => 0, :inactivity_timeout => timeout).get(:keepalive => true)
|
200
|
-
http.stream do |chunk|
|
201
|
-
parser << chunk
|
202
|
-
end
|
203
|
-
http.errback do
|
204
|
-
raise UnexpectedResponse.new http.error
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
end
|
210
|
-
end
|