vimeo 1.3.0 → 1.4.0
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/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
|