yt 0.25.13 → 0.32.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +305 -1
- data/MIT-LICENSE +1 -1
- data/README.md +86 -5
- data/YOUTUBE_IT.md +3 -3
- data/lib/yt.rb +5 -2
- data/lib/yt/actions/list.rb +3 -3
- data/lib/yt/associations/has_authentication.rb +33 -1
- data/lib/yt/associations/has_reports.rb +13 -18
- data/lib/yt/collections/assets.rb +2 -2
- data/lib/yt/collections/authentications.rb +9 -2
- data/lib/yt/collections/base.rb +3 -3
- data/lib/yt/collections/bulk_report_jobs.rb +28 -0
- data/lib/yt/collections/bulk_reports.rb +24 -0
- data/lib/yt/collections/claims.rb +22 -1
- data/lib/yt/collections/comment_threads.rb +41 -0
- data/lib/yt/collections/content_owners.rb +1 -1
- data/lib/yt/collections/group_infos.rb +27 -0
- data/lib/yt/collections/group_items.rb +45 -0
- data/lib/yt/collections/reports.rb +75 -13
- data/lib/yt/collections/revocations.rb +30 -0
- data/lib/yt/collections/video_groups.rb +29 -0
- data/lib/yt/collections/videos.rb +34 -9
- data/lib/yt/constants/geography.rb +326 -0
- data/lib/yt/errors/forbidden.rb +1 -3
- data/lib/yt/errors/no_items.rb +1 -3
- data/lib/yt/errors/request_error.rb +10 -7
- data/lib/yt/errors/server_error.rb +1 -3
- data/lib/yt/errors/unauthorized.rb +3 -3
- data/lib/yt/models/account.rb +12 -0
- data/lib/yt/models/advertising_options_set.rb +4 -4
- data/lib/yt/models/bulk_report.rb +23 -0
- data/lib/yt/models/bulk_report_job.rb +23 -0
- data/lib/yt/models/channel.rb +21 -12
- data/lib/yt/models/claim.rb +13 -2
- data/lib/yt/models/comment.rb +37 -0
- data/lib/yt/models/comment_thread.rb +50 -0
- data/lib/yt/models/content_detail.rb +6 -0
- data/lib/yt/models/content_owner.rb +31 -1
- data/lib/yt/models/group_info.rb +16 -0
- data/lib/yt/models/group_item.rb +15 -0
- data/lib/yt/models/resource.rb +3 -10
- data/lib/yt/models/revocation.rb +12 -0
- data/lib/yt/models/right_owner.rb +0 -2
- data/lib/yt/models/snippet.rb +24 -3
- data/lib/yt/models/video.rb +42 -11
- data/lib/yt/models/video_group.rb +186 -0
- data/lib/yt/request.rb +5 -3
- data/lib/yt/version.rb +2 -2
- data/spec/collections/comment_threads_spec.rb +46 -0
- data/spec/collections/playlist_items_spec.rb +1 -1
- data/spec/collections/reports_spec.rb +2 -2
- data/spec/constants/geography_spec.rb +16 -0
- data/spec/models/annotation_spec.rb +1 -1
- data/spec/models/claim_spec.rb +15 -3
- data/spec/models/comment_spec.rb +40 -0
- data/spec/models/comment_thread_spec.rb +93 -0
- data/spec/models/content_detail_spec.rb +7 -0
- data/spec/models/reference_spec.rb +2 -2
- data/spec/models/request_spec.rb +21 -0
- data/spec/models/resource_spec.rb +0 -15
- data/spec/models/video_spec.rb +1 -1
- data/spec/requests/as_account/account_spec.rb +16 -4
- data/spec/requests/as_account/authentications_spec.rb +1 -13
- data/spec/requests/as_account/channel_spec.rb +15 -45
- data/spec/requests/as_account/playlist_item_spec.rb +3 -3
- data/spec/requests/as_account/playlist_spec.rb +5 -32
- data/spec/requests/as_account/video_spec.rb +2022 -21
- data/spec/requests/as_content_owner/account_spec.rb +4 -0
- data/spec/requests/as_content_owner/bulk_report_job_spec.rb +19 -0
- data/spec/requests/as_content_owner/channel_spec.rb +59 -270
- data/spec/requests/as_content_owner/content_owner_spec.rb +89 -1
- data/spec/requests/as_content_owner/playlist_spec.rb +0 -15
- data/spec/requests/as_content_owner/video_group_spec.rb +112 -0
- data/spec/requests/as_content_owner/video_spec.rb +72 -146
- data/spec/requests/as_server_app/channel_spec.rb +1 -21
- data/spec/requests/as_server_app/comment_spec.rb +22 -0
- data/spec/requests/as_server_app/comment_thread_spec.rb +27 -0
- data/spec/requests/as_server_app/comment_threads_spec.rb +41 -0
- data/spec/requests/as_server_app/playlist_item_spec.rb +2 -2
- data/spec/requests/as_server_app/playlist_spec.rb +1 -22
- data/spec/requests/as_server_app/video_spec.rb +21 -19
- data/spec/requests/as_server_app/videos_spec.rb +5 -5
- data/spec/requests/unauthenticated/video_spec.rb +1 -9
- data/spec/spec_helper.rb +1 -1
- data/yt.gemspec +2 -1
- metadata +51 -17
- data/lib/yt/collections/ids.rb +0 -27
- data/lib/yt/config.rb +0 -54
- data/lib/yt/models/configuration.rb +0 -70
- data/lib/yt/models/description.rb +0 -58
- data/lib/yt/models/url.rb +0 -91
- data/spec/models/configuration_spec.rb +0 -44
- data/spec/models/description_spec.rb +0 -94
- data/spec/models/url_spec.rb +0 -84
- data/spec/requests/as_account/resource_spec.rb +0 -18
data/lib/yt/errors/forbidden.rb
CHANGED
data/lib/yt/errors/no_items.rb
CHANGED
@@ -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
|
@@ -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
|
data/lib/yt/models/account.rb
CHANGED
@@ -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
|
-
|
23
|
-
|
24
|
-
|
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
|
data/lib/yt/models/channel.rb
CHANGED
@@ -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 :
|
181
|
+
has_report :estimated_revenue, Float
|
173
182
|
|
174
183
|
# @macro report_by_day_and_country
|
175
|
-
has_report :
|
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
|
data/lib/yt/models/claim.rb
CHANGED
@@ -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
|