viki 0.0.5 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +25 -17
- data/lib/viki/client.rb +6 -32
- data/lib/viki/request.rb +34 -40
- data/lib/viki/transport.rb +55 -0
- data/lib/viki/utilities.rb +3 -0
- data/lib/viki/version.rb +1 -1
- data/spec/lib/client_spec.rb +7 -13
- data/spec/lib/request_spec.rb +31 -0
- data/spec/requests/{request_spec.rb → request_integration_spec.rb} +1 -1
- metadata +50 -17
data/README.md
CHANGED
@@ -7,23 +7,30 @@ Installation
|
|
7
7
|
----------
|
8
8
|
Manually `gem install viki` or add `gem 'viki'` to Gemfile
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
Add
|
10
|
+
Usage
|
11
|
+
-----
|
12
|
+
Add where necessary
|
13
13
|
|
14
14
|
require 'viki'
|
15
15
|
|
16
16
|
Initialization
|
17
17
|
|
18
|
-
|
18
|
+
client = Viki.new('your_client_id', 'your_client_secret')
|
19
|
+
|
20
|
+
Client is a `Viki::Client` object. When you make a method call, for example `client.movies`, the client will return a `Viki::Request` object - which you will be using to make requests. You may chain methods on the request object. The actual call to the API will only be made when you call `.get` on the request object.
|
19
21
|
|
22
|
+
viki = client.movies #returns a Viki::Request object
|
23
|
+
results = viki.get #hits the API and returns a Viki::APIObject
|
20
24
|
|
21
|
-
|
25
|
+
APIObject Methods
|
26
|
+
-----------------
|
22
27
|
|
23
|
-
|
28
|
+
Responses will be returned in a `Viki::APIObject`. See below
|
29
|
+
|
30
|
+
For results that are paginated, you may use the `APIObject`'s `next` and `prev` methods to retrieve the next and previous 25 records respectively.
|
24
31
|
|
25
32
|
```
|
26
|
-
viki.movies
|
33
|
+
viki = client.movies #returns a Viki::Request
|
27
34
|
movies = viki.get #return records in a Viki::APIObject
|
28
35
|
|
29
36
|
movies.content #content of the API call in JSON format
|
@@ -37,8 +44,9 @@ For results that are paginated. You can use the `APIObject`'s `next` and `prev`
|
|
37
44
|
Examples
|
38
45
|
----------
|
39
46
|
* Results will always be returned in JSON format.
|
47
|
+
* This gem simply converts Ruby methods to API endpoints. Each URL namespace is a method. This means that if there is a `/series/` url namespace, the gem's request object will have an equivalent `.series` method. See examples below for an illustration of this behaviour.
|
48
|
+
* Refer to the [API V3 documentation](http://dev.viki.com/api "Viki API V3 Docs") for complete documentation for all Viki API endpoints.
|
40
49
|
* All URL endpoints in the following examples should include an `access_token` parameter.
|
41
|
-
* Refer to the [API V3 documentation](http://dev.viki.com/api "Viki API V3 Docs") for all endpoints.
|
42
50
|
|
43
51
|
### List Movies
|
44
52
|
URL
|
@@ -51,8 +59,8 @@ URL
|
|
51
59
|
|
52
60
|
Your ruby application
|
53
61
|
|
54
|
-
|
55
|
-
|
62
|
+
client.movies.get #without parameter filters
|
63
|
+
client.movies(genre: 2).get #with parameter filters
|
56
64
|
|
57
65
|
### Show Movie
|
58
66
|
URL
|
@@ -61,7 +69,7 @@ URL
|
|
61
69
|
|
62
70
|
Your ruby application
|
63
71
|
|
64
|
-
|
72
|
+
client.movies(71459).get
|
65
73
|
|
66
74
|
### Subtitles
|
67
75
|
URL
|
@@ -70,7 +78,7 @@ URL
|
|
70
78
|
|
71
79
|
Your ruby application
|
72
80
|
|
73
|
-
|
81
|
+
client.movies(71459).subtitles('en').get
|
74
82
|
|
75
83
|
### Show Episode
|
76
84
|
URL
|
@@ -79,7 +87,7 @@ URL
|
|
79
87
|
|
80
88
|
Your ruby application
|
81
89
|
|
82
|
-
|
90
|
+
client.series(6004).episodes(61168).get
|
83
91
|
|
84
92
|
### List Newscasts
|
85
93
|
|
@@ -93,11 +101,11 @@ URL
|
|
93
101
|
|
94
102
|
Your ruby application
|
95
103
|
|
96
|
-
|
97
|
-
|
104
|
+
client.newscasts.get #without parameter filter
|
105
|
+
client.newscasts(language: 'ko').get #with parameter filter
|
98
106
|
|
99
107
|
RSpec Testing
|
100
|
-
|
108
|
+
-------------
|
101
109
|
To run the tests, create a spec_config.rb file from the sample file.
|
102
110
|
|
103
|
-
Add your client id and client secret into
|
111
|
+
Add your client id and client secret into this file.
|
data/lib/viki/client.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
require 'httparty'
|
2
2
|
require 'viki/api_object'
|
3
|
+
require 'viki/transport'
|
3
4
|
require 'viki/request'
|
4
5
|
require 'multi_json'
|
5
6
|
|
6
7
|
module Viki
|
7
8
|
class Client
|
8
|
-
|
9
|
-
URL_NAMESPACES = [:movies, :series, :episodes, :music_videos, :newscasts, :newsclips,
|
10
|
-
:artists, :featured, :coming_soon, :subtitles, :hardsubs, :genres, :countries,
|
11
|
-
:search, :languages]
|
9
|
+
include Viki::Transport
|
12
10
|
|
13
11
|
def initialize(client_id, client_secret)
|
14
12
|
@client_id = client_id
|
@@ -18,36 +16,12 @@ module Viki
|
|
18
16
|
|
19
17
|
attr_reader :access_token
|
20
18
|
|
21
|
-
include Viki::Request
|
22
|
-
|
23
|
-
def get
|
24
|
-
current_chain = @call_chain
|
25
|
-
@call_chain = []
|
26
|
-
request(current_chain)
|
27
|
-
end
|
28
|
-
|
29
|
-
def reset_access_token
|
30
|
-
@access_token = auth_request(@client_id, @client_secret)
|
31
|
-
end
|
32
|
-
|
33
19
|
private
|
34
20
|
def method_missing(name, *args)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
first_arg, second_arg = args[0], args[1]
|
41
|
-
|
42
|
-
if args.length == 1
|
43
|
-
first_arg.is_a?(Hash) ? curr_call.merge!({ params: first_arg }) : curr_call.merge!({ resource: first_arg })
|
44
|
-
elsif args.length == 2
|
45
|
-
curr_call.merge!({ resource: first_arg })
|
46
|
-
curr_call.merge!({ params: second_arg })
|
47
|
-
end
|
48
|
-
|
49
|
-
@call_chain.push(curr_call)
|
50
|
-
self
|
21
|
+
raise NoMethodError if not URL_NAMESPACES.include? name
|
22
|
+
Viki::Request.new({client_id: @client_id,
|
23
|
+
client_secret: @client_secret,
|
24
|
+
access_token: @access_token}, name, *args)
|
51
25
|
end
|
52
26
|
|
53
27
|
end
|
data/lib/viki/request.rb
CHANGED
@@ -1,57 +1,51 @@
|
|
1
|
-
require 'uri'
|
2
|
-
require 'httparty'
|
3
|
-
require 'multi_json'
|
4
|
-
require 'viki/utilities'
|
5
|
-
|
6
1
|
module Viki
|
7
|
-
|
8
|
-
|
2
|
+
class Request
|
3
|
+
def initialize(auth_data, name, *args)
|
4
|
+
@access_token = auth_data[:access_token]
|
5
|
+
@client_id = auth_data[:client_id]
|
6
|
+
@client_secret = auth_data[:client_secret]
|
9
7
|
|
10
|
-
|
11
|
-
HOST = "http://www.viki.com/api/v3/"
|
12
|
-
|
13
|
-
def auth_request(client_id, client_secret)
|
14
|
-
params = {
|
15
|
-
:grant_type => 'client_credentials',
|
16
|
-
:client_id => client_id,
|
17
|
-
:client_secret => client_secret
|
18
|
-
}
|
19
|
-
response = HTTParty.post('http://viki.com/oauth/token', query: params)
|
20
|
-
json = MultiJson.load(response.body)
|
21
|
-
raise Viki::Error.new(response.header.code, json["error_description"]) if response.header.code != "200"
|
22
|
-
json["access_token"]
|
8
|
+
build_call_chain(name, *args)
|
23
9
|
end
|
24
10
|
|
25
|
-
|
26
|
-
path, params = build_url(call_chain)
|
27
|
-
request_url = HOST + path.chop + ".json"
|
11
|
+
attr_reader :access_token
|
28
12
|
|
29
|
-
|
13
|
+
include Viki::Transport
|
30
14
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
capture response
|
15
|
+
def get
|
16
|
+
current_chain = @call_chain
|
17
|
+
@call_chain = []
|
18
|
+
request(current_chain)
|
19
|
+
end
|
38
20
|
|
39
|
-
|
21
|
+
def reset_access_token
|
22
|
+
@access_token = auth_request(@client_id, @client_secret)
|
40
23
|
end
|
41
24
|
|
42
25
|
private
|
26
|
+
def method_missing(name, *args)
|
27
|
+
build_call_chain(name, *args)
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def build_call_chain(name, *args)
|
32
|
+
@call_chain ||= []
|
33
|
+
raise NoMethodError if not URL_NAMESPACES.include? name
|
34
|
+
|
35
|
+
curr_call = { name: name }
|
43
36
|
|
44
|
-
|
45
|
-
path = ""
|
46
|
-
params = { access_token: self.access_token }
|
37
|
+
first_arg, second_arg = args[0], args[1]
|
47
38
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
39
|
+
if args.length == 1
|
40
|
+
first_arg.is_a?(Hash) ? curr_call.merge!({ params: first_arg }) : curr_call.merge!({ resource: first_arg })
|
41
|
+
elsif args.length == 2
|
42
|
+
curr_call.merge!({ resource: first_arg })
|
43
|
+
curr_call.merge!({ params: second_arg })
|
52
44
|
end
|
53
45
|
|
54
|
-
|
46
|
+
@call_chain.push(curr_call)
|
55
47
|
end
|
48
|
+
|
56
49
|
end
|
57
50
|
end
|
51
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'httparty'
|
3
|
+
require 'multi_json'
|
4
|
+
require 'viki/utilities'
|
5
|
+
|
6
|
+
module Viki
|
7
|
+
module Transport
|
8
|
+
include Viki::Utilities
|
9
|
+
|
10
|
+
private
|
11
|
+
HOST = "http://www.viki.com/api/v3/"
|
12
|
+
|
13
|
+
def auth_request(client_id, client_secret)
|
14
|
+
params = {
|
15
|
+
:grant_type => 'client_credentials',
|
16
|
+
:client_id => client_id,
|
17
|
+
:client_secret => client_secret
|
18
|
+
}
|
19
|
+
response = HTTParty.post('http://viki.com/oauth/token', query: params)
|
20
|
+
json = MultiJson.load(response.body)
|
21
|
+
raise Viki::Error.new(response.header.code, json["error_description"]) if response.header.code != "200"
|
22
|
+
json["access_token"]
|
23
|
+
end
|
24
|
+
|
25
|
+
def request(call_chain)
|
26
|
+
path, params = build_url(call_chain)
|
27
|
+
request_url = HOST + path.chop + ".json"
|
28
|
+
|
29
|
+
response = HTTParty.get(request_url, :query => params)
|
30
|
+
|
31
|
+
if response.header.code == "401"
|
32
|
+
self.reset_access_token
|
33
|
+
params.merge!({ access_token: self.access_token })
|
34
|
+
response = HTTParty.get(request_url, :query => params)
|
35
|
+
end
|
36
|
+
|
37
|
+
capture response
|
38
|
+
|
39
|
+
APIObject.new(response.body, self.access_token)
|
40
|
+
end
|
41
|
+
|
42
|
+
def build_url(call_chain)
|
43
|
+
path = ""
|
44
|
+
params = { access_token: self.access_token }
|
45
|
+
|
46
|
+
call_chain.each do |c|
|
47
|
+
path += "#{c[:name]}/"
|
48
|
+
path += "#{c[:resource]}/" if c.has_key?(:resource)
|
49
|
+
params.merge!(c[:params]) if c.has_key?(:params)
|
50
|
+
end
|
51
|
+
|
52
|
+
return path, params
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/viki/utilities.rb
CHANGED
data/lib/viki/version.rb
CHANGED
data/spec/lib/client_spec.rb
CHANGED
@@ -2,25 +2,19 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Viki::Client do
|
4
4
|
|
5
|
-
describe "
|
5
|
+
describe "method delegation" do
|
6
6
|
before { Viki::Client.any_instance.stub(:auth_request) }
|
7
|
-
subject { Viki::Client.new('chickenrice', 'soronerychickenrice') }
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
subject.should_receive(:request).with([{ :name => :movies, :resource => 1234 },
|
12
|
-
{ :name => :subtitles, :resource => "en" }])
|
13
|
-
subject.get
|
8
|
+
def client
|
9
|
+
Viki::Client.new('chickenrice', 'soronerychickenrice')
|
14
10
|
end
|
15
11
|
|
16
|
-
it "should
|
17
|
-
|
18
|
-
subject.should_receive(:request).with([{ :name => :movies, :resource => 1234, :params => {genre: 2}}])
|
19
|
-
subject.get
|
12
|
+
it "should raise NoMethodError error if part of the call chain is not part of the URL_NAMESPACES list" do
|
13
|
+
expect { client.methodwrong.subtitles('en') }.to raise_error(NoMethodError)
|
20
14
|
end
|
21
15
|
|
22
|
-
it "should
|
23
|
-
|
16
|
+
it "should return a request object when method_missing is called" do
|
17
|
+
client.movies(1234).should be_an_instance_of(Viki::Request)
|
24
18
|
end
|
25
19
|
end
|
26
20
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Viki::Request do
|
4
|
+
describe "#get" do
|
5
|
+
before do
|
6
|
+
Viki::Client.any_instance.stub(:auth_request)
|
7
|
+
Viki::Request.any_instance.stub(:request) { Viki::APIObject }
|
8
|
+
end
|
9
|
+
|
10
|
+
def client
|
11
|
+
Viki.new('chickenrice', 'soronerychickenrice')
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should perform a request to the right url given a call chain" do
|
15
|
+
req = client.movies(1234).subtitles('en')
|
16
|
+
req.should_receive(:request).with([{ :name => :movies, :resource => 1234 },
|
17
|
+
{ :name => :subtitles, :resource => "en" }])
|
18
|
+
req.get
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should perform a request with the right params given a call chain" do
|
22
|
+
req = client.movies(1234, { genre: 2 })
|
23
|
+
req.should_receive(:request).with([{ :name => :movies, :resource => 1234, :params => { genre: 2 } }])
|
24
|
+
req.get
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should raise NoMethodError error if part of the call chain is not part of the URL_NAMESPACES list" do
|
28
|
+
expect { client.methodwrong.subtitles('en') }.to raise_error(NoMethodError)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -128,7 +128,7 @@ describe "Viki" do
|
|
128
128
|
end
|
129
129
|
end
|
130
130
|
|
131
|
-
describe "
|
131
|
+
describe "Access token renewal" do
|
132
132
|
it "should request a new access token when an endpoint returns 401 and client currently has an access_token" do
|
133
133
|
VCR.use_cassette "auth/expired_access_token" do
|
134
134
|
client.access_token.should_not be_empty
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: viki
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,11 +11,11 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-07-
|
14
|
+
date: 2012-07-10 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rspec
|
18
|
-
requirement:
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
19
19
|
none: false
|
20
20
|
requirements:
|
21
21
|
- - ~>
|
@@ -23,10 +23,15 @@ dependencies:
|
|
23
23
|
version: 2.10.0
|
24
24
|
type: :development
|
25
25
|
prerelease: false
|
26
|
-
version_requirements:
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
28
|
+
requirements:
|
29
|
+
- - ~>
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: 2.10.0
|
27
32
|
- !ruby/object:Gem::Dependency
|
28
33
|
name: vcr
|
29
|
-
requirement:
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
30
35
|
none: false
|
31
36
|
requirements:
|
32
37
|
- - ~>
|
@@ -34,10 +39,15 @@ dependencies:
|
|
34
39
|
version: 2.2.2
|
35
40
|
type: :development
|
36
41
|
prerelease: false
|
37
|
-
version_requirements:
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.2.2
|
38
48
|
- !ruby/object:Gem::Dependency
|
39
49
|
name: webmock
|
40
|
-
requirement:
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
41
51
|
none: false
|
42
52
|
requirements:
|
43
53
|
- - ~>
|
@@ -45,10 +55,15 @@ dependencies:
|
|
45
55
|
version: 1.8.7
|
46
56
|
type: :development
|
47
57
|
prerelease: false
|
48
|
-
version_requirements:
|
58
|
+
version_requirements: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ~>
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 1.8.7
|
49
64
|
- !ruby/object:Gem::Dependency
|
50
65
|
name: excon
|
51
|
-
requirement:
|
66
|
+
requirement: !ruby/object:Gem::Requirement
|
52
67
|
none: false
|
53
68
|
requirements:
|
54
69
|
- - ~>
|
@@ -56,10 +71,15 @@ dependencies:
|
|
56
71
|
version: 0.9.6
|
57
72
|
type: :development
|
58
73
|
prerelease: false
|
59
|
-
version_requirements:
|
74
|
+
version_requirements: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ~>
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 0.9.6
|
60
80
|
- !ruby/object:Gem::Dependency
|
61
81
|
name: httparty
|
62
|
-
requirement:
|
82
|
+
requirement: !ruby/object:Gem::Requirement
|
63
83
|
none: false
|
64
84
|
requirements:
|
65
85
|
- - ~>
|
@@ -67,10 +87,15 @@ dependencies:
|
|
67
87
|
version: 0.8.3
|
68
88
|
type: :runtime
|
69
89
|
prerelease: false
|
70
|
-
version_requirements:
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ~>
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 0.8.3
|
71
96
|
- !ruby/object:Gem::Dependency
|
72
97
|
name: multi_json
|
73
|
-
requirement:
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
74
99
|
none: false
|
75
100
|
requirements:
|
76
101
|
- - ~>
|
@@ -78,7 +103,12 @@ dependencies:
|
|
78
103
|
version: 1.3.6
|
79
104
|
type: :runtime
|
80
105
|
prerelease: false
|
81
|
-
version_requirements:
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ~>
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: 1.3.6
|
82
112
|
description: Viki-gem is an official wrapper gem for the Viki V3 API.
|
83
113
|
email:
|
84
114
|
- engineering@viki.com
|
@@ -97,11 +127,13 @@ files:
|
|
97
127
|
- lib/viki/client.rb
|
98
128
|
- lib/viki/error.rb
|
99
129
|
- lib/viki/request.rb
|
130
|
+
- lib/viki/transport.rb
|
100
131
|
- lib/viki/utilities.rb
|
101
132
|
- lib/viki/version.rb
|
102
133
|
- spec/lib/client_spec.rb
|
103
134
|
- spec/lib/error_spec.rb
|
104
|
-
- spec/
|
135
|
+
- spec/lib/request_spec.rb
|
136
|
+
- spec/requests/request_integration_spec.rb
|
105
137
|
- spec/spec_config.rb.sample
|
106
138
|
- spec/spec_helper.rb
|
107
139
|
- spec/support/filter_shared_examples_spec.rb
|
@@ -127,14 +159,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
127
159
|
version: '0'
|
128
160
|
requirements: []
|
129
161
|
rubyforge_project: viki
|
130
|
-
rubygems_version: 1.8.
|
162
|
+
rubygems_version: 1.8.24
|
131
163
|
signing_key:
|
132
164
|
specification_version: 3
|
133
165
|
summary: A thin wrapper around the Viki V3 API
|
134
166
|
test_files:
|
135
167
|
- spec/lib/client_spec.rb
|
136
168
|
- spec/lib/error_spec.rb
|
137
|
-
- spec/
|
169
|
+
- spec/lib/request_spec.rb
|
170
|
+
- spec/requests/request_integration_spec.rb
|
138
171
|
- spec/spec_config.rb.sample
|
139
172
|
- spec/spec_helper.rb
|
140
173
|
- spec/support/filter_shared_examples_spec.rb
|