netflix 0.1.1 → 0.2.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.
- data/.gitignore +1 -0
- data/Rakefile +25 -3
- data/lib/netflix.rb +3 -1
- data/lib/netflix/client.rb +4 -0
- data/lib/netflix/errors.rb +44 -0
- data/lib/netflix/queue.rb +47 -16
- data/lib/netflix/response.rb +29 -0
- data/lib/netflix/user.rb +1 -5
- data/test/error_test.rb +27 -0
- data/test/http_fixtures/netflix_queue_responses.yml +226 -2
- data/test/integration/.gitignore +1 -0
- data/test/integration/queue_test.rb +72 -0
- data/test/integration/rake_test_helper.rb +42 -0
- data/test/queue_test.rb +36 -19
- metadata +24 -13
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg/
|
data/Rakefile
CHANGED
@@ -1,17 +1,39 @@
|
|
1
1
|
require 'rake/testtask'
|
2
2
|
require 'rubygems/package_task'
|
3
3
|
|
4
|
-
Rake::TestTask.new("test") { |t|
|
4
|
+
Rake::TestTask.new("test:unit") { |t|
|
5
5
|
t.libs << 'test'
|
6
|
-
t.test_files = Dir.glob( "test
|
6
|
+
t.test_files = Dir.glob( "test/*_test.rb" ).sort
|
7
7
|
|
8
8
|
t.verbose = true
|
9
9
|
t.warning = true
|
10
10
|
}
|
11
|
+
require File.join(File.dirname(__FILE__), 'test/integration/rake_test_helper')
|
12
|
+
|
13
|
+
file "test/integration/oauth_settings.yml" do |t|
|
14
|
+
credentials = IntegrationTestHelper.obtain_credentials
|
15
|
+
open("test/integration/oauth_settings.yml", 'wb') do |f|
|
16
|
+
YAML.dump(credentials, f)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Rake::TestTask.new("test:integration") { |t|
|
21
|
+
#t.description = "Run integration tests against a REAL netflix account you supply"
|
22
|
+
t.libs << 'test'
|
23
|
+
t.test_files = Dir.glob( "test/integration/**/*_test.rb" ).sort
|
24
|
+
|
25
|
+
t.verbose = true
|
26
|
+
t.warning = true
|
27
|
+
}
|
28
|
+
|
29
|
+
task "test:integration" => "test/integration/oauth_settings.yml"
|
30
|
+
|
31
|
+
desc "run unit tests only"
|
32
|
+
task :test => "test:unit"
|
11
33
|
|
12
34
|
gem_spec = Gem::Specification.new do |s|
|
13
35
|
s.name = "netflix"
|
14
|
-
s.version = "0.
|
36
|
+
s.version = "0.2.0"
|
15
37
|
s.authors = ["Dean Holdren"]
|
16
38
|
s.date = %q{2012-01-09}
|
17
39
|
s.description = "Ruby Netflix API wrapper"
|
data/lib/netflix.rb
CHANGED
data/lib/netflix/client.rb
CHANGED
@@ -16,6 +16,8 @@ module Netflix
|
|
16
16
|
:authorize_url => "https://api-user.netflix.com/oauth/login")
|
17
17
|
if user_access_token && user_access_secret
|
18
18
|
@oauth_access_token = oauth_access_token(user_access_token, user_access_secret)
|
19
|
+
#automatically determine if error should be thrown based on response codes
|
20
|
+
@oauth_access_token.extend(ResponseErrorDecorator)
|
19
21
|
elsif !!user_access_token ^ !!user_access_secret
|
20
22
|
raise ArgumentError 'Must specify both user_access_token and user_access_secret if specifying either'
|
21
23
|
end
|
@@ -36,6 +38,8 @@ module Netflix
|
|
36
38
|
authorize_url = request_token.authorize_url(:oauth_consumer_key =>
|
37
39
|
Netflix::Client.consumer_key)
|
38
40
|
Launchy.open(authorize_url)
|
41
|
+
puts "Go to browser, a page has been opened to establish oauth"
|
42
|
+
printf "Pin from Netflix:"
|
39
43
|
pin = gets.chomp
|
40
44
|
access_token = request_token.get_access_token(:oauth_verifier => pin)
|
41
45
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Netflix
|
4
|
+
module Error
|
5
|
+
class ResponseError < StandardError
|
6
|
+
def initialize(body, headers)
|
7
|
+
@body = body
|
8
|
+
@headers = headers
|
9
|
+
body_obj = JSON.parse(body)
|
10
|
+
message = body_obj["status"]["message"]
|
11
|
+
super(message)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
#4xx level errors
|
15
|
+
class ClientError < ResponseError
|
16
|
+
end
|
17
|
+
#5xx level errors
|
18
|
+
class ServerError < ResponseError
|
19
|
+
end
|
20
|
+
#400
|
21
|
+
class BadRequest < ClientError
|
22
|
+
end
|
23
|
+
#403
|
24
|
+
class Forbidden < ClientError
|
25
|
+
end
|
26
|
+
#404
|
27
|
+
class NotFound < ClientError
|
28
|
+
end
|
29
|
+
#401
|
30
|
+
class Unauthorized < ClientError
|
31
|
+
end
|
32
|
+
#420 (?)
|
33
|
+
class RateLimit < ClientError
|
34
|
+
end
|
35
|
+
|
36
|
+
CODEMAP = {400 => BadRequest, 403 => Forbidden, 404 => NotFound, 401 => Unauthorized, 420 => RateLimit}
|
37
|
+
def self.for(response)
|
38
|
+
#codemap = {400 => BadRequest, 403 => Forbidden, 404 => NotFound, 401 => Unauthorized, 420 => RateLimit}
|
39
|
+
code = response.code.to_i
|
40
|
+
(CODEMAP[code] || ResponseError).new(response.body, response.header)
|
41
|
+
#codemap[code].new(response.body, response.header)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/netflix/queue.rb
CHANGED
@@ -22,20 +22,29 @@ module Netflix
|
|
22
22
|
|
23
23
|
def add(title_ref, position=nil)
|
24
24
|
response = @oauth_access_token.post "/users/#{@user_id}/queues/#{@type}?output=json", {:etag => etag, :title_ref => title_ref, :position=> position}
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
#@map = retrieve
|
26
|
+
#netflix is wacky. GET after an add can be STALE. ughg
|
27
|
+
#so recreate the contents programattically instead
|
28
|
+
response_obj = JSON.parse(response.body)
|
29
|
+
new_queue_item = response_obj["status"]["resources_created"]["queue_item"]
|
30
|
+
new_etag = response_obj["status"]["etag"]
|
31
|
+
repopulate(new_queue_item, new_etag)
|
32
|
+
self
|
30
33
|
end
|
31
34
|
|
32
35
|
def remove(position)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
id = discs[position-1].id
|
37
|
+
#response = @oauth_access_token.delete "/users/#{@user_id}/queues/#{@type}/available/#{position}?output=json" , {'etag' => etag}
|
38
|
+
response = @oauth_access_token.delete "#{id}?output=json"
|
39
|
+
@map = retrieve
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def remove_by_title_ref(title_ref)
|
44
|
+
disc = discs.find {|disc| disc =~ /\/#{title_ref}\//}
|
45
|
+
response = @oauth_access_token.delete "#{disc.id}?output=json"
|
46
|
+
@map = retrieve
|
47
|
+
self
|
39
48
|
end
|
40
49
|
|
41
50
|
def discs
|
@@ -47,13 +56,35 @@ module Netflix
|
|
47
56
|
end
|
48
57
|
end
|
49
58
|
|
59
|
+
def refresh
|
60
|
+
@map = retrieve(etag)
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
50
64
|
private
|
51
|
-
def retrieve
|
52
|
-
|
53
|
-
if
|
54
|
-
|
65
|
+
def retrieve(etag = nil)
|
66
|
+
url = "/users/#{@user_id}/queues/#{@type}/available?max_results=#{MAX_RESULTS}&output=json"
|
67
|
+
if (etag)
|
68
|
+
response = @oauth_access_token.get(url, { 'etag' => etag.to_s })
|
69
|
+
else
|
70
|
+
response = @oauth_access_token.get(url)
|
71
|
+
end
|
72
|
+
JSON.parse(response.body)["queue"]
|
73
|
+
end
|
74
|
+
|
75
|
+
def repopulate(new_queue_item, new_etag)
|
76
|
+
@map["etag"] = new_etag
|
77
|
+
new_queue_item_index = new_queue_item["position"].to_i
|
78
|
+
if @map["queue_item"] #single or array
|
79
|
+
@map["queue_item"] = [@map["queue_item"]].flatten
|
80
|
+
@map["queue_item"].insert((new_queue_item_index - 1), new_queue_item)
|
81
|
+
@map["queue_item"][new_queue_item_index..-1].each {|queue_item|
|
82
|
+
new_position = (queue_item["position"].to_i + 1).to_s
|
83
|
+
queue_item["position"] = new_position
|
84
|
+
queue_item["id"] = queue_item["id"].gsub(/\/(\d+)\/(\d+)/,"/#{new_position}/\\2")
|
85
|
+
}
|
55
86
|
else
|
56
|
-
|
87
|
+
@map["queue_item"] = [new_queue_item]
|
57
88
|
end
|
58
89
|
end
|
59
90
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Netflix
|
2
|
+
module ResponseErrorDecorator
|
3
|
+
def get(*args)
|
4
|
+
response = super(*args)
|
5
|
+
response_or_raise_error(response)
|
6
|
+
end
|
7
|
+
def delete(*args)
|
8
|
+
response = super(*args)
|
9
|
+
response_or_raise_error(response)
|
10
|
+
end
|
11
|
+
def post(*args)
|
12
|
+
response = super(*args)
|
13
|
+
response_or_raise_error(response)
|
14
|
+
end
|
15
|
+
def put(*args)
|
16
|
+
response = super(*args)
|
17
|
+
response_or_raise_error(response)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def response_or_raise_error(response)
|
22
|
+
if response && response.is_a?(Net::HTTPSuccess)
|
23
|
+
response
|
24
|
+
else
|
25
|
+
raise Error.for(response)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/netflix/user.rb
CHANGED
@@ -17,11 +17,7 @@ module Netflix
|
|
17
17
|
private
|
18
18
|
def retrieve
|
19
19
|
response = @oauth_access_token.get "/users/#{@user_id}?output=json"
|
20
|
-
|
21
|
-
JSON.parse(response.body)["user"]
|
22
|
-
else
|
23
|
-
raise "Error retrieving user #{@user_id}"
|
24
|
-
end
|
20
|
+
JSON.parse(response.body)["user"]
|
25
21
|
end
|
26
22
|
|
27
23
|
end
|
data/test/error_test.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ErrorTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
stub_netflix_for_user('nuid_one')
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_handle_404_on_delete
|
9
|
+
#add to disc queue
|
10
|
+
FakeWeb.register_uri(:delete, %r|http://api\.netflix\.com/users/nuid_one/queues/disc/available|,
|
11
|
+
:body => '{"status": {
|
12
|
+
"message": "Title is not in Queue",
|
13
|
+
"status_code": 404,
|
14
|
+
"sub_code": 610
|
15
|
+
}}',
|
16
|
+
:status => ['404', 'Not Found'])
|
17
|
+
|
18
|
+
user = Netflix::Client.new('nuid_access_key', 'nuid_access_secret').user('nuid_one')
|
19
|
+
available_disc_queue = user.available_disc_queue
|
20
|
+
assert available_disc_queue
|
21
|
+
assert_raises(Netflix::Error::NotFound) do
|
22
|
+
available_disc_queue.remove(2)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -324,7 +324,129 @@ nuid_one:
|
|
324
324
|
]
|
325
325
|
}}
|
326
326
|
post:
|
327
|
-
body:
|
327
|
+
body: |
|
328
|
+
{"status": {
|
329
|
+
"resources_created": {"queue_item": {
|
330
|
+
"average_rating": "3.7",
|
331
|
+
"box_art": {
|
332
|
+
"large": "http://cdn-3.nflximg.com/us/boxshots/large/70071613.jpg",
|
333
|
+
"small": "http://cdn-3.nflximg.com/us/boxshots/tiny/70071613.jpg",
|
334
|
+
"medium": "http://cdn-3.nflximg.com/us/boxshots/small/70071613.jpg"
|
335
|
+
},
|
336
|
+
"category": [
|
337
|
+
{
|
338
|
+
"term": "available now",
|
339
|
+
"content": "Available Now",
|
340
|
+
"scheme": "http://api.netflix.com/categories/queue_availability",
|
341
|
+
"label": "available now"
|
342
|
+
},
|
343
|
+
{
|
344
|
+
"term": "Blu-ray",
|
345
|
+
"scheme": "http://api.netflix.com/categories/title_formats",
|
346
|
+
"label": "Blu-ray"
|
347
|
+
},
|
348
|
+
{
|
349
|
+
"term": "R",
|
350
|
+
"scheme": "http://api.netflix.com/categories/mpaa_ratings",
|
351
|
+
"label": "R"
|
352
|
+
},
|
353
|
+
{
|
354
|
+
"term": "Thrillers",
|
355
|
+
"scheme": "http://api.netflix.com/categories/genres",
|
356
|
+
"label": "Thrillers"
|
357
|
+
},
|
358
|
+
{
|
359
|
+
"term": "Crime Thrillers",
|
360
|
+
"scheme": "http://api.netflix.com/categories/genres",
|
361
|
+
"label": "Crime Thrillers"
|
362
|
+
},
|
363
|
+
{
|
364
|
+
"term": "Suspense",
|
365
|
+
"scheme": "http://api.netflix.com/categories/genres",
|
366
|
+
"label": "Suspense"
|
367
|
+
},
|
368
|
+
{
|
369
|
+
"term": "Dramas Based on Contemporary Literature",
|
370
|
+
"scheme": "http://api.netflix.com/categories/genres",
|
371
|
+
"label": "Dramas Based on Contemporary Literature"
|
372
|
+
},
|
373
|
+
{
|
374
|
+
"term": "Dramas Based on the Book",
|
375
|
+
"scheme": "http://api.netflix.com/categories/genres",
|
376
|
+
"label": "Dramas Based on the Book"
|
377
|
+
}
|
378
|
+
],
|
379
|
+
"updated": "1276960028",
|
380
|
+
"id": "http://api.netflix.com/users/nuid_one/queues/disc/available/4/70071613",
|
381
|
+
"link": [
|
382
|
+
{
|
383
|
+
"href": "http://api.netflix.com/users/nuid_one/queues/disc/available",
|
384
|
+
"rel": "http://schemas.netflix.com/queues.available",
|
385
|
+
"title": "available queue"
|
386
|
+
},
|
387
|
+
{
|
388
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70071613",
|
389
|
+
"rel": "http://schemas.netflix.com/catalog/title",
|
390
|
+
"title": "No Country for Old Men"
|
391
|
+
},
|
392
|
+
{
|
393
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70071613/synopsis",
|
394
|
+
"rel": "http://schemas.netflix.com/catalog/titles/synopsis",
|
395
|
+
"title": "synopsis"
|
396
|
+
},
|
397
|
+
{
|
398
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70071613/cast",
|
399
|
+
"rel": "http://schemas.netflix.com/catalog/people.cast",
|
400
|
+
"title": "cast"
|
401
|
+
},
|
402
|
+
{
|
403
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70071613/directors",
|
404
|
+
"rel": "http://schemas.netflix.com/catalog/people.directors",
|
405
|
+
"title": "directors"
|
406
|
+
},
|
407
|
+
{
|
408
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70071613/format_availability",
|
409
|
+
"rel": "http://schemas.netflix.com/catalog/titles/format_availability",
|
410
|
+
"title": "formats"
|
411
|
+
},
|
412
|
+
{
|
413
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70071613/awards",
|
414
|
+
"rel": "http://schemas.netflix.com/catalog/titles/awards",
|
415
|
+
"title": "awards"
|
416
|
+
},
|
417
|
+
{
|
418
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70071613/screen_formats",
|
419
|
+
"rel": "http://schemas.netflix.com/catalog/titles/screen_formats",
|
420
|
+
"title": "screen formats"
|
421
|
+
},
|
422
|
+
{
|
423
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70071613/languages_and_audio",
|
424
|
+
"rel": "http://schemas.netflix.com/catalog/titles/languages_and_audio",
|
425
|
+
"title": "languages and audio"
|
426
|
+
},
|
427
|
+
{
|
428
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70071613/similars",
|
429
|
+
"rel": "http://schemas.netflix.com/catalog/titles.similars",
|
430
|
+
"title": "similars"
|
431
|
+
},
|
432
|
+
{
|
433
|
+
"href": "http://www.netflix.com/Movie/No_Country_for_Old_Men/70071613",
|
434
|
+
"rel": "alternate",
|
435
|
+
"title": "web page"
|
436
|
+
}
|
437
|
+
],
|
438
|
+
"position": "4",
|
439
|
+
"runtime": "7320",
|
440
|
+
"title": {
|
441
|
+
"regular": "No Country for Old Men",
|
442
|
+
"short": "No Country for Old Men"
|
443
|
+
},
|
444
|
+
"release_year": "2007"
|
445
|
+
}},
|
446
|
+
"status_code": "201",
|
447
|
+
"message": "Move successful",
|
448
|
+
"etag": "82198468425"
|
449
|
+
}}
|
328
450
|
delete:
|
329
451
|
body: |
|
330
452
|
{"status": {
|
@@ -1192,6 +1314,108 @@ empty_queue:
|
|
1192
1314
|
"number_of_results": "0"
|
1193
1315
|
}}
|
1194
1316
|
post:
|
1195
|
-
body:
|
1317
|
+
body: |
|
1318
|
+
{"status": {
|
1319
|
+
"resources_created": {"queue_item": {
|
1320
|
+
"average_rating": "3.4",
|
1321
|
+
"box_art": {
|
1322
|
+
"large": "http://cdn-2.nflximg.com/us/boxshots/large/70167072.jpg",
|
1323
|
+
"small": "http://cdn-2.nflximg.com/us/boxshots/tiny/70167072.jpg",
|
1324
|
+
"medium": "http://cdn-2.nflximg.com/us/boxshots/small/70167072.jpg"
|
1325
|
+
},
|
1326
|
+
"category": [
|
1327
|
+
{
|
1328
|
+
"term": "available now",
|
1329
|
+
"content": "Available Now",
|
1330
|
+
"scheme": "http://api.netflix.com/categories/queue_availability",
|
1331
|
+
"label": "available now"
|
1332
|
+
},
|
1333
|
+
{
|
1334
|
+
"term": "Blu-ray",
|
1335
|
+
"scheme": "http://api.netflix.com/categories/title_formats",
|
1336
|
+
"label": "Blu-ray"
|
1337
|
+
},
|
1338
|
+
{
|
1339
|
+
"term": "PG-13",
|
1340
|
+
"scheme": "http://api.netflix.com/categories/mpaa_ratings",
|
1341
|
+
"label": "PG-13"
|
1342
|
+
},
|
1343
|
+
{
|
1344
|
+
"term": "Comedy",
|
1345
|
+
"scheme": "http://api.netflix.com/categories/genres",
|
1346
|
+
"label": "Comedy"
|
1347
|
+
},
|
1348
|
+
{
|
1349
|
+
"term": "Romantic Comedies",
|
1350
|
+
"scheme": "http://api.netflix.com/categories/genres",
|
1351
|
+
"label": "Romantic Comedies"
|
1352
|
+
}
|
1353
|
+
],
|
1354
|
+
"updated": "1323539988",
|
1355
|
+
"id": "http://api.netflix.com/users/empty_queue/queues/disc/available/1/70167072",
|
1356
|
+
"link": [
|
1357
|
+
{
|
1358
|
+
"href": "http://api.netflix.com/users/empty_queue/queues/disc/available",
|
1359
|
+
"rel": "http://schemas.netflix.com/queues.available",
|
1360
|
+
"title": "available queue"
|
1361
|
+
},
|
1362
|
+
{
|
1363
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70167072",
|
1364
|
+
"rel": "http://schemas.netflix.com/catalog/title",
|
1365
|
+
"title": "Arthur"
|
1366
|
+
},
|
1367
|
+
{
|
1368
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70167072/synopsis",
|
1369
|
+
"rel": "http://schemas.netflix.com/catalog/titles/synopsis",
|
1370
|
+
"title": "synopsis"
|
1371
|
+
},
|
1372
|
+
{
|
1373
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70167072/cast",
|
1374
|
+
"rel": "http://schemas.netflix.com/catalog/people.cast",
|
1375
|
+
"title": "cast"
|
1376
|
+
},
|
1377
|
+
{
|
1378
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70167072/directors",
|
1379
|
+
"rel": "http://schemas.netflix.com/catalog/people.directors",
|
1380
|
+
"title": "directors"
|
1381
|
+
},
|
1382
|
+
{
|
1383
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70167072/format_availability",
|
1384
|
+
"rel": "http://schemas.netflix.com/catalog/titles/format_availability",
|
1385
|
+
"title": "formats"
|
1386
|
+
},
|
1387
|
+
{
|
1388
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70167072/screen_formats",
|
1389
|
+
"rel": "http://schemas.netflix.com/catalog/titles/screen_formats",
|
1390
|
+
"title": "screen formats"
|
1391
|
+
},
|
1392
|
+
{
|
1393
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70167072/languages_and_audio",
|
1394
|
+
"rel": "http://schemas.netflix.com/catalog/titles/languages_and_audio",
|
1395
|
+
"title": "languages and audio"
|
1396
|
+
},
|
1397
|
+
{
|
1398
|
+
"href": "http://api.netflix.com/catalog/titles/movies/70167072/similars",
|
1399
|
+
"rel": "http://schemas.netflix.com/catalog/titles.similars",
|
1400
|
+
"title": "similars"
|
1401
|
+
},
|
1402
|
+
{
|
1403
|
+
"href": "http://www.netflix.com/Movie/Arthur/70167072",
|
1404
|
+
"rel": "alternate",
|
1405
|
+
"title": "web page"
|
1406
|
+
}
|
1407
|
+
],
|
1408
|
+
"position": "1",
|
1409
|
+
"runtime": "6600",
|
1410
|
+
"title": {
|
1411
|
+
"regular": "Arthur",
|
1412
|
+
"short": "Arthur"
|
1413
|
+
},
|
1414
|
+
"release_year": "2011"
|
1415
|
+
}},
|
1416
|
+
"status_code": "201",
|
1417
|
+
"message": "Move successful",
|
1418
|
+
"etag": "82198468425"
|
1419
|
+
}}
|
1196
1420
|
delete:
|
1197
1421
|
body:
|
@@ -0,0 +1 @@
|
|
1
|
+
oauth_settings.yml
|
@@ -0,0 +1,72 @@
|
|
1
|
+
$:.unshift File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "lib"))
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'yaml'
|
5
|
+
require 'netflix'
|
6
|
+
|
7
|
+
class QueueTest < Test::Unit::TestCase
|
8
|
+
def setup
|
9
|
+
@oauth_settings = YAML.load_file(File.join(File.dirname(__FILE__),"oauth_settings.yml"))
|
10
|
+
#puts @oauth_settings
|
11
|
+
Netflix::Client.consumer_key = @oauth_settings[:consumer_key]
|
12
|
+
Netflix::Client.consumer_secret = @oauth_settings[:consumer_secret]
|
13
|
+
@client = Netflix::Client.new(@oauth_settings[:user][:access_token], @oauth_settings[:user][:access_secret])
|
14
|
+
|
15
|
+
#Do direct oauth gem retrieval of queue and deletion of all queue entries to get a clean start
|
16
|
+
oauth_access_token = @client.instance_variable_get(:@oauth_access_token)
|
17
|
+
#user_response = oauth_access_token.get "/users/current?output=json"
|
18
|
+
#puts "current_user: #{JSON.parse(user_response.body)}"
|
19
|
+
queue_response = oauth_access_token.get "/users/#{@oauth_settings[:user][:user_id]}/queues/disc/available?output=json"
|
20
|
+
queue_response_json = queue_response.body
|
21
|
+
queue_response_obj = JSON.parse(queue_response_json)
|
22
|
+
puts "get queue response: #{queue_response_obj}"
|
23
|
+
queue = queue_response_obj["queue"]
|
24
|
+
queue_items = queue && queue["queue_item"] && [queue["queue_item"]].flatten
|
25
|
+
if queue_items
|
26
|
+
queue_item_urls = queue_items.map() {|queue_item| queue_item["id"]}
|
27
|
+
queue_item_urls.reverse.each {|queue_item_url|
|
28
|
+
sleep 0.25 # for netflix api queries per second limit
|
29
|
+
response = oauth_access_token.delete queue_item_url
|
30
|
+
puts "delete response= #{response.body}"
|
31
|
+
}
|
32
|
+
end
|
33
|
+
sleep 0.25 # for netflix api queries per second limit
|
34
|
+
@user = @client.user(@oauth_settings[:user][:user_id])
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_get_available_disc_queue
|
38
|
+
available_disc_queue = @user.available_disc_queue
|
39
|
+
assert available_disc_queue, "Expecting user to have a disc_queue"
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_get_discs_add_and_remove
|
43
|
+
sleep 0.25 # for netflix api queries per second limit
|
44
|
+
queue = @user.available_disc_queue
|
45
|
+
assert queue, "Expecting queue"
|
46
|
+
assert_equal 0, queue.etag, "Initial etag should be 0 when no discs"
|
47
|
+
discs = queue.discs
|
48
|
+
assert discs, "Expecting the queue to respond to #discs"
|
49
|
+
assert_equal 0, discs.size, "Expecting the discs list to have size 0 at start"
|
50
|
+
|
51
|
+
sleep 0.25 # for netflix api queries per second limit
|
52
|
+
queue.add("http://api.netflix.com/catalog/titles/movies/70167072")
|
53
|
+
queue_after_add = @user.available_disc_queue
|
54
|
+
assert_not_equal 0, queue.etag, "Etag should not be 0 after a disc is added"
|
55
|
+
discs = queue_after_add.discs
|
56
|
+
assert discs, "Expecting the queue to respond to #discs"
|
57
|
+
assert_equal 1, discs.size, "Expecting the discs list to have size 1 after add"
|
58
|
+
|
59
|
+
disc_one = discs[0]
|
60
|
+
assert_equal "http://api.netflix.com/users/#{@oauth_settings[:user][:user_id]}/queues/disc/available/1/70167072", disc_one.id
|
61
|
+
assert_equal "Arthur", disc_one.title
|
62
|
+
|
63
|
+
sleep 0.25 # for netflix api queries per second limit
|
64
|
+
queue.remove(1)
|
65
|
+
sleep 0.25 # for netflix api queries per second limit
|
66
|
+
queue_after_remove = @user.available_disc_queue
|
67
|
+
discs = queue_after_remove.discs
|
68
|
+
assert discs, "Expecting the queue to respond to #discs"
|
69
|
+
assert_equal 0, discs.size, "Expecting the discs list to have size 0 after remove"
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'oauth'
|
2
|
+
require 'launchy'
|
3
|
+
|
4
|
+
class IntegrationTestHelper
|
5
|
+
def self.obtain_credentials
|
6
|
+
puts "Enter Consumer Key/Secret info before running integration tests, you should have registered with http://developer.netflix.com"
|
7
|
+
printf "Consumer Key:"
|
8
|
+
consumer_key = STDIN.gets.chomp
|
9
|
+
printf "Consumer Secret:"
|
10
|
+
consumer_secret = STDIN. gets.chomp
|
11
|
+
printf "Do you have an access token/secret? ([Y]/n)"
|
12
|
+
answer = STDIN.gets.chomp
|
13
|
+
if ["N","n","No","no"].include?(answer)
|
14
|
+
puts "Launching netflix oauth page, login to TEST account and allow this application"
|
15
|
+
oauth_consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
|
16
|
+
:site => "http://api.netflix.com",
|
17
|
+
:request_token_url => "http://api.netflix.com/oauth/request_token",
|
18
|
+
:access_token_url => "http://api.netflix.com/oauth/access_token",
|
19
|
+
:authorize_url => "https://api-user.netflix.com/oauth/login")
|
20
|
+
request_token = oauth_consumer.get_request_token
|
21
|
+
authorize_url = request_token.authorize_url(:oauth_consumer_key => consumer_key)
|
22
|
+
Launchy.open(authorize_url)
|
23
|
+
puts "Go to browser, a page has been opened to establish oauth"
|
24
|
+
printf "Pin from Netflix:"
|
25
|
+
pin = STDIN.gets.chomp
|
26
|
+
access_token_response = request_token.get_access_token(:oauth_verifier => pin)
|
27
|
+
access_token = access_token_response.token
|
28
|
+
access_secret = access_token_response.secret
|
29
|
+
user_id = access_token_response.params["user_id"]
|
30
|
+
else
|
31
|
+
printf "Access Token:"
|
32
|
+
access_token = STDIN.gets.chomp
|
33
|
+
printf "Access Secret:"
|
34
|
+
access_secret = STDIN.gets.chomp
|
35
|
+
printf "User id:"
|
36
|
+
user_id = STDIN.gets.chomp
|
37
|
+
end
|
38
|
+
|
39
|
+
{:consumer_key => consumer_key, :consumer_secret => consumer_secret, :user => {:access_token => access_token, :access_secret => access_secret, :user_id => user_id}}
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
data/test/queue_test.rb
CHANGED
@@ -3,6 +3,7 @@ require 'test_helper'
|
|
3
3
|
class QueueTest < Test::Unit::TestCase
|
4
4
|
def setup
|
5
5
|
stub_netflix_for_user('nuid_one')
|
6
|
+
stub_netflix_for_user('nuid_sub1')
|
6
7
|
Netflix::Client.consumer_key = 'foo_consumer_key'
|
7
8
|
Netflix::Client.consumer_secret = 'foo_consumer_secret'
|
8
9
|
end
|
@@ -25,18 +26,48 @@ class QueueTest < Test::Unit::TestCase
|
|
25
26
|
assert_equal "Arthur", disc_one.title
|
26
27
|
end
|
27
28
|
|
28
|
-
def
|
29
|
+
def test_add_item_to_queue_end_the_default
|
29
30
|
user = Netflix::Client.new('nuid_access_key', 'nuid_access_secret').user('nuid_one')
|
30
31
|
available_disc_queue = user.available_disc_queue
|
31
32
|
assert available_disc_queue
|
32
|
-
|
33
|
+
#pre tests
|
34
|
+
assert_equal "http://api.netflix.com/users/nuid_one/queues/disc/available/1/70167072", available_disc_queue.discs[0].id
|
35
|
+
assert_equal "http://api.netflix.com/users/nuid_one/queues/disc/available/2/70142826", available_disc_queue.discs[1].id
|
36
|
+
assert_equal "http://api.netflix.com/users/nuid_one/queues/disc/available/3/70108988", available_disc_queue.discs[2].id
|
37
|
+
assert_equal "115673854498", available_disc_queue.etag
|
38
|
+
#operation and tests
|
39
|
+
new_queue = available_disc_queue.add("http://api.netflix.com/catalog/titles/movies/70071613")
|
40
|
+
assert_equal "http://api.netflix.com/users/nuid_one/queues/disc/available/1/70167072", new_queue.discs[0].id
|
41
|
+
assert_equal "http://api.netflix.com/users/nuid_one/queues/disc/available/2/70142826", new_queue.discs[1].id
|
42
|
+
assert_equal "http://api.netflix.com/users/nuid_one/queues/disc/available/3/70108988", new_queue.discs[2].id
|
43
|
+
assert_equal "http://api.netflix.com/users/nuid_one/queues/disc/available/4/70071613", new_queue.discs[3].id
|
44
|
+
assert_equal "1", new_queue.discs[0].instance_variable_get(:@map)["position"]
|
45
|
+
assert_equal "2", new_queue.discs[1].instance_variable_get(:@map)["position"]
|
46
|
+
assert_equal "3", new_queue.discs[2].instance_variable_get(:@map)["position"]
|
47
|
+
assert_equal "4", new_queue.discs[3].instance_variable_get(:@map)["position"]
|
48
|
+
assert_equal "82198468425", new_queue.etag
|
33
49
|
end
|
34
50
|
|
35
51
|
def test_add_item_to_queue_top
|
36
|
-
user = Netflix::Client.new('nuid_access_key', 'nuid_access_secret').user('
|
52
|
+
user = Netflix::Client.new('nuid_access_key', 'nuid_access_secret').user('nuid_sub1')
|
37
53
|
available_disc_queue = user.available_disc_queue
|
38
54
|
assert available_disc_queue
|
39
|
-
|
55
|
+
#pre tests
|
56
|
+
assert_equal "http://api.netflix.com/users/nuid_sub1/queues/disc/available/1/70071613", available_disc_queue.discs[0].id
|
57
|
+
assert_equal "http://api.netflix.com/users/nuid_sub1/queues/disc/available/2/70117306", available_disc_queue.discs[1].id
|
58
|
+
assert_equal "http://api.netflix.com/users/nuid_sub1/queues/disc/available/3/70105135", available_disc_queue.discs[2].id
|
59
|
+
assert_equal "115673854498", available_disc_queue.etag
|
60
|
+
#operation and tests
|
61
|
+
new_queue = available_disc_queue.add("http://api.netflix.com/catalog/titles/movies/70167072", 1)
|
62
|
+
assert_equal "http://api.netflix.com/users/nuid_sub1/queues/disc/available/1/70167072", new_queue.discs[0].id
|
63
|
+
assert_equal "http://api.netflix.com/users/nuid_sub1/queues/disc/available/2/70071613", new_queue.discs[1].id
|
64
|
+
assert_equal "http://api.netflix.com/users/nuid_sub1/queues/disc/available/3/70117306", new_queue.discs[2].id
|
65
|
+
assert_equal "http://api.netflix.com/users/nuid_sub1/queues/disc/available/4/70105135", new_queue.discs[3].id
|
66
|
+
assert_equal "1", new_queue.discs[0].instance_variable_get(:@map)["position"]
|
67
|
+
assert_equal "2", new_queue.discs[1].instance_variable_get(:@map)["position"]
|
68
|
+
assert_equal "3", new_queue.discs[2].instance_variable_get(:@map)["position"]
|
69
|
+
assert_equal "4", new_queue.discs[3].instance_variable_get(:@map)["position"]
|
70
|
+
assert_equal "82198468425", new_queue.etag
|
40
71
|
end
|
41
72
|
|
42
73
|
def test_remove_item_from_queue_by_index
|
@@ -46,21 +77,6 @@ class QueueTest < Test::Unit::TestCase
|
|
46
77
|
available_disc_queue.remove(2)
|
47
78
|
end
|
48
79
|
|
49
|
-
#def test_add_item_to_stale_queue_fails
|
50
|
-
# user = Netflix::Client.new('nuid_access_key', 'nuid_access_secret').user('nuid_one')
|
51
|
-
# available_disc_queue = user.available_disc_queue
|
52
|
-
# assert available_disc_queue
|
53
|
-
# available_disc_queue.add('70071613')
|
54
|
-
# old_available_disc_queue = available_disc_queue
|
55
|
-
#
|
56
|
-
# available_disc_queue = user.available_disc_queue
|
57
|
-
# available_disc_queue.add('70117306')
|
58
|
-
#
|
59
|
-
# assert_raises() {
|
60
|
-
# old_available_disc_queue.add('70105135')
|
61
|
-
# }
|
62
|
-
#end
|
63
|
-
|
64
80
|
def test_empty_queue
|
65
81
|
stub_netflix_for_user('empty_queue')
|
66
82
|
user = Netflix::Client.new('nuid_access_key', 'nuid_access_secret').user('empty_queue')
|
@@ -68,6 +84,7 @@ class QueueTest < Test::Unit::TestCase
|
|
68
84
|
assert available_disc_queue, "Expected a disc_queue"
|
69
85
|
assert available_disc_queue.discs, "Expected the disc_queue to have a discs attribute"
|
70
86
|
assert_equal 0, available_disc_queue.discs.size, "Expected discs to be empty array #{available_disc_queue.discs[0]}}"
|
87
|
+
new_queue = available_disc_queue.add("http://api.netflix.com/catalog/titles/movies/70167072")
|
71
88
|
end
|
72
89
|
|
73
90
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: netflix
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-01-09 00:00:00.
|
12
|
+
date: 2012-01-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: oauth
|
16
|
-
requirement: &
|
16
|
+
requirement: &2155382740 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2155382740
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: json
|
27
|
-
requirement: &
|
27
|
+
requirement: &2155382320 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2155382320
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: launchy
|
38
|
-
requirement: &
|
38
|
+
requirement: &2155381900 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2155381900
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: fakeweb
|
49
|
-
requirement: &
|
49
|
+
requirement: &2155381480 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *2155381480
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: yaml
|
60
|
-
requirement: &
|
60
|
+
requirement: &2155381060 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,24 +65,31 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *2155381060
|
69
69
|
description: Ruby Netflix API wrapper
|
70
70
|
email: deanholdren@gmail.com
|
71
71
|
executables: []
|
72
72
|
extensions: []
|
73
73
|
extra_rdoc_files: []
|
74
74
|
files:
|
75
|
+
- .gitignore
|
75
76
|
- LICENSE
|
76
77
|
- README.rdoc
|
77
78
|
- Rakefile
|
78
79
|
- lib/netflix.rb
|
79
80
|
- lib/netflix/client.rb
|
80
81
|
- lib/netflix/disc.rb
|
82
|
+
- lib/netflix/errors.rb
|
81
83
|
- lib/netflix/json_resource.rb
|
82
84
|
- lib/netflix/queue.rb
|
85
|
+
- lib/netflix/response.rb
|
83
86
|
- lib/netflix/user.rb
|
87
|
+
- test/error_test.rb
|
84
88
|
- test/http_fixtures/netflix_queue_responses.yml
|
85
89
|
- test/http_fixtures/netflix_user_responses.yml
|
90
|
+
- test/integration/.gitignore
|
91
|
+
- test/integration/queue_test.rb
|
92
|
+
- test/integration/rake_test_helper.rb
|
86
93
|
- test/non_user_client.rb
|
87
94
|
- test/queue_test.rb
|
88
95
|
- test/test_helper.rb
|
@@ -107,13 +114,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
114
|
version: '0'
|
108
115
|
requirements: []
|
109
116
|
rubyforge_project:
|
110
|
-
rubygems_version: 1.8.
|
117
|
+
rubygems_version: 1.8.15
|
111
118
|
signing_key:
|
112
119
|
specification_version: 3
|
113
120
|
summary: Ruby Netflix API wrapper
|
114
121
|
test_files:
|
122
|
+
- test/error_test.rb
|
115
123
|
- test/http_fixtures/netflix_queue_responses.yml
|
116
124
|
- test/http_fixtures/netflix_user_responses.yml
|
125
|
+
- test/integration/.gitignore
|
126
|
+
- test/integration/queue_test.rb
|
127
|
+
- test/integration/rake_test_helper.rb
|
117
128
|
- test/non_user_client.rb
|
118
129
|
- test/queue_test.rb
|
119
130
|
- test/test_helper.rb
|