vj-sdk 0.2.1
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 +4 -0
- data/LICENSE +20 -0
- data/README.markdown +0 -0
- data/README.rdoc +7 -0
- data/Rakefile +70 -0
- data/VERSION.yml +4 -0
- data/lib/core_ext/cgi.rb +12 -0
- data/lib/core_ext/hash.rb +52 -0
- data/lib/core_ext/object.rb +15 -0
- data/lib/core_ext/string.rb +11 -0
- data/lib/sdk_connection_harness.rb +101 -0
- data/lib/videojuicer/asset/audio.rb +13 -0
- data/lib/videojuicer/asset/base.rb +80 -0
- data/lib/videojuicer/asset/flash.rb +8 -0
- data/lib/videojuicer/asset/image.rb +10 -0
- data/lib/videojuicer/asset/text.rb +8 -0
- data/lib/videojuicer/asset/video.rb +22 -0
- data/lib/videojuicer/campaign.rb +19 -0
- data/lib/videojuicer/campaign_policy.rb +116 -0
- data/lib/videojuicer/criterion/base.rb +56 -0
- data/lib/videojuicer/criterion/date_range.rb +15 -0
- data/lib/videojuicer/criterion/geolocation.rb +18 -0
- data/lib/videojuicer/criterion/request.rb +15 -0
- data/lib/videojuicer/criterion/time.rb +15 -0
- data/lib/videojuicer/criterion/week_day.rb +20 -0
- data/lib/videojuicer/oauth/multipart_helper.rb +96 -0
- data/lib/videojuicer/oauth/proxy_factory.rb +18 -0
- data/lib/videojuicer/oauth/request_proxy.rb +280 -0
- data/lib/videojuicer/presentation.rb +38 -0
- data/lib/videojuicer/preset.rb +29 -0
- data/lib/videojuicer/promo/base.rb +72 -0
- data/lib/videojuicer/resource/base.rb +175 -0
- data/lib/videojuicer/resource/collection.rb +36 -0
- data/lib/videojuicer/resource/embeddable.rb +30 -0
- data/lib/videojuicer/resource/errors.rb +17 -0
- data/lib/videojuicer/resource/inferrable.rb +141 -0
- data/lib/videojuicer/resource/property_registry.rb +145 -0
- data/lib/videojuicer/resource/relationships/belongs_to.rb +39 -0
- data/lib/videojuicer/resource/types.rb +28 -0
- data/lib/videojuicer/session.rb +74 -0
- data/lib/videojuicer/shared/configurable.rb +103 -0
- data/lib/videojuicer/shared/exceptions.rb +32 -0
- data/lib/videojuicer/user.rb +43 -0
- data/lib/videojuicer.rb +110 -0
- data/spec/assets/audio_spec.rb +25 -0
- data/spec/assets/flash_spec.rb +24 -0
- data/spec/assets/image_spec.rb +25 -0
- data/spec/assets/text_spec.rb +24 -0
- data/spec/assets/video_spec.rb +25 -0
- data/spec/belongs_to_spec.rb +45 -0
- data/spec/campaign_policy_spec.rb +41 -0
- data/spec/campaign_spec.rb +25 -0
- data/spec/collection_spec.rb +31 -0
- data/spec/criterion/date_range_spec.rb +24 -0
- data/spec/criterion/geolocation_spec.rb +23 -0
- data/spec/criterion/request_spec.rb +23 -0
- data/spec/criterion/time_spec.rb +23 -0
- data/spec/criterion/week_day_spec.rb +23 -0
- data/spec/files/audio.mp3 +0 -0
- data/spec/files/empty_file +0 -0
- data/spec/files/flash.swf +0 -0
- data/spec/files/image.jpg +0 -0
- data/spec/files/text.txt +1 -0
- data/spec/files/video.mov +0 -0
- data/spec/helpers/be_equal_to.rb +26 -0
- data/spec/helpers/spec_fixtures.rb +227 -0
- data/spec/helpers/spec_helper.rb +53 -0
- data/spec/presentation_spec.rb +25 -0
- data/spec/preset_spec.rb +30 -0
- data/spec/promos/audio_spec.rb +23 -0
- data/spec/promos/image_spec.rb +24 -0
- data/spec/promos/text_spec.rb +23 -0
- data/spec/promos/video_spec.rb +23 -0
- data/spec/property_registry_spec.rb +130 -0
- data/spec/request_proxy_spec.rb +90 -0
- data/spec/session_spec.rb +98 -0
- data/spec/shared/asset_spec.rb +39 -0
- data/spec/shared/configurable_spec.rb +75 -0
- data/spec/shared/dependent_spec.rb +40 -0
- data/spec/shared/embeddable_spec.rb +34 -0
- data/spec/shared/model_spec.rb +74 -0
- data/spec/shared/resource_spec.rb +140 -0
- data/spec/spec.opts +3 -0
- data/spec/user_spec.rb +42 -0
- data/spec/videojuicer_spec.rb +122 -0
- data/tasks/vj-core.rb +72 -0
- data/vj-sdk.gemspec +168 -0
- metadata +209 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "base")
|
2
|
+
|
3
|
+
module Videojuicer
|
4
|
+
module Criterion
|
5
|
+
class Request < Base
|
6
|
+
|
7
|
+
property :referrer, String, :nullable => false
|
8
|
+
property :exclude, Boolean
|
9
|
+
|
10
|
+
def matcher_keys
|
11
|
+
[:referrer, :exclude]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "base")
|
2
|
+
|
3
|
+
module Videojuicer
|
4
|
+
module Criterion
|
5
|
+
class WeekDay < Base
|
6
|
+
property :monday, Boolean
|
7
|
+
property :tuesday, Boolean
|
8
|
+
property :wednesday, Boolean
|
9
|
+
property :thursday, Boolean
|
10
|
+
property :friday, Boolean
|
11
|
+
property :saturday, Boolean
|
12
|
+
property :sunday, Boolean
|
13
|
+
property :exclude, Boolean
|
14
|
+
|
15
|
+
def matcher_keys
|
16
|
+
[:monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday, :exclude]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# Cribbed almost entirely from Merb's multipart request helper.
|
2
|
+
# Thanks, Yehuda!
|
3
|
+
|
4
|
+
module Videojuicer
|
5
|
+
module OAuth
|
6
|
+
module Multipart
|
7
|
+
|
8
|
+
require 'rubygems'
|
9
|
+
gem "mime-types"
|
10
|
+
require 'mime/types'
|
11
|
+
|
12
|
+
class Param
|
13
|
+
attr_accessor :key, :value
|
14
|
+
|
15
|
+
# ==== Parameters
|
16
|
+
# key<~to_s>:: The parameter key.
|
17
|
+
# value<~to_s>:: The parameter value.
|
18
|
+
def initialize(key, value)
|
19
|
+
@key = key
|
20
|
+
@value = value
|
21
|
+
end
|
22
|
+
|
23
|
+
# ==== Returns
|
24
|
+
# String:: The parameter in a form suitable for a multipart request.
|
25
|
+
def to_multipart
|
26
|
+
return %(Content-Disposition: form-data; name="#{key}"\r\n\r\n#{value}\r\n)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class FileParam
|
31
|
+
attr_accessor :key, :filename, :content
|
32
|
+
|
33
|
+
# ==== Parameters
|
34
|
+
# key<~to_s>:: The parameter key.
|
35
|
+
# filename<~to_s>:: Name of the file for this parameter.
|
36
|
+
# content<~to_s>:: Content of the file for this parameter.
|
37
|
+
def initialize(key, filename, content)
|
38
|
+
@key = key
|
39
|
+
@filename = filename
|
40
|
+
@content = content
|
41
|
+
end
|
42
|
+
|
43
|
+
# ==== Returns
|
44
|
+
# String::
|
45
|
+
# The file parameter in a form suitable for a multipart request.
|
46
|
+
def to_multipart
|
47
|
+
return %(Content-Disposition: form-data; name="#{key}"; filename="#{filename}"\r\n) + "Content-Type: #{MIME::Types.type_for(@filename).first}\r\n\r\n" + content + "\r\n"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class Post
|
52
|
+
BOUNDARY = '----------0xKhTmLbOuNdArY'
|
53
|
+
CONTENT_TYPE = "multipart/form-data, boundary=" + BOUNDARY
|
54
|
+
|
55
|
+
# ==== Parameters
|
56
|
+
# params<Hash>:: Optional params for the controller.
|
57
|
+
def initialize(params = {})
|
58
|
+
@multipart_params = []
|
59
|
+
push_params(params)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Saves the params in an array of multipart params as Param and
|
63
|
+
# FileParam objects.
|
64
|
+
#
|
65
|
+
# ==== Parameters
|
66
|
+
# params<Hash>:: The params to add to the multipart params.
|
67
|
+
# prefix<~to_s>:: An optional prefix for the request string keys.
|
68
|
+
def push_params(params, prefix = nil)
|
69
|
+
params.sort_by {|k| k.to_s}.each do |key, value|
|
70
|
+
param_key = prefix.nil? ? key : "#{prefix}[#{key}]"
|
71
|
+
if value.respond_to?(:read)
|
72
|
+
@multipart_params << FileParam.new(param_key, value.path, value.read)
|
73
|
+
value.rewind
|
74
|
+
else
|
75
|
+
if value.is_a?(Hash) || value.is_a?(Mash)
|
76
|
+
value.keys.each do |k|
|
77
|
+
push_params(value, param_key)
|
78
|
+
end
|
79
|
+
else
|
80
|
+
@multipart_params << Param.new(param_key, value)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# ==== Returns
|
87
|
+
# Array[String, String]:: The query and the content type.
|
88
|
+
def to_multipart
|
89
|
+
query = @multipart_params.collect { |param| "--" + BOUNDARY + "\r\n" + param.to_multipart }.join("") + "--" + BOUNDARY + "--"
|
90
|
+
return query, CONTENT_TYPE
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
=begin rdoc
|
2
|
+
|
3
|
+
ProxyFactory is a mixin that provides a convenience DSL for creating
|
4
|
+
new RequestProxy objects. It is intended for internal use within the SDK.
|
5
|
+
|
6
|
+
=end
|
7
|
+
|
8
|
+
module Videojuicer
|
9
|
+
module OAuth
|
10
|
+
module ProxyFactory
|
11
|
+
|
12
|
+
def proxy_for(options={})
|
13
|
+
Videojuicer::OAuth::RequestProxy.new(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,280 @@
|
|
1
|
+
=begin rdoc
|
2
|
+
|
3
|
+
The RequestProxy is, as the name suggests, a proxy through which HTTP requests are made
|
4
|
+
in order to have them correctly signed for verification under the OAuth protocol.
|
5
|
+
|
6
|
+
More information on OAuth: http://oauth.net
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
=end
|
11
|
+
|
12
|
+
require 'cgi'
|
13
|
+
require 'hmac'
|
14
|
+
require File.join(File.dirname(__FILE__), 'multipart_helper')
|
15
|
+
|
16
|
+
module Videojuicer
|
17
|
+
module OAuth
|
18
|
+
|
19
|
+
class RequestProxy
|
20
|
+
|
21
|
+
# Requests to the following ports will not include the port in the signature base string.
|
22
|
+
# See OAuth spec 1.0a section 9.1.2 for details.
|
23
|
+
EXCLUDED_BASE_STRING_PORTS = [80, 443].freeze
|
24
|
+
|
25
|
+
include Videojuicer::Exceptions
|
26
|
+
include Videojuicer::Configurable
|
27
|
+
|
28
|
+
# Initializes a new RequestProxy object which can be used to make requests.
|
29
|
+
# Accepts all the same options as Videojuicer::configure! as well as:
|
30
|
+
# +token+ - The OAuth token to use in requests made through this proxy.
|
31
|
+
# +token_secret+ - The OAuth token secret to use when encrypting the request signature.
|
32
|
+
def initialize(options={})
|
33
|
+
configure!(options)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Makes a GET request given path and params.
|
37
|
+
# The host will be ascertained from the configuration options.
|
38
|
+
def get(path, params={}); make_request(:get, host, port, path, params); end
|
39
|
+
|
40
|
+
# Makes a POST request given path and params.
|
41
|
+
# The host will be ascertained from the configuration options.
|
42
|
+
def post(path, params={}); make_request(:post, host, port, path, params); end
|
43
|
+
|
44
|
+
# Makes a PUT request given path and params.
|
45
|
+
# The host will be ascertained from the configuration options.
|
46
|
+
def put(path, params={}); make_request(:put, host, port, path, params); end
|
47
|
+
|
48
|
+
# Makes a DELETE request given path and params.
|
49
|
+
# The host will be ascertained from the configuration options.
|
50
|
+
def delete(path, params={}); make_request(:delete, host, port, path, params); end
|
51
|
+
|
52
|
+
# Does the actual work of making a request. Returns a Net::HTTPResponse object.
|
53
|
+
def make_request(method, host, port, path, params={})
|
54
|
+
# Strip the files from the parameters to determine what, from the whole bundle, needs signing
|
55
|
+
signature_params, multipart_params = split_by_signature_eligibility(params)
|
56
|
+
|
57
|
+
if multipart_params.any?
|
58
|
+
# Sign the params and include the as multipart
|
59
|
+
multipart_params = flatten_params(
|
60
|
+
authify_params(method, path, signature_params).deep_merge(multipart_params)
|
61
|
+
)
|
62
|
+
query_string = ""
|
63
|
+
else
|
64
|
+
# Use the query string
|
65
|
+
query_string = authified_query_string(method, path, signature_params)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Generate the HTTP Request and handle the response
|
69
|
+
url = "#{host_stub(protocol, host, port)}#{path}"
|
70
|
+
request = request_class_for_method(method).new("#{path}?#{query_string}")
|
71
|
+
# Generate the multipart body and headers
|
72
|
+
if multipart_params.any?
|
73
|
+
post_body, content_type = Multipart::Post.new(multipart_params).to_multipart
|
74
|
+
request.content_length = post_body.length
|
75
|
+
request.content_type = content_type
|
76
|
+
request.body = post_body
|
77
|
+
else
|
78
|
+
# Send a content-length on POST and PUT to avoid an HTTP 411 response
|
79
|
+
case method
|
80
|
+
when :post, :put
|
81
|
+
request = request_class_for_method(method).new("#{path}")
|
82
|
+
request.content_type = "application/x-www-form-urlencoded"
|
83
|
+
request.body = query_string
|
84
|
+
request.content_length = query_string.length
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
begin
|
90
|
+
#response = HTTPClient.send(method, url, multipart_params)
|
91
|
+
response = Net::HTTP.start(host, port) {|http| http.request(request) }
|
92
|
+
rescue EOFError => e
|
93
|
+
raise "EOF error when accessing #{url.inspect}"
|
94
|
+
rescue Errno::ECONNREFUSED => e
|
95
|
+
raise "Could not connect to #{url.inspect}"
|
96
|
+
end
|
97
|
+
|
98
|
+
return handle_response(response, request)
|
99
|
+
end
|
100
|
+
|
101
|
+
def host_stub(_protocol=protocol, _host=host, _port=port)
|
102
|
+
"#{_protocol}://#{_host}:#{_port}"
|
103
|
+
end
|
104
|
+
|
105
|
+
# Handles an HTTPResponse object appropriately. Redirects are followed,
|
106
|
+
# error states raise errors and success responses are returned directly.
|
107
|
+
def handle_response(response, request)
|
108
|
+
c = response.code.to_i
|
109
|
+
case c
|
110
|
+
when 200..399
|
111
|
+
# Successful or redirected response
|
112
|
+
response
|
113
|
+
when 415
|
114
|
+
# Validation error
|
115
|
+
response
|
116
|
+
when 401
|
117
|
+
# Authentication problem
|
118
|
+
response_error Unauthenticated, request, response
|
119
|
+
when 403
|
120
|
+
# Attempted to perform a forbidden action
|
121
|
+
response_error Forbidden, request, response
|
122
|
+
when 404
|
123
|
+
# Resource URL not valid
|
124
|
+
response_error NoResource, request, response
|
125
|
+
when 406
|
126
|
+
# Excuse me WTF r u doin
|
127
|
+
response_error NotAcceptable, request, response
|
128
|
+
when 411
|
129
|
+
# App-side server error where request is not properly constructed.
|
130
|
+
response_error ContentLengthRequired, request, response
|
131
|
+
when 500..600
|
132
|
+
# Remote application failure
|
133
|
+
response_error RemoteApplicationError, request, response
|
134
|
+
else
|
135
|
+
response_error UnhandledHTTPStatus, request, response
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Handles the response as an error of the desired type.
|
140
|
+
def response_error(exception_klass, request, response)
|
141
|
+
begin
|
142
|
+
e = JSON.parse(response.body)
|
143
|
+
e = e["error"]
|
144
|
+
raise exception_klass, "#{e["message"]} \n #{(e["backtrace"] || []).join("\n")}"
|
145
|
+
rescue JSON::ParserError
|
146
|
+
raise exception_klass, "#{exception_klass.to_s} : Response code was #{response.code} for request: #{request.path}"
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
# Splits a given parameter hash into two hashes - one containing all
|
152
|
+
# string and non-binary parameters, and one containing all file/binary parameters.
|
153
|
+
# This action is performed recursively so that:
|
154
|
+
# params = {:user=>{:attributes=>{:file=>some_file, :name=>"user name"}}, :foo=>"bar"}
|
155
|
+
# normal, multipart = split_multipart_params(params)
|
156
|
+
# normal.inspect # => {:user=>{:attributes=>{:name=>"user name"}}, :foo=>"bar"}
|
157
|
+
# multipart.inspect # => {:user=>{:attributes=>{:file=>some_file}}}
|
158
|
+
def split_by_signature_eligibility(params, *hash_path)
|
159
|
+
strings = {}
|
160
|
+
files = {}
|
161
|
+
params.each do |key, value|
|
162
|
+
if value.is_a?(Hash)
|
163
|
+
# Call recursively
|
164
|
+
s, f = split_by_signature_eligibility(value, *(hash_path+[key]))
|
165
|
+
strings = strings.deep_merge(s)
|
166
|
+
files = files.deep_merge(f)
|
167
|
+
else
|
168
|
+
# Insert it into files at the current key path if it is a binary,
|
169
|
+
# and into strings if it is not.
|
170
|
+
pwd = (value.respond_to?(:read))? files : strings
|
171
|
+
hash_path.each do |component|
|
172
|
+
pwd[component] ||= {}
|
173
|
+
pwd = pwd[component]
|
174
|
+
end
|
175
|
+
pwd[key] = value
|
176
|
+
end
|
177
|
+
end
|
178
|
+
return strings, files
|
179
|
+
end
|
180
|
+
|
181
|
+
def signed_url(method, path, params={})
|
182
|
+
"#{protocol}://#{host}:#{port}#{path}?#{authified_query_string(method, path, params)}"
|
183
|
+
end
|
184
|
+
|
185
|
+
# Authifies the given parameters and converts them into a query string.
|
186
|
+
def authified_query_string(method, path, params={})
|
187
|
+
normalize_params(authify_params(method, path, params))
|
188
|
+
end
|
189
|
+
|
190
|
+
# Takes a set of business parameters you want sent to the provider, and merges them
|
191
|
+
# with the proxy configuration to produce a set of parameters that will be accepted
|
192
|
+
# by the OAuth provider.
|
193
|
+
def authify_params(method, path, params)
|
194
|
+
params = {
|
195
|
+
:oauth_consumer_key=>consumer_key,
|
196
|
+
:oauth_token=>token,
|
197
|
+
:api_version=>api_version,
|
198
|
+
:oauth_timestamp=>Time.now.to_i,
|
199
|
+
:oauth_nonce=>rand(9999),
|
200
|
+
:oauth_signature_method=>"HMAC-SHA1",
|
201
|
+
:seed_name=>seed_name,
|
202
|
+
:user_id=>user_id
|
203
|
+
}.merge(params)
|
204
|
+
params.delete_if {|k,v| (!v) or (v.to_s.empty?) }
|
205
|
+
params[:oauth_signature] = signature(method, path, params)
|
206
|
+
return params
|
207
|
+
end
|
208
|
+
|
209
|
+
# Calculates and returns the encrypted signature for this proxy object and the
|
210
|
+
# given request properties.
|
211
|
+
def signature(method, path, params)
|
212
|
+
base = signature_base_string(method, path, params)
|
213
|
+
signature_octet = HMAC::SHA1.digest(signature_secret, base)
|
214
|
+
signature_base64 = [signature_octet].pack('m').chomp.gsub(/\n/, '')
|
215
|
+
end
|
216
|
+
|
217
|
+
# Calculates and returns the signature secret to be used for this proxy object.
|
218
|
+
def signature_secret
|
219
|
+
[consumer_secret, token_secret].collect {|e| CGI.rfc3986_escape(e.to_s)}.join("&")
|
220
|
+
end
|
221
|
+
|
222
|
+
# Returns the unencrypted signature base string for this proxy object and the
|
223
|
+
# given request properties.
|
224
|
+
def signature_base_string(method, path, params)
|
225
|
+
s = [method.to_s.upcase, "#{protocol}://#{signature_base_string_host}#{path}", normalize_params(params)].collect {|e| CGI.rfc3986_escape(e)}.join("&")
|
226
|
+
end
|
227
|
+
|
228
|
+
def signature_base_string_host
|
229
|
+
if EXCLUDED_BASE_STRING_PORTS.include?(port.to_i)
|
230
|
+
# Natural port. Ignore the port
|
231
|
+
host
|
232
|
+
else
|
233
|
+
# Weird port. Expect a signature.
|
234
|
+
"#{host}:#{port}"
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# Returns a string representing a normalised parameter hash. Supports nesting for
|
239
|
+
# rails or merb-style object[attr] properties supplied as nested hashes. For instance,
|
240
|
+
# the key 'bar inside {:foo=>{:bar=>"baz"}} will be named foo[bar] in the signature
|
241
|
+
# and in the eventual request object.
|
242
|
+
def normalize_params(params, *hash_path)
|
243
|
+
flatten_params(params).sort {|a,b| a.to_s <=> b.to_s}.collect {|k, v| "#{CGI.rfc3986_escape(k)}=#{CGI.rfc3986_escape(v.to_s)}" }.join("&")
|
244
|
+
end
|
245
|
+
|
246
|
+
def flatten_params(params, *hash_path)
|
247
|
+
op = {}
|
248
|
+
params.sort {|a,b| a.to_s<=>b.to_s}.each do |key, value|
|
249
|
+
path = hash_path.dup
|
250
|
+
path << key.to_s
|
251
|
+
|
252
|
+
if value.is_a?(Hash)
|
253
|
+
op.merge! flatten_params(value, *path)
|
254
|
+
elsif value
|
255
|
+
key_path = path.first + path[1..(path.length-1)].collect {|h| "[#{h}]"}.join("")
|
256
|
+
op[key_path] = value
|
257
|
+
end
|
258
|
+
end
|
259
|
+
return op
|
260
|
+
end
|
261
|
+
|
262
|
+
# Returns the Net::HTTPRequest subclass needed to make a request for the given method.
|
263
|
+
def request_class_for_method(m, in_module=Net::HTTP)
|
264
|
+
case (m.is_a?(Symbol) ? m : m.downcase.to_sym rescue :get)
|
265
|
+
when :post
|
266
|
+
in_module::Post
|
267
|
+
when :put
|
268
|
+
in_module::Put
|
269
|
+
when :head
|
270
|
+
in_module::Head
|
271
|
+
when :delete
|
272
|
+
in_module::Delete
|
273
|
+
else
|
274
|
+
in_module::Get
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Videojuicer
|
2
|
+
class Presentation
|
3
|
+
include Videojuicer::Resource
|
4
|
+
include Videojuicer::Resource::Embeddable
|
5
|
+
include Videojuicer::Exceptions
|
6
|
+
|
7
|
+
property :slug, String
|
8
|
+
property :title, String
|
9
|
+
property :author, String
|
10
|
+
property :author_url, String
|
11
|
+
property :abstract, String
|
12
|
+
property :user_id, Integer, :writer=>:private
|
13
|
+
belongs_to :user, :class=>Videojuicer::User
|
14
|
+
property :callback_url, String
|
15
|
+
|
16
|
+
property :state, String, :default=>"ready" # see the STATES constant for values
|
17
|
+
property :disclosure, String, :default=>"public" # see DISCLOSURES constant for values
|
18
|
+
property :publish_from, DateTime
|
19
|
+
property :publish_until, DateTime
|
20
|
+
|
21
|
+
property :document_layout, String
|
22
|
+
property :document_content, String # the presentation document
|
23
|
+
property :document_type, String, :default=>"SMIL 3.0"
|
24
|
+
|
25
|
+
property :created_at, DateTime
|
26
|
+
property :updated_at, DateTime
|
27
|
+
|
28
|
+
property :image_asset_id, Integer # FIXME make me a relationship helper
|
29
|
+
|
30
|
+
property :tag_list, String
|
31
|
+
|
32
|
+
def permalink
|
33
|
+
proxy = proxy_for(config)
|
34
|
+
"#{proxy.host_stub}/presentations/#{id}.html?seed_name=#{seed_name}".gsub(":80/","/")
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Videojuicer
|
2
|
+
class Preset
|
3
|
+
include Videojuicer::Resource
|
4
|
+
|
5
|
+
property :name, String
|
6
|
+
property :derived_type, String
|
7
|
+
property :created_at, DateTime
|
8
|
+
property :updated_at, DateTime
|
9
|
+
|
10
|
+
property :file_format, String
|
11
|
+
|
12
|
+
property :audio_bit_rate, Integer # bits per second
|
13
|
+
property :audio_channels, Integer
|
14
|
+
property :audio_format, String
|
15
|
+
property :audio_sample_rate, Integer # hertz
|
16
|
+
|
17
|
+
property :video_bit_rate, Integer # bits per second
|
18
|
+
property :video_format, String
|
19
|
+
property :video_frame_rate, Float # frames per second
|
20
|
+
|
21
|
+
property :width, Integer # pixels
|
22
|
+
property :height, Integer # pixels
|
23
|
+
|
24
|
+
def self.formats
|
25
|
+
response = instance_proxy.get(resource_route(:formats))
|
26
|
+
JSON.parse(response.body)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Videojuicer
|
2
|
+
module Promo
|
3
|
+
def self.model_map
|
4
|
+
{ :audio => Videojuicer::Promo::Audio,
|
5
|
+
:images => Videojuicer::Promo::Image,
|
6
|
+
:texts => Videojuicer::Promo::Text,
|
7
|
+
:videos => Videojuicer::Promo::Video
|
8
|
+
}
|
9
|
+
end
|
10
|
+
|
11
|
+
class Base
|
12
|
+
|
13
|
+
def self.inherited(base)
|
14
|
+
base.send(:include, Videojuicer::Resource)
|
15
|
+
base.send(:extend, Videojuicer::Promo::Base::ClassMethods)
|
16
|
+
base.send(:include, Videojuicer::Promo::Base::InstanceMethods)
|
17
|
+
|
18
|
+
base.property :campaign_policy_id, Integer
|
19
|
+
base.property :asset_id, Integer
|
20
|
+
base.property :role, String
|
21
|
+
base.property :href, String
|
22
|
+
end
|
23
|
+
|
24
|
+
module ClassMethods
|
25
|
+
def singular_name
|
26
|
+
"promo"
|
27
|
+
end
|
28
|
+
|
29
|
+
def base_path(options={})
|
30
|
+
"/promos/#{self.to_s.split("::").last.snake_case}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def get(*args); raise NoMethodError; end
|
34
|
+
def all(*args); raise NoMethodError; end
|
35
|
+
def first(*args); raise NoMethodError; end
|
36
|
+
end
|
37
|
+
|
38
|
+
module InstanceMethods
|
39
|
+
def save(*args); raise NoMethodError; end
|
40
|
+
def destroy(*args); raise NoMethodError; end
|
41
|
+
def asset
|
42
|
+
Videojuicer::Asset.const_get(self.class.to_s.split("::").last).get(asset_id)
|
43
|
+
end
|
44
|
+
def matcher_keys
|
45
|
+
[:campaign_policy_id, :asset_id, :role, :href]
|
46
|
+
end
|
47
|
+
def matcher_attributes
|
48
|
+
matcher_keys.inject({}) do |memo, attr|
|
49
|
+
memo.update(attr => self.send(attr))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
class Audio < Base
|
57
|
+
end
|
58
|
+
|
59
|
+
class Image < Base
|
60
|
+
end
|
61
|
+
|
62
|
+
class Text < Base
|
63
|
+
end
|
64
|
+
|
65
|
+
class Video < Base
|
66
|
+
end
|
67
|
+
|
68
|
+
class Heart < Base
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|