flixit 0.0.11

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.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Leandro Pedroni
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,21 @@
1
+ flixit
2
+ ======
3
+
4
+ Heavily based on the [flixcloud gem](http://github.com/flixcloud/flix_cloud-gem).
5
+ I removed dependancies on a specific httpclient. To play nice with fakeweb this gem relies on rest-client.
6
+ I will improve tests as I go.
7
+
8
+ Note on Patches/Pull Requests
9
+ -----------------------------
10
+ * Fork the project.
11
+ * Make your feature addition or bug fix.
12
+ * Add tests for it. This is important so I don't break it in a
13
+ future version unintentionally.
14
+ * Commit, do not mess with rakefile, version, or history.
15
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
16
+ * Send me a pull request. Bonus points for topic branches.
17
+
18
+ Copyright
19
+ ---------
20
+
21
+ Copyright (c) 2010 Leandro Pedroni. See LICENSE for details.
@@ -0,0 +1,50 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "flixit"
8
+ gem.summary = %Q{Interface with flixcloud.com api}
9
+ gem.description = %Q{Performs requests and interprets responses with flixcloud.com}
10
+ gem.email = "ilpoldo@gmail.com"
11
+ gem.homepage = "http://github.com/ilpoldo/flixit"
12
+ gem.authors = ["Leandro Pedroni"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ gem.add_development_dependency "fredo", ">= 0.1.5"
15
+
16
+ gem.add_dependency('rest-client', '>= 1.4.0')
17
+ gem.add_dependency('builder', '>= 2.1.1')
18
+ gem.add_dependency('crack', '>= 0.1.6')
19
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
20
+ end
21
+ Jeweler::GemcutterTasks.new
22
+ rescue LoadError
23
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
24
+ end
25
+
26
+ require 'spec/rake/spectask'
27
+ Spec::Rake::SpecTask.new(:spec) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.spec_files = FileList['spec/**/*_spec.rb']
30
+ end
31
+
32
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
33
+ spec.libs << 'lib' << 'spec'
34
+ spec.pattern = 'spec/**/*_spec.rb'
35
+ spec.rcov = true
36
+ end
37
+
38
+ task :spec => :check_dependencies
39
+
40
+ task :default => :spec
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "flixit #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.11
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'rest_client'
3
+ require 'builder'
4
+ require 'crack'
5
+
6
+ require 'flixit/ext/hash'
7
+ require 'flixit/record'
8
+ require 'flixit/job'
9
+ require 'flixit/file_locations'
10
+ require 'flixit/file'
11
+ require 'flixit/parameters'
12
+ require 'flixit/response'
13
+ require 'flixit/exceptions'
14
+ require 'flixit/notification'
15
+
16
+ module Flixit
17
+
18
+ VERSION = ::File.exist?('VERSION') ? ::File.read('VERSION') : ""
19
+
20
+ end
@@ -0,0 +1,9 @@
1
+ class Flixit::Error < StandardError; end
2
+ class Flixit::SaveError < Flixit::Error; end
3
+ class Flixit::CreateError < Flixit::Error; end
4
+ class Flixit::ServerBrokeConnection < Flixit::Error; end
5
+ class Flixit::RequestTimeout < Flixit::Error; end
6
+ class Flixit::ConnectionRefused < Flixit::Error; end
7
+
8
+ class Flixit::AuthenticationError < Flixit::Error
9
+ end
@@ -0,0 +1,22 @@
1
+ module Flixit
2
+ module Extensions
3
+ # Both methods ripped directly out of rails
4
+ module Hash
5
+ def deep_merge(other_hash)
6
+ self.merge(other_hash) do |key, oldval, newval|
7
+ oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
8
+ newval = newval.to_hash if newval.respond_to?(:to_hash)
9
+ oldval.class.to_s == 'Hash' && newval.class.to_s == 'Hash' ? oldval.deep_merge(newval) : newval
10
+ end
11
+ end
12
+
13
+ # Returns a new hash with +self+ and +other_hash+ merged recursively.
14
+ # Modifies the receiver in place.
15
+ def deep_merge!(other_hash)
16
+ replace(deep_merge(other_hash))
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ Hash.send(:include, Flixit::Extensions::Hash) unless Hash.instance_methods.include?('deep_merge')
@@ -0,0 +1,21 @@
1
+ class Flixit::File < Flixit::Record
2
+
3
+ attr_accessor :url, :size, :width, :height, :duration, :cost
4
+
5
+ record_column :parameters, 'Parameters'
6
+
7
+ def valid?
8
+ self.errors = []
9
+
10
+ unless url
11
+ self.errors << "url is required"
12
+ end
13
+
14
+ if parameters && !parameters.valid?
15
+ self.errors << {:parameters => parameters.errors}
16
+ end
17
+
18
+ errors.empty?
19
+ end
20
+
21
+ end
@@ -0,0 +1,34 @@
1
+ class Flixit::FileLocations < Flixit::Record
2
+
3
+ record_column :input, 'File'
4
+ record_column :output, 'File'
5
+ record_column :watermark, 'File'
6
+ record_column :thumbnails, 'File'
7
+
8
+ def valid?
9
+ self.errors = []
10
+
11
+ if input
12
+ unless input.valid?
13
+ self.errors << {:input => input.errors}
14
+ end
15
+ else
16
+ self.errors << "input is required"
17
+ end
18
+
19
+ if output
20
+ unless output.valid?
21
+ self.errors << {:output => output.errors}
22
+ end
23
+ else
24
+ self.errors << "output is required"
25
+ end
26
+
27
+ if watermark && !watermark.valid?
28
+ self.errors << {:watermark => watermark.errors}
29
+ end
30
+
31
+ errors.empty?
32
+ end
33
+
34
+ end
@@ -0,0 +1,161 @@
1
+ class Flixit::Job < Flixit::Record
2
+
3
+ attr_accessor :id, :initialized_at, :api_key, :recipe_id, :recipe_name, :response, :notification_url
4
+
5
+ record_column :file_locations, 'FileLocations'
6
+
7
+ def initialize(attrs={})
8
+ super
9
+ self.shortcut_attributes = attrs
10
+ end
11
+
12
+ def valid?
13
+ self.errors = []
14
+
15
+ if file_locations
16
+ unless file_locations.valid?
17
+ self.errors << {:file_locations => file_locations.errors}
18
+ end
19
+ else
20
+ self.errors << "file_locations is required"
21
+ end
22
+
23
+ if recipe_id || recipe_name
24
+ if recipe_id && recipe_name
25
+ self.errors << "recipe_id and recipe_name cannot both be used"
26
+ end
27
+ else
28
+ self.errors << "recipe_id or recipe_name is required"
29
+ end
30
+
31
+ unless api_key
32
+ self.errors << "api_key is required"
33
+ end
34
+
35
+ errors.empty?
36
+ end
37
+
38
+ def save
39
+ return false unless valid?
40
+
41
+ self.response = post('jobs', to_xml)
42
+
43
+ if response.success?
44
+ self.id = response.body_as_hash['job']['id']
45
+ self.initialized_at = response.body_as_hash['job']['initialized_job_at']
46
+ else
47
+ self.errors = response.errors
48
+ end
49
+
50
+ response.success?
51
+ end
52
+
53
+ def save!
54
+ raise Flixit::SaveError unless save
55
+ true
56
+ end
57
+
58
+ def self.create(attrs={})
59
+ job = new(attrs)
60
+ job.save
61
+ job
62
+ end
63
+
64
+ def self.create!(attrs={})
65
+ job = create(attrs)
66
+ raise Flixit::CreateError unless job.id
67
+ job
68
+ end
69
+
70
+ def to_xml
71
+ xml = Builder::XmlMarkup.new
72
+
73
+ xml.instruct! :xml, :version => "1.0", :encoding => "UTF-8"
74
+
75
+ xml.tag!("api-request") do
76
+ xml.tag!("api-key", api_key)
77
+
78
+ if recipe_name
79
+ xml.tag!("recipe-name", recipe_name)
80
+ else
81
+ xml.tag!("recipe-id", recipe_id)
82
+ end
83
+
84
+ if notification_url
85
+ xml.tag!('notification-url', notification_url)
86
+ end
87
+
88
+ if file_locations
89
+ xml.tag!("file-locations") do
90
+ if file_locations.input
91
+ xml.input do
92
+ xml.url(file_locations.input.url)
93
+ if file_locations.input.parameters
94
+ xml.parameters do
95
+ xml.user(file_locations.input.parameters.user)
96
+ xml.password(file_locations.input.parameters.password)
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ if file_locations.output
103
+ xml.output do
104
+ xml.url(file_locations.output.url)
105
+ if file_locations.output.parameters
106
+ xml.parameters do
107
+ xml.user(file_locations.output.parameters.user)
108
+ xml.password(file_locations.output.parameters.password)
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ if file_locations.watermark
115
+ xml.watermark do
116
+ xml.url(file_locations.watermark.url)
117
+ if file_locations.watermark.parameters
118
+ xml.parameters do
119
+ xml.user(file_locations.watermark.parameters.user)
120
+ xml.password(file_locations.watermark.parameters.password)
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ if file_locations.thumbnails
127
+ xml.thumbnails do
128
+ xml.url(file_locations.thumbnails.url)
129
+ xml.prefix "thumb_"
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+
136
+ xml.target!
137
+ end
138
+
139
+
140
+ protected
141
+
142
+ def shortcut_attributes=(attrs)
143
+ translated_attributes = {}
144
+
145
+ attrs.each do |key, value|
146
+ if match = key.to_s.match(/^(input|output|watermark|thumbnails)_(url|user|password)$/)
147
+ file_type = match[1].to_sym
148
+ parameter_type = match[2].to_sym
149
+
150
+ if parameter_type == :url
151
+ translated_attributes.deep_merge!(:file_locations => { file_type => { :url => value}})
152
+ else
153
+ translated_attributes.deep_merge!(:file_locations => { file_type => { :parameters => { parameter_type => value}}})
154
+ end
155
+ end
156
+ end
157
+
158
+ self.attributes = translated_attributes unless translated_attributes.empty?
159
+ end
160
+
161
+ end
@@ -0,0 +1,32 @@
1
+ class Flixit::Notification < Flixit::Record
2
+ attr_accessor :xml, :id, :finished_job_at, :initialized_job_at,
3
+ :recipe_name, :recipe_id, :state, :error_message
4
+
5
+ record_column :input_media_file, 'File'
6
+ record_column :output_media_file, 'File'
7
+ record_column :watermark_file, 'File'
8
+
9
+ def initialize(attrs={})
10
+ if attrs.is_a?(String)
11
+ self.xml = attrs
12
+ attrs = Crack::XML.parse(attrs)
13
+ end
14
+
15
+ attrs = attrs['job'] if attrs['job']
16
+
17
+ super(attrs)
18
+ end
19
+
20
+ def successful?
21
+ state == 'successful_job'
22
+ end
23
+
24
+ def failed?
25
+ state == 'failed_job'
26
+ end
27
+
28
+ def cancelled?
29
+ state == 'cancelled_job'
30
+ end
31
+
32
+ end
@@ -0,0 +1,19 @@
1
+ class Flixit::Parameters < Flixit::File
2
+
3
+ attr_accessor :user, :password
4
+
5
+ def valid?
6
+ self.errors = []
7
+
8
+ unless user
9
+ self.errors << "user is required"
10
+ end
11
+
12
+ unless password
13
+ self.errors << "password is required"
14
+ end
15
+
16
+ errors.empty?
17
+ end
18
+
19
+ end
@@ -0,0 +1,45 @@
1
+ class Flixit::Record
2
+
3
+ attr_accessor :errors
4
+
5
+ def initialize(attrs={})
6
+ self.errors = []
7
+ self.attributes = attrs
8
+ end
9
+
10
+ def attributes=(attrs)
11
+ attrs.each do |key, value|
12
+ send("#{key}=", value) if respond_to?("#{key}=")
13
+ end
14
+ end
15
+
16
+ def self.record_column(attribute, klass)
17
+ eval %{
18
+ attr_reader :#{attribute}
19
+
20
+ def #{attribute}=(value)
21
+ if @#{attribute}
22
+ @#{attribute}.attributes = value
23
+ else
24
+ @#{attribute} = Flixit::#{klass}.new(value)
25
+ end
26
+ end
27
+ }
28
+ end
29
+
30
+
31
+ protected
32
+
33
+ def post(path, body)
34
+ begin
35
+ Flixit::Response.new(RestClient.post "https://flixcloud.com/#{path}", body, :content_type => :xml, :accept => :xml)
36
+ # rescue HTTPClient::KeepAliveDisconnected
37
+ # raise Flixit::ServerBrokeConnection, $!.message
38
+ # rescue HTTPClient::ReceiveTimeoutError
39
+ # raise Flixit::RequestTimeout, $!.message
40
+ # rescue HTTPClient::ConnectTimeoutError
41
+ # raise Flixit::ConnectionRefused, $!.message
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,29 @@
1
+ class Flixit::Response
2
+
3
+ attr_accessor :code, :body, :errors, :body_as_hash
4
+
5
+ def initialize(response)
6
+ self.body = response.body
7
+ case self.code = response.code
8
+ when 401 then raise Flixit::AuthenticationError
9
+ else
10
+ self.body_as_hash = Crack::XML.parse(response.body)
11
+ self.errors = []
12
+ process_response_xml
13
+ end
14
+ end
15
+
16
+ def success?
17
+ 201 == code.to_i
18
+ end
19
+
20
+
21
+ protected
22
+
23
+ def process_response_xml
24
+ if body_as_hash['errors'] && body_as_hash['errors'].is_a?(Hash) && body_as_hash['errors']['error']
25
+ self.errors = Array(body_as_hash['errors']['error'])
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Flixit" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ context "Create a Job" do
5
+ before(:each) do
6
+ @job = Flixit::Job.new(:recipe_id => 1,
7
+ :api_key => 'this_is_an_api_key',
8
+ :file_locations => { :input => {:url => 'http://flixcloud.com/somefile.mp4'},
9
+ :output => {:url => 's3://flixcloud/somefile.flv'},
10
+ :thumbnails => {:url => "s3://flixcloud/somefile/",:prefix => 'thumbnail'}})
11
+ Fredo.post "https://flixcloud.com/jobs" do
12
+ %{<?xml version="1.0" encoding="UTF-8"?><job><id type="integer">3254</id><initialized-job-at type="datetime">2009-02-11T01:23:54Z</initialized-job-at></job>}
13
+ end
14
+
15
+ end
16
+
17
+ it "formats a message for flixcloud" do
18
+ @job.to_xml.should eql(%{<?xml version=\"1.0\" encoding=\"UTF-8\"?><api-request><api-key>this_is_an_api_key</api-key><recipe-id>1</recipe-id><file-locations><input><url>http://flixcloud.com/somefile.mp4</url></input><output><url>s3://flixcloud/somefile.flv</url></output><thumbnails><url>s3://flixcloud/somefile/</url><prefix>thumb_</prefix></thumbnails></file-locations></api-request>})
19
+ end
20
+
21
+ it "posts a message to flixcloud" do
22
+ @job.save
23
+ end
24
+
25
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,10 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'flixit'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+ require 'fredo'
7
+
8
+ Spec::Runner.configure do |config|
9
+
10
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flixit
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 11
9
+ version: 0.0.11
10
+ platform: ruby
11
+ authors:
12
+ - Leandro Pedroni
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-04-27 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 2
30
+ - 9
31
+ version: 1.2.9
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: fredo
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ - 1
44
+ - 5
45
+ version: 0.1.5
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: rest-client
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 1
57
+ - 4
58
+ - 0
59
+ version: 1.4.0
60
+ type: :runtime
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: builder
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 2
71
+ - 1
72
+ - 1
73
+ version: 2.1.1
74
+ type: :runtime
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: crack
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ segments:
84
+ - 0
85
+ - 1
86
+ - 6
87
+ version: 0.1.6
88
+ type: :runtime
89
+ version_requirements: *id005
90
+ description: Performs requests and interprets responses with flixcloud.com
91
+ email: ilpoldo@gmail.com
92
+ executables: []
93
+
94
+ extensions: []
95
+
96
+ extra_rdoc_files:
97
+ - LICENSE
98
+ - README.md
99
+ files:
100
+ - .document
101
+ - .gitignore
102
+ - LICENSE
103
+ - README.md
104
+ - Rakefile
105
+ - VERSION
106
+ - lib/flixit.rb
107
+ - lib/flixit/exceptions.rb
108
+ - lib/flixit/ext/hash.rb
109
+ - lib/flixit/file.rb
110
+ - lib/flixit/file_locations.rb
111
+ - lib/flixit/job.rb
112
+ - lib/flixit/notification.rb
113
+ - lib/flixit/parameters.rb
114
+ - lib/flixit/record.rb
115
+ - lib/flixit/response.rb
116
+ - spec/flixit_spec.rb
117
+ - spec/job_spec.rb
118
+ - spec/spec.opts
119
+ - spec/spec_helper.rb
120
+ has_rdoc: true
121
+ homepage: http://github.com/ilpoldo/flixit
122
+ licenses: []
123
+
124
+ post_install_message:
125
+ rdoc_options:
126
+ - --charset=UTF-8
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ segments:
134
+ - 0
135
+ version: "0"
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ segments:
141
+ - 0
142
+ version: "0"
143
+ requirements: []
144
+
145
+ rubyforge_project:
146
+ rubygems_version: 1.3.6
147
+ signing_key:
148
+ specification_version: 3
149
+ summary: Interface with flixcloud.com api
150
+ test_files:
151
+ - spec/flixit_spec.rb
152
+ - spec/job_spec.rb
153
+ - spec/spec_helper.rb