yt 0.9.1 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/HISTORY.md +1 -0
- data/README.md +2 -1
- data/lib/yt/collections/policies.rb +37 -0
- data/lib/yt/models/content_owner.rb +4 -0
- data/lib/yt/models/policy.rb +44 -0
- data/lib/yt/models/policy_rule.rb +133 -0
- data/lib/yt/version.rb +1 -1
- data/spec/models/policy_rule_spec.rb +63 -0
- data/spec/models/policy_spec.rb +41 -0
- data/spec/requests/as_content_owner/content_owner_spec.rb +26 -0
- metadata +8 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5fe9ccf19b87eba1932a8381ec62e4c7e18bb997
|
4
|
+
data.tar.gz: bcc2aefb8c393bac857f94157267d66ab96301ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3f0ddfe5fcf4c20b72a77478efba519a33db0bf9565b52a47daaa6f768fe68015d3436d4535fdd759443462903c5ec788750ef5595317672c7492d903c25db2
|
7
|
+
data.tar.gz: 0dcc83e353408a679b723516e3801eafd2b1710ee25584040a9d9c359fa8dadac24b44949779b6b4f042a09e3ebd633b737b3c64815bf826ed571bdb0f0169e2
|
data/Gemfile.lock
CHANGED
data/HISTORY.md
CHANGED
data/README.md
CHANGED
@@ -41,7 +41,7 @@ To install on your system, run
|
|
41
41
|
|
42
42
|
To use inside a bundled Ruby project, add this line to the Gemfile:
|
43
43
|
|
44
|
-
gem 'yt', '~> 0.9.
|
44
|
+
gem 'yt', '~> 0.9.2'
|
45
45
|
|
46
46
|
Since the gem follows [Semantic Versioning](http://semver.org),
|
47
47
|
indicating the full version in your Gemfile (~> *major*.*minor*.*patch*)
|
@@ -107,6 +107,7 @@ content_owner.claims.where(q: 'Fullscreen').count #=> 24
|
|
107
107
|
content_owner.claims.first #=> #<Yt::Models::Claim @id=...>
|
108
108
|
|
109
109
|
content_owner.references.where(asset_id: "ABCDEFG").first => #<Yt::Models::Reference @id=...>
|
110
|
+
content_owner.policies.first => #<Yt::Models::Policy @id=...>
|
110
111
|
```
|
111
112
|
|
112
113
|
*All the above methods require authentication (see below).*
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'yt/collections/base'
|
2
|
+
require 'yt/models/policy'
|
3
|
+
|
4
|
+
module Yt
|
5
|
+
module Collections
|
6
|
+
# Provides methods to interact with a collection of Content ID policies.
|
7
|
+
#
|
8
|
+
# Resources with policies are: {Yt::Models::ContentOwner content owners}.
|
9
|
+
class Policies < Base
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def new_item(data)
|
14
|
+
Yt::Policy.new data: data
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Hash] the parameters to submit to YouTube to list policies
|
18
|
+
# saved by the content owner.
|
19
|
+
# @see https://developers.google.com/youtube/partner/docs/v1/policies/list
|
20
|
+
def list_params
|
21
|
+
|
22
|
+
super.tap do |params|
|
23
|
+
params[:params] = policies_params
|
24
|
+
params[:path] = '/youtube/partner/v1/policies'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def policies_params
|
29
|
+
{onBehalfOfContentOwner: @parent.owner_name}.tap do |params|
|
30
|
+
(@extra_params ||= {}).each do |key, value|
|
31
|
+
params[key.to_s.camelize :lower] = value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -19,6 +19,10 @@ module Yt
|
|
19
19
|
# @return [Yt::Collection::References] the references administered by the content owner.
|
20
20
|
has_many :references
|
21
21
|
|
22
|
+
# @!attribute [r] policies
|
23
|
+
# @return [Yt::Collection::Policies] the policies saved by the content owner.
|
24
|
+
has_many :policies
|
25
|
+
|
22
26
|
def initialize(options = {})
|
23
27
|
super options
|
24
28
|
@owner_name = options[:owner_name]
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'yt/models/base'
|
2
|
+
require 'yt/models/policy_rule'
|
3
|
+
|
4
|
+
module Yt
|
5
|
+
module Models
|
6
|
+
# Provides methods to interact with YouTube ContentID policies.
|
7
|
+
# A policy resource specifies rules that define a particular usage or
|
8
|
+
# match policy that a partner can associate with an asset or claim.
|
9
|
+
# @see https://developers.google.com/youtube/partner/docs/v1/policies
|
10
|
+
class Policy < Base
|
11
|
+
def initialize(options = {})
|
12
|
+
@data = options[:data]
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [String] the ID that YouTube assigns and uses to uniquely
|
16
|
+
# identify the policy.
|
17
|
+
def id
|
18
|
+
@id ||= @data['id']
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [String] the policy’s name.
|
22
|
+
def name
|
23
|
+
@name ||= @data['name']
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [String] the policy’s description.
|
27
|
+
def description
|
28
|
+
@name ||= @data['description']
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [String] the time the policy was updated.
|
32
|
+
def time_updated
|
33
|
+
@time_updated ||= Time.parse @data['timeUpdated']
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [Array<PolicyRule>] a list of rules that specify the action
|
37
|
+
# that YouTube should take and may optionally specify the conditions
|
38
|
+
# under which that action is enforced.
|
39
|
+
def rules
|
40
|
+
@rules ||= @data['rules'].map{|rule| PolicyRule.new data: rule}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'yt/models/base'
|
2
|
+
|
3
|
+
module Yt
|
4
|
+
module Models
|
5
|
+
# Provides methods to interact with YouTube ContentID policy rules.
|
6
|
+
# Rules that specify the action that YouTube should take and may optionally
|
7
|
+
# specify the conditions under which that action is enforced.
|
8
|
+
# @see https://developers.google.com/youtube/partner/docs/v1/policies
|
9
|
+
class PolicyRule
|
10
|
+
def initialize(options = {})
|
11
|
+
@data = options[:data]
|
12
|
+
end
|
13
|
+
|
14
|
+
ACTIONS = %q(block monetize takedown track)
|
15
|
+
|
16
|
+
# Return the policy that YouTube should enforce if the rule’s conditions
|
17
|
+
# are all valid for an asset or for an attempt to view that asset on
|
18
|
+
# YouTube. Valid values for this property are: block, monetize, takedown,
|
19
|
+
# track.
|
20
|
+
# @return [String] the policy that YouTube should enforce.
|
21
|
+
def action
|
22
|
+
@action ||= @data['action']
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Array] A list of additional actions that YouTube should take
|
26
|
+
# if the conditions in the rule are met. Valid values for this property
|
27
|
+
# are: review.
|
28
|
+
def subaction
|
29
|
+
@subaction ||= @data['subaction']
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return the list of territories where the policy applies.
|
33
|
+
# Each territory is an ISO 3166 two-letter country code.
|
34
|
+
# YouTube determines whether the condition is satisfied based on the
|
35
|
+
# user’s location.
|
36
|
+
# @return [Array<String>] the territories where the policy applies.
|
37
|
+
# @example (with 'block' action) only block a video for U.S. users:
|
38
|
+
# included_territories #=> ['us']
|
39
|
+
def included_territories
|
40
|
+
territories_type == 'include' ? territories : []
|
41
|
+
end
|
42
|
+
|
43
|
+
# Return the list of territories where the policy does not apply.
|
44
|
+
# Each territory is an ISO 3166 two-letter country code.
|
45
|
+
# YouTube determines whether the condition is satisfied based on the
|
46
|
+
# user’s location.
|
47
|
+
# @return [Array<String>] the territories where the policy does not apply.
|
48
|
+
# @example (with 'block' action) only allow U.S. users to view a video:
|
49
|
+
# excluded_territories #=> ['us']
|
50
|
+
def excluded_territories
|
51
|
+
territories_type == 'exclude' ? territories : []
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [Array<Hash<Symbol, Float>>] the intervals of time the user-
|
55
|
+
# or partner-uploaded content needs to match a reference file for the
|
56
|
+
# rule to apply. :low is the minimum (inclusive) allowed value and
|
57
|
+
# :high is the maximum (inclusive) allowed value for the rule to apply.
|
58
|
+
# @example videos that match the reference for 20 to 30 seconds:
|
59
|
+
# match_duration #= [{low: 20.0, high: 30.0}]
|
60
|
+
def match_duration
|
61
|
+
@match_duration ||= match_duration_list.map{|r| low_and_high r}
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [Array<Hash<Symbol, Float>>] the intervals of percentages the
|
65
|
+
# user- or partner-uploaded content needs to match a reference file for
|
66
|
+
# the rule to apply. :low is the minimum (inclusive) allowed value and
|
67
|
+
# :high is the maximum (inclusive) allowed value for the rule to apply.
|
68
|
+
# @example videos that match the reference for 40%~50% of their duration:
|
69
|
+
# match_percent #= [{low: 40.0, high: 50.0}]
|
70
|
+
def match_percent
|
71
|
+
@match_percent ||= match_percent_list.map{|r| low_and_high r}
|
72
|
+
end
|
73
|
+
|
74
|
+
# @return [Array<Hash<Symbol, Float>>] the intervals of duration that the
|
75
|
+
# reference must have for the rule to apply. :low is the minimum
|
76
|
+
# (inclusive) allowed value, :high is the maximum (inclusive) allowed
|
77
|
+
# value for the rule to apply.
|
78
|
+
# @example references that are between 20 and 30 seconds:
|
79
|
+
# reference_duration #= [{low: 20.0, high: 30.0}]
|
80
|
+
def reference_duration
|
81
|
+
@reference_duration ||= reference_duration_list.map{|r| low_and_high r}
|
82
|
+
end
|
83
|
+
|
84
|
+
# @return [Array<Hash<Symbol, Float>>] the intervals of percentages the
|
85
|
+
# reference file needs to match the user- or partner-uploaded content
|
86
|
+
# for the rule to apply. :low is the minimum (inclusive) allowed value,
|
87
|
+
# :high is the maximum (inclusive) allowed value for the rule to apply.
|
88
|
+
# @example videos that match either 0%~10% or 40%~50% of a reference:
|
89
|
+
# reference_percent #= [{low: 0.0, high: 10.0}, {low: 40.0, high: 50.0}]
|
90
|
+
def reference_percent
|
91
|
+
@reference_percent ||= reference_percent_list.map{|r| low_and_high r}
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def conditions
|
97
|
+
@conditions ||= @data.fetch 'conditions', {}
|
98
|
+
end
|
99
|
+
|
100
|
+
def territories_object
|
101
|
+
@territories_object ||= conditions.fetch 'requiredTerritories', {}
|
102
|
+
end
|
103
|
+
|
104
|
+
def territories_type
|
105
|
+
@territories_type ||= territories_object['type']
|
106
|
+
end
|
107
|
+
|
108
|
+
def territories
|
109
|
+
@territories ||= territories_object['territories']
|
110
|
+
end
|
111
|
+
|
112
|
+
def match_duration_list
|
113
|
+
@match_duration_list ||= conditions.fetch 'matchDuration', []
|
114
|
+
end
|
115
|
+
|
116
|
+
def match_percent_list
|
117
|
+
@match_percent_list ||= conditions.fetch 'matchPercent', []
|
118
|
+
end
|
119
|
+
|
120
|
+
def reference_duration_list
|
121
|
+
@reference_duration_list ||= conditions.fetch 'referenceDuration', []
|
122
|
+
end
|
123
|
+
|
124
|
+
def reference_percent_list
|
125
|
+
@reference_percent_list ||= conditions.fetch 'referencePercent', []
|
126
|
+
end
|
127
|
+
|
128
|
+
def low_and_high(range)
|
129
|
+
{low: range['low'], high: range['high']}
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
data/lib/yt/version.rb
CHANGED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yt/models/policy_rule'
|
3
|
+
|
4
|
+
describe Yt::PolicyRule do
|
5
|
+
subject(:policy_rule) { Yt::PolicyRule.new data: data }
|
6
|
+
|
7
|
+
describe '#action' do
|
8
|
+
context 'given fetching a policy rule returns an action' do
|
9
|
+
let(:data) { {"action"=>"takedown"} }
|
10
|
+
it { expect(policy_rule.action).to eq 'takedown' }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#subaction' do
|
15
|
+
context 'given fetching a policy rule returns a subaction' do
|
16
|
+
let(:data) { {"subaction"=>"review"} }
|
17
|
+
it { expect(policy_rule.subaction).to eq 'review' }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#included_territories' do
|
22
|
+
context 'given fetching a policy rule returns included territories' do
|
23
|
+
let(:data) { {"conditions"=>{"requiredTerritories"=>{"type"=>"include", "territories"=>["US", "CA"]}}} }
|
24
|
+
let(:data) { {"conditions"=>{"requiredTerritories"=>{"type"=>"include", "territories"=>["US", "CA"]}}} }
|
25
|
+
it { expect(policy_rule.included_territories).to eq %w(US CA) }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#excluded_territories' do
|
30
|
+
context 'given fetching a policy rule returns excluded territories' do
|
31
|
+
let(:data) { {"conditions"=>{"requiredTerritories"=>{"type"=>"exclude", "territories"=>["US", "CA"]}}} }
|
32
|
+
it { expect(policy_rule.excluded_territories).to eq %w(US CA) }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#match_duration' do
|
37
|
+
context 'given fetching a policy rule returns a match duration list' do
|
38
|
+
let(:data) { {"conditions"=>{"matchDuration"=>[{"high"=>60.0}]}} }
|
39
|
+
it { expect(policy_rule.match_duration).to match_array [{low: nil, high: 60.0}] }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#match_percent' do
|
44
|
+
context 'given fetching a policy rule returns a match percent list' do
|
45
|
+
let(:data) { {"conditions"=>{"matchPercent"=>[{"high"=>60.0}]}} }
|
46
|
+
it { expect(policy_rule.match_percent).to match_array [{low: nil, high: 60.0}] }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#reference_duration' do
|
51
|
+
context 'given fetching a policy rule returns a reference duration list' do
|
52
|
+
let(:data) { {"conditions"=>{"referenceDuration"=>[{"low"=>60.0, "high"=>600.0}, {"low"=>20.0, "high"=>30.0}]}} }
|
53
|
+
it { expect(policy_rule.reference_duration).to match_array [{low: 60.0, high: 600.0}, {low: 20.0, high: 30.0}] }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#reference_percent' do
|
58
|
+
context 'given fetching a policy rule returns a reference percent list' do
|
59
|
+
let(:data) { {"conditions"=>{"referencePercent"=>[{"low"=>60.0, "high"=>600.0}, {"low"=>20.0, "high"=>30.0}]}} }
|
60
|
+
it { expect(policy_rule.reference_percent).to match_array [{low: 60.0, high: 600.0}, {low: 20.0, high: 30.0}] }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yt/models/policy'
|
3
|
+
|
4
|
+
describe Yt::Policy do
|
5
|
+
subject(:policy) { Yt::Policy.new data: data }
|
6
|
+
|
7
|
+
describe '#id' do
|
8
|
+
context 'given fetching a policy returns an id' do
|
9
|
+
let(:data) { {"id"=>"S123456789"} }
|
10
|
+
it { expect(policy.id).to eq 'S123456789' }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#name' do
|
15
|
+
context 'given fetching a policy returns a name' do
|
16
|
+
let(:data) { {"name"=>"Block in all countries"} }
|
17
|
+
it { expect(policy.name).to eq 'Block in all countries' }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#description' do
|
22
|
+
context 'given fetching a policy returns a description' do
|
23
|
+
let(:data) { {"description"=>"Block videos in every country"} }
|
24
|
+
it { expect(policy.description).to eq 'Block videos in every country' }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#time_updated' do
|
29
|
+
context 'given fetching a policy returns a timeUpdated' do
|
30
|
+
let(:data) { {"timeUpdated"=>"1970-01-16T20:33:03.675Z"} }
|
31
|
+
it { expect(policy.time_updated.year).to be 1970 }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#rules' do
|
36
|
+
context 'given fetching a policy returns rules' do
|
37
|
+
let(:data) { {"rules"=>[{"action"=>"track"},{"action"=>"track"}]} }
|
38
|
+
it { expect(policy.rules.size).to be 2 }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -113,4 +113,30 @@ describe Yt::ContentOwner, :partner do
|
|
113
113
|
end
|
114
114
|
end
|
115
115
|
end
|
116
|
+
|
117
|
+
describe '.policies' do
|
118
|
+
describe 'given the content owner has policies' do
|
119
|
+
let(:policy) { $content_owner.policies.first }
|
120
|
+
let(:rule) { policy.rules.first }
|
121
|
+
|
122
|
+
it 'returns valid metadata' do
|
123
|
+
expect(policy.id).to be_a String
|
124
|
+
expect(policy.name).to be_a String
|
125
|
+
expect(policy.time_updated).to be_a Time
|
126
|
+
expect(rule.action).to be_in Yt::PolicyRule::ACTIONS
|
127
|
+
expect(rule.included_territories).to be_an Array
|
128
|
+
expect(rule.excluded_territories).to be_an Array
|
129
|
+
expect(rule.match_duration).to be_an Array
|
130
|
+
expect(rule.match_percent).to be_an Array
|
131
|
+
expect(rule.reference_duration).to be_an Array
|
132
|
+
expect(rule.reference_percent).to be_an Array
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe '.where(id: policy_id) given an unknown policy ID' do
|
137
|
+
let(:policy) { $content_owner.policies.where(id: policy_id).first }
|
138
|
+
let(:policy_id) { '--not-a-matching-reference-id--' }
|
139
|
+
it { expect(policy).not_to be }
|
140
|
+
end
|
141
|
+
end
|
116
142
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Claudio Baccigalupo
|
@@ -140,6 +140,7 @@ files:
|
|
140
140
|
- lib/yt/collections/partnered_channels.rb
|
141
141
|
- lib/yt/collections/playlist_items.rb
|
142
142
|
- lib/yt/collections/playlists.rb
|
143
|
+
- lib/yt/collections/policies.rb
|
143
144
|
- lib/yt/collections/ratings.rb
|
144
145
|
- lib/yt/collections/references.rb
|
145
146
|
- lib/yt/collections/reports.rb
|
@@ -173,6 +174,8 @@ files:
|
|
173
174
|
- lib/yt/models/id.rb
|
174
175
|
- lib/yt/models/playlist.rb
|
175
176
|
- lib/yt/models/playlist_item.rb
|
177
|
+
- lib/yt/models/policy.rb
|
178
|
+
- lib/yt/models/policy_rule.rb
|
176
179
|
- lib/yt/models/rating.rb
|
177
180
|
- lib/yt/models/reference.rb
|
178
181
|
- lib/yt/models/request.rb
|
@@ -209,6 +212,8 @@ files:
|
|
209
212
|
- spec/models/description_spec.rb
|
210
213
|
- spec/models/playlist_item_spec.rb
|
211
214
|
- spec/models/playlist_spec.rb
|
215
|
+
- spec/models/policy_rule_spec.rb
|
216
|
+
- spec/models/policy_spec.rb
|
212
217
|
- spec/models/rating_spec.rb
|
213
218
|
- spec/models/reference_spec.rb
|
214
219
|
- spec/models/request_spec.rb
|
@@ -291,6 +296,8 @@ test_files:
|
|
291
296
|
- spec/models/description_spec.rb
|
292
297
|
- spec/models/playlist_item_spec.rb
|
293
298
|
- spec/models/playlist_spec.rb
|
299
|
+
- spec/models/policy_rule_spec.rb
|
300
|
+
- spec/models/policy_spec.rb
|
294
301
|
- spec/models/rating_spec.rb
|
295
302
|
- spec/models/reference_spec.rb
|
296
303
|
- spec/models/request_spec.rb
|