yt 0.33.4 → 0.34.1

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/MIT-LICENSE +2 -2
  4. data/README.md +7 -7
  5. data/lib/yt/actions/get.rb +3 -3
  6. data/lib/yt/actions/insert.rb +1 -1
  7. data/lib/yt/actions/list.rb +2 -3
  8. data/lib/yt/associations/has_authentication.rb +5 -3
  9. data/lib/yt/collections/authentications.rb +2 -2
  10. data/lib/yt/collections/branding_settings.rb +30 -0
  11. data/lib/yt/collections/captions.rb +30 -0
  12. data/lib/yt/collections/channel_sections.rb +45 -0
  13. data/lib/yt/collections/device_flows.rb +3 -2
  14. data/lib/yt/collections/live_cuepoints.rb +37 -0
  15. data/lib/yt/collections/reports.rb +14 -6
  16. data/lib/yt/collections/revocations.rb +4 -4
  17. data/lib/yt/collections/user_infos.rb +2 -2
  18. data/lib/yt/models/account.rb +5 -1
  19. data/lib/yt/models/branding_setting.rb +29 -0
  20. data/lib/yt/models/caption.rb +52 -0
  21. data/lib/yt/models/channel.rb +29 -0
  22. data/lib/yt/models/channel_section.rb +25 -0
  23. data/lib/yt/models/content_owner.rb +5 -1
  24. data/lib/yt/models/group_info.rb +1 -1
  25. data/lib/yt/models/live_cuepoint.rb +23 -0
  26. data/lib/yt/models/playlist.rb +4 -5
  27. data/lib/yt/models/reference.rb +1 -1
  28. data/lib/yt/models/resource.rb +45 -22
  29. data/lib/yt/models/resumable_session.rb +1 -2
  30. data/lib/yt/models/snippet.rb +5 -0
  31. data/lib/yt/models/statistics_set.rb +5 -0
  32. data/lib/yt/models/user_info.rb +1 -0
  33. data/lib/yt/models/video.rb +9 -1
  34. data/lib/yt/models/video_group.rb +3 -0
  35. data/lib/yt/request.rb +5 -0
  36. data/lib/yt/version.rb +1 -1
  37. data/lib/yt.rb +1 -0
  38. metadata +19 -92
  39. data/.gitignore +0 -27
  40. data/.rspec +0 -3
  41. data/.travis.yml +0 -7
  42. data/Gemfile +0 -4
  43. data/Rakefile +0 -11
  44. data/bin/yt +0 -23
  45. data/gemfiles/Gemfile.activesupport-3.x +0 -4
  46. data/gemfiles/Gemfile.activesupport-4.x +0 -4
  47. data/lib/yt/models/iterator.rb +0 -16
  48. data/yt.gemspec +0 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c89bfab3bb32975237aa1b79a1f0897a240ea494f3d3928a03b423c734b71f6
4
- data.tar.gz: 6c58ab20408d9fdf79265fc499d1ee0f88623295de50592a25948e8029aaf91a
3
+ metadata.gz: d762b0553bfa8bd58e917e9ff11a1f38958c3b072fe35f0a1e77f19aa48926d0
4
+ data.tar.gz: 2b50a350f9d9c13f067fde5f35e7dfaf0aee824bdf98f1399690c6eddd74a730
5
5
  SHA512:
6
- metadata.gz: 2bcd96aa69c14456e067f0cad222148743334e8d8f89f3a052923f687e2d06e3a53db772898ec43399d1cdff20352fc9e56f63745bdbbebe69641511255cf5a9
7
- data.tar.gz: 52245373b815ad681f7516bea9157597c7b5b118db206a50c7ca2746cf61b8c591f2fb4765c63787427cac26fb803ce11053c1d12855e4d213fdbfb54b372e0c
6
+ metadata.gz: 839ac9877b734b3254fd2224091e88d82797621183c5a6b1893d70181fe5fe0391b8ca3a5829b7074a8b694198221968ba2d1151a1d47cc8d7dd67f4fed26943
7
+ data.tar.gz: cec4e6c32178f4de39919271f3875012c9ea56233236029135bc4ea7b1113859871319e90491963e27047cb0f0916e999fdd9d02675fd1c3aa3d93f7917a24d9
data/CHANGELOG.md CHANGED
@@ -6,6 +6,30 @@ 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.34.1 - 2026-01-08
10
+
11
+ * [FEATURE] Add channel.channel_sections
12
+ * [FEATURE] Add branding_setting.unsubscribed_trailer
13
+ * [FEATURE] Add engaged_views
14
+ * [FEATURE] Add account.sub (thank you @jkowens)
15
+ * [FEATURE] Add content_owner.live_cuepoints
16
+ * [FIX] Fetch channel_id from channel handle url
17
+ * [BUGFIX] upload_thumbnail and upload_video with path url (thank you @mrj)
18
+ * [IMPROVEMENT] Use `URI.decode_www_form` for Ruby 4.0 (thank you @jules-w2)
19
+
20
+ ## 0.34.0 - 2024-08-25
21
+
22
+ * Ruby 2.1+ required https://github.com/nullscreen/yt/pull/425
23
+ * [IMPROVEMENT] Use new oauth2 endpoints https://github.com/nullscreen/yt/pull/422
24
+ * [REMOVAL] Remove `Playlist#tags` as 'snippet.tags[]' deprecated https://github.com/nullscreen/yt/pull/421
25
+ * [FEATURE] Add captions associated with a video https://github.com/nullscreen/yt/pull/419
26
+ * [BUGFIX] Remove dependency on the deprecated open-uri in Ruby 3 https://github.com/nullscreen/yt/pull/412 (thank you @kalemi19)
27
+
28
+ **Breaking change**
29
+
30
+ If your code runs on version of Ruby 2.1 or earlier, it will not be supported.
31
+ Please make sure to upgrade Ruby version to later than 2.1 before upgrade Yt.
32
+
9
33
  ## 0.33.4 - 2021-01-15
10
34
 
11
35
  * [REMOVAL] remove retry for quota errors
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014–present Fullscreen, Inc.
1
+ Copyright (c) 2014–present Nullscreen
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
17
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
18
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
19
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -43,7 +43,7 @@ To install on your system, run
43
43
 
44
44
  To use inside a bundled Ruby project, add this line to the Gemfile:
45
45
 
46
- gem 'yt', '~> 0.32.0'
46
+ gem 'yt', '~> 0.34.0'
47
47
 
48
48
  Since the gem follows [Semantic Versioning](http://semver.org),
49
49
  indicating the full version in your Gemfile (~> *major*.*minor*.*patch*)
@@ -56,7 +56,7 @@ Available resources
56
56
  Yt::Account
57
57
  -----------
58
58
 
59
- Check [fullscreen.github.io/yt](http://fullscreen.github.io/yt/accounts.html) for the list of methods available for `Yt::Account`.
59
+ Check [nullscreen.github.io/yt](http://nullscreen.github.io/yt/accounts.html) for the list of methods available for `Yt::Account`.
60
60
 
61
61
 
62
62
  Yt::ContentOwner
@@ -109,22 +109,22 @@ content_owner.assets.first.custom_id #=> "MoKNJFOIRroc"
109
109
  Yt::Channel
110
110
  -----------
111
111
 
112
- Check [fullscreen.github.io/yt](http://fullscreen.github.io/yt/channels.html) for the list of methods available for `Yt::Channel`.
112
+ Check [nullscreen.github.io/yt](http://nullscreen.github.io/yt/channels.html) for the list of methods available for `Yt::Channel`.
113
113
 
114
114
  Yt::Video
115
115
  ---------
116
116
 
117
- Check [fullscreen.github.io/yt](http://fullscreen.github.io/yt/videos.html) for the list of methods available for `Yt::Video`.
117
+ Check [nullscreen.github.io/yt](http://nullscreen.github.io/yt/videos.html) for the list of methods available for `Yt::Video`.
118
118
 
119
119
  Yt::Playlist
120
120
  ------------
121
121
 
122
- Check [fullscreen.github.io/yt](http://fullscreen.github.io/yt/playlists.html) for the list of methods available for `Yt::Playlist`.
122
+ Check [nullscreen.github.io/yt](http://nullscreen.github.io/yt/playlists.html) for the list of methods available for `Yt::Playlist`.
123
123
 
124
124
  Yt::PlaylistItem
125
125
  ----------------
126
126
 
127
- Check [fullscreen.github.io/yt](http://fullscreen.github.io/yt/playlist_items.html) for the list of methods available for `Yt::PlaylistItem`.
127
+ Check [nullscreen.github.io/yt](http://nullscreen.github.io/yt/playlist_items.html) for the list of methods available for `Yt::PlaylistItem`.
128
128
 
129
129
  Yt::CommentThread
130
130
  ----------------
@@ -217,7 +217,7 @@ videos.where(id: 'jNQXAC9IVRw,invalid').map(&:title) #=> ["Fullscreen Creator Pl
217
217
  Yt::Annotation
218
218
  --------------
219
219
 
220
- Check [fullscreen.github.io/yt](http://fullscreen.github.io/yt/annotations.html) for the list of methods available for `Yt::Annotation`.
220
+ Check [nullscreen.github.io/yt](http://nullscreen.github.io/yt/annotations.html) for the list of methods available for `Yt::Annotation`.
221
221
 
222
222
 
223
223
  Yt::MatchPolicy
@@ -14,7 +14,7 @@ module Yt
14
14
  private
15
15
 
16
16
  def get_request(params = {})
17
- @list_request = Yt::Request.new(params).tap do |request|
17
+ @get_request = Yt::Request.new(params).tap do |request|
18
18
  print "#{request.as_curl}\n" if Yt.configuration.developing?
19
19
  end
20
20
  end
@@ -24,10 +24,10 @@ module Yt
24
24
  params[:method] = :get
25
25
  params[:host] = 'www.googleapis.com'
26
26
  params[:auth] = @auth
27
- params[:exptected_response] = Net::HTTPOK
27
+ params[:expected_response] = Net::HTTPOK
28
28
  params[:api_key] = Yt.configuration.api_key if Yt.configuration.api_key
29
29
  end
30
30
  end
31
31
  end
32
32
  end
33
- end
33
+ end
@@ -39,4 +39,4 @@ module Yt
39
39
  end
40
40
  end
41
41
  end
42
- end
42
+ end
@@ -1,5 +1,4 @@
1
1
  require 'yt/request'
2
- require 'yt/models/iterator'
3
2
  require 'yt/errors/no_items'
4
3
  require 'yt/config'
5
4
 
@@ -17,7 +16,7 @@ module Yt
17
16
 
18
17
  def list
19
18
  @last_index, @page_token = 0, nil
20
- Yt::Iterator.new(-> {total_results}) do |items|
19
+ Enumerator.new(-> {total_results}) do |items|
21
20
  while next_item = find_next
22
21
  items << next_item
23
22
  end
@@ -118,7 +117,7 @@ module Yt
118
117
  params[:host] = 'www.googleapis.com'
119
118
  params[:auth] = @auth
120
119
  params[:path] = path
121
- params[:exptected_response] = Net::HTTPOK
120
+ params[:expected_response] = Net::HTTPOK
122
121
  params[:api_key] = Yt.configuration.api_key if Yt.configuration.api_key
123
122
  end
124
123
  end
@@ -32,6 +32,7 @@ module Yt
32
32
  @force = options[:force]
33
33
  @scopes = options[:scopes]
34
34
  @authentication = options[:authentication]
35
+ @state = options[:state]
35
36
  end
36
37
 
37
38
  def auth
@@ -48,7 +49,7 @@ module Yt
48
49
 
49
50
  def authentication_url
50
51
  host = 'accounts.google.com'
51
- path = '/o/oauth2/auth'
52
+ path = '/o/oauth2/v2/auth'
52
53
  query = authentication_url_params.to_param
53
54
  URI::HTTPS.build(host: host, path: path, query: query).to_s
54
55
  end
@@ -188,8 +189,9 @@ module Yt
188
189
  params[:redirect_uri] = @redirect_uri
189
190
  params[:response_type] = :code
190
191
  params[:access_type] = :offline
191
- params[:approval_prompt] = @force ? :force : :auto
192
+ params[:prompt] = :consent if @force
192
193
  # params[:include_granted_scopes] = true
194
+ params[:state] = @state if @state
193
195
  end
194
196
  end
195
197
 
@@ -243,4 +245,4 @@ module Yt
243
245
  end
244
246
  end
245
247
  end
246
- end
248
+ end
@@ -16,8 +16,8 @@ module Yt
16
16
 
17
17
  def list_params
18
18
  super.tap do |params|
19
- params[:host] = 'accounts.google.com'
20
- params[:path] = '/o/oauth2/token'
19
+ params[:host] = 'oauth2.googleapis.com'
20
+ params[:path] = '/token'
21
21
  params[:request_format] = :form
22
22
  params[:method] = :post
23
23
  params[:auth] = nil
@@ -0,0 +1,30 @@
1
+ require 'yt/collections/base'
2
+ require 'yt/models/branding_setting'
3
+
4
+ module Yt
5
+ module Collections
6
+ # @private
7
+ class BrandingSettings < Base
8
+
9
+ private
10
+
11
+ def attributes_for_new_item(data)
12
+ { data: data['brandingSettings'] }
13
+ end
14
+
15
+ # @return [Hash] the parameters to submit to YouTube to get the
16
+ # branding_settings of a resource, for instance a channel.
17
+ # @see https://developers.google.com/youtube/v3/docs/channels#resource
18
+ def list_params
19
+ super.tap do |params|
20
+ params[:path] = "/youtube/v3/#{@parent.kind.pluralize}"
21
+ params[:params] = branding_settings_params
22
+ end
23
+ end
24
+
25
+ def branding_settings_params
26
+ { max_results: 50, part: 'brandingSettings', id: @parent.id }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ require 'yt/collections/base'
2
+
3
+ module Yt
4
+ module Collections
5
+ # Provides methods to interact with a collection of video captions.
6
+ class Captions < Resources
7
+
8
+ private
9
+
10
+ def attributes_for_new_item(data)
11
+ {id: data['id'], snippet: data['snippet'], auth: @auth}
12
+ end
13
+
14
+ def list_params
15
+ super.tap do |params|
16
+ params[:path] = "/youtube/v3/captions"
17
+ params[:params] = captions_params
18
+ end
19
+ end
20
+
21
+ def captions_params
22
+ {}.tap do |params|
23
+ params[:part] = 'snippet'
24
+ params[:video_id] = @parent.id if @parent
25
+ apply_where_params! params
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,45 @@
1
+ require 'yt/collections/base'
2
+ require 'yt/models/channel_section'
3
+
4
+ module Yt
5
+ module Collections
6
+ # Provides methods for a collection of YouTube channel sections.
7
+ #
8
+ # Resources with channel_sections is {Yt::Models::Channel channels}.
9
+ class ChannelSections < Base
10
+
11
+ def attributes_for_new_item(data)
12
+ {}.tap do |attributes|
13
+ attributes[:id] = data['id']
14
+ attributes[:snippet] = data['snippet']
15
+ attributes[:content_details] = data['contentDetails']
16
+ end
17
+ end
18
+
19
+ # @return [Hash] the parameters to submit to YouTube to list channel sections.
20
+ # @see https://developers.google.com/youtube/v3/docs/channelSections/list
21
+ def list_params
22
+ super.tap do |params|
23
+ params[:params] = channel_sections_params
24
+ params[:path] = '/youtube/v3/channelSections'
25
+ end
26
+ end
27
+
28
+ def channel_sections_params
29
+ {}.tap do |params|
30
+ params[:part] = 'snippet'
31
+ params.merge! @parent.channel_sections_params if @parent
32
+ # TODO: when to mine, when to on_behalf_of_content_owner
33
+ # if @parent.auth
34
+ # if @parent.auth.owner_name
35
+ # params[:on_behalf_of_content_owner] = @parent.auth.owner_name
36
+ # else
37
+ # params[:mine] = true
38
+ # end
39
+ # end
40
+ params
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -15,9 +15,10 @@ module Yt
15
15
 
16
16
  def list_params
17
17
  super.tap do |params|
18
- params[:path] = '/o/oauth2/device/code'
18
+ params[:host] = 'oauth2.googleapis.com'
19
+ params[:path] = '/device/code'
19
20
  end
20
21
  end
21
22
  end
22
23
  end
23
- end
24
+ end
@@ -0,0 +1,37 @@
1
+ require 'yt/collections/base'
2
+ require 'yt/models/live_cuepoint'
3
+
4
+ module Yt
5
+ module Collections
6
+ # Provides methods to insert live cuepoints.
7
+ #
8
+ # Resources with live_cuepoints are: {Yt::Models::ContentOwner content owners}.
9
+ class LiveCuepoints < Base
10
+ def insert(attributes = {})
11
+ underscore_keys! attributes
12
+ body = attributes.slice(*body_params)
13
+ params = {on_behalf_of_content_owner: @auth.owner_name}
14
+ apply_where_params! params
15
+ do_insert(params: params, body: body)
16
+ end
17
+
18
+ private
19
+
20
+ def body_params
21
+ [:id, :cue_type, :insertion_offset_time_ms, :walltime_ms, :duration_secs]
22
+ end
23
+
24
+ # @return [Hash] the parameters to submit to YouTube to add a live cuepoint.
25
+ # @see https://developers.google.com/youtube/v3/live/docs/liveBroadcasts/cuepoint
26
+ def insert_params
27
+ super.tap do |params|
28
+ params[:path] = '/youtube/v3/liveBroadcasts/cuepoint'
29
+ end
30
+ end
31
+
32
+ def attributes_for_new_item(data)
33
+ {data: data, auth: @auth, id: data['id']}
34
+ end
35
+ end
36
+ end
37
+ end
@@ -47,19 +47,28 @@ module Yt
47
47
  playlist_page: 'YT_PLAYLIST_PAGE',
48
48
  campaign_card: 'CAMPAIGN_CARD',
49
49
  end_screen: 'END_SCREEN',
50
- info_card: 'INFO_CARD'
50
+ info_card: 'INFO_CARD',
51
+ hashtags: 'HASHTAGS',
52
+ live_redirect: 'LIVE_REDIRECT',
53
+ product_page: 'PRODUCT_PAGE',
54
+ shorts: 'SHORTS',
55
+ sound_page: 'SOUND_PAGE',
56
+ video_remixes: 'VIDEO_REMIXES',
57
+ immersive_live: 'IMMERSIVE_LIVE',
58
+ shorts_content_links: 'SHORTS_CONTENT_LINKS'
51
59
  }
52
60
 
53
- # @see https://developers.google.com/youtube/analytics/v1/dimsmets/dims#Playback_Location_Dimensions
61
+ # @see https://developers.google.com/youtube/analytics/dimensions#Playback_Location_Dimensions
54
62
  PLAYBACK_LOCATIONS = {
55
63
  channel: 'CHANNEL',
56
64
  watch: 'WATCH',
57
65
  embedded: 'EMBEDDED',
58
66
  other: 'YT_OTHER',
59
67
  external_app: 'EXTERNAL_APP',
60
- search: 'SEARCH', # undocumented but returned by the API
61
- browse: 'BROWSE', # undocumented but returned by the API
62
- mobile: 'MOBILE' # only present for data < September 10, 2013
68
+ search: 'SEARCH',
69
+ browse: 'BROWSE',
70
+ mobile: 'MOBILE', # only present for data < September 10, 2013
71
+ shorts_feed: 'SHORTS_FEED' # undocumented but returned by the API
63
72
  }
64
73
 
65
74
  # @see https://developers.google.com/youtube/analytics/v1/dimsmets/dims#Playback_Detail_Dimensions
@@ -203,7 +212,6 @@ module Yt
203
212
  params[:filters] = ((params[:filters] || '').split(';') + ["country==US"]).compact.uniq.join(';') if @dimension == :state && !@state
204
213
  params[:filters] = ((params[:filters] || '').split(';') + ["country==#{@country}"]).compact.uniq.join(';') if @country && !@state
205
214
  params[:filters] = ((params[:filters] || '').split(';') + ["province==US-#{@state}"]).compact.uniq.join(';') if @state
206
- params[:filters] = ((params[:filters] || '').split(';') + ['isCurated==1']).compact.uniq.join(';') if @dimension == :playlist
207
215
  params[:filters] = ((params[:filters] || '').split(';') + ['insightPlaybackLocationType==EMBEDDED']).compact.uniq.join(';') if @dimension == :embedded_player_location
208
216
  params[:filters] = ((params[:filters] || '').split(';') + ['insightTrafficSourceType==RELATED_VIDEO']).compact.uniq.join(';') if @dimension == :related_video
209
217
  params[:filters] = ((params[:filters] || '').split(';') + ['insightTrafficSourceType==YT_SEARCH']).compact.uniq.join(';') if @dimension == :search_term
@@ -15,10 +15,10 @@ module Yt
15
15
 
16
16
  def list_params
17
17
  super.tap do |params|
18
- params[:host] = 'accounts.google.com'
19
- params[:path] = '/o/oauth2/revoke'
20
- params[:request_format] = nil
21
- params[:method] = :get
18
+ params[:host] = 'oauth2.googleapis.com'
19
+ params[:path] = '/revoke'
20
+ params[:request_format] = :form
21
+ params[:method] = :post
22
22
  params[:auth] = nil
23
23
  params[:body] = nil
24
24
  params[:camelize_body] = false
@@ -13,7 +13,7 @@ module Yt
13
13
  # @see https://developers.google.com/+/api/latest/people/getOpenIdConnect
14
14
  def list_params
15
15
  super.tap do |params|
16
- params[:path] = '/oauth2/v2/userinfo'
16
+ params[:path] = '/oauth2/v3/userinfo'
17
17
  params[:expected_response] = Net::HTTPOK
18
18
  end
19
19
  end
@@ -33,4 +33,4 @@ module Yt
33
33
  end
34
34
  end
35
35
  end
36
- end
36
+ end
@@ -15,6 +15,10 @@ module Yt
15
15
  # @return [String] the (Google+) account’s ID.
16
16
  delegate :id, to: :user_info
17
17
 
18
+ # @!attribute [r] sub
19
+ # @return [String] the (Google) account’s unique ID.
20
+ delegate :sub, to: :user_info
21
+
18
22
  # @!attribute [r] email
19
23
  # @return [String] the account’s email address.
20
24
  delegate :email, to: :user_info
@@ -70,7 +74,7 @@ module Yt
70
74
  # @option params [Boolean] :self_declared_made_for_kids The video’s made for kids self-declaration.
71
75
  # @return [Yt::Models::Video] the newly uploaded video.
72
76
  def upload_video(path_or_url, params = {})
73
- file = open path_or_url, 'rb'
77
+ file = URI.open(path_or_url)
74
78
  session = resumable_sessions.insert file.size, upload_body(params)
75
79
 
76
80
  session.update(body: file) do |data|
@@ -0,0 +1,29 @@
1
+ require 'yt/models/base'
2
+
3
+ module Yt
4
+ module Models
5
+ # @private
6
+ # Encapsulates branding settings about the resource, such as trailer on channel
7
+ # @see https://developers.google.com/youtube/v3/docs/channels#resource-representation
8
+ class BrandingSetting < Base
9
+ attr_reader :data
10
+
11
+ def initialize(options = {})
12
+ @data = options[:data]
13
+ end
14
+
15
+ has_attribute :channel, default: {}
16
+
17
+ def unsubscribed_trailer
18
+ channel['unsubscribedTrailer']
19
+ end
20
+
21
+ has_attribute :image, default: {}
22
+
23
+ def banner_external_url
24
+ image['bannerExternalUrl']
25
+ end
26
+ end
27
+ end
28
+ end
29
+
@@ -0,0 +1,52 @@
1
+ require 'yt/models/resource'
2
+ require "fileutils"
3
+
4
+ module Yt
5
+ module Models
6
+ # Provides methods to interact with YouTube video captions.
7
+ # @see https://developers.google.com/youtube/v3/docs/captions
8
+ class Caption < Resource
9
+
10
+ # @return [String] the ID used to identify the caption.
11
+ has_attribute :id
12
+
13
+ delegate :video_id, to: :snippet
14
+ delegate :last_updated, to: :snippet
15
+ delegate :language, to: :snippet
16
+ delegate :name, to: :snippet
17
+ delegate :status, to: :snippet
18
+
19
+ # Downloads a caption file.
20
+ # @param [String] path A name for the downloaded file with caption content.
21
+ # @see https://developers.google.com/youtube/v3/docs/captions#resource
22
+ def download(path)
23
+ case io
24
+ when StringIO then File.open(path, 'w') { |f| f.write(io.read) }
25
+ when Tempfile then io.close; FileUtils.mv(io.path, path)
26
+ end
27
+ end
28
+
29
+ def io
30
+ @io ||= get_request(download_params).open_uri
31
+ end
32
+
33
+ private
34
+
35
+ # @return [Hash] the parameters to submit to YouTube to download caption.
36
+ # @see https://developers.google.com/youtube/v3/docs/captions/download
37
+ def download_params
38
+ {}.tap do |params|
39
+ params[:method] = :get
40
+ params[:host] = 'youtube.googleapis.com'
41
+ params[:auth] = @auth
42
+ params[:exptected_response] = Net::HTTPOK
43
+ params[:api_key] = Yt.configuration.api_key if Yt.configuration.api_key
44
+ params[:path] = "/youtube/v3/captions/#{@id}"
45
+ if @auth.owner_name
46
+ params[:params] = {on_behalf_of_content_owner: @auth.owner_name}
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -126,6 +126,10 @@ module Yt
126
126
  # explicitly select the option to keep all subscriptions private.
127
127
  has_many :subscribed_channels
128
128
 
129
+ # @!attribute [r] channel_sections
130
+ # @return [Yt::Collections::ChannelSections] the channel’s channel sections.
131
+ has_many :channel_sections
132
+
129
133
  ### ANALYTICS ###
130
134
 
131
135
  # @macro reports
@@ -133,6 +137,9 @@ module Yt
133
137
  # @macro report_by_channel_dimensions
134
138
  has_report :views, Integer
135
139
 
140
+ # @macro report_by_channel_dimensions
141
+ has_report :engaged_views, Integer
142
+
136
143
  # @macro report_by_channel_dimensions
137
144
  has_report :estimated_minutes_watched, Integer
138
145
 
@@ -229,6 +236,18 @@ module Yt
229
236
  statistics_set.hidden_subscriber_count == false
230
237
  end
231
238
 
239
+ ### BRANDING SETTINGS ###
240
+
241
+ has_one :branding_setting
242
+
243
+ # @!attribute [r] unsubscribed_trailer
244
+ # @return [String] the channel’s trailer video id.
245
+ delegate :unsubscribed_trailer, to: :branding_setting
246
+
247
+ # @!attribute [r] banner_external_url
248
+ # @return [String] the channel’s banner image URL.
249
+ delegate :banner_external_url, to: :branding_setting
250
+
232
251
  ### CONTENT OWNER DETAILS ###
233
252
 
234
253
  has_one :content_owner_detail
@@ -286,6 +305,16 @@ module Yt
286
305
  if options[:content_owner_details]
287
306
  @content_owner_detail = ContentOwnerDetail.new data: options[:content_owner_details]
288
307
  end
308
+ if options[:branding_settings]
309
+ @branding_setting = BrandingSetting.new data: options[:branding_settings]
310
+ end
311
+ end
312
+
313
+ # @private
314
+ # Used for `has_many :channel_sections` to return all youtube#channelSection items
315
+ # of the channel.
316
+ def channel_sections_params
317
+ {channel_id: id}
289
318
  end
290
319
 
291
320
  # @private
@@ -0,0 +1,25 @@
1
+ require 'yt/models/base'
2
+
3
+ module Yt
4
+ module Models
5
+ class ChannelSection < Base
6
+ attr_reader :data
7
+
8
+ # @private
9
+ def initialize(options = {})
10
+ @id = options[:id]
11
+ @data = options[:snippet]
12
+ end
13
+
14
+ has_attribute :type
15
+ has_attribute :channel_id
16
+ has_attribute :position, type: Integer
17
+
18
+ ### ID ###
19
+
20
+ # @!attribute [r] id
21
+ # @return [String] the ID that YouTube uses to identify each resource.
22
+ attr_reader :id
23
+ end
24
+ end
25
+ end
@@ -11,6 +11,10 @@ module Yt
11
11
  # @return [Yt::Collections::PartneredChannels] the channels managed by the CMS account.
12
12
  has_many :partnered_channels
13
13
 
14
+ # @!attribute [r] live_cuepoints
15
+ # @return [Yt::Collections::LiveCuepoints] the live_cuepoints inserted by the content owner.
16
+ has_many :live_cuepoints
17
+
14
18
  # @!attribute [r] claims
15
19
  # @return [Yt::Collections::Claims] the claims administered by the content owner.
16
20
  has_many :claims
@@ -54,7 +58,7 @@ module Yt
54
58
  # @option params [String] :content_type The type of content being uploaded.
55
59
  # @return [Yt::Models::Reference] the newly uploaded reference.
56
60
  def upload_reference_file(path_or_url, params = {})
57
- file = open path_or_url, 'rb'
61
+ file = URI.open(path_or_url)
58
62
  session = resumable_sessions.insert file.size, params
59
63
 
60
64
  session.update(body: file) do |data|
@@ -13,4 +13,4 @@ module Yt
13
13
  has_attribute :published_at, type: Time
14
14
  end
15
15
  end
16
- end
16
+ end