yt 0.11.1 → 0.11.2

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +2 -0
  4. data/CHANGELOG.md +31 -33
  5. data/README.md +94 -3
  6. data/lib/yt.rb +1 -0
  7. data/lib/yt/actions/base.rb +19 -0
  8. data/lib/yt/actions/insert.rb +2 -0
  9. data/lib/yt/actions/list.rb +0 -7
  10. data/lib/yt/actions/modify.rb +2 -0
  11. data/lib/yt/collections/assets.rb +32 -0
  12. data/lib/yt/collections/authentications.rb +1 -0
  13. data/lib/yt/collections/claims.rb +16 -1
  14. data/lib/yt/collections/ownerships.rb +34 -0
  15. data/lib/yt/collections/references.rb +2 -12
  16. data/lib/yt/collections/resources.rb +0 -10
  17. data/lib/yt/models/account.rb +1 -1
  18. data/lib/yt/models/advertising_options_set.rb +33 -0
  19. data/lib/yt/models/asset.rb +100 -0
  20. data/lib/yt/models/channel.rb +1 -1
  21. data/lib/yt/models/claim.rb +22 -0
  22. data/lib/yt/models/content_owner.rb +16 -4
  23. data/lib/yt/models/match_policy.rb +2 -12
  24. data/lib/yt/models/ownership.rb +70 -0
  25. data/lib/yt/models/reference.rb +1 -1
  26. data/lib/yt/models/request.rb +13 -2
  27. data/lib/yt/models/resource.rb +0 -10
  28. data/lib/yt/models/resumable_session.rb +1 -0
  29. data/lib/yt/models/right_owner.rb +69 -0
  30. data/lib/yt/version.rb +1 -1
  31. data/spec/models/asset_spec.rb +20 -0
  32. data/spec/models/ownership_spec.rb +59 -0
  33. data/spec/models/right_owner_spec.rb +71 -0
  34. data/spec/requests/as_content_owner/advertising_options_set_spec.rb +15 -0
  35. data/spec/requests/as_content_owner/asset_spec.rb +12 -0
  36. data/spec/requests/as_content_owner/content_owner_spec.rb +37 -2
  37. data/spec/requests/as_content_owner/ownership_spec.rb +19 -0
  38. metadata +21 -3
  39. data/Gemfile.lock +0 -69
@@ -9,8 +9,8 @@ module Yt
9
9
  class References < Base
10
10
  def insert(attributes = {})
11
11
  underscore_keys! attributes
12
- body = {contentType: attributes[:content_type] }
13
- params = {claimId: attributes[:claim_id], onBehalfOfContentOwner: @auth.owner_name}
12
+ body = {content_type: attributes[:content_type] }
13
+ params = {claim_id: attributes[:claim_id], on_behalf_of_content_owner: @auth.owner_name}
14
14
  do_insert(params: params, body: body)
15
15
  end
16
16
 
@@ -41,16 +41,6 @@ module Yt
41
41
  def references_params
42
42
  apply_where_params! on_behalf_of_content_owner: @parent.owner_name
43
43
  end
44
-
45
- # If we dropped support for ActiveSupport 3, then we could simply
46
- # invoke transform_keys!{|key| key.to_s.underscore.to_sym}
47
- def underscore_keys!(hash)
48
- hash.dup.each_key{|key| hash[underscore key] = hash.delete key}
49
- end
50
-
51
- def underscore(value)
52
- value.to_s.underscore.to_sym
53
- end
54
44
  end
55
45
  end
56
46
  end
@@ -59,12 +59,6 @@ module Yt
59
59
  (part[:keys] & attributes.keys).any?
60
60
  end
61
61
 
62
- # If we dropped support for ActiveSupport 3, then we could simply
63
- # invoke transform_keys!{|key| key.to_s.underscore.to_sym}
64
- def underscore_keys!(hash)
65
- hash.dup.each_key{|key| hash[underscore key] = hash.delete key}
66
- end
67
-
68
62
  # @return [Hash] the original hash with angle brackets characters in its
69
63
  # values replaced with similar Unicode characters accepted by Youtube.
70
64
  # @see https://support.google.com/youtube/answer/57404?hl=en
@@ -79,10 +73,6 @@ module Yt
79
73
  def camelize(value)
80
74
  value.to_s.camelize(:lower).to_sym
81
75
  end
82
-
83
- def underscore(value)
84
- value.to_s.underscore.to_sym
85
- end
86
76
  end
87
77
  end
88
78
  end
@@ -56,7 +56,7 @@ module Yt
56
56
  # Tells `has_many :videos` that account.videos should return all the
57
57
  # videos *owned by* the account (public, private, unlisted).
58
58
  def videos_params
59
- {forMine: true}
59
+ {for_mine: true}
60
60
  end
61
61
  end
62
62
  end
@@ -0,0 +1,33 @@
1
+ require 'yt/models/base'
2
+
3
+ module Yt
4
+ module Models
5
+ # Encapsulates advertising options of a video, such as the types of ads
6
+ # that can run during the video as well as the times when ads are allowed
7
+ # to run during the video.
8
+ # @see https://developers.google.com/youtube/partner/docs/v1/videoAdvertisingOptions#resource
9
+ class AdvertisingOptionsSet < Base
10
+ def initialize(options = {})
11
+ @auth = options[:auth]
12
+ @video_id = options[:video_id]
13
+ end
14
+
15
+ def update(attributes = {})
16
+ underscore_keys! attributes
17
+ do_patch body: attributes
18
+ true
19
+ end
20
+
21
+ private
22
+
23
+ # @see https://developers.google.com/youtube/partner/docs/v1/videoAdvertisingOptions/patch
24
+ def patch_params
25
+ super.tap do |params|
26
+ params[:expected_response] = Net::HTTPOK
27
+ params[:path] = "/youtube/partner/v1/videoAdvertisingOptions/#{@video_id}"
28
+ params[:params] = {on_behalf_of_content_owner: @auth.owner_name}
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,100 @@
1
+ require 'yt/models/base'
2
+
3
+ module Yt
4
+ module Models
5
+ # Provides methods to interact with YouTube ContentID assets.
6
+ # @see https://developers.google.com/youtube/partner/docs/v1/assets
7
+ class Asset < Base
8
+ attr_reader :auth
9
+
10
+ def initialize(options = {})
11
+ @data = options[:data]
12
+ @id = options[:id]
13
+ @auth = options[:auth]
14
+ end
15
+
16
+ # @!attribute [r] ownership
17
+ # @return [Yt::Models::Ownership] the asset’s ownership.
18
+ has_one :ownership
19
+ delegate :general_owners, :performance_owners, :synchronization_owners,
20
+ :mechanical_owners, to: :ownership
21
+
22
+ # Soft-deletes the asset.
23
+ # @note YouTube API does not provide a +delete+ method for the Asset
24
+ # resource, but only an +update+ method. Updating the +status+ of a
25
+ # Asset to "inactive" can be considered a soft-deletion.
26
+ # @note Despite what the documentation says, YouTube API never returns
27
+ # the status of an asset, so it’s impossible to update, although the
28
+ # documentation says this should be the case. If YouTube ever fixes
29
+ # the API, then the following code can be uncommented.
30
+ # @return [Boolean] whether the asset is inactive.
31
+ # def delete
32
+ # body = {id: id, status: :inactive}
33
+ # do_update(body: body) {|data| @data = data}
34
+ # inactive?
35
+ # end
36
+
37
+ # @return [String] the ID that YouTube assigns and uses to uniquely
38
+ # identify the asset.
39
+ def id
40
+ @id ||= @data['id']
41
+ end
42
+
43
+ # @return [String] the asset’s type. This value determines the metadata
44
+ # fields that you can set for the asset. In addition, certain API
45
+ # functions may only be supported for specific types of assets. For
46
+ # example, composition assets may have more complex ownership data than
47
+ # other types of assets.
48
+ # Valid values for this property are: art_track_video, composition,
49
+ # episode, general, movie, music_video, season, show, sound_recording,
50
+ # video_game, and web.
51
+ def type
52
+ @type ||= @data['type']
53
+ end
54
+
55
+ # Status
56
+
57
+ STATUSES = %q(active inactive pending)
58
+
59
+ # @return [String] the asset’s status. Valid values are: active,
60
+ # inactive, and pending.
61
+ # @note Despite what the documentation says, YouTube API never returns
62
+ # the status of an asset, so it’s impossible to update, although the
63
+ # documentation says this should be the case. If YouTube ever fixes
64
+ # the API, then the following code can be uncommented.
65
+ # def status
66
+ # @status ||= @data["status"]
67
+ # end
68
+ #
69
+ # # @return [Boolean] whether the asset is active.
70
+ # def active?
71
+ # status == 'active'
72
+ # end
73
+ #
74
+ # # @return [Boolean] whether the asset is inactive.
75
+ # def inactive?
76
+ # status == 'inactive'
77
+ # end
78
+ #
79
+ # # @return [Boolean] whether the asset is pending.
80
+ # def pending?
81
+ # status == 'pending'
82
+ # end
83
+
84
+ private
85
+
86
+ # @see https://developers.google.com/youtube/partner/docs/v1/assets/update
87
+ # @note Despite what the documentation says, YouTube API never returns
88
+ # the status of an asset, so it’s impossible to update, although the
89
+ # documentation says this should be the case. If YouTube ever fixes
90
+ # the API, then the following code can be uncommented.
91
+ # def update_params
92
+ # super.tap do |params|
93
+ # params[:expected_response] = Net::HTTPOK
94
+ # params[:path] = "/youtube/partner/v1/assets/#{id}"
95
+ # params[:params] = {on_behalf_of_content_owner: @auth.owner_name}
96
+ # end
97
+ # end
98
+ end
99
+ end
100
+ end
@@ -124,7 +124,7 @@ module Yt
124
124
  # Tells `has_many :videos` that channel.videos should return all the
125
125
  # videos publicly available on the channel.
126
126
  def videos_params
127
- {channelId: id}
127
+ {channel_id: id}
128
128
  end
129
129
 
130
130
  # @private
@@ -7,6 +7,19 @@ module Yt
7
7
  class Claim < Base
8
8
  def initialize(options = {})
9
9
  @data = options[:data]
10
+ @id = options[:id]
11
+ @auth = options[:auth]
12
+ end
13
+
14
+ # Soft-deletes the claim.
15
+ # @note YouTube API does not provide a +delete+ method for the Asset
16
+ # resource, but only an +update+ method. Updating the +status+ of a
17
+ # Asset to "inactive" can be considered a soft-deletion.
18
+ # @return [Boolean] whether the claim is inactive.
19
+ def delete
20
+ body = {status: :inactive}
21
+ do_patch(body: body) {|data| @data = data}
22
+ inactive?
10
23
  end
11
24
 
12
25
  # @return [String] the ID that YouTube assigns and uses to uniquely
@@ -137,6 +150,15 @@ module Yt
137
150
  def match_reference_id
138
151
  @match_reference_id ||= @data.fetch('matchInfo', {})['referenceId']
139
152
  end
153
+
154
+ # @see https://developers.google.com/youtube/partner/docs/v1/claims/update
155
+ def patch_params
156
+ super.tap do |params|
157
+ params[:expected_response] = Net::HTTPOK
158
+ params[:path] = "/youtube/partner/v1/claims/#{id}"
159
+ params[:params] = {on_behalf_of_content_owner: @auth.owner_name}
160
+ end
161
+ end
140
162
  end
141
163
  end
142
164
  end
@@ -8,19 +8,23 @@ module Yt
8
8
  class ContentOwner < Account
9
9
 
10
10
  # @!attribute [r] partnered_channels
11
- # @return [Yt::Collection::PartneredChannels] the channels managed by the CMS account.
11
+ # @return [Yt::Collections::PartneredChannels] the channels managed by the CMS account.
12
12
  has_many :partnered_channels
13
13
 
14
14
  # @!attribute [r] claims
15
- # @return [Yt::Collection::Claims] the claims administered by the content owner.
15
+ # @return [Yt::Collections::Claims] the claims administered by the content owner.
16
16
  has_many :claims
17
17
 
18
+ # @!attribute [r] assets
19
+ # @return [Yt::Collection::Assets] the assets administered by the content owner.
20
+ has_many :assets
21
+
18
22
  # @!attribute [r] references
19
- # @return [Yt::Collection::References] the references administered by the content owner.
23
+ # @return [Yt::Collections::References] the references administered by the content owner.
20
24
  has_many :references
21
25
 
22
26
  # @!attribute [r] policies
23
- # @return [Yt::Collection::Policies] the policies saved by the content owner.
27
+ # @return [Yt::Collections::Policies] the policies saved by the content owner.
24
28
  has_many :policies
25
29
 
26
30
  def initialize(options = {})
@@ -31,6 +35,14 @@ module Yt
31
35
  def create_reference(params = {})
32
36
  references.insert params
33
37
  end
38
+
39
+ def create_asset(params = {})
40
+ assets.insert params
41
+ end
42
+
43
+ def create_claim(params = {})
44
+ claims.insert params
45
+ end
34
46
  end
35
47
  end
36
48
  end
@@ -13,7 +13,7 @@ module Yt
13
13
 
14
14
  def update(attributes = {})
15
15
  underscore_keys! attributes
16
- do_patch body: {policyId: attributes[:policy_id]}
16
+ do_patch body: attributes.slice(:policy_id)
17
17
  true
18
18
  end
19
19
 
@@ -25,20 +25,10 @@ module Yt
25
25
  def patch_params
26
26
  super.tap do |params|
27
27
  params[:path] = "/youtube/partner/v1/assets/#{@asset_id}/matchPolicy"
28
- params[:params] = {onBehalfOfContentOwner: @auth.owner_name}
28
+ params[:params] = {on_behalf_of_content_owner: @auth.owner_name}
29
29
  params[:expected_response] = Net::HTTPOK
30
30
  end
31
31
  end
32
-
33
- # If we dropped support for ActiveSupport 3, then we could simply
34
- # invoke transform_keys!{|key| key.to_s.underscore.to_sym}
35
- def underscore_keys!(hash)
36
- hash.dup.each_key{|key| hash[underscore key] = hash.delete key}
37
- end
38
-
39
- def underscore(value)
40
- value.to_s.underscore.to_sym
41
- end
42
32
  end
43
33
  end
44
34
  end
@@ -0,0 +1,70 @@
1
+ require 'yt/models/base'
2
+ require 'yt/models/right_owner'
3
+
4
+ module Yt
5
+ module Models
6
+ # Provides methods to interact with YouTube ContentID asset ownership,
7
+ # which provide ownership information for the specified asset.
8
+ # @see https://developers.google.com/youtube/partner/docs/v1/ownership
9
+ class Ownership < Base
10
+ def initialize(options = {})
11
+ @data = options[:data] || {}
12
+ @auth = options[:auth]
13
+ @asset_id = options[:asset_id]
14
+ end
15
+
16
+ def update(attributes = {})
17
+ underscore_keys! attributes
18
+ do_update body: attributes
19
+ true
20
+ end
21
+
22
+ # Assigns 100% of the general ownership of the asset to @auth.
23
+ def obtain!
24
+ update general: [{ratio: 100, owner: @auth.owner_name, type: :exclude}]
25
+ end
26
+
27
+ # @return [Array<RightOwner>] a list that identifies the owners of an
28
+ # asset and the territories where each owner has ownership.
29
+ # General asset ownership is used for all types of assets and is the
30
+ # only type of ownership data that can be provided for assets that are
31
+ # not compositions.
32
+ def general_owners
33
+ @general_owners ||= as_owners @data['general']
34
+ end
35
+
36
+ # @return [Array<RightOwner>] a list that identifies owners of the
37
+ # performance rights for a composition asset.
38
+ def performance_owners
39
+ @performance_owners ||= as_owners @data['performance']
40
+ end
41
+
42
+ # @return [Array<RightOwner>] a list that identifies owners of the
43
+ # synchronization rights for a composition asset.
44
+ def synchronization_owners
45
+ @synchronization_owners ||= as_owners @data['synchronization']
46
+ end
47
+
48
+ # @return [Array<RightOwner>] a list that identifies owners of the
49
+ # mechanical rights for a composition asset.
50
+ def mechanical_owners
51
+ @mechanical_owners ||= as_owners @data['mechanical']
52
+ end
53
+
54
+ private
55
+
56
+ # @see https://developers.google.com/youtube/partner/docs/v1/ownership/update
57
+ def update_params
58
+ super.tap do |params|
59
+ params[:expected_response] = Net::HTTPOK
60
+ params[:path] = "/youtube/partner/v1/assets/#{@asset_id}/ownership"
61
+ params[:params] = {on_behalf_of_content_owner: @auth.owner_name}
62
+ end
63
+ end
64
+
65
+ def as_owners(data)
66
+ (data || []).map{|owner_data| Yt::RightOwner.new data: owner_data}
67
+ end
68
+ end
69
+ end
70
+ end
@@ -196,7 +196,7 @@ module Yt
196
196
  super.tap do |params|
197
197
  params[:expected_response] = Net::HTTPOK
198
198
  params[:path] = "/youtube/partner/v1/references/#{id}"
199
- params[:params] = {onBehalfOfContentOwner: @auth.owner_name}
199
+ params[:params] = {on_behalf_of_content_owner: @auth.owner_name}
200
200
  end
201
201
  end
202
202
  end
@@ -15,7 +15,6 @@ module Yt
15
15
  class Request
16
16
  def initialize(options = {})
17
17
  @auth = options[:auth]
18
- @body = options[:body]
19
18
  @file = options[:file]
20
19
  @body_type = options.fetch :body_type, :json
21
20
  @expected_response = options.fetch :expected_response, Net::HTTPSuccess
@@ -24,9 +23,14 @@ module Yt
24
23
  @host = options.fetch :host, google_api_host
25
24
  @method = options.fetch :method, :get
26
25
  @path = options[:path]
27
- @query = options.fetch(:params, {}).to_param
26
+ @body = options[:body]
27
+ camelize_keys! @body if options.fetch(:camelize_body, true)
28
+ params = options.fetch :params, {}
29
+ camelize_keys! params if options.fetch(:camelize_params, true)
30
+ @query = params.to_param
28
31
  end
29
32
 
33
+
30
34
  def run
31
35
  p as_curl if Yt.configuration.developing?
32
36
 
@@ -132,6 +136,13 @@ module Yt
132
136
  end if body
133
137
  end
134
138
 
139
+ def camelize_keys!(object)
140
+ return object unless object.is_a?(Hash)
141
+ object.dup.each_key do |key|
142
+ object[key.to_s.camelize(:lower).to_sym] = object.delete key
143
+ end
144
+ end
145
+
135
146
  # There are two cases to run a request again: YouTube responds with a
136
147
  # random error that can be fixed by waiting for some seconds and running
137
148
  # the exact same query, or the access token needs to be refreshed.
@@ -80,12 +80,6 @@ module Yt
80
80
  part[:required] || (part[:keys] & attributes.keys).any?
81
81
  end
82
82
 
83
- # If we dropped support for ActiveSupport 3, then we could simply
84
- # invoke transform_keys!{|key| key.to_s.underscore.to_sym}
85
- def underscore_keys!(hash)
86
- hash.dup.each_key{|key| hash[underscore key] = hash.delete key}
87
- end
88
-
89
83
  # @return [Hash] the original hash with angle brackets characters in its
90
84
  # values replaced with similar Unicode characters accepted by Youtube.
91
85
  # @see https://support.google.com/youtube/answer/57404?hl=en
@@ -100,10 +94,6 @@ module Yt
100
94
  def camelize(value)
101
95
  value.to_s.camelize(:lower).to_sym
102
96
  end
103
-
104
- def underscore(value)
105
- value.to_s.underscore.to_sym
106
- end
107
97
  end
108
98
  end
109
99
  end