yt 0.6.4 → 0.6.5
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/HISTORY.md +1 -0
- data/README.md +5 -1
- data/TODO.md +53 -8
- data/bin/yt +4 -0
- data/lib/yt/actions/delete_all.rb +2 -2
- data/lib/yt/actions/list.rb +10 -3
- data/lib/yt/collections/reports.rb +4 -3
- data/lib/yt/collections/subscriptions.rb +1 -1
- data/lib/yt/models/channel.rb +1 -1
- data/lib/yt/models/details_set.rb +25 -4
- data/lib/yt/models/playlist.rb +1 -1
- data/lib/yt/models/playlist_item.rb +1 -1
- data/lib/yt/models/request.rb +22 -8
- data/lib/yt/models/subscription.rb +1 -0
- data/lib/yt/models/video.rb +1 -1
- data/lib/yt/version.rb +1 -1
- data/spec/models/details_set_spec.rb +48 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c7f28e1adc91466df73429cd2e12988092acabd
|
4
|
+
data.tar.gz: a66cb8c64a3764ffcad1e1988fa025ca5a9d5094
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b422e2ac62121f98113de5a65f53c2925009ddc3dc78737ffa9c145427201eb53df3723ebe0cdde108f5dfcfa05655c3bea9413ec03309e363075214a01b760a
|
7
|
+
data.tar.gz: 90bcf64d69cbb1161f694d22b5782cedcc0668f34025824fdea4da2e396af80a28b263abf9f52b0508cf14f7fe14c8f75ae49788cdc520e6b0395d9e5f4ada08
|
data/Gemfile.lock
CHANGED
data/HISTORY.md
CHANGED
@@ -7,6 +7,7 @@ v0.6 - 2014/06/05
|
|
7
7
|
* Allow account.videos to be chained with .where, such as in account.videos.where(q: 'query')
|
8
8
|
* Retry request once when YouTube times out
|
9
9
|
* Handle annotations with "never" as the timestamp, without text, singleton positions, of private videos
|
10
|
+
* New methods for Video: hd?, stereoscopic?, captioned?, licensed?
|
10
11
|
|
11
12
|
v0.5 - 2014/05/16
|
12
13
|
-----------------
|
data/README.md
CHANGED
@@ -27,6 +27,10 @@ video = Yt::Video.new id: 'MESycYJytkU'
|
|
27
27
|
video.title #=> "Fullscreen Creator Platform"
|
28
28
|
video.public? #=> true
|
29
29
|
video.duration #=> 86
|
30
|
+
video.hd? #=> true
|
31
|
+
video.stereoscopic? #=> false
|
32
|
+
video.captioned? #=> true
|
33
|
+
video.licensed? #=> false
|
30
34
|
video.annotations.count #=> 1
|
31
35
|
```
|
32
36
|
|
@@ -332,7 +336,7 @@ To install on your system, run
|
|
332
336
|
|
333
337
|
To use inside a bundled Ruby project, add this line to the Gemfile:
|
334
338
|
|
335
|
-
gem 'yt', '~> 0.6.
|
339
|
+
gem 'yt', '~> 0.6.5'
|
336
340
|
|
337
341
|
Since the gem follows [Semantic Versioning](http://semver.org),
|
338
342
|
indicating the full version in your Gemfile (~> *major*.*minor*.*patch*)
|
data/TODO.md
CHANGED
@@ -1,13 +1,58 @@
|
|
1
1
|
* methods like Yt::Account.new(params = {}) should use HashWithIndifferentAccess
|
2
2
|
* add canonical_url to Resource, then use it in promo
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
List of supported methods
|
5
|
+
=========================
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
* ENV support
|
7
|
+
YouTube Data API V3 (https://developers.google.com/youtube/v3/docs)
|
8
|
+
-------------------------------------------------------------------
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
- [ ] Activities
|
11
|
+
- [ ] list
|
12
|
+
- [ ] insert
|
13
|
+
- [ ] ChannelBanners
|
14
|
+
- [ ] insert
|
15
|
+
- [ ] Channels
|
16
|
+
- [ ] list
|
17
|
+
- [ ] update
|
18
|
+
- [ ] ChannelSections
|
19
|
+
- [ ] list
|
20
|
+
- [ ] insert
|
21
|
+
- [ ] update
|
22
|
+
- [ ] delete
|
23
|
+
- [ ] GuideCategories
|
24
|
+
- [ ] list
|
25
|
+
- [ ] I18nLanguages
|
26
|
+
- [ ] list
|
27
|
+
- [ ] I18nRegions
|
28
|
+
- [ ] list
|
29
|
+
- [ ] PlaylistItems
|
30
|
+
- [ ] list
|
31
|
+
- [ ] insert
|
32
|
+
- [ ] update
|
33
|
+
- [ ] delete
|
34
|
+
- [ ] Playlists
|
35
|
+
- [ ] list
|
36
|
+
- [ ] insert
|
37
|
+
- [ ] update
|
38
|
+
- [ ] delete
|
39
|
+
- [ ] Search
|
40
|
+
- [ ] list
|
41
|
+
- [ ] Subscriptions
|
42
|
+
- [ ] list
|
43
|
+
- [ ] insert
|
44
|
+
- [ ] delete
|
45
|
+
- [ ] Thumbnails
|
46
|
+
- [ ] set
|
47
|
+
- [ ] VideoCategories
|
48
|
+
- [ ] list
|
49
|
+
- [ ] Videos
|
50
|
+
- [ ] list
|
51
|
+
- [ ] insert
|
52
|
+
- [ ] update
|
53
|
+
- [ ] rate
|
54
|
+
- [ ] getRating
|
55
|
+
- [ ] delete
|
56
|
+
- [ ] Watermarks
|
57
|
+
- [ ] set
|
58
|
+
- [ ] unset
|
data/bin/yt
CHANGED
@@ -23,4 +23,8 @@ channel.videos.each do |video|
|
|
23
23
|
puts " Description: #{video.description}"
|
24
24
|
puts " Thumbnail: #{video.thumbnail_url}"
|
25
25
|
puts " Public? #{video.public?}"
|
26
|
+
puts " hd? #{video.hd?}"
|
27
|
+
puts " stereoscopic? #{video.stereoscopic?}"
|
28
|
+
puts " captioned? #{video.captioned?}"
|
29
|
+
puts " licensed? #{video.licensed?}"
|
26
30
|
end
|
data/lib/yt/actions/list.rb
CHANGED
@@ -8,7 +8,7 @@ module Yt
|
|
8
8
|
alias size count
|
9
9
|
|
10
10
|
def first!
|
11
|
-
first.tap{|item| raise Errors::NoItems unless item}
|
11
|
+
first.tap{|item| raise Errors::NoItems, last_request unless item}
|
12
12
|
end
|
13
13
|
|
14
14
|
private
|
@@ -48,13 +48,20 @@ module Yt
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def fetch_page(params = {})
|
51
|
-
|
52
|
-
response = request.run
|
51
|
+
response = request(params).run
|
53
52
|
token = response.body['nextPageToken']
|
54
53
|
items = response.body.fetch items_key, []
|
55
54
|
{items: items, token: token}
|
56
55
|
end
|
57
56
|
|
57
|
+
def request(params = {})
|
58
|
+
@last_request = Yt::Request.new params
|
59
|
+
end
|
60
|
+
|
61
|
+
def last_request
|
62
|
+
@last_request.request_error_message if @last_request
|
63
|
+
end
|
64
|
+
|
58
65
|
def list_params
|
59
66
|
path = "/youtube/v3/#{list_resources.to_s.demodulize.camelize :lower}"
|
60
67
|
|
data/lib/yt/models/channel.rb
CHANGED
@@ -4,7 +4,7 @@ require 'yt/associations/views'
|
|
4
4
|
|
5
5
|
module Yt
|
6
6
|
module Models
|
7
|
-
#
|
7
|
+
# A channel resource contains information about a YouTube channel.
|
8
8
|
# @see https://developers.google.com/youtube/v3/docs/channels
|
9
9
|
class Channel < Resource
|
10
10
|
include Associations::Earnings
|
@@ -2,8 +2,8 @@ require 'yt/models/base'
|
|
2
2
|
|
3
3
|
module Yt
|
4
4
|
module Models
|
5
|
-
# Encapsulates information about the content
|
6
|
-
#
|
5
|
+
# Encapsulates information about the video content, including the length
|
6
|
+
# of the video and an indication of whether captions are available.
|
7
7
|
# @see https://developers.google.com/youtube/v3/docs/videos#resource
|
8
8
|
class DetailsSet < Base
|
9
9
|
|
@@ -11,9 +11,30 @@ module Yt
|
|
11
11
|
@data = options[:data]
|
12
12
|
end
|
13
13
|
|
14
|
-
# @return [Integer] the duration of the
|
14
|
+
# @return [Integer] the duration of the video (in seconds).
|
15
15
|
def duration
|
16
|
-
@duration
|
16
|
+
@duration ||= to_seconds @data.fetch('duration', 0)
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Boolean] whether the video is available in 3D.
|
20
|
+
def stereoscopic?
|
21
|
+
@stereoscopic ||= @data['dimension'] == '3d'
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [Boolean] whether the video is available in high definition.
|
25
|
+
def hd?
|
26
|
+
@hd ||= @data['definition'] == 'hd'
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [Boolean] whether captions are available for the video.
|
30
|
+
def captioned?
|
31
|
+
@hd ||= @data['caption'] == 'true'
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Boolean] whether the video represents licensed content, which
|
35
|
+
# means that the content has been claimed by a YouTube content partner.
|
36
|
+
def licensed?
|
37
|
+
@licensed ||= @data.fetch 'licensedContent', false
|
17
38
|
end
|
18
39
|
|
19
40
|
private
|
data/lib/yt/models/playlist.rb
CHANGED
@@ -17,7 +17,7 @@ module Yt
|
|
17
17
|
# @raise [Yt::Errors::Unauthorized] if {Resource#auth auth} does not
|
18
18
|
# return an account with permissions to delete the playlist.
|
19
19
|
# @return [Boolean] whether the playlist does not exist anymore.
|
20
|
-
def delete
|
20
|
+
def delete(options = {})
|
21
21
|
do_delete {@id = nil}
|
22
22
|
!exists?
|
23
23
|
end
|
data/lib/yt/models/request.rb
CHANGED
@@ -19,7 +19,7 @@ module Yt
|
|
19
19
|
@body_type = options.fetch :body_type, :json
|
20
20
|
@expected_response = options.fetch :expected_response, Net::HTTPSuccess
|
21
21
|
@format = options.fetch :format, :json
|
22
|
-
@headers = options.fetch :headers,
|
22
|
+
@headers = options.fetch :headers, gzip_headers
|
23
23
|
@host = options.fetch :host, google_api_host
|
24
24
|
@method = options.fetch :method, :get
|
25
25
|
@path = options[:path]
|
@@ -34,6 +34,13 @@ module Yt
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
+
def request_error_message
|
38
|
+
{}.tap do |message|
|
39
|
+
message[:request_curl] = as_curl
|
40
|
+
message[:response_body] = JSON(response.body) rescue response.inspect
|
41
|
+
end.to_json
|
42
|
+
end
|
43
|
+
|
37
44
|
private
|
38
45
|
|
39
46
|
def response
|
@@ -59,6 +66,19 @@ module Yt
|
|
59
66
|
@headers.each{|name, value| request.add_field name, value}
|
60
67
|
end
|
61
68
|
|
69
|
+
# To receive a gzip-encoded response you must do two things:
|
70
|
+
# - Set the Accept-Encoding HTTP request header to gzip.
|
71
|
+
# - Modify your user agent to contain the string gzip.
|
72
|
+
# Note that HTTP headers are case-insensitive.
|
73
|
+
# @see https://developers.google.com/youtube/v3/getting-started#gzip
|
74
|
+
# @see http://www.ietf.org/rfc/rfc2616.txt
|
75
|
+
def gzip_headers
|
76
|
+
@gzip_headers ||= {}.tap do |headers|
|
77
|
+
headers['accept-encoding'] = 'gzip'
|
78
|
+
headers['user-agent'] = 'Yt (gzip)'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
62
82
|
def set_body!(request)
|
63
83
|
case @body_type
|
64
84
|
when :json then request.body = @body.to_json
|
@@ -157,17 +177,11 @@ module Yt
|
|
157
177
|
end
|
158
178
|
end
|
159
179
|
|
160
|
-
def request_error_message
|
161
|
-
{}.tap do |message|
|
162
|
-
message[:request_curl] = as_curl
|
163
|
-
message[:response_body] = JSON(response.body) rescue response.inspect
|
164
|
-
end.to_json
|
165
|
-
end
|
166
|
-
|
167
180
|
def as_curl
|
168
181
|
'curl'.tap do |curl|
|
169
182
|
curl << " -X #{http_request.method}"
|
170
183
|
http_request.each_header do |name, value|
|
184
|
+
next if gzip_headers.has_key? name
|
171
185
|
curl << %Q{ -H "#{name}: #{value}"}
|
172
186
|
end
|
173
187
|
curl << %Q{ -d '#{http_request.body}'} if http_request.body
|
data/lib/yt/models/video.rb
CHANGED
@@ -8,7 +8,7 @@ module Yt
|
|
8
8
|
# @!attribute [r] details_set
|
9
9
|
# @return [Yt::Models::DetailsSet] the video’s content details.
|
10
10
|
has_one :details_set
|
11
|
-
delegate :duration, to: :details_set
|
11
|
+
delegate :duration, :hd?, :stereoscopic?, :captioned?, :licensed?, to: :details_set
|
12
12
|
|
13
13
|
# @!attribute [r] rating
|
14
14
|
# @return [Yt::Models::Rating] the video’s rating.
|
data/lib/yt/version.rb
CHANGED
@@ -25,4 +25,52 @@ describe Yt::DetailsSet do
|
|
25
25
|
it { expect(details_set.duration).to eq 51 }
|
26
26
|
end
|
27
27
|
end
|
28
|
+
|
29
|
+
describe '#stereoscopic?' do
|
30
|
+
context 'given a 3D video' do
|
31
|
+
let(:data) { {"dimension"=>"3d"} }
|
32
|
+
it { expect(details_set).to be_stereoscopic }
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'given a 2D video' do
|
36
|
+
let(:data) { {"dimension"=>"2d"} }
|
37
|
+
it { expect(details_set).not_to be_stereoscopic }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#hd?' do
|
42
|
+
context 'given a high-definition video' do
|
43
|
+
let(:data) { {"definition"=>"hd"} }
|
44
|
+
it { expect(details_set).to be_hd }
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'given a standard-definition video' do
|
48
|
+
let(:data) { {"definition"=>"sd"} }
|
49
|
+
it { expect(details_set).not_to be_hd }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#captioned?' do
|
54
|
+
context 'given a video with captions' do
|
55
|
+
let(:data) { {"caption"=>"true"} }
|
56
|
+
it { expect(details_set).to be_captioned }
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'given a video without captions' do
|
60
|
+
let(:data) { {"caption"=>"false"} }
|
61
|
+
it { expect(details_set).not_to be_captioned }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#captioned?' do
|
66
|
+
context 'given a video with licensed content' do
|
67
|
+
let(:data) { {"licensedContent"=>true} }
|
68
|
+
it { expect(details_set).to be_licensed }
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'given a video without licensed content' do
|
72
|
+
let(:data) { {"licensedContent"=>false} }
|
73
|
+
it { expect(details_set).not_to be_licensed }
|
74
|
+
end
|
75
|
+
end
|
28
76
|
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.6.
|
4
|
+
version: 0.6.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Claudio Baccigalupo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|