yt 0.32.3 → 0.32.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +4 -1
- data/.travis.yml +2 -4
- data/CHANGELOG.md +9 -0
- data/README.md +54 -30
- data/lib/yt/actions/get.rb +33 -0
- data/lib/yt/collections/claims.rb +8 -0
- data/lib/yt/collections/content_owners.rb +6 -2
- data/lib/yt/collections/snippets.rb +1 -1
- data/lib/yt/config.rb +54 -0
- data/lib/yt/models/asset.rb +17 -3
- data/lib/yt/models/asset_metadata.rb +1 -1
- data/lib/yt/models/base.rb +2 -0
- data/lib/yt/models/claim.rb +11 -0
- data/lib/yt/models/configuration.rb +70 -0
- data/lib/yt/models/content_owner.rb +29 -0
- data/lib/yt/models/resource.rb +1 -1
- data/lib/yt/version.rb +1 -1
- data/spec/collections/claims_spec.rb +34 -2
- data/spec/models/asset_spec.rb +13 -1
- data/spec/models/configuration_spec.rb +44 -0
- data/spec/requests/as_account/account_spec.rb +1 -6
- data/spec/requests/as_account/channel_spec.rb +1 -1
- data/spec/requests/as_account/playlist_item_spec.rb +2 -2
- data/spec/requests/as_account/playlist_spec.rb +4 -4
- data/spec/requests/as_account/video_spec.rb +5 -5
- data/spec/requests/as_content_owner/account_spec.rb +1 -1
- data/spec/requests/as_content_owner/asset_spec.rb +16 -5
- data/spec/requests/as_content_owner/claim_spec.rb +17 -0
- data/spec/requests/as_content_owner/content_owner_spec.rb +51 -10
- data/spec/requests/as_server_app/channel_spec.rb +3 -3
- data/spec/requests/as_server_app/comment_thread_spec.rb +2 -2
- data/spec/requests/as_server_app/playlist_item_spec.rb +2 -2
- data/spec/requests/as_server_app/playlist_spec.rb +2 -2
- data/yt.gemspec +1 -1
- metadata +18 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b60bee886ed9551a6b9590fa99ad1146472dc90d332a50854a0d7ba490b40f93
|
4
|
+
data.tar.gz: 72e08ae6b64e508e873a1d47f00c71e021d994bfb3bb65b2c1b52e4e6709950a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87f08494b156a1846e63eff41c154cbfc462e1a65c1391bdc530ae1a84ef891150b72b0e604359a2d20d45a5fd0db88a7429c38ffa80b3a2f721b25452ebd119
|
7
|
+
data.tar.gz: 0453b6e46b53d2c3b2c0ffcdccd0daba325c97f96ebfacb37939172e6137c271236f94ef2fc05d25a6df3b8784c84040ab4b71064ea861b10e90e201a3198128
|
data/.rspec
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,15 @@ 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.32.4 - 2019-06-26
|
10
|
+
|
11
|
+
* [FEATURE] Add `ownership_effective` method to access asset ownership ("effective") via the asset object.
|
12
|
+
* [FEATURE] List content owners of others with `content_owner.content_owners`
|
13
|
+
* [FEATURE] Add `match_info` to insert claim request.
|
14
|
+
* [FEATURE] Add `upload_reference_file` method for Reference file upload (thank you @jcohenho)
|
15
|
+
* [FEATURE] Get one asset [by request](https://developers.google.com/youtube/partner/docs/v1/assets/get) (thank you @jcohenho)
|
16
|
+
* [FEATURE] Add `update` method to Yt::Claim (thank you @jcohenho)
|
17
|
+
|
9
18
|
## 0.32.3 - 2019-03-15
|
10
19
|
|
11
20
|
* [ENHANCEMENT] Add `Yt::URL` to get id, kind, and its resource (channel, video, playlist)
|
data/README.md
CHANGED
@@ -8,7 +8,7 @@ The **source code** is available on [GitHub](https://github.com/Fullscreen/yt) a
|
|
8
8
|
[![Build Status](http://img.shields.io/travis/Fullscreen/yt/master.svg)](https://travis-ci.org/Fullscreen/yt)
|
9
9
|
[![Coverage Status](http://img.shields.io/coveralls/Fullscreen/yt/master.svg)](https://coveralls.io/r/Fullscreen/yt)
|
10
10
|
[![Dependency Status](http://img.shields.io/gemnasium/Fullscreen/yt.svg)](https://gemnasium.com/Fullscreen/yt)
|
11
|
-
[![Code Climate](
|
11
|
+
[![Code Climate](https://codeclimate.com/github/Fullscreen/yt.png)](https://codeclimate.com/github/Fullscreen/yt)
|
12
12
|
[![Online docs](http://img.shields.io/badge/docs-✓-green.svg)](http://www.rubydoc.info/gems/yt/frames)
|
13
13
|
[![Gem Version](http://img.shields.io/gem/v/yt.svg)](http://rubygems.org/gems/yt)
|
14
14
|
|
@@ -44,7 +44,7 @@ To install on your system, run
|
|
44
44
|
|
45
45
|
To use inside a bundled Ruby project, add this line to the Gemfile:
|
46
46
|
|
47
|
-
gem 'yt', '~> 0.
|
47
|
+
gem 'yt', '~> 0.32.0'
|
48
48
|
|
49
49
|
Since the gem follows [Semantic Versioning](http://semver.org),
|
50
50
|
indicating the full version in your Gemfile (~> *major*.*minor*.*patch*)
|
@@ -266,6 +266,11 @@ asset = content_owner.assets.where(id: 'A969176766549462', fetch_metadata: 'effe
|
|
266
266
|
asset.metadata_effective.title #=> "Neu la anh" (different due to ownership conflicts)
|
267
267
|
```
|
268
268
|
|
269
|
+
```ruby
|
270
|
+
asset = content_owner.assets.where(id: 'A125058570526569', fetch_ownership: 'effective').first
|
271
|
+
asset.ownership_effective.general_owners.first.owner # => "XOuN81q-MeEUVrsiZeK1lQ"
|
272
|
+
```
|
273
|
+
|
269
274
|
* to search for an asset
|
270
275
|
|
271
276
|
```ruby
|
@@ -295,6 +300,32 @@ claim.claim_history #=> #<Yt::Models::ClaimHistory ...>
|
|
295
300
|
claim.claim_history.events[0].type #=> "claim_create"
|
296
301
|
|
297
302
|
claim.delete #=> true
|
303
|
+
|
304
|
+
data = {
|
305
|
+
is_manual_claim: true,
|
306
|
+
content_type: 'audiovisual',
|
307
|
+
asset_id: 'A123123123123123',
|
308
|
+
policy: { id: 'S123123123123123' },
|
309
|
+
video_id: 'myvIdeoIdYT',
|
310
|
+
match_info: {
|
311
|
+
match_segments: [
|
312
|
+
{
|
313
|
+
manual_segment: {
|
314
|
+
start: '00:00:20.000',
|
315
|
+
finish: '00:01:20.000'
|
316
|
+
}
|
317
|
+
},
|
318
|
+
{
|
319
|
+
manual_segment: {
|
320
|
+
start: '00:02:30.000',
|
321
|
+
finish: '00:03:50.000'
|
322
|
+
}
|
323
|
+
}
|
324
|
+
]
|
325
|
+
}
|
326
|
+
}
|
327
|
+
|
328
|
+
content_owner.claims.insert(data)
|
298
329
|
```
|
299
330
|
|
300
331
|
*The methods above require to be authenticated as the video’s content owner (see below).*
|
@@ -492,23 +523,6 @@ end
|
|
492
523
|
so use the approach that you prefer.
|
493
524
|
If a variable is set in both places, then `Yt.configure` takes precedence.
|
494
525
|
|
495
|
-
Why you should use Yt…
|
496
|
-
======================
|
497
|
-
|
498
|
-
… and not [youtube_it](https://github.com/kylejginavan/youtube_it)?
|
499
|
-
Because youtube_it does not support YouTube API V3, and the YouTube API V2 has
|
500
|
-
been [officially deprecated as of March 4, 2014](https://developers.google.com/youtube/2.0/developers_guide_protocol_audience).
|
501
|
-
If you need help upgrading your code, check [YOUTUBE_IT.md](https://github.com/Fullscreen/yt/blob/master/YOUTUBE_IT.md),
|
502
|
-
a step-by-step comparison between youtube_it and Yt to make upgrade easier.
|
503
|
-
|
504
|
-
… and not [Google Api Client](https://github.com/google/google-api-ruby-client)?
|
505
|
-
Because Google Api Client is poorly coded, poorly documented and adds many
|
506
|
-
dependencies, bloating the size of your project.
|
507
|
-
|
508
|
-
… and not your own code? Because Yt is fully tested, well documented,
|
509
|
-
has few dependencies and helps you forget about the burden of dealing with
|
510
|
-
Google API!
|
511
|
-
|
512
526
|
How to test
|
513
527
|
===========
|
514
528
|
|
@@ -517,15 +531,6 @@ Yt comes with two different sets of tests:
|
|
517
531
|
1. tests in `spec/models`, `spec/collections` and `spec/errors` **do not hit** the YouTube API
|
518
532
|
1. tests in `spec/requests` **hit** the YouTube API and require authentication
|
519
533
|
|
520
|
-
The reason why some tests actually hit the YouTube API is because they are
|
521
|
-
meant to really integrate Yt with YouTube. YouTube API is not exactly
|
522
|
-
*the most reliable* API out there, so we need to make sure that the responses
|
523
|
-
match the documentation.
|
524
|
-
|
525
|
-
You don’t have to run all the tests every time you change code.
|
526
|
-
Travis CI is already set up to do this for when whenever you push a branch
|
527
|
-
or create a pull request for this project.
|
528
|
-
|
529
534
|
To only run tests against models, collections and errors (which do not hit the API), type:
|
530
535
|
|
531
536
|
```bash
|
@@ -539,8 +544,26 @@ rspec
|
|
539
544
|
```
|
540
545
|
|
541
546
|
This will fail unless you have set up a test YouTube application and some
|
542
|
-
tests YouTube accounts to hit the API.
|
543
|
-
|
547
|
+
tests YouTube accounts (with appropriate fixture data) to hit the API.
|
548
|
+
Furthermore, tests that require authentication are divided into three
|
549
|
+
roles, which correspond to each directory in `spec/requests`:
|
550
|
+
|
551
|
+
* Account-based tests, which require a valid refresh token along with
|
552
|
+
the application-level credentials the refresh token was created with
|
553
|
+
(`YT_TEST_DEVICE_REFRESH_TOKEN`, `YT_TEST_DEVICE_CLIENT_ID`, and
|
554
|
+
`YT_TEST_DEVICE_CLIENT_SECRET` respectively).
|
555
|
+
* Server application tests, which use a server API key
|
556
|
+
(`YT_TEST_SERVER_API_KEY`).
|
557
|
+
* Tests that excercise YouTube's partner functionality. This requires an
|
558
|
+
a partner channel id (`YT_TEST_CONTENT_OWNER_NAME`), a refresh token
|
559
|
+
that's authenticated with that channel
|
560
|
+
(`YT_TEST_CONTENT_OWNER_REFRESH_TOKEN`), and the corresponding
|
561
|
+
application (`YT_TEST_PARTNER_CLIENT_ID` and
|
562
|
+
(`YT_TEST_PARTNER_CLIENT_SECRET`).
|
563
|
+
|
564
|
+
The refresh tokens need to be generated with the `youtube`,
|
565
|
+
`yt-analytics` and `userinfo.profile` permissions in order for tests to
|
566
|
+
pass.
|
544
567
|
|
545
568
|
How to release new versions
|
546
569
|
===========================
|
@@ -568,3 +591,4 @@ the [YouTube Analytics API](https://developers.google.com/youtube/analytics).
|
|
568
591
|
If you find that a method is missing, fork the project, add the missing code,
|
569
592
|
write the appropriate tests, then submit a pull request, and it will gladly
|
570
593
|
be merged!
|
594
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'yt/request'
|
2
|
+
|
3
|
+
module Yt
|
4
|
+
module Actions
|
5
|
+
module Get
|
6
|
+
include Base
|
7
|
+
|
8
|
+
def get
|
9
|
+
response = get_request(get_params).run
|
10
|
+
@data.merge! response.body
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def get_request(params = {})
|
17
|
+
@list_request = Yt::Request.new(params).tap do |request|
|
18
|
+
print "#{request.as_curl}\n" if Yt.configuration.developing?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_params
|
23
|
+
{}.tap do |params|
|
24
|
+
params[:method] = :get
|
25
|
+
params[:host] = 'www.googleapis.com'
|
26
|
+
params[:auth] = @auth
|
27
|
+
params[:exptected_response] = Net::HTTPOK
|
28
|
+
params[:api_key] = Yt.configuration.api_key if Yt.configuration.api_key
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -11,6 +11,7 @@ module Yt
|
|
11
11
|
underscore_keys! attributes
|
12
12
|
body = attributes.slice :asset_id, :video_id, :content_type, :policy
|
13
13
|
body[:policy] = {id: attributes[:policy_id]} if attributes[:policy_id]
|
14
|
+
body[:match_info] = match_attributes(attributes[:match_info]) if attributes[:match_info]
|
14
15
|
params = attributes.slice(:is_manual_claim).merge({on_behalf_of_content_owner: @auth.owner_name})
|
15
16
|
do_insert(params: params, body: body)
|
16
17
|
end
|
@@ -38,6 +39,13 @@ module Yt
|
|
38
39
|
super
|
39
40
|
end
|
40
41
|
|
42
|
+
def match_attributes(attributes = {})
|
43
|
+
segments = attributes[:match_segments].map do |segment|
|
44
|
+
{ manual_segment: (segment[:manual_segment] || segment).slice(:start, :finish) }
|
45
|
+
end
|
46
|
+
{ matchSegments: segments }
|
47
|
+
end
|
48
|
+
|
41
49
|
# @return [Hash] the parameters to submit to YouTube to list claims
|
42
50
|
# administered by the content owner.
|
43
51
|
# @see https://developers.google.com/youtube/partner/docs/v1/claims/list
|
data/lib/yt/config.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'yt/models/configuration'
|
2
|
+
|
3
|
+
module Yt
|
4
|
+
# Provides methods to read and write global configuration settings.
|
5
|
+
#
|
6
|
+
# A typical usage is to set the API keys retrieved from the
|
7
|
+
# {http://console.developers.google.com Google Developers Console}.
|
8
|
+
#
|
9
|
+
# @example Set the API key for a server-only YouTube app:
|
10
|
+
# Yt.configure do |config|
|
11
|
+
# config.api_key = 'ABCDEFGHIJ1234567890'
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# @example Set the API client id/secret for a web-client YouTube app:
|
15
|
+
# Yt.configure do |config|
|
16
|
+
# config.client_id = 'ABCDEFGHIJ1234567890'
|
17
|
+
# config.client_secret = 'ABCDEFGHIJ1234567890'
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# Note that Yt.configure has precedence over values through with
|
21
|
+
# environment variables (see {Yt::Models::Configuration}).
|
22
|
+
#
|
23
|
+
module Config
|
24
|
+
# Yields the global configuration to the given block.
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# Yt.configure do |config|
|
28
|
+
# config.api_key = 'ABCDEFGHIJ1234567890'
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# @yield [Yt::Models::Configuration] The global configuration.
|
32
|
+
def configure
|
33
|
+
yield configuration if block_given?
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns the global {Yt::Models::Configuration} object.
|
37
|
+
#
|
38
|
+
# While this method _can_ be used to read and write configuration settings,
|
39
|
+
# it is easier to use {Yt::Config#configure} Yt.configure}.
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# Yt.configuration.api_key = 'ABCDEFGHIJ1234567890'
|
43
|
+
#
|
44
|
+
# @return [Yt::Models::Configuration] The global configuration.
|
45
|
+
def configuration
|
46
|
+
@configuration ||= Yt::Configuration.new
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# @note Config is the only module auto-loaded in the Yt module,
|
51
|
+
# in order to have a syntax as easy as Yt.configure
|
52
|
+
|
53
|
+
extend Config
|
54
|
+
end
|
data/lib/yt/models/asset.rb
CHANGED
@@ -12,6 +12,7 @@ module Yt
|
|
12
12
|
@data = options.fetch(:data, {})
|
13
13
|
@id = options[:id]
|
14
14
|
@auth = options[:auth]
|
15
|
+
@params = options[:params]
|
15
16
|
end
|
16
17
|
|
17
18
|
def update(attributes = {})
|
@@ -34,6 +35,10 @@ module Yt
|
|
34
35
|
@metadata_effective ||= Yt::Models::AssetMetadata.new data: @data.fetch('metadataEffective', {})
|
35
36
|
end
|
36
37
|
|
38
|
+
def ownership_effective
|
39
|
+
@ownership_effective ||= Yt::Models::Ownership.new data: @data.fetch('ownershipEffective', {})
|
40
|
+
end
|
41
|
+
|
37
42
|
# Soft-deletes the asset.
|
38
43
|
# @note YouTube API does not provide a +delete+ method for the Asset
|
39
44
|
# resource, but only an +update+ method. Updating the +status+ of a
|
@@ -64,11 +69,11 @@ module Yt
|
|
64
69
|
# +'show'+, +'sound_recording'+, +'video_game'+, +'web'+.
|
65
70
|
has_attribute :type
|
66
71
|
|
67
|
-
# @return [Array<
|
72
|
+
# @return [Array<String>] the list of asset labels associated
|
68
73
|
# with the asset. You can apply a label to multiple assets to group
|
69
74
|
# them. You can use the labels as search filters to perform bulk updates,
|
70
75
|
# to download reports, or to filter YouTube Analytics.
|
71
|
-
has_attribute :label
|
76
|
+
has_attribute :label, default: []
|
72
77
|
|
73
78
|
# Status
|
74
79
|
|
@@ -106,6 +111,15 @@ module Yt
|
|
106
111
|
params[:params] = {on_behalf_of_content_owner: @auth.owner_name}
|
107
112
|
end
|
108
113
|
end
|
114
|
+
|
115
|
+
# @return [Hash] the parameters to submit to YouTube to get an asset.
|
116
|
+
# @see https://developers.google.com/youtube/partner/docs/v1/assets/get
|
117
|
+
def get_params
|
118
|
+
super.tap do |params|
|
119
|
+
params[:path] = "/youtube/partner/v1/assets/#{@id}"
|
120
|
+
params[:params] = {on_behalf_of_content_owner: @auth.owner_name}.merge! @params
|
121
|
+
end
|
122
|
+
end
|
109
123
|
end
|
110
124
|
end
|
111
|
-
end
|
125
|
+
end
|
data/lib/yt/models/base.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'yt/actions/delete'
|
2
2
|
require 'yt/actions/update'
|
3
3
|
require 'yt/actions/patch'
|
4
|
+
require 'yt/actions/get'
|
4
5
|
|
5
6
|
require 'yt/associations/has_attribute'
|
6
7
|
require 'yt/associations/has_authentication'
|
@@ -17,6 +18,7 @@ module Yt
|
|
17
18
|
include Actions::Delete
|
18
19
|
include Actions::Update
|
19
20
|
include Actions::Patch
|
21
|
+
include Actions::Get
|
20
22
|
|
21
23
|
include Associations::HasAttribute
|
22
24
|
extend Associations::HasReports
|
data/lib/yt/models/claim.rb
CHANGED
@@ -14,6 +14,17 @@ module Yt
|
|
14
14
|
@asset = options[:asset] if options[:asset]
|
15
15
|
end
|
16
16
|
|
17
|
+
# Updates the attributes of a claim.
|
18
|
+
# @note If you are submitting an update request, and your request does
|
19
|
+
# not specify a value for a property that already has a value, the
|
20
|
+
# property's existing value will be deleted.
|
21
|
+
# @return [Boolean] whether the claim was successfully updated.
|
22
|
+
def update(attributes = {})
|
23
|
+
underscore_keys! attributes
|
24
|
+
do_patch body: attributes
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
17
28
|
# @!attribute [r] claim_history
|
18
29
|
# @return [Yt::Collections::ClaimHistories] the claim's history.
|
19
30
|
has_one :claim_history
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Yt
|
2
|
+
module Models
|
3
|
+
# Provides an object to store global configuration settings.
|
4
|
+
#
|
5
|
+
# This class is typically not used directly, but by calling
|
6
|
+
# {Yt::Config#configure Yt.configure}, which creates and updates a single
|
7
|
+
# instance of {Yt::Models::Configuration}.
|
8
|
+
#
|
9
|
+
# @example Set the API client id/secret for a web-client YouTube app:
|
10
|
+
# Yt.configure do |config|
|
11
|
+
# config.client_id = 'ABCDEFGHIJ1234567890'
|
12
|
+
# config.client_secret = 'ABCDEFGHIJ1234567890'
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# @see Yt::Config for more examples.
|
16
|
+
#
|
17
|
+
# An alternative way to set global configuration settings is by storing
|
18
|
+
# them in the following environment variables:
|
19
|
+
#
|
20
|
+
# * +YT_CLIENT_ID+ to store the Client ID for web/device apps
|
21
|
+
# * +YT_CLIENT_SECRET+ to store the Client Secret for web/device apps
|
22
|
+
# * +YT_API_KEY+ to store the API key for server/browser apps
|
23
|
+
# * +YT_LOG_LEVEL+ to store the verbosity level of the logs
|
24
|
+
#
|
25
|
+
# In case both methods are used together,
|
26
|
+
# {Yt::Config#configure Yt.configure} takes precedence.
|
27
|
+
#
|
28
|
+
# @example Set the API client id/secret for a web-client YouTube app:
|
29
|
+
# ENV['YT_CLIENT_ID'] = 'ABCDEFGHIJ1234567890'
|
30
|
+
# ENV['YT_CLIENT_SECRET'] = 'ABCDEFGHIJ1234567890'
|
31
|
+
#
|
32
|
+
class Configuration
|
33
|
+
# @return [String] the Client ID for web/device YouTube applications.
|
34
|
+
# @see https://console.developers.google.com Google Developers Console
|
35
|
+
attr_accessor :client_id
|
36
|
+
|
37
|
+
# @return [String] the Client Secret for web/device YouTube applications.
|
38
|
+
# @see https://console.developers.google.com Google Developers Console
|
39
|
+
attr_accessor :client_secret
|
40
|
+
|
41
|
+
# @return [String] the API key for server/browser YouTube applications.
|
42
|
+
# @see https://console.developers.google.com Google Developers Console
|
43
|
+
attr_accessor :api_key
|
44
|
+
|
45
|
+
# @return [String] the level of output to print for debugging purposes.
|
46
|
+
attr_accessor :log_level
|
47
|
+
|
48
|
+
# Initialize the global configuration settings, using the values of
|
49
|
+
# the specified following environment variables by default.
|
50
|
+
def initialize
|
51
|
+
@client_id = ENV['YT_CLIENT_ID']
|
52
|
+
@client_secret = ENV['YT_CLIENT_SECRET']
|
53
|
+
@api_key = ENV['YT_API_KEY']
|
54
|
+
@log_level = ENV['YT_LOG_LEVEL']
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [Boolean] whether the logging output is extra-verbose.
|
58
|
+
# Useful when developing (e.g., to print the curl of every request).
|
59
|
+
def developing?
|
60
|
+
log_level.to_s.in? %w(devel)
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [Boolean] whether the logging output is verbose.
|
64
|
+
# Useful when debugging (e.g., to print the curl of failing requests).
|
65
|
+
def debugging?
|
66
|
+
log_level.to_s.in? %w(devel debug)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -46,6 +46,22 @@ module Yt
|
|
46
46
|
@display_name = options[:display_name]
|
47
47
|
end
|
48
48
|
|
49
|
+
# Uploads a reference file to YouTube.
|
50
|
+
# @param [String] path_or_url is the video or audio file to upload. Can either be the
|
51
|
+
# path of a local file or the URL of a remote file.
|
52
|
+
# @param [Hash] params the metadata to add to the uploaded reference.
|
53
|
+
# @option params [String] :asset_id The id of the asset the uploaded reference belongs to.
|
54
|
+
# @option params [String] :content_type The type of content being uploaded.
|
55
|
+
# @return [Yt::Models::Reference] the newly uploaded reference.
|
56
|
+
def upload_reference_file(path_or_url, params = {})
|
57
|
+
file = open path_or_url, 'rb'
|
58
|
+
session = resumable_sessions.insert file.size, params
|
59
|
+
|
60
|
+
session.update(body: file) do |data|
|
61
|
+
Yt::Reference.new id: data['id'], data: data, auth: self
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
49
65
|
def create_reference(params = {})
|
50
66
|
references.insert params
|
51
67
|
end
|
@@ -60,6 +76,12 @@ module Yt
|
|
60
76
|
|
61
77
|
### PRIVATE API ###
|
62
78
|
|
79
|
+
# @private
|
80
|
+
# Tells `has_many :resumable_sessions` what path to hit to upload a file.
|
81
|
+
def upload_path
|
82
|
+
'/upload/youtube/partner/v1/references'
|
83
|
+
end
|
84
|
+
|
63
85
|
# @private
|
64
86
|
# Tells `has_many :videos` that account.videos should return all the
|
65
87
|
# videos *on behalf of* the content owner (public, private, unlisted).
|
@@ -67,6 +89,13 @@ module Yt
|
|
67
89
|
{for_content_owner: true, on_behalf_of_content_owner: @owner_name}
|
68
90
|
end
|
69
91
|
|
92
|
+
# @private
|
93
|
+
# Tells `has_many :resumable_sessions` what params are set for the object
|
94
|
+
# associated to the uploaded file.
|
95
|
+
def upload_params
|
96
|
+
{part: 'snippet,status', on_behalf_of_content_owner: self.owner_name}
|
97
|
+
end
|
98
|
+
|
70
99
|
# @private
|
71
100
|
# Tells `has_many :video_groups` that content_owner.video_groups should
|
72
101
|
# return all the video-groups *on behalf of* the content owner
|
data/lib/yt/models/resource.rb
CHANGED
data/lib/yt/version.rb
CHANGED
@@ -3,11 +3,43 @@ require 'yt/collections/claims'
|
|
3
3
|
require 'yt/models/content_owner'
|
4
4
|
|
5
5
|
describe Yt::Collections::Claims do
|
6
|
-
subject(:collection) { Yt::Collections::Claims.new parent: content_owner }
|
7
6
|
let(:content_owner) { Yt::ContentOwner.new owner_name: 'any-name' }
|
7
|
+
let(:collection) { Yt::Collections::Claims.new parent: content_owner, auth: content_owner }
|
8
8
|
let(:page) { {items: [], token: 'any-token'} }
|
9
9
|
let(:query) { {q: 'search string'} }
|
10
10
|
|
11
|
+
describe "#insert" do
|
12
|
+
let(:attributes) {
|
13
|
+
{
|
14
|
+
asset_id: 'some_asset_id',
|
15
|
+
video_id: 'some_video_id',
|
16
|
+
content_type: 'audiovisual',
|
17
|
+
policy: { id: 'some_policy_id' },
|
18
|
+
match_info: { match_segments: [ { manual_segment: { start: "00:01:00.000", finish: "00:02:00.000" } } ] },
|
19
|
+
is_manual_claim: true
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
before do
|
24
|
+
allow(collection).to receive(:do_insert)
|
25
|
+
collection.insert(attributes.deep_dup)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'calls do_insert with appropriate body' do
|
29
|
+
body = {
|
30
|
+
asset_id: 'some_asset_id',
|
31
|
+
video_id: 'some_video_id',
|
32
|
+
content_type: 'audiovisual',
|
33
|
+
policy: { id: 'some_policy_id' },
|
34
|
+
match_info: { matchSegments: [ { manual_segment: { start: "00:01:00.000", finish: "00:02:00.000" } } ] }
|
35
|
+
}
|
36
|
+
expect(collection).to have_received(:do_insert).with(
|
37
|
+
params: { is_manual_claim: true, on_behalf_of_content_owner: content_owner.owner_name },
|
38
|
+
body: body
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
11
43
|
describe '#count' do
|
12
44
|
context 'called once with .where(query) and once without' do
|
13
45
|
after do
|
@@ -27,4 +59,4 @@ describe Yt::Collections::Claims do
|
|
27
59
|
end
|
28
60
|
end
|
29
61
|
end
|
30
|
-
end
|
62
|
+
end
|
data/spec/models/asset_spec.rb
CHANGED
@@ -17,4 +17,16 @@ describe Yt::Asset do
|
|
17
17
|
it { expect(asset.type).to eq 'web' }
|
18
18
|
end
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
|
+
describe '#ownership_effective' do
|
22
|
+
context 'given fetching a asset returns an ownershipEffective' do
|
23
|
+
let(:data) {
|
24
|
+
{"ownershipEffective"=>{"kind"=>"youtubePartner#rightsOwnership",
|
25
|
+
"general"=>[{"ratio"=>100.0, "owner"=>"XOuN81q-MeEUVrsiZeK1lQ", "type"=>"exclude"}]}}
|
26
|
+
}
|
27
|
+
it { expect(asset.ownership_effective).to be_a Yt::Ownership }
|
28
|
+
it { expect(asset.ownership_effective.general_owners.first).to be_a Yt::RightOwner }
|
29
|
+
it { expect(asset.ownership_effective.general_owners.first.owner).to eq "XOuN81q-MeEUVrsiZeK1lQ" }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Yt::Configuration do
|
4
|
+
subject(:config) { Yt::Configuration.new }
|
5
|
+
|
6
|
+
describe '#client_id' do
|
7
|
+
context 'without an environment variable YT_CLIENT_ID' do
|
8
|
+
before { ENV['YT_CLIENT_ID'] = nil }
|
9
|
+
it {expect(config.client_id).to be_nil }
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'given an environment variable YT_CLIENT_ID' do
|
13
|
+
let(:client_id) { '1234567890.apps.googleusercontent.com' }
|
14
|
+
before { ENV['YT_CLIENT_ID'] = client_id}
|
15
|
+
it {expect(config.client_id).to eq client_id }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#client_secret' do
|
20
|
+
context 'without an environment variable YT_CLIENT_SECRET' do
|
21
|
+
before { ENV['YT_CLIENT_SECRET'] = nil }
|
22
|
+
it {expect(config.client_secret).to be_nil }
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'given an environment variable YT_CLIENT_SECRET' do
|
26
|
+
let(:client_secret) { '1234567890' }
|
27
|
+
before { ENV['YT_CLIENT_SECRET'] = client_secret}
|
28
|
+
it {expect(config.client_secret).to eq client_secret }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#api_key' do
|
33
|
+
context 'without an environment variable YT_API_KEY' do
|
34
|
+
before { ENV['YT_API_KEY'] = nil }
|
35
|
+
it {expect(config.api_key).to be_nil }
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'given an environment variable YT_API_KEY' do
|
39
|
+
let(:api_key) { '123456789012345678901234567890' }
|
40
|
+
before { ENV['YT_API_KEY'] = api_key}
|
41
|
+
it {expect(config.api_key).to eq api_key }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
require 'yt/models/account'
|
4
4
|
|
5
5
|
describe Yt::Account, :device_app do
|
6
|
-
describe 'can create playlists' do
|
6
|
+
describe 'can create playlists', rate_limited: true do
|
7
7
|
let(:params) { {title: 'Test Yt playlist', privacy_status: 'unlisted'} }
|
8
8
|
before { @playlist = $account.create_playlist params }
|
9
9
|
it { expect(@playlist).to be_a Yt::Playlist }
|
@@ -26,11 +26,6 @@ describe Yt::Account, :device_app do
|
|
26
26
|
uploads = related_playlists.select{|p| p.title.starts_with? 'Uploads'}
|
27
27
|
expect(uploads).not_to be_empty
|
28
28
|
end
|
29
|
-
|
30
|
-
specify 'includes private playlists (such as History)' do
|
31
|
-
history = related_playlists.select{|p| p.title == 'History'}
|
32
|
-
expect(history).not_to be_empty
|
33
|
-
end
|
34
29
|
end
|
35
30
|
|
36
31
|
describe '.videos' do
|
@@ -180,7 +180,7 @@ describe Yt::Channel, :device_app do
|
|
180
180
|
expect(channel.subscriptions.size).to be
|
181
181
|
end
|
182
182
|
|
183
|
-
describe 'playlists can be deleted' do
|
183
|
+
describe 'playlists can be deleted', rate_limited: true do
|
184
184
|
let(:title) { "Yt Test Delete All Playlists #{rand}" }
|
185
185
|
before { $account.create_playlist params }
|
186
186
|
|
@@ -5,7 +5,7 @@ describe Yt::PlaylistItem, :device_app do
|
|
5
5
|
subject(:item) { Yt::PlaylistItem.new id: id, auth: $account }
|
6
6
|
|
7
7
|
context 'given an existing playlist item' do
|
8
|
-
let(:id) { '
|
8
|
+
let(:id) { 'UExiai1JRGU2Zzh2c0FQT0RFci1xRUZjRERvWHhqRzhEVC41MjE1MkI0OTQ2QzJGNzNG' }
|
9
9
|
|
10
10
|
it 'returns valid metadata' do
|
11
11
|
expect(item.title).to be_a String
|
@@ -28,7 +28,7 @@ describe Yt::PlaylistItem, :device_app do
|
|
28
28
|
it { expect{item.snippet}.to raise_error Yt::Errors::RequestError }
|
29
29
|
end
|
30
30
|
|
31
|
-
context 'given one of my own playlist items that I want to update' do
|
31
|
+
context 'given one of my own playlist items that I want to update', rate_limited: true do
|
32
32
|
before(:all) do
|
33
33
|
@my_playlist = $account.create_playlist title: "Yt Test Update Playlist Item #{rand}"
|
34
34
|
@my_playlist.add_video '9bZkp7q19f0'
|
@@ -7,7 +7,7 @@ describe Yt::Playlist, :device_app do
|
|
7
7
|
subject(:playlist) { Yt::Playlist.new id: id, auth: $account }
|
8
8
|
|
9
9
|
context 'given an existing playlist' do
|
10
|
-
let(:id) { '
|
10
|
+
let(:id) { 'PLpjK416fmKwQlQ0KvTWFmXZZa3d4IO2ro' } # from YouTube Creators
|
11
11
|
|
12
12
|
it 'returns valid metadata' do
|
13
13
|
expect(playlist.title).to be_a String
|
@@ -56,7 +56,7 @@ describe Yt::Playlist, :device_app do
|
|
56
56
|
end
|
57
57
|
|
58
58
|
context 'given someone else’s playlist' do
|
59
|
-
let(:id) { '
|
59
|
+
let(:id) { 'PLpjK416fmKwQlQ0KvTWFmXZZa3d4IO2ro' } # from YouTube Creators
|
60
60
|
let(:video_id) { '9bZkp7q19f0' }
|
61
61
|
|
62
62
|
it { expect{playlist.delete}.to fail.with 'playlistForbidden' }
|
@@ -65,14 +65,14 @@ describe Yt::Playlist, :device_app do
|
|
65
65
|
it { expect{playlist.delete_playlist_items}.to raise_error Yt::Errors::RequestError }
|
66
66
|
end
|
67
67
|
|
68
|
-
context 'given one of my own playlists that I want to delete' do
|
68
|
+
context 'given one of my own playlists that I want to delete', rate_limited: true do
|
69
69
|
before(:all) { @my_playlist = $account.create_playlist title: "Yt Test Delete Playlist #{rand}" }
|
70
70
|
let(:id) { @my_playlist.id }
|
71
71
|
|
72
72
|
it { expect(playlist.delete).to be true }
|
73
73
|
end
|
74
74
|
|
75
|
-
context 'given one of my own playlists that I want to update' do
|
75
|
+
context 'given one of my own playlists that I want to update', rate_limited: true do
|
76
76
|
before(:all) { @my_playlist = $account.create_playlist title: "Yt Test Update Playlist #{rand}" }
|
77
77
|
after(:all) { @my_playlist.delete }
|
78
78
|
let(:id) { @my_playlist.id }
|
@@ -276,7 +276,7 @@ describe Yt::Video, :device_app do
|
|
276
276
|
end
|
277
277
|
end
|
278
278
|
|
279
|
-
it 'returns valid reports for video-related metrics' do
|
279
|
+
it 'returns valid reports for video-related metrics', extended_permissions: true do
|
280
280
|
# Some reports are only available to Content Owners.
|
281
281
|
# See content owner test for more details about what the methods return.
|
282
282
|
expect{video.views}.not_to raise_error
|
@@ -327,7 +327,7 @@ describe Yt::Video, :device_app do
|
|
327
327
|
context 'passing the parameter in underscore syntax' do
|
328
328
|
let(:attrs) { {publish_at: new_scheduled_at} }
|
329
329
|
|
330
|
-
specify 'only updates the timestamp to publish the video' do
|
330
|
+
specify 'only updates the timestamp to publish the video', flaky: true do
|
331
331
|
expect(video.update attrs).to be true
|
332
332
|
expect(video.privacy_status).to eq old_privacy_status
|
333
333
|
expect(video.title).to eq old_title
|
@@ -369,13 +369,13 @@ describe Yt::Video, :device_app do
|
|
369
369
|
let(:id) { $account.videos.where(order: 'viewCount').first.id }
|
370
370
|
let(:update) { video.upload_thumbnail path_or_url }
|
371
371
|
|
372
|
-
context 'given the path to a local JPG image file' do
|
372
|
+
context 'given the path to a local JPG image file', extended_permissions: true do
|
373
373
|
let(:path_or_url) { File.expand_path '../thumbnail.jpg', __FILE__ }
|
374
374
|
|
375
375
|
it { expect{update}.not_to raise_error }
|
376
376
|
end
|
377
377
|
|
378
|
-
context 'given the path to a remote PNG image file' do
|
378
|
+
context 'given the path to a remote PNG image file', extended_permissions: true do
|
379
379
|
let(:path_or_url) { 'https://bit.ly/yt_thumbnail' }
|
380
380
|
|
381
381
|
it { expect{update}.not_to raise_error }
|
@@ -396,7 +396,7 @@ describe Yt::Video, :device_app do
|
|
396
396
|
# @see https://developers.google.com/youtube/v3/docs/videos#fileDetails
|
397
397
|
# @see https://developers.google.com/youtube/v3/docs/videos#processingDetails.fileDetailsAvailability
|
398
398
|
context 'given one of my own videos' do
|
399
|
-
let(:id) {
|
399
|
+
let(:id) { $account.videos.first.id }
|
400
400
|
|
401
401
|
it 'returns valid file details' do
|
402
402
|
expect(video.file_name).to be_a String
|
@@ -4,16 +4,27 @@ require 'yt/models/content_owner'
|
|
4
4
|
describe Yt::Asset, :partner do
|
5
5
|
describe '.ownership' do
|
6
6
|
let(:asset) { Yt::Asset.new id: asset_id, auth: $content_owner }
|
7
|
+
|
7
8
|
describe 'given an asset administered by the content owner' do
|
8
9
|
let(:asset_id) { ENV['YT_TEST_PARTNER_ASSET_ID'] }
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
describe 'when performing an update' do
|
12
|
+
specify 'the ownership can be obtained' do
|
13
|
+
expect(asset.ownership).to be_a Yt::Ownership
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'the asset can be updated' do
|
17
|
+
let(:attrs) { {metadata_mine: {notes: 'Yt notes'}} }
|
18
|
+
it { expect(asset.update attrs).to be true }
|
19
|
+
end
|
12
20
|
end
|
13
21
|
|
14
|
-
describe '
|
15
|
-
let(:
|
16
|
-
|
22
|
+
describe 'when performing a get' do
|
23
|
+
let(:asset_with_metadata_mine) { Yt::Asset.new id: asset_id, auth: $content_owner, params: {fetch_metadata: 'mine'} }
|
24
|
+
|
25
|
+
specify 'the metadata mine can be obtained' do
|
26
|
+
expect(asset_with_metadata_mine.get.metadata_mine.custom_id).to be_a String
|
27
|
+
end
|
17
28
|
end
|
18
29
|
end
|
19
30
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yt/models/content_owner'
|
3
|
+
|
4
|
+
describe Yt::Claim, :partner do
|
5
|
+
describe '.ownership' do
|
6
|
+
let(:claim) { Yt::Claim.new id: claim_id, auth: $content_owner }
|
7
|
+
|
8
|
+
describe 'given a claim administered by the content owner' do
|
9
|
+
let(:claim_id) { ENV['YT_TEST_PARTNER_CLAIM_ID'] }
|
10
|
+
|
11
|
+
describe 'the claim can be updated' do
|
12
|
+
let(:attrs) { {block_outside_ownership: true} }
|
13
|
+
it { expect(claim.update attrs).to be true }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'yt/models/content_owner'
|
3
|
+
require 'yt/models/match_policy'
|
3
4
|
|
4
5
|
describe Yt::ContentOwner, :partner do
|
5
6
|
describe '.partnered_channels' do
|
@@ -264,6 +265,26 @@ describe Yt::ContentOwner, :partner do
|
|
264
265
|
it { expect(reference).not_to be }
|
265
266
|
end
|
266
267
|
end
|
268
|
+
|
269
|
+
describe '.upload_reference_file' do
|
270
|
+
let(:asset) { Yt::Asset.new id: ENV['YT_TEST_PARTNER_ASSET_ID'], auth: $content_owner }
|
271
|
+
let(:match_policy) { Yt::MatchPolicy.new asset_id: ENV['YT_TEST_PARTNER_ASSET_ID'], auth: $content_owner }
|
272
|
+
|
273
|
+
let(:upload_params) { {asset_id: asset.id, content_type: 'video'} }
|
274
|
+
let(:reference) { $content_owner.upload_reference_file path_or_url, upload_params }
|
275
|
+
after { reference.delete }
|
276
|
+
|
277
|
+
before do
|
278
|
+
asset.ownership.update(assetId: asset.id) && asset.ownership.obtain!
|
279
|
+
match_policy.update policy_id: ENV['YT_TEST_PARTNER_POLICY_ID']
|
280
|
+
end
|
281
|
+
|
282
|
+
context 'given the URL of a remote video file' do
|
283
|
+
let(:path_or_url) { ENV['YT_REMOTE_VIDEO_URL'] }
|
284
|
+
|
285
|
+
it { expect(reference).to be_a Yt::Reference }
|
286
|
+
end
|
287
|
+
end
|
267
288
|
end
|
268
289
|
|
269
290
|
describe '.policies' do
|
@@ -305,16 +326,6 @@ describe Yt::ContentOwner, :partner do
|
|
305
326
|
end
|
306
327
|
end
|
307
328
|
|
308
|
-
describe '.bulk_report_jobs' do
|
309
|
-
describe 'given the content owner has bulk report jobs' do
|
310
|
-
let(:job) { $content_owner.bulk_report_jobs.first }
|
311
|
-
|
312
|
-
it 'returns valid job' do
|
313
|
-
expect(job.id).to be_a String
|
314
|
-
expect(job.report_type_id).to be_a String
|
315
|
-
end
|
316
|
-
end
|
317
|
-
end
|
318
329
|
# @note: The following test works, but YouTube API endpoint to mark
|
319
330
|
# an asset as 'invalid' (soft-delete) does not work, and apparently
|
320
331
|
# there is no way to update the status of a asset.
|
@@ -326,4 +337,34 @@ describe Yt::ContentOwner, :partner do
|
|
326
337
|
# after { @asset.delete } # This does not seem to work
|
327
338
|
# it { expect(@asset).to be_a Yt::Asset }
|
328
339
|
# end
|
340
|
+
|
341
|
+
describe '.bulk_report_jobs' do
|
342
|
+
describe 'given the content owner has bulk report jobs' do
|
343
|
+
let(:job) { $content_owner.bulk_report_jobs.first }
|
344
|
+
|
345
|
+
it 'returns valid job' do
|
346
|
+
expect(job.id).to be_a String
|
347
|
+
expect(job.report_type_id).to be_a String
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
describe '.content_owners' do
|
353
|
+
describe '.where(id: content_owner_ids)' do
|
354
|
+
let(:content_owner_a) { $content_owner.content_owners.where(id: content_owner_ids).first }
|
355
|
+
|
356
|
+
context 'given valid content owner names' do
|
357
|
+
let(:content_owner_ids) { 'a8MUrfnFEzBX3uLQepd5mg,GIfKLveZoYetfSFgvG2VtQ' }
|
358
|
+
|
359
|
+
it 'returns valid content owner' do
|
360
|
+
expect(content_owner_a.display_name).to be_a String
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
context 'given an unknown content owner ID' do
|
365
|
+
let(:content_owner_ids) { '--not-a-valid-owner-id--' }
|
366
|
+
it { expect(content_owner_a).not_to be }
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
329
370
|
end
|
@@ -5,7 +5,7 @@ describe Yt::Channel, :server_app do
|
|
5
5
|
subject(:channel) { Yt::Channel.new attrs }
|
6
6
|
|
7
7
|
context 'given an existing channel ID' do
|
8
|
-
let(:attrs) { {id: '
|
8
|
+
let(:attrs) { {id: 'UCAmh1DexLGcMtDlzMCIxo4w'} }
|
9
9
|
|
10
10
|
it 'returns valid snippet data' do
|
11
11
|
expect(channel.snippet).to be_a Yt::Snippet
|
@@ -29,7 +29,7 @@ describe Yt::Channel, :server_app do
|
|
29
29
|
end
|
30
30
|
|
31
31
|
context 'with a hidden list of subscriptions' do
|
32
|
-
let(:attrs) { {id: '
|
32
|
+
let(:attrs) { {id: 'UCZDZGN_73I019o6UYD2-4bg'} }
|
33
33
|
it { expect{channel.subscribed_channels.size}.to raise_error Yt::Errors::Forbidden }
|
34
34
|
end
|
35
35
|
end
|
@@ -51,4 +51,4 @@ describe Yt::Channel, :server_app do
|
|
51
51
|
it { expect(channel.videos.size).to be_zero }
|
52
52
|
end
|
53
53
|
end
|
54
|
-
end
|
54
|
+
end
|
@@ -6,11 +6,11 @@ describe Yt::CommentThread, :server_app do
|
|
6
6
|
subject(:comment_thread) { Yt::CommentThread.new attrs }
|
7
7
|
|
8
8
|
context 'given an existing comment thread ID about a channel' do
|
9
|
-
let(:attrs) { {id: '
|
9
|
+
let(:attrs) { {id: 'UgzzJVW75s5KrSaf0Ah4AaABAg'} }
|
10
10
|
|
11
11
|
it { expect(comment_thread.video_id).to be_nil }
|
12
12
|
it { expect(comment_thread.total_reply_count).to be_an Integer }
|
13
|
-
it { expect(comment_thread.can_reply?).to be
|
13
|
+
it { expect(comment_thread.can_reply?).to be true }
|
14
14
|
it { expect(comment_thread).to be_public }
|
15
15
|
|
16
16
|
it { expect(comment_thread.top_level_comment).to be_a Yt::Comment }
|
@@ -5,7 +5,7 @@ describe Yt::PlaylistItem, :server_app do
|
|
5
5
|
subject(:item) { Yt::PlaylistItem.new id: id }
|
6
6
|
|
7
7
|
context 'given an existing playlist item' do
|
8
|
-
let(:id) { '
|
8
|
+
let(:id) { 'UExiai1JRGU2Zzh2c0FQT0RFci1xRUZjRERvWHhqRzhEVC41MjE1MkI0OTQ2QzJGNzNG' }
|
9
9
|
|
10
10
|
it 'returns valid snippet data' do
|
11
11
|
expect(item.snippet).to be_a Yt::Snippet
|
@@ -27,4 +27,4 @@ describe Yt::PlaylistItem, :server_app do
|
|
27
27
|
|
28
28
|
it { expect{item.snippet}.to raise_error Yt::Errors::RequestError }
|
29
29
|
end
|
30
|
-
end
|
30
|
+
end
|
@@ -5,7 +5,7 @@ describe Yt::Playlist, :server_app do
|
|
5
5
|
subject(:playlist) { Yt::Playlist.new attrs }
|
6
6
|
|
7
7
|
context 'given an existing playlist ID' do
|
8
|
-
let(:attrs) { {id: '
|
8
|
+
let(:attrs) { {id: 'PLpjK416fmKwQ6Ene4GKRLICznoE1QFyt4'} }
|
9
9
|
|
10
10
|
it 'returns valid snippet data' do
|
11
11
|
expect(playlist.snippet).to be_a Yt::Snippet
|
@@ -30,4 +30,4 @@ describe Yt::Playlist, :server_app do
|
|
30
30
|
it { expect{playlist.snippet}.to raise_error Yt::Errors::NoItems }
|
31
31
|
it { expect{playlist.status}.to raise_error Yt::Errors::NoItems }
|
32
32
|
end
|
33
|
-
end
|
33
|
+
end
|
data/yt.gemspec
CHANGED
@@ -22,7 +22,6 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.require_paths = ["lib"]
|
23
23
|
|
24
24
|
spec.add_dependency 'activesupport' # '3 (Ruby 1.9) or 4 (Ruby 2)'
|
25
|
-
spec.add_dependency 'yt-support', '>= 0.1'
|
26
25
|
|
27
26
|
# For development / Code coverage / Documentation
|
28
27
|
spec.add_development_dependency 'bundler' #, '~> 1.0'
|
@@ -30,4 +29,5 @@ Gem::Specification.new do |spec|
|
|
30
29
|
spec.add_development_dependency 'rake' #, '~> 10.0'
|
31
30
|
spec.add_development_dependency 'yard' #, '~> 0.8.0'
|
32
31
|
spec.add_development_dependency 'coveralls' #, '~> 0.7.0'
|
32
|
+
spec.add_development_dependency 'pry'
|
33
33
|
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.32.
|
4
|
+
version: 0.32.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Claudio Baccigalupo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-06-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -25,21 +25,21 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0
|
34
|
-
type: :
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: yard
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -81,7 +81,7 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: coveralls
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
@@ -95,7 +95,7 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: pry
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
@@ -133,6 +133,7 @@ files:
|
|
133
133
|
- lib/yt/actions/base.rb
|
134
134
|
- lib/yt/actions/delete.rb
|
135
135
|
- lib/yt/actions/delete_all.rb
|
136
|
+
- lib/yt/actions/get.rb
|
136
137
|
- lib/yt/actions/insert.rb
|
137
138
|
- lib/yt/actions/list.rb
|
138
139
|
- lib/yt/actions/modify.rb
|
@@ -185,6 +186,7 @@ files:
|
|
185
186
|
- lib/yt/collections/video_categories.rb
|
186
187
|
- lib/yt/collections/video_groups.rb
|
187
188
|
- lib/yt/collections/videos.rb
|
189
|
+
- lib/yt/config.rb
|
188
190
|
- lib/yt/constants/geography.rb
|
189
191
|
- lib/yt/errors/forbidden.rb
|
190
192
|
- lib/yt/errors/missing_auth.rb
|
@@ -208,6 +210,7 @@ files:
|
|
208
210
|
- lib/yt/models/claim_history.rb
|
209
211
|
- lib/yt/models/comment.rb
|
210
212
|
- lib/yt/models/comment_thread.rb
|
213
|
+
- lib/yt/models/configuration.rb
|
211
214
|
- lib/yt/models/content_detail.rb
|
212
215
|
- lib/yt/models/content_owner.rb
|
213
216
|
- lib/yt/models/content_owner_detail.rb
|
@@ -268,6 +271,7 @@ files:
|
|
268
271
|
- spec/models/claim_spec.rb
|
269
272
|
- spec/models/comment_spec.rb
|
270
273
|
- spec/models/comment_thread_spec.rb
|
274
|
+
- spec/models/configuration_spec.rb
|
271
275
|
- spec/models/content_detail_spec.rb
|
272
276
|
- spec/models/content_owner_detail_spec.rb
|
273
277
|
- spec/models/file_detail_spec.rb
|
@@ -305,6 +309,7 @@ files:
|
|
305
309
|
- spec/requests/as_content_owner/bulk_report_job_spec.rb
|
306
310
|
- spec/requests/as_content_owner/channel_spec.rb
|
307
311
|
- spec/requests/as_content_owner/claim_history_spec.rb
|
312
|
+
- spec/requests/as_content_owner/claim_spec.rb
|
308
313
|
- spec/requests/as_content_owner/content_owner_spec.rb
|
309
314
|
- spec/requests/as_content_owner/match_policy_spec.rb
|
310
315
|
- spec/requests/as_content_owner/ownership_spec.rb
|
@@ -376,6 +381,7 @@ test_files:
|
|
376
381
|
- spec/models/claim_spec.rb
|
377
382
|
- spec/models/comment_spec.rb
|
378
383
|
- spec/models/comment_thread_spec.rb
|
384
|
+
- spec/models/configuration_spec.rb
|
379
385
|
- spec/models/content_detail_spec.rb
|
380
386
|
- spec/models/content_owner_detail_spec.rb
|
381
387
|
- spec/models/file_detail_spec.rb
|
@@ -413,6 +419,7 @@ test_files:
|
|
413
419
|
- spec/requests/as_content_owner/bulk_report_job_spec.rb
|
414
420
|
- spec/requests/as_content_owner/channel_spec.rb
|
415
421
|
- spec/requests/as_content_owner/claim_history_spec.rb
|
422
|
+
- spec/requests/as_content_owner/claim_spec.rb
|
416
423
|
- spec/requests/as_content_owner/content_owner_spec.rb
|
417
424
|
- spec/requests/as_content_owner/match_policy_spec.rb
|
418
425
|
- spec/requests/as_content_owner/ownership_spec.rb
|