vimeo 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -253,8 +253,8 @@ Some methods have optional variables. Pass these as a hash at the end of a call.
253
253
  upload.get_quota
254
254
  upload.verify_chunks("ticket_id")
255
255
 
256
- # supports File, String (a file path), #read
257
- upload.upload("movie.mp4")
256
+ # all-in-one solution, supports File, String (a file path), #read
257
+ video_id = upload.upload("movie.mp4")
258
258
 
259
259
  ### Vimeo::Advanced::Video
260
260
 
@@ -327,4 +327,4 @@ The upload method will automatically get an upload ticket, perform the multipart
327
327
  * [HTTParty](http://github.com/jnunemaker/httparty): Easily one of the best tools I have used since I started using Ruby.
328
328
  * [Jeweler](http://github.com/technicalpickles/jeweler): Great tool for creating gems for Github.
329
329
 
330
- ### Copyright (c) 2009 Matt Hooks. See LICENSE for details.
330
+ ### Copyright (c) 2009-2010 Matt Hooks. See LICENSE for details.
data/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  :patch: 0
3
- :major: 1
4
3
  :build:
5
- :minor: 3
4
+ :major: 1
5
+ :minor: 4
@@ -7,6 +7,7 @@ require 'advanced/group'
7
7
  require 'advanced/group_events'
8
8
  require 'advanced/group_forums'
9
9
  require 'advanced/person'
10
+ require 'advanced/simple_upload'
10
11
  require 'advanced/test'
11
12
  require 'advanced/upload'
12
13
  require 'advanced/video'
@@ -14,6 +15,6 @@ require 'advanced/video_embed'
14
15
 
15
16
  module Vimeo
16
17
  module Advanced
17
-
18
+
18
19
  end
19
20
  end
@@ -0,0 +1,46 @@
1
+ module Vimeo
2
+ module Advanced
3
+ module SimpleUpload
4
+ class UploadError < RuntimeError; end
5
+
6
+ autoload :Task, 'vimeo/advanced/simple_upload/task'
7
+ autoload :Chunk, 'vimeo/advanced/simple_upload/chunk'
8
+
9
+ # Uploads data (IO streams or files) to Vimeo.
10
+ def upload(uploadable)
11
+ case uploadable
12
+ when File
13
+ upload_file(uploadable)
14
+ when String
15
+ upload_file(File.new(uploadable))
16
+ else
17
+ upload_io(uploadable)
18
+ end
19
+ end
20
+
21
+ protected
22
+
23
+ # Uploads an IO to Vimeo.
24
+ def upload_io(io, size, filename = 'io.data')
25
+ raise "#{io.inspect} must respond to #read" unless io.respond_to?(:read)
26
+ task = Task.new(self, @oauth_consumer, io, size, filename)
27
+ task.execute
28
+ task.video_id
29
+ end
30
+
31
+ # Helper for uploading files to Vimeo.
32
+ def upload_file(file)
33
+ file_path = file.path
34
+
35
+ size = File.size(file_path)
36
+ basename = File.basename(file_path)
37
+ io = File.open(file_path)
38
+ io.binmode
39
+
40
+ upload_io(io, size, basename).tap do
41
+ io.close
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,50 @@
1
+ module Vimeo
2
+ module Advanced
3
+ module SimpleUpload
4
+ class Chunk
5
+ MULTIPART_BOUNDARY = "-----------RubyMultipartPost"
6
+
7
+ attr_reader :id, :index
8
+ attr_reader :task, :vimeo
9
+ attr_reader :data, :size
10
+
11
+ def initialize(task, data)
12
+ @task = task
13
+ @vimeo = task.vimeo
14
+ @data = data
15
+ @size = data.size
16
+ @index = task.chunks.count
17
+ end
18
+
19
+ # Performs the upload via Multipart.
20
+ def upload
21
+ endpoint = "#{task.endpoint}&chunk_id=#{index}"
22
+
23
+ response = task.oauth_consumer.request(:post, endpoint, vimeo.get_access_token, {}, {}) do |req|
24
+ req.set_content_type("multipart/form-data", { "boundary" => MULTIPART_BOUNDARY })
25
+
26
+ io = StringIO.new(data)
27
+ io.instance_variable_set :"@original_filename", task.filename
28
+ def io.original_filename; @original_filename; end
29
+ def io.content_type; "application/octet-stream"; end
30
+
31
+ parts = []
32
+ parts << Parts::FilePart.new(MULTIPART_BOUNDARY, "file_data", io)
33
+ parts << Parts::EpiloguePart.new(MULTIPART_BOUNDARY)
34
+
35
+ ios = parts.map{|p| p.to_io }
36
+ req.content_length = parts.inject(0) {|sum,i| sum + i.length }
37
+ req.body_stream = CompositeReadIO.new(*ios)
38
+
39
+ :continue
40
+ end
41
+
42
+ # free memory (for big file uploads)
43
+ @data = nil
44
+
45
+ @id = response.body
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,85 @@
1
+ module Vimeo
2
+ module Advanced
3
+ module SimpleUpload
4
+ class Task
5
+ CHUNK_SIZE = 2 * 1024 * 1024 # 2 megabytes
6
+
7
+ attr_reader :vimeo, :oauth_consumer
8
+ attr_reader :io, :size, :filename
9
+ attr_reader :chunks, :endpoint
10
+ attr_reader :id, :video_id
11
+
12
+ def initialize(vimeo, oauth_consumer, io, size, filename)
13
+ @vimeo, @oauth_consumer = vimeo, oauth_consumer
14
+ @io, @size, @filename = io, size, filename
15
+ @chunks = []
16
+ end
17
+
18
+ # Uploads the file to Vimeo and returns the +video_id+ on success.
19
+ def execute
20
+ check_quota
21
+ authorize
22
+ upload
23
+ raise UploadError.new, "Validation of chunks failed." unless valid?
24
+ complete
25
+
26
+ return video_id
27
+ end
28
+
29
+ protected
30
+
31
+ # Checks whether the file can be uploaded.
32
+ def check_quota
33
+ quota = vimeo.get_quota
34
+ free = quota["user"]["upload_space"]["free"].to_i
35
+
36
+ raise UploadError.new, "file size exceeds quota. required: #{size}, free: #{free}" if size > free
37
+ end
38
+
39
+ # Gets a +ticket_id+ for the upload.
40
+ def authorize
41
+ ticket = vimeo.get_ticket
42
+
43
+ @id = ticket["ticket"]["id"]
44
+ @endpoint = ticket["ticket"]["endpoint"]
45
+ max_file_size = ticket["ticket"]["max_file_size"].to_i
46
+
47
+ raise UploadError.new, "file was too big: #{size}, maximum: #{max_file_size}" if size > max_file_size
48
+ end
49
+
50
+ # Performs the upload.
51
+ def upload
52
+ while (chunk_data = io.read(CHUNK_SIZE)) do
53
+ chunk = Chunk.new(self, chunk_data)
54
+ chunk.upload
55
+ chunks << chunk
56
+ end
57
+ end
58
+
59
+ # Tells vimeo that the upload is complete.
60
+ def complete
61
+ @video_id = vimeo.complete(id, filename)
62
+ end
63
+
64
+ # Compares Vimeo's chunk list with own chunk list. Returns +true+ if identical.
65
+ def valid?
66
+ received, sent = received_chunk_sizes, sent_chunk_sizes
67
+ sent.all? { |id, size| received[id] == size }
68
+ end
69
+
70
+ # Returns a hash of the sent chunks and their respective sizes.
71
+ def sent_chunk_sizes
72
+ Hash[chunks.map { |chunk| [chunk.id, chunk.size] }]
73
+ end
74
+
75
+ # Returns a of Vimeo's received chunks and their respective sizes.
76
+ def received_chunk_sizes
77
+ verification = vimeo.verify_chunks(id)
78
+ chunk_list = verification["ticket"]["chunks"]["chunk"]
79
+ chunk_list = [chunk_list] unless chunk_list.is_a?(Array)
80
+ Hash[chunk_list.map { |chunk| [chunk["id"], chunk["size"].to_i] }]
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -4,14 +4,6 @@ module Vimeo
4
4
  module Advanced
5
5
 
6
6
  class Upload < Vimeo::Advanced::Base
7
- class UploadError < RuntimeError; end
8
-
9
- # 2 megabytes
10
- CHUNK_SIZE = 2 * 1024 * 1024
11
-
12
- # multipart boundary
13
- BOUNDARY = "-----------RubyMultipartPost"
14
-
15
7
  # Check to make sure an upload ticket is still valid.
16
8
  create_api_method :check_ticket,
17
9
  "vimeo.videos.upload.checkTicket",
@@ -36,106 +28,8 @@ module Vimeo
36
28
  "vimeo.videos.upload.verifyChunks",
37
29
  :required => [:ticket_id]
38
30
 
31
+ include Vimeo::Advanced::SimpleUpload
39
32
 
40
- # Uploads data (IO streams or files) to Vimeo.
41
- def upload(uploadable)
42
- case uploadable
43
- when File
44
- upload_file(uploadable)
45
- when String
46
- upload_file(File.new(uploadable))
47
- else
48
- upload_io(uploadable)
49
- end
50
- end
51
-
52
- protected
53
-
54
- def upload_chunk(chunk_id, data, endpoint, filename)
55
- endpoint += "&chunk_id=#{chunk_id}"
56
-
57
- response = @oauth_consumer.request(:post, endpoint, get_access_token, {}, {}) do |req|
58
- req.set_content_type("multipart/form-data", { "boundary" => BOUNDARY })
59
-
60
- io = StringIO.new(data)
61
- io.instance_variable_set :"@original_filename", filename
62
- def io.original_filename; @original_filename; end
63
- def io.content_type; "application/octet-stream"; end
64
-
65
- parts = []
66
- parts << Parts::FilePart.new(BOUNDARY, "file_data", io)
67
- parts << Parts::EpiloguePart.new(BOUNDARY)
68
-
69
- ios = parts.map{|p| p.to_io }
70
- req.content_length = parts.inject(0) {|sum,i| sum + i.length }
71
- req.body_stream = CompositeReadIO.new(*ios)
72
-
73
- :continue
74
- end
75
-
76
- response.body
77
- end
78
-
79
- def upload_io(io, size, filename = 'io.data')
80
- raise "#{io.inspect} must respond to #read" unless io.respond_to?(:read)
81
-
82
- quota_response = get_quota
83
- user = quota_response["user"]
84
- upload_space = user["upload_space"]
85
- free = upload_space["free"].to_i
86
-
87
- raise UploadError.new, "file size exceeds quota. required: #{size}, free: #{free}" if size > free
88
-
89
- ticket_response = get_ticket
90
- ticket = ticket_response["ticket"]
91
- max_file_size = ticket["max_file_size"].to_i
92
- ticket_id = ticket["id"]
93
- endpoint = ticket["endpoint"]
94
-
95
- raise UploadError.new, "file was too big: #{size}, maximum: #{max_file_size}" if size > max_file_size
96
-
97
- chunk_sizes = {}
98
- chunk_index = 0
99
-
100
- while (chunk = io.read(CHUNK_SIZE)) do
101
-
102
- chunk_id = upload_chunk(chunk_index, chunk, endpoint, filename)
103
- chunk_sizes[chunk_id] = chunk.length
104
- chunk_index += 1
105
- end
106
-
107
- validate_chunks_after_upload(ticket_id, chunk_sizes)
108
-
109
- complete(ticket_id, filename)
110
- end
111
-
112
- def upload_file(file)
113
- file_path = file.path
114
-
115
- size = File.size(file_path)
116
- basename = File.basename(file_path)
117
- io = File.open(file_path)
118
- io.binmode
119
-
120
- upload_io(io, size, basename).tap do
121
- io.close
122
- end
123
- end
124
-
125
- def validate_chunks_after_upload(ticket_id, chunk_sizes)
126
- verification = verify_chunks(ticket_id)
127
- ticket = verification["ticket"]
128
- chunk_list = Array(ticket["chunks"]["chunk"])
129
- received_chunks = Hash[chunk_list.map { |chunk| [chunk["id"], chunk["size"].to_i] }]
130
-
131
- chunk_sizes.each do |id, size|
132
- vimeo_size = received_chunks[id]
133
-
134
- if vimeo_size != size
135
- raise UploadError.new, "Chunk (id: #{id}) was invalid - was: #{vimeo_size}, should be: #{size}."
136
- end
137
- end
138
- end
139
33
  end # Upload
140
34
  end # Advanced
141
35
  end # Vimeo
@@ -105,7 +105,7 @@ module Vimeo
105
105
 
106
106
  create_api_method :set_title,
107
107
  "vimeo.videos.setTitle",
108
- :required => [:title, :video_id]
108
+ :required => [:video_id, :title]
109
109
 
110
110
  # comments
111
111
  create_api_method :add_comment,
@@ -128,4 +128,4 @@ module Vimeo
128
128
 
129
129
  end # Video
130
130
  end # Advanced
131
- end # Vimeo
131
+ end # Vimeo
data/vimeo.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{vimeo}
8
- s.version = "1.3.0"
8
+ s.version = "1.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Matt Hooks"]
12
- s.date = %q{2010-11-12}
12
+ s.date = %q{2011-03-30}
13
13
  s.description = %q{A full featured Ruby implementation of the Vimeo API.}
14
14
  s.email = %q{matthooks@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -34,6 +34,9 @@ Gem::Specification.new do |s|
34
34
  "lib/vimeo/advanced/group_events.rb",
35
35
  "lib/vimeo/advanced/group_forums.rb",
36
36
  "lib/vimeo/advanced/person.rb",
37
+ "lib/vimeo/advanced/simple_upload.rb",
38
+ "lib/vimeo/advanced/simple_upload/chunk.rb",
39
+ "lib/vimeo/advanced/simple_upload/task.rb",
37
40
  "lib/vimeo/advanced/test.rb",
38
41
  "lib/vimeo/advanced/upload.rb",
39
42
  "lib/vimeo/advanced/video.rb",
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vimeo
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 7
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 1.3.0
10
+ version: 1.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Matt Hooks
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-12 00:00:00 -06:00
18
+ date: 2011-03-30 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -190,6 +190,9 @@ files:
190
190
  - lib/vimeo/advanced/group_events.rb
191
191
  - lib/vimeo/advanced/group_forums.rb
192
192
  - lib/vimeo/advanced/person.rb
193
+ - lib/vimeo/advanced/simple_upload.rb
194
+ - lib/vimeo/advanced/simple_upload/chunk.rb
195
+ - lib/vimeo/advanced/simple_upload/task.rb
193
196
  - lib/vimeo/advanced/test.rb
194
197
  - lib/vimeo/advanced/upload.rb
195
198
  - lib/vimeo/advanced/video.rb