yt 0.25.13 → 0.32.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 (96) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +305 -1
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +86 -5
  5. data/YOUTUBE_IT.md +3 -3
  6. data/lib/yt.rb +5 -2
  7. data/lib/yt/actions/list.rb +3 -3
  8. data/lib/yt/associations/has_authentication.rb +33 -1
  9. data/lib/yt/associations/has_reports.rb +13 -18
  10. data/lib/yt/collections/assets.rb +2 -2
  11. data/lib/yt/collections/authentications.rb +9 -2
  12. data/lib/yt/collections/base.rb +3 -3
  13. data/lib/yt/collections/bulk_report_jobs.rb +28 -0
  14. data/lib/yt/collections/bulk_reports.rb +24 -0
  15. data/lib/yt/collections/claims.rb +22 -1
  16. data/lib/yt/collections/comment_threads.rb +41 -0
  17. data/lib/yt/collections/content_owners.rb +1 -1
  18. data/lib/yt/collections/group_infos.rb +27 -0
  19. data/lib/yt/collections/group_items.rb +45 -0
  20. data/lib/yt/collections/reports.rb +75 -13
  21. data/lib/yt/collections/revocations.rb +30 -0
  22. data/lib/yt/collections/video_groups.rb +29 -0
  23. data/lib/yt/collections/videos.rb +34 -9
  24. data/lib/yt/constants/geography.rb +326 -0
  25. data/lib/yt/errors/forbidden.rb +1 -3
  26. data/lib/yt/errors/no_items.rb +1 -3
  27. data/lib/yt/errors/request_error.rb +10 -7
  28. data/lib/yt/errors/server_error.rb +1 -3
  29. data/lib/yt/errors/unauthorized.rb +3 -3
  30. data/lib/yt/models/account.rb +12 -0
  31. data/lib/yt/models/advertising_options_set.rb +4 -4
  32. data/lib/yt/models/bulk_report.rb +23 -0
  33. data/lib/yt/models/bulk_report_job.rb +23 -0
  34. data/lib/yt/models/channel.rb +21 -12
  35. data/lib/yt/models/claim.rb +13 -2
  36. data/lib/yt/models/comment.rb +37 -0
  37. data/lib/yt/models/comment_thread.rb +50 -0
  38. data/lib/yt/models/content_detail.rb +6 -0
  39. data/lib/yt/models/content_owner.rb +31 -1
  40. data/lib/yt/models/group_info.rb +16 -0
  41. data/lib/yt/models/group_item.rb +15 -0
  42. data/lib/yt/models/resource.rb +3 -10
  43. data/lib/yt/models/revocation.rb +12 -0
  44. data/lib/yt/models/right_owner.rb +0 -2
  45. data/lib/yt/models/snippet.rb +24 -3
  46. data/lib/yt/models/video.rb +42 -11
  47. data/lib/yt/models/video_group.rb +186 -0
  48. data/lib/yt/request.rb +5 -3
  49. data/lib/yt/version.rb +2 -2
  50. data/spec/collections/comment_threads_spec.rb +46 -0
  51. data/spec/collections/playlist_items_spec.rb +1 -1
  52. data/spec/collections/reports_spec.rb +2 -2
  53. data/spec/constants/geography_spec.rb +16 -0
  54. data/spec/models/annotation_spec.rb +1 -1
  55. data/spec/models/claim_spec.rb +15 -3
  56. data/spec/models/comment_spec.rb +40 -0
  57. data/spec/models/comment_thread_spec.rb +93 -0
  58. data/spec/models/content_detail_spec.rb +7 -0
  59. data/spec/models/reference_spec.rb +2 -2
  60. data/spec/models/request_spec.rb +21 -0
  61. data/spec/models/resource_spec.rb +0 -15
  62. data/spec/models/video_spec.rb +1 -1
  63. data/spec/requests/as_account/account_spec.rb +16 -4
  64. data/spec/requests/as_account/authentications_spec.rb +1 -13
  65. data/spec/requests/as_account/channel_spec.rb +15 -45
  66. data/spec/requests/as_account/playlist_item_spec.rb +3 -3
  67. data/spec/requests/as_account/playlist_spec.rb +5 -32
  68. data/spec/requests/as_account/video_spec.rb +2022 -21
  69. data/spec/requests/as_content_owner/account_spec.rb +4 -0
  70. data/spec/requests/as_content_owner/bulk_report_job_spec.rb +19 -0
  71. data/spec/requests/as_content_owner/channel_spec.rb +59 -270
  72. data/spec/requests/as_content_owner/content_owner_spec.rb +89 -1
  73. data/spec/requests/as_content_owner/playlist_spec.rb +0 -15
  74. data/spec/requests/as_content_owner/video_group_spec.rb +112 -0
  75. data/spec/requests/as_content_owner/video_spec.rb +72 -146
  76. data/spec/requests/as_server_app/channel_spec.rb +1 -21
  77. data/spec/requests/as_server_app/comment_spec.rb +22 -0
  78. data/spec/requests/as_server_app/comment_thread_spec.rb +27 -0
  79. data/spec/requests/as_server_app/comment_threads_spec.rb +41 -0
  80. data/spec/requests/as_server_app/playlist_item_spec.rb +2 -2
  81. data/spec/requests/as_server_app/playlist_spec.rb +1 -22
  82. data/spec/requests/as_server_app/video_spec.rb +21 -19
  83. data/spec/requests/as_server_app/videos_spec.rb +5 -5
  84. data/spec/requests/unauthenticated/video_spec.rb +1 -9
  85. data/spec/spec_helper.rb +1 -1
  86. data/yt.gemspec +2 -1
  87. metadata +51 -17
  88. data/lib/yt/collections/ids.rb +0 -27
  89. data/lib/yt/config.rb +0 -54
  90. data/lib/yt/models/configuration.rb +0 -70
  91. data/lib/yt/models/description.rb +0 -58
  92. data/lib/yt/models/url.rb +0 -91
  93. data/spec/models/configuration_spec.rb +0 -44
  94. data/spec/models/description_spec.rb +0 -94
  95. data/spec/models/url_spec.rb +0 -84
  96. data/spec/requests/as_account/resource_spec.rb +0 -18
@@ -3,11 +3,9 @@ require 'yt/errors/request_error'
3
3
  module Yt
4
4
  module Errors
5
5
  class Forbidden < RequestError
6
- private
7
-
8
6
  def explanation
9
7
  'A request to YouTube API was considered forbidden by the server'
10
8
  end
11
9
  end
12
10
  end
13
- end
11
+ end
@@ -3,11 +3,9 @@ require 'yt/errors/request_error'
3
3
  module Yt
4
4
  module Errors
5
5
  class NoItems < RequestError
6
- private
7
-
8
6
  def explanation
9
7
  'A request to YouTube API returned no items but some were expected'
10
8
  end
11
9
  end
12
10
  end
13
- end
11
+ end
@@ -19,6 +19,10 @@ module Yt
19
19
  response_body.fetch 'error', {}
20
20
  end
21
21
 
22
+ def description
23
+ response_body.fetch 'error_description', {}
24
+ end
25
+
22
26
  def reasons
23
27
  case kind
24
28
  when Hash then kind.fetch('errors', []).map{|e| e['reason']}
@@ -26,12 +30,15 @@ module Yt
26
30
  end
27
31
  end
28
32
 
29
- private
30
-
31
33
  def explanation
32
34
  'A request to YouTube API failed'
33
35
  end
34
36
 
37
+ def response_body
38
+ json['response_body'].is_a?(Hash) ? json['response_body'] : {}
39
+ end
40
+
41
+ private
35
42
 
36
43
  def details
37
44
  <<-MSG.gsub(/^ {8}/, '')
@@ -56,10 +63,6 @@ module Yt
56
63
  def more_details
57
64
  end
58
65
 
59
- def response_body
60
- json['response_body'].is_a?(Hash) ? json['response_body'] : {}
61
- end
62
-
63
66
  def request_curl
64
67
  json['request_curl']
65
68
  end
@@ -71,4 +74,4 @@ module Yt
71
74
  end
72
75
 
73
76
  Error = Errors::RequestError
74
- end
77
+ end
@@ -3,11 +3,9 @@ require 'yt/errors/request_error'
3
3
  module Yt
4
4
  module Errors
5
5
  class ServerError < RequestError
6
- private
7
-
8
6
  def explanation
9
7
  'A request to YouTube API caused an unexpected server error'
10
8
  end
11
9
  end
12
10
  end
13
- end
11
+ end
@@ -4,12 +4,12 @@ require 'yt/config'
4
4
  module Yt
5
5
  module Errors
6
6
  class Unauthorized < RequestError
7
- private
8
-
9
7
  def explanation
10
8
  'A request to YouTube API was sent without a valid authentication'
11
9
  end
12
10
 
11
+ private
12
+
13
13
  def more_details
14
14
  if [Yt.configuration.client_id, Yt.configuration.api_key].none?
15
15
  <<-MSG.gsub(/^ {10}/, '')
@@ -47,4 +47,4 @@ module Yt
47
47
  end
48
48
  end
49
49
  end
50
- end
50
+ end
@@ -160,6 +160,11 @@ module Yt
160
160
  # upload videos using the resumable upload protocol.
161
161
  has_many :resumable_sessions
162
162
 
163
+ # @!attribute [r] video_groups
164
+ # @return [Yt::Collections::VideoGroups] the video-groups created by the
165
+ # account.
166
+ has_many :video_groups
167
+
163
168
  ### PRIVATE API ###
164
169
 
165
170
  has_authentication
@@ -180,6 +185,13 @@ module Yt
180
185
  {for_mine: true}
181
186
  end
182
187
 
188
+ # @private
189
+ # Tells `has_many :video_groups` that content_owner.groups should return
190
+ # all the video-groups *owned by* the account
191
+ def video_groups_params
192
+ {mine: true}
193
+ end
194
+
183
195
  # @private
184
196
  # Tells `has_many :resumable_sessions` what path to hit to upload a file.
185
197
  def upload_path
@@ -19,9 +19,9 @@ module Yt
19
19
  true
20
20
  end
21
21
 
22
- def ad_formats
23
- @data['adFormats']
24
- end
22
+ has_attribute :ad_formats
23
+ has_attribute :ad_breaks
24
+ has_attribute :tp_ad_server_video_id
25
25
 
26
26
  private
27
27
 
@@ -35,4 +35,4 @@ module Yt
35
35
  end
36
36
  end
37
37
  end
38
- end
38
+ end
@@ -0,0 +1,23 @@
1
+ require 'yt/models/base'
2
+
3
+ module Yt
4
+ module Models
5
+ # Provides methods to interact with YouTube Analytics bulk reports.
6
+ # @see https://developers.google.com/youtube/reporting/v1/reference/rest/v1/jobs.reports
7
+ class BulkReport < Base
8
+ # @private
9
+ attr_reader :auth
10
+
11
+ has_attribute :id
12
+ has_attribute :start_time, type: Time
13
+ has_attribute :end_time, type: Time
14
+ has_attribute :download_url
15
+
16
+ # @private
17
+ def initialize(options = {})
18
+ @data = options.fetch(:data, {})
19
+ @auth = options[:auth]
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require 'yt/models/base'
2
+
3
+ module Yt
4
+ module Models
5
+ # Provides methods to interact with YouTube Analytics bulk report jobs.
6
+ # @see https://developers.google.com/youtube/reporting/v1/reference/rest/v1/jobs
7
+ class BulkReportJob < Base
8
+ # @private
9
+ attr_reader :id, :auth, :report_type_id
10
+
11
+ # @private
12
+ def initialize(options = {})
13
+ @id = options[:id]
14
+ @auth = options[:auth]
15
+ @report_type_id = options[:report_type_id]
16
+ end
17
+
18
+ # @!attribute [r] bulk_reports
19
+ # @return [Yt::Collections::BulkReports] the bulk reports of this job.
20
+ has_many :bulk_reports
21
+ end
22
+ end
23
+ end
@@ -114,9 +114,6 @@ module Yt
114
114
  # @macro report_by_channel_dimensions
115
115
  has_report :views, Integer
116
116
 
117
- # @macro report_by_day
118
- has_report :uniques, Integer
119
-
120
117
  # @macro report_by_channel_dimensions
121
118
  has_report :estimated_minutes_watched, Integer
122
119
 
@@ -141,12 +138,6 @@ module Yt
141
138
  # @macro report_by_day_and_country
142
139
  has_report :subscribers_lost, Integer
143
140
 
144
- # @macro report_by_day_and_country
145
- has_report :favorites_added, Integer
146
-
147
- # @macro report_by_day_and_country
148
- has_report :favorites_removed, Integer
149
-
150
141
  # @macro report_by_day_and_country
151
142
  has_report :videos_added_to_playlists, Integer
152
143
 
@@ -168,11 +159,29 @@ module Yt
168
159
  # @macro report_by_day_and_state
169
160
  has_report :annotation_close_rate, Float
170
161
 
162
+ # @macro report_by_day_and_state
163
+ has_report :card_impressions, Integer
164
+
165
+ # @macro report_by_day_and_state
166
+ has_report :card_clicks, Integer
167
+
168
+ # @macro report_by_day_and_state
169
+ has_report :card_click_rate, Float
170
+
171
+ # @macro report_by_day_and_state
172
+ has_report :card_teaser_impressions, Integer
173
+
174
+ # @macro report_by_day_and_state
175
+ has_report :card_teaser_clicks, Integer
176
+
177
+ # @macro report_by_day_and_state
178
+ has_report :card_teaser_click_rate, Float
179
+
171
180
  # @macro report_by_day_and_country
172
- has_report :earnings, Float
181
+ has_report :estimated_revenue, Float
173
182
 
174
183
  # @macro report_by_day_and_country
175
- has_report :impressions, Integer
184
+ has_report :ad_impressions, Integer
176
185
 
177
186
  # @macro report_by_day_and_country
178
187
  has_report :monetized_playbacks, Integer
@@ -305,4 +314,4 @@ module Yt
305
314
  end
306
315
  end
307
316
  end
308
- end
317
+ end
@@ -5,12 +5,13 @@ module Yt
5
5
  # Provides methods to interact with YouTube ContentID claims.
6
6
  # @see https://developers.google.com/youtube/partner/docs/v1/claims
7
7
  class Claim < Base
8
- attr_reader :auth
8
+ attr_reader :auth, :data
9
9
 
10
10
  def initialize(options = {})
11
11
  @data = options[:data]
12
12
  @id = options[:id]
13
13
  @auth = options[:auth]
14
+ @asset = options[:asset] if options[:asset]
14
15
  end
15
16
 
16
17
  # @!attribute [r] claim_history
@@ -113,6 +114,16 @@ module Yt
113
114
  content_type == 'audiovisual'
114
115
  end
115
116
 
117
+ # @return [String] the source of the claim
118
+ def source
119
+ @data.fetch('origin', {})['source']
120
+ end
121
+
122
+ # @return [Yt::Models::Asset] the asset of the claim
123
+ def asset
124
+ @asset
125
+ end
126
+
116
127
  # @return [Time] the date and time that the claim was created.
117
128
  has_attribute :created_at, type: Time, from: :time_created
118
129
 
@@ -153,4 +164,4 @@ module Yt
153
164
  end
154
165
  end
155
166
  end
156
- end
167
+ end
@@ -0,0 +1,37 @@
1
+ require 'yt/models/resource'
2
+
3
+ module Yt
4
+ module Models
5
+ # Provides methods to interact with YouTube comment.
6
+ # @see https://developers.google.com/youtube/v3/docs/comments
7
+ class Comment < Resource
8
+
9
+ ### SNIPPET ###
10
+
11
+ # @!attribute [r] video_id
12
+ # @return [String] the ID of the video that the comment refers to.
13
+ delegate :video_id, to: :snippet
14
+
15
+ # @!attribute [r] author_display_name
16
+ # @return [String] the display name of the user who posted the comment.
17
+ delegate :author_display_name, to: :snippet
18
+
19
+ # @!attribute [r] text_display
20
+ # @return [String] the comment's text.
21
+ delegate :text_display, to: :snippet
22
+
23
+ # @!attribute [r] parent_id
24
+ # @return [String] the unique ID of the parent comment. This property is only
25
+ # set if the comment was submitted as a reply to another comment.
26
+ delegate :parent_id, to: :snippet
27
+
28
+ # @!attribute [r] like_count
29
+ # @return [Integer] the total number of likes (positive ratings) the comment has received.
30
+ delegate :like_count, to: :snippet
31
+
32
+ # @!attribute [r] updated_at
33
+ # @return [Time] the date and time when the comment was last updated.
34
+ delegate :updated_at, to: :snippet
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,50 @@
1
+ require 'yt/models/resource'
2
+
3
+ module Yt
4
+ module Models
5
+ # Provides methods to interact with YouTube comment thread.
6
+ # @see https://developers.google.com/youtube/v3/docs/commentThreads
7
+ class CommentThread < Resource
8
+
9
+ ### SNIPPET ###
10
+
11
+ # @!attribute [r] video_id
12
+ # @return [String] the ID of the video that the comment thread referto, if
13
+ # any. If this property is not present or does not have a value, then the
14
+ # thread applies to the channel and not to a specific video.
15
+ delegate :video_id, to: :snippet
16
+
17
+ # @!attribute [r] total_reply_count
18
+ # @return [String] The total number of replies that have been submitted
19
+ # in response to the top level comment.
20
+ delegate :total_reply_count, to: :snippet
21
+
22
+ # @return [Boolean] whether the thread, including all of its comments and
23
+ # comment replies, is visible to all YouTube users.
24
+ delegate :public?, to: :snippet
25
+
26
+ # @return [Boolean] whether the current viewer can reply to the thread.
27
+ delegate :can_reply?, to: :snippet
28
+
29
+ # @!attribute [r] top_level_comment
30
+ # @return [Yt::TopLevelComment] the top level comment object.
31
+ delegate :top_level_comment, to: :snippet
32
+
33
+ # @!attribute [r] text_display
34
+ # @return [String] the top level comment's display text.
35
+ delegate :text_display, to: :top_level_comment
36
+
37
+ # @!attribute [r] author_display_name
38
+ # @return [String] the top level comment's author name.
39
+ delegate :author_display_name, to: :top_level_comment
40
+
41
+ # @!attribute [r] like_count
42
+ # @return [String] the top level comment's likes count.
43
+ delegate :like_count, to: :top_level_comment
44
+
45
+ # @!attribute [r] updated_at
46
+ # @return [String] the top level comment's last updated time.
47
+ delegate :updated_at, to: :top_level_comment
48
+ end
49
+ end
50
+ end
@@ -29,6 +29,12 @@ module Yt
29
29
  content_rating['ytRating']
30
30
  end
31
31
 
32
+ # @return [<String>] the length of the video as an ISO 8601 time, HH:MM:SS.
33
+ def length
34
+ hh, mm, ss = duration / 3600, duration / 60 % 60, duration % 60
35
+ [hh, mm, ss].map{|t| t.to_s.rjust(2,'0')}.join(':')
36
+ end
37
+
32
38
  private
33
39
 
34
40
  # @return [Integer] the duration of the resource as reported by YouTube.
@@ -27,9 +27,23 @@ module Yt
27
27
  # @return [Yt::Collections::Policies] the policies saved by the content owner.
28
28
  has_many :policies
29
29
 
30
+ # @return [String] The display name of the content owner.
31
+ attr_reader :display_name
32
+
33
+ # @!attribute [r] video_groups
34
+ # @return [Yt::Collections::VideoGroups] the video-groups managed by the
35
+ # content owner.
36
+ has_many :video_groups
37
+
38
+ # @!attribute [r] bulk_report_jobs
39
+ # @return [Yt::Collections::BulkReportJobs] the bulk reporting jobs managed by the
40
+ # content owner.
41
+ has_many :bulk_report_jobs
42
+
30
43
  def initialize(options = {})
31
44
  super options
32
45
  @owner_name = options[:owner_name]
46
+ @display_name = options[:display_name]
33
47
  end
34
48
 
35
49
  def create_reference(params = {})
@@ -43,6 +57,22 @@ module Yt
43
57
  def create_claim(params = {})
44
58
  claims.insert params
45
59
  end
60
+
61
+ ### PRIVATE API ###
62
+
63
+ # @private
64
+ # Tells `has_many :videos` that account.videos should return all the
65
+ # videos *on behalf of* the content owner (public, private, unlisted).
66
+ def videos_params
67
+ {for_content_owner: true, on_behalf_of_content_owner: @owner_name}
68
+ end
69
+
70
+ # @private
71
+ # Tells `has_many :video_groups` that content_owner.video_groups should
72
+ # return all the video-groups *on behalf of* the content owner
73
+ def video_groups_params
74
+ {on_behalf_of_content_owner: @owner_name}
75
+ end
46
76
  end
47
77
  end
48
- end
78
+ end