panda 0.4.5 → 0.4.7
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/LICENSE +1 -1
- data/README.md +12 -10
- data/VERSION +1 -1
- data/lib/panda/panda.rb +113 -94
- data/panda.gemspec +5 -6
- data/spec/panda_spec.rb +18 -9
- metadata +47 -25
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -11,8 +11,8 @@ Panda gem provides an interface to access the [Panda](http://pandastream.com) AP
|
|
11
11
|
require 'panda'
|
12
12
|
|
13
13
|
### Creating an instance of the client
|
14
|
-
|
15
|
-
|
14
|
+
|
15
|
+
Panda.connect!({
|
16
16
|
:cloud_id => 'cloud_id',
|
17
17
|
:access_key => 'access_key',
|
18
18
|
:secret_key => 'secret_key',
|
@@ -20,8 +20,10 @@ Panda gem provides an interface to access the [Panda](http://pandastream.com) AP
|
|
20
20
|
})
|
21
21
|
|
22
22
|
### Posting a video
|
23
|
-
|
24
|
-
|
23
|
+
|
24
|
+
Panda.post('/videos.json', {:file => File.open("panda.mp4")}) # Note that you will need a movie file to test this. You can grab http://panda-test-harness-videos.s3.amazonaws.com/panda.mp4
|
25
|
+
|
26
|
+
Panda.post('/videos.json', {:source_url => 'http://www.example.com/original_video.mp4'})
|
25
27
|
=>{"duration"=>nil,
|
26
28
|
"created_at"=>"2010/01/15 14:48:42 +0000",
|
27
29
|
"original_filename"=>"panda.mp4",
|
@@ -40,7 +42,7 @@ Panda gem provides an interface to access the [Panda](http://pandastream.com) AP
|
|
40
42
|
|
41
43
|
### Getting all videos
|
42
44
|
|
43
|
-
|
45
|
+
Panda.get('/videos.json')
|
44
46
|
=> [{"duration"=>14010,
|
45
47
|
"created_at"=>"2010/01/13 16:45:29 +0000",
|
46
48
|
"original_filename"=>"panda.mp4",
|
@@ -59,7 +61,7 @@ Panda gem provides an interface to access the [Panda](http://pandastream.com) AP
|
|
59
61
|
|
60
62
|
### Getting video encodings
|
61
63
|
|
62
|
-
|
64
|
+
Panda.get('/videos/0ee6b656-0063-11df-a433-1231390041c1/encodings.json')
|
63
65
|
=> [{"encoder_id"=>nil,
|
64
66
|
"created_at"=>"2010/01/13 16:45:30 +0000",
|
65
67
|
"video_id"=>"0ee6b656-0063-11df-a433-1231390041c1",
|
@@ -79,11 +81,11 @@ Panda gem provides an interface to access the [Panda](http://pandastream.com) AP
|
|
79
81
|
|
80
82
|
### Deleting a video encoding
|
81
83
|
|
82
|
-
|
84
|
+
Panda.delete('/encodings/0f815986-0063-11df-a433-1231390041c1.json')
|
83
85
|
|
84
86
|
### Deleting a video
|
85
87
|
|
86
|
-
|
88
|
+
Panda.delete('/videos/0ee6b656-0063-11df-a433-1231390041c1.json')
|
87
89
|
|
88
90
|
## Generating signatures
|
89
91
|
|
@@ -91,13 +93,13 @@ All requests to your Panda cloud are signed using HMAC-SHA256, based on a timest
|
|
91
93
|
|
92
94
|
To do this, a method `signed_params()` is supported:
|
93
95
|
|
94
|
-
|
96
|
+
Panda.signed_params('POST', '/videos.json')
|
95
97
|
# => {'access_key' => '8df50af4-074f-11df-b278-1231350015b1',
|
96
98
|
# 'cloud_id' => 'your-cloud-id',
|
97
99
|
# 'signature' => 'LejCdm0O83+jk6/Q5SfGmk14WTO1pB6Sh6Z5eA2w5C0=',
|
98
100
|
# 'timestamp' => '2010-02-26T15:01:46.221513'}
|
99
101
|
|
100
|
-
|
102
|
+
Panda.signed_params('GET', '/videos.json', {'some_params' => 'some_value'})
|
101
103
|
# => {'access_key' => '8df50af4-074f-11df-b278-1231350015b1',
|
102
104
|
# 'cloud_id' => 'your-cloud-id',
|
103
105
|
# 'signature' => 'uHnGZ+kI9mT3C4vW71Iop9z2N7UKCv38v2l2dvREUIQ=',
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.7
|
data/lib/panda/panda.rb
CHANGED
@@ -1,125 +1,144 @@
|
|
1
1
|
require 'restclient'
|
2
2
|
|
3
3
|
class Panda
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
DEFAULT_API_HOST="api.pandastream.com"
|
4
|
+
def self.connect!(auth_params)
|
5
|
+
@@connection = Connection.new(auth_params)
|
6
|
+
end
|
8
7
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
if auth_params.class == String
|
13
|
-
init_from_url(auth_params)
|
14
|
-
else
|
15
|
-
init_from_hash(auth_params)
|
16
|
-
end
|
17
|
-
|
18
|
-
@connection = RestClient::Resource.new(api_url)
|
8
|
+
def self.get(request_uri, params={})
|
9
|
+
@@connection.get(request_uri, params)
|
19
10
|
end
|
20
11
|
|
12
|
+
def self.post(request_uri, params)
|
13
|
+
@@connection.post(request_uri, params)
|
14
|
+
end
|
21
15
|
|
22
|
-
|
23
|
-
|
24
|
-
rescue_restclient_exception do
|
25
|
-
query = signed_query("GET", request_uri, params)
|
26
|
-
body_of @connection[request_uri + '?' + query].get
|
27
|
-
end
|
16
|
+
def self.put(request_uri, params)
|
17
|
+
@@connection.put(request_uri, params)
|
28
18
|
end
|
29
19
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
|
20
|
+
def self.delete(request_uri, params={})
|
21
|
+
@@connection.delete(request_uri, params)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.authentication_params(*params)
|
25
|
+
raise "Method deprecated. Please use signed_params instead."
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.signed_params(verb, request_uri, params = {}, timestamp_str = nil)
|
29
|
+
@@connection.signed_params(verb, request_uri, params, timestamp_str)
|
34
30
|
end
|
31
|
+
|
32
|
+
class Connection
|
33
|
+
attr_reader :api_host, :api_port, :access_key, :secret_key, :api_version
|
34
|
+
|
35
|
+
DEFAULT_API_PORT=80
|
36
|
+
DEFAULT_API_HOST="api.pandastream.com"
|
37
|
+
|
38
|
+
def initialize(auth_params)
|
39
|
+
@api_version = 2
|
40
|
+
|
41
|
+
if auth_params.class == String
|
42
|
+
init_from_url(auth_params)
|
43
|
+
else
|
44
|
+
init_from_hash(auth_params)
|
45
|
+
end
|
46
|
+
|
47
|
+
@connection = RestClient::Resource.new(api_url)
|
48
|
+
end
|
35
49
|
|
36
|
-
|
37
|
-
|
38
|
-
|
50
|
+
def get(request_uri, params={})
|
51
|
+
rescue_restclient_exception do
|
52
|
+
query = signed_query("GET", request_uri, params)
|
53
|
+
body_of @connection[request_uri + '?' + query].get
|
54
|
+
end
|
39
55
|
end
|
40
|
-
end
|
41
56
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
57
|
+
def post(request_uri, params)
|
58
|
+
rescue_restclient_exception do
|
59
|
+
body_of @connection[request_uri].post(signed_params("POST", request_uri, params))
|
60
|
+
end
|
46
61
|
end
|
47
|
-
end
|
48
62
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
auth_params['signature'] = ApiAuthentication.authenticate(verb, request_uri, @api_host, @secret_key, params.merge(auth_params))
|
55
|
-
return auth_params
|
56
|
-
end
|
63
|
+
def put(request_uri, params)
|
64
|
+
rescue_restclient_exception do
|
65
|
+
body_of @connection[request_uri].put(signed_params("PUT", request_uri, params))
|
66
|
+
end
|
67
|
+
end
|
57
68
|
|
58
|
-
|
59
|
-
|
60
|
-
|
69
|
+
def delete(request_uri, params={})
|
70
|
+
rescue_restclient_exception do
|
71
|
+
query = signed_query("DELETE", request_uri, params)
|
72
|
+
body_of @connection[request_uri + '?' + query].delete
|
73
|
+
end
|
74
|
+
end
|
61
75
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
76
|
+
def signed_query(*args)
|
77
|
+
ApiAuthentication.hash_to_query(signed_params(*args))
|
78
|
+
end
|
79
|
+
|
80
|
+
def signed_params(verb, request_uri, params = {}, timestamp_str = nil)
|
81
|
+
auth_params = params
|
82
|
+
auth_params['cloud_id'] = @cloud_id
|
83
|
+
auth_params['access_key'] = @access_key
|
84
|
+
auth_params['timestamp'] = timestamp_str || Time.now.iso8601(6)
|
85
|
+
|
86
|
+
params_to_sign = auth_params.reject{|k,v| ['file'].include?(k)}
|
87
|
+
auth_params['signature'] = ApiAuthentication.generate_signature(verb, request_uri, @api_host, @secret_key, params_to_sign)
|
88
|
+
auth_params
|
89
|
+
end
|
67
90
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
91
|
+
def api_url
|
92
|
+
"http://#{@api_host}:#{@api_port}/#{@prefix}"
|
93
|
+
end
|
72
94
|
|
73
|
-
|
74
|
-
|
75
|
-
|
95
|
+
def setup_bucket(params={})
|
96
|
+
granting_params = { :s3_videos_bucket => params[:bucket], :user_aws_key => params[:access_key], :user_aws_secret => params[:secret_key] }
|
97
|
+
put("/clouds/#{@cloud_id}.json", granting_params)
|
98
|
+
end
|
76
99
|
|
77
|
-
|
78
|
-
granting_params = { :s3_videos_bucket => params[:bucket], :user_aws_key => params[:access_key], :user_aws_secret => params[:secret_key] }
|
79
|
-
put("/clouds/#{@cloud_id}.json", granting_params)
|
80
|
-
end
|
100
|
+
private
|
81
101
|
|
82
|
-
|
102
|
+
def rescue_restclient_exception(&block)
|
103
|
+
begin
|
104
|
+
yield
|
105
|
+
rescue RestClient::Exception => e
|
106
|
+
e.http_body
|
107
|
+
end
|
108
|
+
end
|
83
109
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
rescue RestClient::Exception => e
|
88
|
-
e.http_body
|
110
|
+
# API change on rest-client 1.4
|
111
|
+
def body_of(response)
|
112
|
+
response.respond_to?(:body) ? response.body : response
|
89
113
|
end
|
90
|
-
end
|
91
114
|
|
92
|
-
# API change on rest-client 1.4
|
93
|
-
def body_of(response)
|
94
|
-
response.respond_to?(:body) ? response.body : response
|
95
|
-
end
|
96
115
|
|
116
|
+
def init_from_url(url)
|
117
|
+
params = url.scan(/^([^:@]+):([^:@]+)@([^:@]+)(:[\d]+)?\/([^:@]+)$/).flatten
|
97
118
|
|
98
|
-
|
99
|
-
|
119
|
+
@access_key = params[0]
|
120
|
+
@secret_key = params[1]
|
121
|
+
@cloud_id = params[4]
|
122
|
+
@api_host = params[2]
|
100
123
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
124
|
+
if params[3]
|
125
|
+
@api_port = params[3][1..-1]
|
126
|
+
else
|
127
|
+
@api_port = DEFAULT_API_PORT
|
128
|
+
end
|
129
|
+
@prefix = "v#{@api_version}"
|
105
130
|
|
106
|
-
if params[3]
|
107
|
-
@api_port = params[3][1..-1]
|
108
|
-
else
|
109
|
-
@api_port = DEFAULT_API_PORT
|
110
131
|
end
|
111
|
-
@prefix = "v#{@api_version}"
|
112
|
-
|
113
|
-
end
|
114
132
|
|
115
|
-
|
116
|
-
|
133
|
+
def init_from_hash(hash_params)
|
134
|
+
params = { :api_host => DEFAULT_API_HOST, :api_port => DEFAULT_API_PORT }.merge(hash_params)
|
117
135
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
end
|
136
|
+
@cloud_id = params["cloud_id"] || params[:cloud_id]
|
137
|
+
@access_key = params["access_key"] || params[:access_key]
|
138
|
+
@secret_key = params["secret_key"] || params[:secret_key]
|
139
|
+
@api_host = params["api_host"] || params[:api_host]
|
140
|
+
@api_port = params["api_port"] || params[:api_port]
|
141
|
+
@prefix = params["prefix_url"] || "v#{@api_version}"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
data/panda.gemspec
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{panda}
|
8
|
-
s.version = "0.4.
|
8
|
+
s.version = "0.4.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["New Bamboo"]
|
12
|
-
s.date = %q{2010-03-
|
12
|
+
s.date = %q{2010-03-18}
|
13
13
|
s.description = %q{Panda Client}
|
14
14
|
s.email = %q{info@pandastream.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -34,7 +34,7 @@ Gem::Specification.new do |s|
|
|
34
34
|
s.homepage = %q{http://github.com/newbamboo/panda_gem}
|
35
35
|
s.rdoc_options = ["--charset=UTF-8"]
|
36
36
|
s.require_paths = ["lib"]
|
37
|
-
s.rubygems_version = %q{1.3.
|
37
|
+
s.rubygems_version = %q{1.3.6}
|
38
38
|
s.summary = %q{Panda Client}
|
39
39
|
s.test_files = [
|
40
40
|
"spec/panda_spec.rb",
|
@@ -66,4 +66,3 @@ Gem::Specification.new do |s|
|
|
66
66
|
s.add_dependency(%q<rest-client>, [">= 1.2"])
|
67
67
|
end
|
68
68
|
end
|
69
|
-
|
data/spec/panda_spec.rb
CHANGED
@@ -6,10 +6,7 @@ describe Panda do
|
|
6
6
|
Time.stub!(:now).and_return(mock("time", :iso8601 => "2009-11-04T17:54:11+00:00"))
|
7
7
|
end
|
8
8
|
|
9
|
-
describe "Connected
|
10
|
-
before(:each) do
|
11
|
-
@panda = Panda.new({"access_key" => "my_access_key", "secret_key" => "my_secret_key", "api_host" => "myapihost", "api_port" => 85, "cloud_id" => 'my_cloud_id' })
|
12
|
-
end
|
9
|
+
describe "Connected", :shared => true do
|
13
10
|
|
14
11
|
it "should make get request with signed request to panda server" do
|
15
12
|
FakeWeb.register_uri(:get, "http://myapihost:85/v2/videos?timestamp=2009-11-04T17%3A54%3A11%2B00%3A00&signature=CxSYPM65SeeWH4CE%2FLcq7Ny2NtwxlpS8QOXG2BKe4p8%3D&access_key=my_access_key&cloud_id=my_cloud_id", :body => "abc")
|
@@ -73,19 +70,31 @@ describe Panda do
|
|
73
70
|
|
74
71
|
resource.stub!(:get).and_raise(e)
|
75
72
|
|
76
|
-
panda = Panda.new({"access_key" => "my_access_key", "secret_key" => "my_secret_key", "api_host" => "myapihost", "api_port" => 85, "cloud_id" => 'my_cloud_id' })
|
73
|
+
panda = Panda::Connection.new({"access_key" => "my_access_key", "secret_key" => "my_secret_key", "api_host" => "myapihost", "api_port" => 85, "cloud_id" => 'my_cloud_id' })
|
77
74
|
panda.get("/videos").should == "abc"
|
78
75
|
end
|
79
76
|
end
|
80
77
|
|
81
78
|
describe "Connected with a string url" do
|
82
79
|
before(:each) do
|
83
|
-
@
|
80
|
+
@panda = Panda::Connection.new("my_access_key:my_secret_key@myapihost:85/my_cloud_id")
|
84
81
|
end
|
85
82
|
|
86
|
-
|
87
|
-
|
88
|
-
|
83
|
+
it_should_behave_like "Connected"
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "Panda.connect " do
|
87
|
+
before(:each) do
|
88
|
+
Panda.connect!({"access_key" => "my_access_key", "secret_key" => "my_secret_key", "api_host" => "myapihost", "api_port" => 85, "cloud_id" => 'my_cloud_id' })
|
89
|
+
@panda = Panda
|
89
90
|
end
|
91
|
+
it_should_behave_like "Connected"
|
92
|
+
end
|
93
|
+
describe "Panda::Connection.new" do
|
94
|
+
before(:each) do
|
95
|
+
@panda = Panda::Connection.new({"access_key" => "my_access_key", "secret_key" => "my_secret_key", "api_host" => "myapihost", "api_port" => 85, "cloud_id" => 'my_cloud_id' })
|
96
|
+
end
|
97
|
+
it_should_behave_like "Connected"
|
90
98
|
end
|
99
|
+
|
91
100
|
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: panda
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 4
|
8
|
+
- 7
|
9
|
+
version: 0.4.7
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- New Bamboo
|
@@ -9,59 +14,74 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-03-
|
17
|
+
date: 2010-03-18 00:00:00 +00:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: rspec
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 2
|
30
|
+
- 9
|
23
31
|
version: 1.2.9
|
24
|
-
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
25
34
|
- !ruby/object:Gem::Dependency
|
26
35
|
name: fakeweb
|
27
|
-
|
28
|
-
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
38
|
requirements:
|
31
39
|
- - ">="
|
32
40
|
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
33
43
|
version: "0"
|
34
|
-
|
44
|
+
type: :development
|
45
|
+
version_requirements: *id002
|
35
46
|
- !ruby/object:Gem::Dependency
|
36
47
|
name: fakeweb-matcher
|
37
|
-
|
38
|
-
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
48
|
+
prerelease: false
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
40
50
|
requirements:
|
41
51
|
- - ">="
|
42
52
|
- !ruby/object:Gem::Version
|
53
|
+
segments:
|
54
|
+
- 0
|
43
55
|
version: "0"
|
44
|
-
|
56
|
+
type: :development
|
57
|
+
version_requirements: *id003
|
45
58
|
- !ruby/object:Gem::Dependency
|
46
59
|
name: ruby-hmac
|
47
|
-
|
48
|
-
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
prerelease: false
|
61
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
50
62
|
requirements:
|
51
63
|
- - ">="
|
52
64
|
- !ruby/object:Gem::Version
|
65
|
+
segments:
|
66
|
+
- 0
|
67
|
+
- 3
|
68
|
+
- 2
|
53
69
|
version: 0.3.2
|
54
|
-
|
70
|
+
type: :runtime
|
71
|
+
version_requirements: *id004
|
55
72
|
- !ruby/object:Gem::Dependency
|
56
73
|
name: rest-client
|
57
|
-
|
58
|
-
|
59
|
-
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
prerelease: false
|
75
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
60
76
|
requirements:
|
61
77
|
- - ">="
|
62
78
|
- !ruby/object:Gem::Version
|
79
|
+
segments:
|
80
|
+
- 1
|
81
|
+
- 2
|
63
82
|
version: "1.2"
|
64
|
-
|
83
|
+
type: :runtime
|
84
|
+
version_requirements: *id005
|
65
85
|
description: Panda Client
|
66
86
|
email: info@pandastream.com
|
67
87
|
executables: []
|
@@ -98,18 +118,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
98
118
|
requirements:
|
99
119
|
- - ">="
|
100
120
|
- !ruby/object:Gem::Version
|
121
|
+
segments:
|
122
|
+
- 0
|
101
123
|
version: "0"
|
102
|
-
version:
|
103
124
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
125
|
requirements:
|
105
126
|
- - ">="
|
106
127
|
- !ruby/object:Gem::Version
|
128
|
+
segments:
|
129
|
+
- 0
|
107
130
|
version: "0"
|
108
|
-
version:
|
109
131
|
requirements: []
|
110
132
|
|
111
133
|
rubyforge_project:
|
112
|
-
rubygems_version: 1.3.
|
134
|
+
rubygems_version: 1.3.6
|
113
135
|
signing_key:
|
114
136
|
specification_version: 3
|
115
137
|
summary: Panda Client
|