yt 0.13.9 → 0.13.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +4 -0
- data/lib/yt/collections/resumable_sessions.rb +8 -22
- data/lib/yt/models/account.rb +38 -3
- data/lib/yt/models/resumable_session.rb +10 -7
- data/lib/yt/models/video.rb +37 -0
- data/lib/yt/version.rb +1 -1
- data/spec/requests/as_account/authentications_spec.rb +1 -7
- data/spec/requests/as_account/thumbnail.jpg +0 -0
- data/spec/requests/as_account/video_spec.rb +22 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f38c80c9cc34b749849ed9934a037fe7707614ce
|
4
|
+
data.tar.gz: 2a9a06c9f14a9fabe19aa0d74e47e2a2fe2aaf6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d39da84ceb5bd9941ea7a90b32ca01e2c94d1aa101289ac7ff012728663f08279bf2d6e961761aeb3043f973fe9304109d4449b95c45e78126784bc7d278bdc4
|
7
|
+
data.tar.gz: fed816b3f0ef773b7b3f1050135c1a1e08b953ada0ba4aeafc69571c9e0f0408158190a20bcb4be0f4bca803a246254d2738502fed05ec4b4c61f512e09c585c
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,10 @@ For more information about changelogs, check
|
|
6
6
|
[Keep a Changelog](http://keepachangelog.com) and
|
7
7
|
[Vandamme](http://tech-angels.github.io/vandamme).
|
8
8
|
|
9
|
+
## 0.13.9 - 2015-02-17
|
10
|
+
|
11
|
+
* [FEATURE] New `video.upload_thumbnail` to upload the thumbnail for a video.
|
12
|
+
|
9
13
|
## 0.13.9 - 2015-02-16
|
10
14
|
|
11
15
|
* [ENHANCEMENT] Accept `force: true` in `authentication_url` to force approval prompt.
|
data/README.md
CHANGED
@@ -236,6 +236,7 @@ Use [Yt::Video](http://rubydoc.info/github/Fullscreen/yt/master/Yt/Models/Video)
|
|
236
236
|
|
237
237
|
* read the attributes of a video
|
238
238
|
* update the attributes of a video
|
239
|
+
* upload a thumbnail for a video
|
239
240
|
* access the annotations of a video
|
240
241
|
* delete a video
|
241
242
|
* like and dislike a video
|
@@ -322,6 +323,9 @@ video = Yt::Video.new id: 'MESycYJytkU', auth: account
|
|
322
323
|
video.update title: 'A title', description: 'A description <with angle brackets>'
|
323
324
|
video.update tags: ['a tag'], categoryId: '21', license: 'creativeCommon'
|
324
325
|
|
326
|
+
video.upload_thumbnail 'my_thumbnail.jpg'
|
327
|
+
video.upload_thumbnail 'http://example.com/remote.png'
|
328
|
+
|
325
329
|
video.views since: 7.days.ago #=> {Wed, 28 May 2014 => 12.0, Thu, 29 May 2014 => 3.0, …}
|
326
330
|
video.comments until: 2.days.ago #=> {Wed, 28 May 2014 => 9.0, Thu, 29 May 2014 => 4.0, …}
|
327
331
|
video.likes from: 8.days.ago #=> {Tue, 27 May 2014 => 7.0, Wed, 28 May 2014 => 0.0, …}
|
@@ -11,26 +11,12 @@ module Yt
|
|
11
11
|
class ResumableSessions < Base
|
12
12
|
|
13
13
|
# Starts a resumable session by sending to YouTube the metadata of the
|
14
|
-
#
|
15
|
-
# URL to upload the
|
16
|
-
# @param [Integer] content_length the size (bytes) of the
|
17
|
-
# @param [Hash] options the metadata to add to the uploaded
|
18
|
-
|
19
|
-
# @option options [String] :description The video’s description.
|
20
|
-
# @option options [Array<String>] :title The video’s tags.
|
21
|
-
# @option options [Integer] :category_id The video’s category ID.
|
22
|
-
# @option options [String] :privacy_status The video’s privacy status.
|
23
|
-
def insert(content_length, options = {})
|
14
|
+
# object to upload. If the request succeeds, YouTube returns a unique
|
15
|
+
# URL to upload the object file (and eventually resume the upload).
|
16
|
+
# @param [Integer] content_length the size (bytes) of the object to upload.
|
17
|
+
# @param [Hash] options the metadata to add to the uploaded object.
|
18
|
+
def insert(content_length, body = {})
|
24
19
|
@headers = headers_for content_length
|
25
|
-
body = {}
|
26
|
-
|
27
|
-
snippet = options.slice :title, :description, :tags, :category_id
|
28
|
-
snippet[:categoryId] = snippet.delete(:category_id) if snippet[:category_id]
|
29
|
-
body[:snippet] = snippet if snippet.any?
|
30
|
-
|
31
|
-
status = options[:privacy_status]
|
32
|
-
body[:status] = {privacyStatus: status} if status
|
33
|
-
|
34
20
|
do_insert body: body, headers: @headers
|
35
21
|
end
|
36
22
|
|
@@ -43,15 +29,15 @@ module Yt
|
|
43
29
|
def insert_params
|
44
30
|
super.tap do |params|
|
45
31
|
params[:response_format] = nil
|
46
|
-
params[:path] =
|
47
|
-
params[:params] =
|
32
|
+
params[:path] = @parent.upload_path
|
33
|
+
params[:params] = @parent.upload_params.merge uploadType: 'resumable'
|
48
34
|
end
|
49
35
|
end
|
50
36
|
|
51
37
|
def headers_for(content_length)
|
52
38
|
{}.tap do |headers|
|
53
39
|
headers['x-upload-content-length'] = content_length
|
54
|
-
headers['X-Upload-Content-Type'] =
|
40
|
+
headers['X-Upload-Content-Type'] = @parent.upload_content_type
|
55
41
|
end
|
56
42
|
end
|
57
43
|
|
data/lib/yt/models/account.rb
CHANGED
@@ -46,7 +46,7 @@ module Yt
|
|
46
46
|
# @return [Yt::Collections::Playlists] the account’s playlists.
|
47
47
|
has_many :playlists
|
48
48
|
|
49
|
-
# Uploads a video
|
49
|
+
# Uploads a video using resumable sessions
|
50
50
|
# @param [String] path_or_url the video to upload. Can either be the
|
51
51
|
# path of a local file or the URL of a remote file.
|
52
52
|
# @param [Hash] params the metadata to add to the uploaded video.
|
@@ -57,8 +57,11 @@ module Yt
|
|
57
57
|
# @return [Yt::Models::Video] the newly uploaded video.
|
58
58
|
def upload_video(path_or_url, params = {})
|
59
59
|
file = open path_or_url, 'rb'
|
60
|
-
session = resumable_sessions.insert file.size, params
|
61
|
-
|
60
|
+
session = resumable_sessions.insert file.size, upload_body(params)
|
61
|
+
|
62
|
+
session.update(body: file) do |data|
|
63
|
+
Yt::Video.new id: data['id'], snippet: data['snippet'], status: data['privacyStatus'], auth: self
|
64
|
+
end
|
62
65
|
end
|
63
66
|
|
64
67
|
def create_playlist(params = {})
|
@@ -71,6 +74,38 @@ module Yt
|
|
71
74
|
def videos_params
|
72
75
|
{for_mine: true}
|
73
76
|
end
|
77
|
+
|
78
|
+
# @private
|
79
|
+
# Tells `has_many :resumable_sessions` what path to hit to upload a file.
|
80
|
+
def upload_path
|
81
|
+
'/upload/youtube/v3/videos'
|
82
|
+
end
|
83
|
+
# @private
|
84
|
+
# Tells `has_many :resumable_sessions` what params are set for the object
|
85
|
+
# associated to the uploaded file.
|
86
|
+
def upload_params
|
87
|
+
{part: 'snippet,status'}
|
88
|
+
end
|
89
|
+
|
90
|
+
# @private
|
91
|
+
# Tells `has_many :resumable_sessions` what metadata to set in the object
|
92
|
+
# associated to the uploaded file.
|
93
|
+
def upload_body(params = {})
|
94
|
+
{}.tap do |body|
|
95
|
+
snippet = params.slice :title, :description, :tags, :category_id
|
96
|
+
snippet[:categoryId] = snippet.delete(:category_id) if snippet[:category_id]
|
97
|
+
body[:snippet] = snippet if snippet.any?
|
98
|
+
|
99
|
+
status = params[:privacy_status]
|
100
|
+
body[:status] = {privacyStatus: status} if status
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# @private
|
105
|
+
# Tells `has_many :resumable_sessions` what type of file can be uploaded.
|
106
|
+
def upload_content_type
|
107
|
+
'video/*'
|
108
|
+
end
|
74
109
|
end
|
75
110
|
end
|
76
111
|
end
|
@@ -13,14 +13,17 @@ module Yt
|
|
13
13
|
@headers = options[:headers]
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
def update(params = {})
|
17
|
+
do_update(params) {|data| yield data}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Uploads a thumbnail using the current resumable session
|
21
|
+
# @param [#read] file A binary object that contains the image content.
|
18
22
|
# Can either be a File, a StringIO (for instance using open-uri), etc.
|
19
|
-
# @return
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
23
|
+
# @return the new thumbnail resource for the given image.
|
24
|
+
# @see https://developers.google.com/youtube/v3/docs/thumbnails#resource
|
25
|
+
def upload_thumbnail(file)
|
26
|
+
do_update(body: file) {|data| data['items'].first}
|
24
27
|
end
|
25
28
|
|
26
29
|
private
|
data/lib/yt/models/video.rb
CHANGED
@@ -73,6 +73,11 @@ module Yt
|
|
73
73
|
delegate :view_count, :like_count, :dislike_count, :favorite_count,
|
74
74
|
:comment_count, to: :statistics_set
|
75
75
|
|
76
|
+
# @!attribute [r] resumable_sessions
|
77
|
+
# @return [Yt::Collections::ResumableSessions] the sessions used to
|
78
|
+
# upload thumbnails using the resumable upload protocol.
|
79
|
+
has_many :resumable_sessions
|
80
|
+
|
76
81
|
# Override Resource's new to set statistics and content details as well
|
77
82
|
# if the response includes them
|
78
83
|
def initialize(options = {})
|
@@ -163,6 +168,20 @@ module Yt
|
|
163
168
|
!liked?
|
164
169
|
end
|
165
170
|
|
171
|
+
# Uploads a thumbnail
|
172
|
+
# @param [String] path_or_url the image to upload. Can either be the
|
173
|
+
# path of a local file or the URL of a remote file.
|
174
|
+
# @return the new thumbnail resource for the given image.
|
175
|
+
# @see https://developers.google.com/youtube/v3/docs/thumbnails#resource
|
176
|
+
def upload_thumbnail(path_or_url)
|
177
|
+
file = open path_or_url, 'rb'
|
178
|
+
session = resumable_sessions.insert file.size
|
179
|
+
|
180
|
+
session.update(body: file) do |data|
|
181
|
+
snippet.instance_variable_set :@thumbnails, data['items'].first
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
166
185
|
# @private
|
167
186
|
# Tells `has_reports` to retrieve the reports from YouTube Analytics API
|
168
187
|
# either as a Channel or as a Content Owner.
|
@@ -178,6 +197,24 @@ module Yt
|
|
178
197
|
end
|
179
198
|
end
|
180
199
|
|
200
|
+
# @private
|
201
|
+
# Tells `has_many :resumable_sessions` what path to hit to upload a file.
|
202
|
+
def upload_path
|
203
|
+
'/upload/youtube/v3/thumbnails/set'
|
204
|
+
end
|
205
|
+
# @private
|
206
|
+
# Tells `has_many :resumable_sessions` what params are set for the object
|
207
|
+
# associated to the uploaded file.
|
208
|
+
def upload_params
|
209
|
+
{video_id: id}
|
210
|
+
end
|
211
|
+
|
212
|
+
# @private
|
213
|
+
# Tells `has_many :resumable_sessions` what type of file can be uploaded.
|
214
|
+
def upload_content_type
|
215
|
+
'application/octet-stream'
|
216
|
+
end
|
217
|
+
|
181
218
|
private
|
182
219
|
|
183
220
|
# @see https://developers.google.com/youtube/v3/docs/videos/update
|
data/lib/yt/version.rb
CHANGED
@@ -109,15 +109,9 @@ describe Yt::Account, :device_app do
|
|
109
109
|
it { expect{account.authentication}.to raise_error Yt::Errors::MissingAuth }
|
110
110
|
end
|
111
111
|
|
112
|
-
# @note: This test is a reflection of another irrational behavior of
|
113
|
-
# YouTube API. When passing a wrong 'device_code', YouTube crashes and
|
114
|
-
# raises 500, instead of an expected MissingAuth.
|
115
|
-
# The day YouTube fixes it, then this test will finally fail and the
|
116
|
-
# commented line will be restored.
|
117
112
|
context 'and an invalid device code' do
|
118
113
|
before { attrs[:device_code] = '--not-a-valid-device-code--' }
|
119
|
-
|
120
|
-
it { expect{account.authentication}.to raise_error Yt::Errors::ServerError }
|
114
|
+
it { expect{account.authentication}.to raise_error Yt::Errors::MissingAuth }
|
121
115
|
end
|
122
116
|
end
|
123
117
|
|
Binary file
|
@@ -342,4 +342,26 @@ describe Yt::Video, :device_app do
|
|
342
342
|
end
|
343
343
|
end
|
344
344
|
end
|
345
|
+
|
346
|
+
# @note: This should somehow test that the thumbnail *changes*. However,
|
347
|
+
# YouTube does not change the URL of the thumbnail even though the content
|
348
|
+
# changes. A full test would have to *download* the thumbnails before and
|
349
|
+
# after, and compare the files. For now, not raising error is enough.
|
350
|
+
# Eventually, change to `expect{update}.to change{video.thumbnail_url}`
|
351
|
+
context 'given one of my own videos for which I want to upload a thumbnail' do
|
352
|
+
let(:id) { $account.videos.where(order: 'viewCount').first.id }
|
353
|
+
let(:update) { video.upload_thumbnail path_or_url }
|
354
|
+
|
355
|
+
context 'given the path to a local JPG image file' do
|
356
|
+
let(:path_or_url) { File.expand_path '../thumbnail.jpg', __FILE__ }
|
357
|
+
|
358
|
+
it { expect{update}.not_to raise_error }
|
359
|
+
end
|
360
|
+
|
361
|
+
context 'given the path to a remote PNG image file' do
|
362
|
+
let(:path_or_url) { 'https://bit.ly/yt_thumbnail' }
|
363
|
+
|
364
|
+
it { expect{update}.not_to raise_error }
|
365
|
+
end
|
366
|
+
end
|
345
367
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.13.
|
4
|
+
version: 0.13.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Claudio Baccigalupo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02-
|
11
|
+
date: 2015-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -257,6 +257,7 @@ files:
|
|
257
257
|
- spec/requests/as_account/playlist_item_spec.rb
|
258
258
|
- spec/requests/as_account/playlist_spec.rb
|
259
259
|
- spec/requests/as_account/resource_spec.rb
|
260
|
+
- spec/requests/as_account/thumbnail.jpg
|
260
261
|
- spec/requests/as_account/video.mp4
|
261
262
|
- spec/requests/as_account/video_spec.rb
|
262
263
|
- spec/requests/as_content_owner/account_spec.rb
|
@@ -353,6 +354,7 @@ test_files:
|
|
353
354
|
- spec/requests/as_account/playlist_item_spec.rb
|
354
355
|
- spec/requests/as_account/playlist_spec.rb
|
355
356
|
- spec/requests/as_account/resource_spec.rb
|
357
|
+
- spec/requests/as_account/thumbnail.jpg
|
356
358
|
- spec/requests/as_account/video.mp4
|
357
359
|
- spec/requests/as_account/video_spec.rb
|
358
360
|
- spec/requests/as_content_owner/account_spec.rb
|