viki 0.0.5 → 1.0.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/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
|