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 +3 -3
- data/VERSION.yml +2 -2
- data/lib/vimeo/advanced.rb +2 -1
- data/lib/vimeo/advanced/simple_upload.rb +46 -0
- data/lib/vimeo/advanced/simple_upload/chunk.rb +50 -0
- data/lib/vimeo/advanced/simple_upload/task.rb +85 -0
- data/lib/vimeo/advanced/upload.rb +1 -107
- data/lib/vimeo/advanced/video.rb +2 -2
- data/vimeo.gemspec +5 -2
- metadata +7 -4
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
data/lib/vimeo/advanced.rb
CHANGED
@@ -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
|
data/lib/vimeo/advanced/video.rb
CHANGED
@@ -105,7 +105,7 @@ module Vimeo
|
|
105
105
|
|
106
106
|
create_api_method :set_title,
|
107
107
|
"vimeo.videos.setTitle",
|
108
|
-
:required => [:
|
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.
|
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{
|
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:
|
4
|
+
hash: 7
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
8
|
+
- 4
|
9
9
|
- 0
|
10
|
-
version: 1.
|
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:
|
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
|