animoto 0.0.0.alpha9 → 0.1.0.beta0

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.
Files changed (96) hide show
  1. data/README.md +26 -13
  2. data/integration/test.rb +2 -3
  3. data/lib/animoto/assets/base.rb +29 -0
  4. data/lib/animoto/assets/footage.rb +34 -0
  5. data/lib/animoto/assets/image.rb +25 -0
  6. data/lib/animoto/assets/song.rb +27 -0
  7. data/lib/animoto/assets/title_card.rb +35 -0
  8. data/lib/animoto/callbacks/base.rb +45 -0
  9. data/lib/animoto/callbacks/directing.rb +7 -0
  10. data/lib/animoto/callbacks/directing_and_rendering.rb +7 -0
  11. data/lib/animoto/callbacks/rendering.rb +7 -0
  12. data/lib/animoto/client.rb +133 -80
  13. data/lib/animoto/http_engines/base.rb +40 -0
  14. data/lib/animoto/http_engines/curl_adapter.rb +17 -5
  15. data/lib/animoto/http_engines/net_http_adapter.rb +6 -4
  16. data/lib/animoto/http_engines/patron_adapter.rb +7 -2
  17. data/lib/animoto/http_engines/rest_client_adapter.rb +3 -3
  18. data/lib/animoto/http_engines/typhoeus_adapter.rb +4 -4
  19. data/lib/animoto/manifests/base.rb +18 -0
  20. data/lib/animoto/manifests/directing.rb +146 -0
  21. data/lib/animoto/manifests/directing_and_rendering.rb +51 -0
  22. data/lib/animoto/manifests/rendering.rb +71 -0
  23. data/lib/animoto/resources/base.rb +133 -0
  24. data/lib/animoto/resources/jobs/base.rb +61 -0
  25. data/lib/animoto/resources/jobs/directing.rb +27 -0
  26. data/lib/animoto/resources/jobs/directing_and_rendering.rb +28 -0
  27. data/lib/animoto/resources/jobs/rendering.rb +35 -0
  28. data/lib/animoto/resources/storyboard.rb +36 -0
  29. data/lib/animoto/resources/video.rb +50 -0
  30. data/lib/animoto/response_parsers/base.rb +44 -0
  31. data/lib/animoto/response_parsers/json_adapter.rb +8 -7
  32. data/lib/animoto/response_parsers/yajl_adapter.rb +9 -8
  33. data/lib/animoto/support/content_type.rb +49 -0
  34. data/lib/animoto/support/coverable.rb +31 -0
  35. data/lib/animoto/support/dynamic_class_loader.rb +166 -0
  36. data/lib/animoto/support/errors.rb +5 -0
  37. data/lib/animoto/support/standard_envelope.rb +66 -0
  38. data/lib/animoto/support/visual.rb +32 -0
  39. data/lib/animoto.rb +7 -1
  40. data/spec/animoto/assets/base_spec.rb +5 -0
  41. data/spec/animoto/{footage_spec.rb → assets/footage_spec.rb} +4 -4
  42. data/spec/animoto/{image_spec.rb → assets/image_spec.rb} +4 -4
  43. data/spec/animoto/{song_spec.rb → assets/song_spec.rb} +3 -3
  44. data/spec/animoto/{title_card_spec.rb → assets/title_card_spec.rb} +4 -4
  45. data/spec/animoto/callbacks/base_spec.rb +76 -0
  46. data/spec/animoto/callbacks/directing_and_rendering_spec.rb +5 -0
  47. data/spec/animoto/callbacks/directing_spec.rb +5 -0
  48. data/spec/animoto/callbacks/rendering_spec.rb +5 -0
  49. data/spec/animoto/client_spec.rb +29 -5
  50. data/spec/animoto/{http_engine_spec.rb → http_engines/base_spec.rb} +5 -5
  51. data/spec/animoto/{directing_and_rendering_manifest_spec.rb → manifests/directing_and_rendering_spec.rb} +3 -3
  52. data/spec/animoto/{directing_manifest_spec.rb → manifests/directing_spec.rb} +8 -8
  53. data/spec/animoto/{rendering_manifest_spec.rb → manifests/rendering_spec.rb} +7 -7
  54. data/spec/animoto/{resource_spec.rb → resources/base_spec.rb} +7 -7
  55. data/spec/animoto/{job_spec.rb → resources/jobs/base_spec.rb} +9 -5
  56. data/spec/animoto/{directing_and_rendering_job_spec.rb → resources/jobs/directing_and_rendering_spec.rb} +7 -7
  57. data/spec/animoto/{directing_job_spec.rb → resources/jobs/directing_spec.rb} +7 -7
  58. data/spec/animoto/{rendering_job_spec.rb → resources/jobs/rendering_spec.rb} +8 -8
  59. data/spec/animoto/resources/storyboard_spec.rb +8 -0
  60. data/spec/animoto/resources/video_spec.rb +5 -0
  61. data/spec/animoto/response_parsers/json_adapter_spec.rb +2 -2
  62. data/spec/animoto/response_parsers/yajl_adapter_spec.rb +2 -2
  63. data/spec/animoto/support/coverable_spec.rb +5 -0
  64. data/spec/animoto/support/standard_envelope_spec.rb +5 -0
  65. data/spec/animoto/support/visual_spec.rb +5 -0
  66. metadata +56 -48
  67. data/lib/animoto/asset.rb +0 -19
  68. data/lib/animoto/content_type.rb +0 -47
  69. data/lib/animoto/coverable.rb +0 -29
  70. data/lib/animoto/directing_and_rendering_job.rb +0 -19
  71. data/lib/animoto/directing_and_rendering_manifest.rb +0 -25
  72. data/lib/animoto/directing_job.rb +0 -18
  73. data/lib/animoto/directing_manifest.rb +0 -112
  74. data/lib/animoto/dynamic_class_loader.rb +0 -64
  75. data/lib/animoto/errors.rb +0 -3
  76. data/lib/animoto/footage.rb +0 -16
  77. data/lib/animoto/http_engine.rb +0 -34
  78. data/lib/animoto/image.rb +0 -16
  79. data/lib/animoto/job.rb +0 -37
  80. data/lib/animoto/manifest.rb +0 -14
  81. data/lib/animoto/rendering_job.rb +0 -24
  82. data/lib/animoto/rendering_manifest.rb +0 -37
  83. data/lib/animoto/resource.rb +0 -149
  84. data/lib/animoto/response_parser.rb +0 -38
  85. data/lib/animoto/song.rb +0 -14
  86. data/lib/animoto/standard_envelope.rb +0 -27
  87. data/lib/animoto/storyboard.rb +0 -22
  88. data/lib/animoto/title_card.rb +0 -26
  89. data/lib/animoto/video.rb +0 -29
  90. data/lib/animoto/visual.rb +0 -30
  91. data/spec/animoto/asset_spec.rb +0 -5
  92. data/spec/animoto/coverable_spec.rb +0 -5
  93. data/spec/animoto/standard_envelope_spec.rb +0 -5
  94. data/spec/animoto/storyboard_spec.rb +0 -8
  95. data/spec/animoto/video_spec.rb +0 -5
  96. data/spec/animoto/visual_spec.rb +0 -5
data/README.md CHANGED
@@ -31,6 +31,19 @@ This document does not cover the details of the Animoto API itself. For such inf
31
31
  <a name="getting_started_using_the_ruby_client"></a>
32
32
  ## Getting Started using the Ruby Client
33
33
 
34
+ ### Installation
35
+
36
+ You can install the Animoto API Ruby Client either through [RubyGems](http://rubygems.org):
37
+
38
+ gem install animoto -v 0.1.0.alpha0 --pre
39
+
40
+ Or by cloning [the repository](http://github.com/animoto/animoto_api_client_ruby) on [GitHub](http://github.com/) and building it from source:
41
+
42
+ git clone git://github.com/animoto/animoto_api_client_ruby.git
43
+ cd animoto_api_client_ruby
44
+ gem build animoto.gemspec
45
+ gem install animoto-0.1.0.alpha0.gem
46
+
34
47
  ### Prerequisites
35
48
 
36
49
  #### Readers of this document should be familiar with...
@@ -87,7 +100,7 @@ client and using HTTP callbacks for status updates.
87
100
  # create a directing and rendering manifest with the video title and
88
101
  # producer. Also include rendering parameters like resolution, framerate,
89
102
  # and format.
90
- manifest = DirectingAndRenderingManifest.new(
103
+ manifest = Manifests::DirectingAndRendering.new(
91
104
  :title => "Amazing Title!",
92
105
  :producer => "Fishy Joe",
93
106
  :resolution => "720p",
@@ -96,13 +109,13 @@ client and using HTTP callbacks for status updates.
96
109
  )
97
110
 
98
111
  # Add some images, text, and footage to our manifest.
99
- manifest << Image.new("http://website.com/picture.png")
100
- manifest << Image.new("http://website.com/hooray.png", :spotlit => true)
101
- manifest << TitleCard.new("Woohoo!", "Hooray for everything!")
102
- manifest << Footage.new("http://website.com/movie.mp4", :duration => 3.5)
112
+ manifest << Assets::Image.new("http://website.com/picture.png")
113
+ manifest << Assets::Image.new("http://website.com/hooray.png", :spotlit => true)
114
+ manifest << Assets::TitleCard.new("Woohoo!", "Hooray for everything!")
115
+ manifest << Assets::Footage.new("http://website.com/movie.mp4", :duration => 3.5)
103
116
 
104
117
  # Setup the soundtrack.
105
- manifest << Song.new("http://website.com/song.mp3", :artist => "Fishy Joe")
118
+ manifest << Assets::Song.new("http://website.com/song.mp3", :artist => "Fishy Joe")
106
119
 
107
120
  # Setup to get http callbacks for status notification (see below for
108
121
  # polling example).
@@ -128,16 +141,16 @@ status.
128
141
 
129
142
  # Create a directing manifest. The directing manifest controls the images
130
143
  # and other visual elements that will be in our final video.
131
- manifest = DirectingManifest.new(:title => "Amazing Title!")
144
+ manifest = Manifests::Directing.new(:title => "Amazing Title!")
132
145
 
133
146
  # Add some images, text, and footage to our manifest.
134
- manifest << Image.new("http://website.com/picture.png")
135
- manifest << Image.new("http://website.com/hooray.png", :spotlit => true)
136
- manifest << TitleCard.new("Woohoo!", "Hooray for everything!")
137
- manifest << Footage.new("http://website.com/movie.mp4", :duration => 3.5)
147
+ manifest << Assets::Image.new("http://website.com/picture.png")
148
+ manifest << Assets::Image.new("http://website.com/hooray.png", :spotlit => true)
149
+ manifest << Assets::TitleCard.new("Woohoo!", "Hooray for everything!")
150
+ manifest << Assets::Footage.new("http://website.com/movie.mp4", :duration => 3.5)
138
151
 
139
152
  # Setup the soundtrack.
140
- manifest << Song.new("http://website.com/song.mp3")
153
+ manifest << Assets::Song.new("http://website.com/song.mp3")
141
154
 
142
155
  # Request a new directing job by sending the API our directing manifest.
143
156
  directing_job = client.direct!(manifest)
@@ -154,7 +167,7 @@ status.
154
167
 
155
168
  # Now it's time to render the storyboard into a video. First we create
156
169
  # a rendering manifest.
157
- manifest = RenderingManifest.new(storyboard, :resolution => "720p", :framerate => 24, :format => 'h264')
170
+ manifest = Manifests::Rendering.new(storyboard, :resolution => "720p", :framerate => 24, :format => 'h264')
158
171
 
159
172
  # Send the manifest to the API.
160
173
  rendering_job = client.render!(manifest)
data/integration/test.rb CHANGED
@@ -33,7 +33,7 @@ raise "Example code not found in README (expected at xpath '#{example_code_path}
33
33
  code = code_node.text
34
34
 
35
35
  puts "Replacing example credentials with valid ones"
36
- code.sub!(/Client\.new\(.+\)/, %Q{Client.new("#{credentials[:key]}","#{credentials[:secret]}")})
36
+ code.sub!(/Client\.new\(.+\)/, %Q{Client.new("#{credentials[:key]}","#{credentials[:secret]}",:endpoint => "#{credentials[:endpoint]}")})
37
37
 
38
38
  puts "Replacing example assets with valid ones"
39
39
  code.gsub!(/Image\.new\(.+\)/) { %Q{Image.new("#{assets[:images].shift}")} }
@@ -46,5 +46,4 @@ puts "Executing example"
46
46
  eval code
47
47
 
48
48
  puts
49
- puts "If you're seeing this, things should have worked fine!"
50
- puts "Enjoy your video at #{video.download_url}"
49
+ puts "If you're seeing this, things should have worked fine!"
@@ -0,0 +1,29 @@
1
+ module Animoto
2
+ module Assets
3
+
4
+ # @abstract
5
+ class Base
6
+
7
+ # The URL of this asset.
8
+ # @return [String]
9
+ attr_accessor :source
10
+
11
+ # Creates a new asset.
12
+ #
13
+ # @param [String] source the URL of this asset
14
+ # @return [Assets::Base] the asset
15
+ def initialize source, options = {}
16
+ @source = source
17
+ end
18
+
19
+ # Returns a representation of this asset as a Hash. Used mainly for generating
20
+ # manifests.
21
+ #
22
+ # @return [Hash<String,Object>] this asset as a Hash
23
+ def to_hash
24
+ { 'source_url' => @source }
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,34 @@
1
+ module Animoto
2
+ module Assets
3
+ class Footage < Animoto::Assets::Base
4
+ include Support::Visual
5
+ include Support::Coverable
6
+
7
+ # Whether or not to mix the audio of this footage with the video's soundtrack.
8
+ # @return [Boolean]
9
+ attr_accessor :audio_mix
10
+
11
+ # The time in seconds of where to start extracting a clip from this footage to
12
+ # add to the video.
13
+ # @return [Float]
14
+ attr_accessor :start_time
15
+
16
+ # The duration in seconds of how long this footage should run in the video.
17
+ # @return [Float]
18
+ attr_accessor :duration
19
+
20
+ # Returns a representation of this Footage as a Hash.
21
+ #
22
+ # @return [Hash<String,Object>] this asset as a Hash
23
+ # @see Animoto::Support::Visual#to_hash
24
+ # @see Animoto::Assets::Base#to_hash
25
+ def to_hash
26
+ hash = super
27
+ hash['audio_mix'] = 'MIX' if audio_mix
28
+ hash['start_time'] = start_time if start_time
29
+ hash['duration'] = duration if duration
30
+ hash
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,25 @@
1
+ module Animoto
2
+ module Assets
3
+ class Image < Animoto::Assets::Base
4
+ include Support::Visual
5
+ include Support::Coverable
6
+
7
+ # The EXIF rotation value for how this image should be rotated in the video.
8
+ # @return [Integer]
9
+ attr_accessor :rotation
10
+
11
+ # Returns a representation of this Image as a Hash.
12
+ #
13
+ # @return [Hash<String,Object>] this asset as a Hash
14
+ # @see Animoto::Support::Visual#to_hash
15
+ # @see Animoto::Assets::Base#to_hash
16
+ def to_hash
17
+ hash = super
18
+ hash['rotation'] = rotation if rotation
19
+ hash['spotlit'] = spotlit? unless @spotlit.nil?
20
+ hash['cover'] = cover? unless @cover.nil?
21
+ hash
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ module Animoto
2
+ module Assets
3
+ class Song < Animoto::Assets::Base
4
+
5
+ # The offset in seconds from the beginning denoting where to start
6
+ # using this song in the video.
7
+ # @return [Float]
8
+ attr_accessor :start_time
9
+
10
+ # The duration in seconds of how long this song should play.
11
+ # @return [Float]
12
+ attr_accessor :duration
13
+
14
+ # Returns a representation of this Song as a Hash.
15
+ #
16
+ # @return [Hash<String,Object>] this asset as a Hash
17
+ # @see Animoto::Assets::Base#to_hash
18
+ def to_hash
19
+ hash = super
20
+ hash['start_time'] = start_time if start_time
21
+ hash['duration'] = duration if duration
22
+ hash
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,35 @@
1
+ module Animoto
2
+ module Assets
3
+ class TitleCard
4
+ include Support::Visual
5
+
6
+ # The main text of this title card.
7
+ # @return [String]
8
+ attr_accessor :title
9
+
10
+ # The secondary text of this title card.
11
+ # @return [String]
12
+ attr_accessor :subtitle
13
+
14
+ # Creates a new TitleCard.
15
+ #
16
+ # @param [String] title the main text
17
+ # @param [String] subtitle the secondary text
18
+ def initialize title, subtitle = nil
19
+ @title, @subtitle = title, subtitle
20
+ end
21
+
22
+ # Returns a representation of this TitleCard as a Hash.
23
+ #
24
+ # @return [Hash<String,Object>] this TitleCard as a Hash
25
+ # @see Animoto::Support::Visual#to_hash
26
+ def to_hash
27
+ hash = super
28
+ hash['h1'] = title
29
+ hash['h2'] = subtitle if subtitle
30
+ hash['spotlit'] = spotlit? unless @spotlit.nil?
31
+ hash
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,45 @@
1
+ module Animoto
2
+ module Callbacks
3
+
4
+ # @abstract
5
+ class Base
6
+ include Support::StandardEnvelope
7
+
8
+ # @return [String]
9
+ # @see Animoto::Support::StandardEnvelope::ClassMethods#payload_key
10
+ def self.payload_key
11
+ super + '_callback'
12
+ end
13
+
14
+ # @return [Hash<Symbol,Object>]
15
+ # @see Animoto::Support::StandardEnvelope::ClassMethods#unpack_standard_envelope
16
+ def self.unpack_standard_envelope body = {}
17
+ super.merge({ :state => body['response']['payload'][payload_key]['state'] })
18
+ end
19
+
20
+ # The state of the job when it completed.
21
+ # @return [String]
22
+ attr_reader :state
23
+
24
+ # Errors for the job.
25
+ # @return [Array<Animoto::Error>]
26
+ attr_reader :errors
27
+
28
+ # The url for this job.
29
+ # @return [String]
30
+ attr_reader :url
31
+
32
+ # Creates a new Callback.
33
+ #
34
+ # @param [String] body the request body of the HTTP callback
35
+ # @return [Callbacks::Base] the Callback
36
+ def initialize body
37
+ params = unpack_standard_envelope(body)
38
+ @state = params[:state]
39
+ @errors = params[:errors].collect { |e| Animoto::Error.new(e['message']) }
40
+ @url = params[:url]
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,7 @@
1
+ module Animoto
2
+ module Callbacks
3
+ class Directing < Animoto::Callbacks::Base
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Animoto
2
+ module Callbacks
3
+ class DirectingAndRendering < Animoto::Callbacks::Base
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Animoto
2
+ module Callbacks
3
+ class Rendering < Animoto::Callbacks::Base
4
+
5
+ end
6
+ end
7
+ end
@@ -2,30 +2,39 @@ require 'yaml'
2
2
  require 'uri'
3
3
  require 'logger'
4
4
 
5
- require 'animoto/errors'
6
- require 'animoto/content_type'
7
- require 'animoto/standard_envelope'
8
- require 'animoto/resource'
9
- require 'animoto/asset'
10
- require 'animoto/visual'
11
- require 'animoto/coverable'
12
- require 'animoto/footage'
13
- require 'animoto/image'
14
- require 'animoto/song'
15
- require 'animoto/title_card'
16
- require 'animoto/manifest'
17
- require 'animoto/directing_manifest'
18
- require 'animoto/rendering_manifest'
19
- require 'animoto/directing_and_rendering_manifest'
20
- require 'animoto/storyboard'
21
- require 'animoto/video'
22
- require 'animoto/job'
23
- require 'animoto/directing_and_rendering_job'
24
- require 'animoto/directing_job'
25
- require 'animoto/rendering_job'
26
- require 'animoto/dynamic_class_loader'
27
- require 'animoto/http_engine'
28
- require 'animoto/response_parser'
5
+ require 'animoto/support/content_type'
6
+ require 'animoto/support/coverable'
7
+ require 'animoto/support/dynamic_class_loader'
8
+ require 'animoto/support/errors'
9
+ require 'animoto/support/standard_envelope'
10
+ require 'animoto/support/visual'
11
+
12
+ require 'animoto/resources/base'
13
+ require 'animoto/resources/storyboard'
14
+ require 'animoto/resources/video'
15
+ require 'animoto/resources/jobs/base'
16
+ require 'animoto/resources/jobs/directing_and_rendering'
17
+ require 'animoto/resources/jobs/directing'
18
+ require 'animoto/resources/jobs/rendering'
19
+
20
+ require 'animoto/assets/base'
21
+ require 'animoto/assets/footage'
22
+ require 'animoto/assets/image'
23
+ require 'animoto/assets/song'
24
+ require 'animoto/assets/title_card'
25
+
26
+ require 'animoto/manifests/base'
27
+ require 'animoto/manifests/directing'
28
+ require 'animoto/manifests/directing_and_rendering'
29
+ require 'animoto/manifests/rendering'
30
+
31
+ require 'animoto/callbacks/base'
32
+ require 'animoto/callbacks/directing'
33
+ require 'animoto/callbacks/directing_and_rendering'
34
+ require 'animoto/callbacks/rendering'
35
+
36
+ require 'animoto/http_engines/base'
37
+ require 'animoto/response_parsers/base'
29
38
 
30
39
  module Animoto
31
40
  class Client
@@ -33,8 +42,54 @@ module Animoto
33
42
  API_VERSION = 1
34
43
  BASE_CONTENT_TYPE = "application/vnd.animoto"
35
44
 
36
- attr_accessor :key, :secret, :endpoint, :logger
37
- attr_reader :http_engine, :response_parser
45
+ # Your API key.
46
+ # @return [String]
47
+ attr_accessor :key
48
+
49
+ # Your API secret.
50
+ # @return [String]
51
+ attr_accessor :secret
52
+
53
+ # The base URL where all requests will be sent.
54
+ # @return [String]
55
+ attr_accessor :endpoint
56
+
57
+ # A logger.
58
+ # @return [Logger]
59
+ attr_accessor :logger
60
+
61
+ # The engine to handle HTTP requests.
62
+ # @return [HTTPEngines::Base]
63
+ # @overload http_engine
64
+ # Returns the HTTP engine.
65
+ # @return [HTTPEngines::Base]
66
+ # @overload http_engine=(engine)
67
+ # Sets the HTTP engine.
68
+ #
69
+ # @param [HTTPEngines::Base,Symbol,Class] engine you may pass a
70
+ # HTTPEngine instance to use, or the symbolic name of an adapter to use,
71
+ # or a Class whose instances respond to #request and return a String of
72
+ # the response body
73
+ # @see Animoto::HTTPEngines::Base
74
+ # @return [HTTPEngines::Base] the engine instance
75
+ # @raise [ArgumentError] if given a class without the correct interface
76
+ attr_reader :http_engine
77
+
78
+ # The engine to handle parsing XML or JSON responses.
79
+ # @return [ResponseParsers::Base]
80
+ # @overload response_parser
81
+ # Returns the parser.
82
+ # @return [ResponseParsers::Base]
83
+ # @overload response_parser=(parser)
84
+ # Sets the parser.
85
+ #
86
+ # @param [ResponseParsers::Base,Symbol,Class] parser you may pass a
87
+ # ResponseParser instance to use, or the symbolic name of an adapter to use,
88
+ # or a Class whose instances respond to #parse, #unparse, and #format.
89
+ # @see Animoto::ResponseParsers::Base
90
+ # @return [ResponseParsers::Base] the parser instance
91
+ # @raise [ArgumentError] if given a class without the correct interface
92
+ attr_reader :response_parser
38
93
 
39
94
  # Creates a new Client object which handles credentials, versioning, making requests, and
40
95
  # parsing responses.
@@ -60,18 +115,9 @@ module Animoto
60
115
  __send__ :response_parser=, options[:response_parser] || :json
61
116
  end
62
117
 
63
- # Set the HTTP engine this client will use.
64
- #
65
- # @param [HTTPEngine, Symbol, Class] engine you may pass a
66
- # HTTPEngine instance to use, or the symbolic name of a adapter to use,
67
- # or a Class whose instances respond to #request and return a String of
68
- # the response body
69
- # @see Animoto::HTTPEngine
70
- # @return [HTTPEngine] the engine instance
71
- # @raise [ArgumentError] if given a class without the correct interface
72
118
  def http_engine= engine
73
119
  @http_engine = case engine
74
- when Animoto::HTTPEngine
120
+ when Animoto::HTTPEngines::Base
75
121
  engine
76
122
  when Class
77
123
  if engine.instance_methods.include?('request')
@@ -80,21 +126,13 @@ module Animoto
80
126
  raise ArgumentError
81
127
  end
82
128
  else
83
- Animoto::HTTPEngine[engine].new
129
+ Animoto::HTTPEngines[engine].new
84
130
  end
85
131
  end
86
132
 
87
- # Set the response parser this client will use.
88
- #
89
- # @param [ResponseParser, Symbol, Class] parser you may pass a
90
- # ResponseParser instance to use, or the symbolic name of a adapter to use,
91
- # or a Class whose instances respond to #parse, #unparse, and #format.
92
- # @see Animoto::ResponseParser
93
- # @return [ResponseParser] the parser instance
94
- # @raise [ArgumentError] if given a class without the correct interface
95
133
  def response_parser= parser
96
134
  @response_parser = case parser
97
- when Animoto::ResponseParser
135
+ when Animoto::ResponseParsers::Base
98
136
  parser
99
137
  when Class
100
138
  if %{format parse unparse}.all? { |m| parser.instance_methods.include? m }
@@ -103,53 +141,62 @@ module Animoto
103
141
  raise ArgumentError
104
142
  end
105
143
  else
106
- Animoto::ResponseParser[parser].new
144
+ Animoto::ResponseParsers[parser].new
107
145
  end
108
146
  end
109
147
 
110
148
  # Finds a resource by its URL.
111
149
  #
112
- # @param [Class] klass the Resource class you're finding
150
+ # @param [Class] klass the resource class you're finding
113
151
  # @param [String] url the URL of the resource you want
114
- # @param [Hash] options
115
- # @return [Resource] the Resource object found
152
+ # @param [Hash<Symbol,Object>] options
153
+ # @return [Resources::Base] the resource object found
116
154
  def find klass, url, options = {}
117
155
  klass.load(find_request(klass, url, options))
118
156
  end
119
157
 
158
+ # Returns a callback object of the specified type given the callback body.
159
+ #
160
+ # @param [Class] klass the callback class
161
+ # @param [String] body the HTTP body of the callback
162
+ # @return [Callbacks::Base] the callback object
163
+ def process_callback klass, body
164
+ klass.new(response_parser.parse(body))
165
+ end
166
+
120
167
  # Sends a request to start directing a storyboard.
121
168
  #
122
- # @param [DirectingManifest] manifest the manifest to direct
123
- # @param [Hash] options
124
- # @return [DirectingJob] a job to monitor the status of the directing
169
+ # @param [Manifests::Directing] manifest the manifest to direct
170
+ # @param [Hash<Symbol,Object>] options
171
+ # @return [Jobs::Directing] a job to monitor the status of the directing
125
172
  def direct! manifest, options = {}
126
- DirectingJob.load(send_manifest(manifest, DirectingJob.endpoint, options))
173
+ Resources::Jobs::Directing.load(send_manifest(manifest, Resources::Jobs::Directing.endpoint, options))
127
174
  end
128
175
 
129
176
  # Sends a request to start rendering a video.
130
177
  #
131
- # @param [RenderingManifest] manifest the manifest to render
132
- # @param [Hash] options
133
- # @return [RenderingJob] a job to monitor the status of the rendering
178
+ # @param [Manifests::Rendering] manifest the manifest to render
179
+ # @param [Hash<Symbol,Object>] options
180
+ # @return [Jobs::Rendering] a job to monitor the status of the rendering
134
181
  def render! manifest, options = {}
135
- RenderingJob.load(send_manifest(manifest, RenderingJob.endpoint, options))
182
+ Resources::Jobs::Rendering.load(send_manifest(manifest, Resources::Jobs::Rendering.endpoint, options))
136
183
  end
137
184
 
138
185
  # Sends a request to start directing and rendering a video.
139
186
  #
140
- # @param [DirectingAndRenderingManifest] manifest the manifest to direct and render
141
- # @param [Hash] options
142
- # @return [DirectingAndRenderingJob] a job to monitor the status of the directing and rendering
187
+ # @param [Manifests::DirectingAndRendering] manifest the manifest to direct and render
188
+ # @param [Hash<Symbol,Object>] options
189
+ # @return [Jobs::DirectingAndRendering] a job to monitor the status of the directing and rendering
143
190
  def direct_and_render! manifest, options = {}
144
- DirectingAndRenderingJob.load(send_manifest(manifest, DirectingAndRenderingJob.endpoint, options))
191
+ Resources::Jobs::DirectingAndRendering.load(send_manifest(manifest, Resources::Jobs::DirectingAndRendering.endpoint, options))
145
192
  end
146
193
 
147
194
  # Update a resource with the latest attributes. Useful to update the state of a Job to
148
195
  # see if it's ready if you are not using HTTP callbacks.
149
196
  #
150
- # @param [Resource] resource the resource to update
151
- # @param [Hash] options
152
- # @return [Resource] the given resource with the latest attributes
197
+ # @param [Resources::Base] resource the resource to update
198
+ # @param [Hash<Symbol,Object>] options
199
+ # @return [Resources::Base] the given resource with the latest attributes
153
200
  def reload! resource, options = {}
154
201
  resource.load(find_request(resource.class, resource.url, options))
155
202
  end
@@ -159,6 +206,7 @@ module Animoto
159
206
  # Sets the API credentials from an .animotorc file. First looks for one in the current
160
207
  # directory, then checks ~/.animotorc, then finally /etc/.animotorc.
161
208
  #
209
+ # @return [void]
162
210
  # @raise [ArgumentError] if none of the files are found
163
211
  def configure_from_rc_file
164
212
  current_path = Dir.pwd + '/.animotorc'
@@ -183,18 +231,18 @@ module Animoto
183
231
  #
184
232
  # @param [Class] klass the Resource class you're looking for
185
233
  # @param [String] url the URL of the resource
186
- # @param [Hash] options
187
- # @return [Hash] deserialized response body
234
+ # @param [Hash<Symbol,Object>] options
235
+ # @return [Hash<String,Object>] deserialized response body
188
236
  def find_request klass, url, options = {}
189
237
  request(:get, url, nil, { "Accept" => content_type_of(klass) }, options)
190
238
  end
191
239
 
192
240
  # Builds a request requiring a manifest.
193
241
  #
194
- # @param [Manifest] manifest the manifest being acted on
242
+ # @param [Manifests::Base] manifest the manifest being acted on
195
243
  # @param [String] endpoint the endpoint to send the request to
196
- # @param [Hash] options
197
- # @return [Hash] deserialized response body
244
+ # @param [Hash<Symbol,Object>] options
245
+ # @return [Hash<String,Object>] deserialized response body
198
246
  def send_manifest manifest, endpoint, options = {}
199
247
  u = URI.parse(self.endpoint)
200
248
  u.path = endpoint
@@ -211,25 +259,30 @@ module Animoto
211
259
  #
212
260
  # @param [Symbol] method which HTTP method to use (should be lowercase, i.e. :get instead of :GET)
213
261
  # @param [String] url the URL of the request
214
- # @param [String, nil] body the request body
262
+ # @param [String,nil] body the request body
215
263
  # @param [Hash<String,String>] headers the request headers (will be sent as-is, which means you should
216
264
  # specify "Content-Type" => "..." instead of, say, :content_type => "...")
217
- # @param [Hash] options
218
- # @return [Hash] deserialized response body
265
+ # @param [Hash<Symbol,Object>] options
266
+ # @return [Hash<String,Object>] deserialized response body
219
267
  # @raise [Error]
220
268
  def request method, url, body, headers = {}, options = {}
221
- error = catch(:fail) do
269
+ code, body = catch(:fail) do
222
270
  options = { :username => @key, :password => @secret }.merge(options)
223
271
  @logger.info "Sending request to #{url.inspect} with body #{body}"
224
272
  response = http_engine.request(method, url, body, headers, options)
225
273
  @logger.info "Received response #{response}"
226
274
  return response_parser.parse(response)
227
275
  end
228
- if error
229
- errors = response_parser.parse(error)['response']['status']['errors']
230
- err_string = errors.collect { |e| e['message'] }.join(', ')
231
- @logger.error "Error response from server: #{err_string}"
232
- raise Animoto::Error.new(err_string)
276
+ if code
277
+ if body.empty?
278
+ @logger.error "HTTP error (#{code})"
279
+ raise Animoto::Error.new("HTTP error (#{code})")
280
+ else
281
+ errors = response_parser.parse(body)['response']['status']['errors']
282
+ err_string = errors.collect { |e| e['message'] }.join(', ')
283
+ @logger.error "Error response from server: #{err_string}"
284
+ raise Animoto::Error.new(err_string)
285
+ end
233
286
  else
234
287
  @logger.error "Error sending request to #{url.inspect}"
235
288
  raise Animoto::Error
@@ -240,7 +293,7 @@ module Animoto
240
293
  end
241
294
 
242
295
  # Creates the full content type string given a Resource class or instance
243
- # @param [Class,ContentType] klass_or_instance the class or instance to build the
296
+ # @param [Class,Support::ContentType] klass_or_instance the class or instance to build the
244
297
  # content type for
245
298
  # @return [String] the full content type with the version and format included (i.e.
246
299
  # "application/vnd.animoto.storyboard-v1+json")