yt 0.32.3 → 0.32.4
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/.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
|
[](https://travis-ci.org/Fullscreen/yt)
|
9
9
|
[](https://coveralls.io/r/Fullscreen/yt)
|
10
10
|
[](https://gemnasium.com/Fullscreen/yt)
|
11
|
-
[](https://codeclimate.com/github/Fullscreen/yt)
|
12
12
|
[](http://www.rubydoc.info/gems/yt/frames)
|
13
13
|
[](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
|