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 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