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.
- 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
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'yt/collections/base'
|
|
2
|
+
require 'yt/models/group_item'
|
|
3
|
+
|
|
4
|
+
module Yt
|
|
5
|
+
module Collections
|
|
6
|
+
# @private
|
|
7
|
+
class GroupItems < Base
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def attributes_for_new_item(data)
|
|
12
|
+
super(data).tap do |attributes|
|
|
13
|
+
attributes[:video] = data['video']
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def list_params
|
|
18
|
+
super.tap do |params|
|
|
19
|
+
params[:host] = 'youtubeanalytics.googleapis.com'
|
|
20
|
+
params[:path] = "/v2/groupItems"
|
|
21
|
+
params[:params] = {group_id: @parent.id}
|
|
22
|
+
if @auth.owner_name
|
|
23
|
+
params[:params][:on_behalf_of_content_owner] = @auth.owner_name
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def eager_load_items_from(items)
|
|
29
|
+
if included_relationships.include?(:video)
|
|
30
|
+
all_video_ids = items.map{|item| item['resource']['id']}.uniq
|
|
31
|
+
all_video_ids.each_slice(50) do |video_ids|
|
|
32
|
+
conditions = {id: video_ids.join(',')}
|
|
33
|
+
conditions[:part] = 'snippet,status,statistics,contentDetails'
|
|
34
|
+
videos = Collections::Videos.new(auth: @auth).where conditions
|
|
35
|
+
items.each do |item|
|
|
36
|
+
video = videos.find{|v| v.id == item['resource']['id']}
|
|
37
|
+
item['video'] = video if video
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
super
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -11,12 +11,15 @@ module Yt
|
|
|
11
11
|
hash[:traffic_source] = {name: 'insightTrafficSourceType', parse: ->(source, *values) { @metrics.keys.zip(values.map{|v| {TRAFFIC_SOURCES.key(source) => v}}).to_h} }
|
|
12
12
|
hash[:playback_location] = {name: 'insightPlaybackLocationType', parse: ->(location, *values) { @metrics.keys.zip(values.map{|v| {PLAYBACK_LOCATIONS.key(location) => v}}).to_h} }
|
|
13
13
|
hash[:embedded_player_location] = {name: 'insightPlaybackLocationDetail', parse: ->(url, *values) {@metrics.keys.zip(values.map{|v| {url => v}}).to_h} }
|
|
14
|
+
hash[:subscribed_status] = {name: 'subscribedStatus', parse: ->(status, *values) {@metrics.keys.zip(values.map{|v| {SUBSCRIBED_STATUSES.key(status) => v}}).to_h} }
|
|
14
15
|
hash[:related_video] = {name: 'insightTrafficSourceDetail', parse: ->(video_id, *values) { @metrics.keys.zip(values.map{|v| {video_id => v}}).to_h} }
|
|
15
16
|
hash[:search_term] = {name: 'insightTrafficSourceDetail', parse: ->(search_term, *values) {@metrics.keys.zip(values.map{|v| {search_term => v}}).to_h} }
|
|
16
17
|
hash[:referrer] = {name: 'insightTrafficSourceDetail', parse: ->(url, *values) {@metrics.keys.zip(values.map{|v| {url => v}}).to_h} }
|
|
17
18
|
hash[:video] = {name: 'video', parse: ->(video_id, *values) { @metrics.keys.zip(values.map{|v| {video_id => v}}).to_h} }
|
|
18
19
|
hash[:playlist] = {name: 'playlist', parse: ->(playlist_id, *values) { @metrics.keys.zip(values.map{|v| {playlist_id => v}}).to_h} }
|
|
19
|
-
hash[:device_type] = {name: 'deviceType', parse: ->(type, *values) {@metrics.keys.zip(values.map{|v| {type
|
|
20
|
+
hash[:device_type] = {name: 'deviceType', parse: ->(type, *values) {@metrics.keys.zip(values.map{|v| {DEVICE_TYPES.key(type) => v}}).to_h} }
|
|
21
|
+
hash[:operating_system] = {name: 'operatingSystem', parse: ->(os, *values) {@metrics.keys.zip(values.map{|v| {OPERATING_SYSTEMS.key(os) => v}}).to_h} }
|
|
22
|
+
hash[:youtube_product] = {name: 'youtubeProduct', parse: ->(product, *values) {@metrics.keys.zip(values.map{|v| {YOUTUBE_PRODUCTS.key(product) => v}}).to_h} }
|
|
20
23
|
hash[:country] = {name: 'country', parse: ->(country_code, *values) { @metrics.keys.zip(values.map{|v| {country_code => v}}).to_h} }
|
|
21
24
|
hash[:state] = {name: 'province', parse: ->(country_and_state_code, *values) { @metrics.keys.zip(values.map{|v| {country_and_state_code[3..-1] => v}}).to_h} }
|
|
22
25
|
hash[:gender_age_group] = {name: 'gender,ageGroup', parse: ->(gender, *values) { [gender.downcase.to_sym, *values] }}
|
|
@@ -43,6 +46,8 @@ module Yt
|
|
|
43
46
|
google: 'GOOGLE_SEARCH',
|
|
44
47
|
notification: 'NOTIFICATION',
|
|
45
48
|
playlist_page: 'YT_PLAYLIST_PAGE',
|
|
49
|
+
campaign_card: 'CAMPAIGN_CARD',
|
|
50
|
+
end_screen: 'END_SCREEN',
|
|
46
51
|
info_card: 'INFO_CARD'
|
|
47
52
|
}
|
|
48
53
|
|
|
@@ -53,17 +58,72 @@ module Yt
|
|
|
53
58
|
embedded: 'EMBEDDED',
|
|
54
59
|
other: 'YT_OTHER',
|
|
55
60
|
external_app: 'EXTERNAL_APP',
|
|
61
|
+
search: 'SEARCH', # undocumented but returned by the API
|
|
62
|
+
browse: 'BROWSE', # undocumented but returned by the API
|
|
56
63
|
mobile: 'MOBILE' # only present for data < September 10, 2013
|
|
57
64
|
}
|
|
58
65
|
|
|
66
|
+
# @see https://developers.google.com/youtube/analytics/v1/dimsmets/dims#Playback_Detail_Dimensions
|
|
67
|
+
SUBSCRIBED_STATUSES = {
|
|
68
|
+
subscribed: 'SUBSCRIBED',
|
|
69
|
+
unsubscribed: 'UNSUBSCRIBED'
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# @see https://developers.google.com/youtube/analytics/v1/dimsmets/dims#youtubeProduct
|
|
73
|
+
YOUTUBE_PRODUCTS = {
|
|
74
|
+
core: 'CORE',
|
|
75
|
+
gaming: 'GAMING',
|
|
76
|
+
kids: 'KIDS',
|
|
77
|
+
unknown: 'UNKNOWN'
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# @see https://developers.google.com/youtube/analytics/v1/dimsmets/dims#Device_Dimensions
|
|
81
|
+
DEVICE_TYPES = {
|
|
82
|
+
desktop: 'DESKTOP',
|
|
83
|
+
game_console: 'GAME_CONSOLE',
|
|
84
|
+
mobile: 'MOBILE',
|
|
85
|
+
tablet: 'TABLET',
|
|
86
|
+
tv: 'TV',
|
|
87
|
+
unknown_platform: 'UNKNOWN_PLATFORM'
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# @see https://developers.google.com/youtube/analytics/v1/dimsmets/dims#Device_Dimensions
|
|
91
|
+
OPERATING_SYSTEMS = {
|
|
92
|
+
android: 'ANDROID',
|
|
93
|
+
bada: 'BADA',
|
|
94
|
+
blackberry: 'BLACKBERRY',
|
|
95
|
+
chromecast: 'CHROMECAST',
|
|
96
|
+
docomo: 'DOCOMO',
|
|
97
|
+
firefox: 'FIREFOX',
|
|
98
|
+
hiptop: 'HIPTOP',
|
|
99
|
+
ios: 'IOS',
|
|
100
|
+
linux: 'LINUX',
|
|
101
|
+
macintosh: 'MACINTOSH',
|
|
102
|
+
meego: 'MEEGO',
|
|
103
|
+
nintendo_3ds: 'NINTENDO_3DS',
|
|
104
|
+
other: 'OTHER',
|
|
105
|
+
playstation: 'PLAYSTATION',
|
|
106
|
+
playstation_vita: 'PLAYSTATION_VITA',
|
|
107
|
+
realmedia: 'REALMEDIA',
|
|
108
|
+
smart_tv: 'SMART_TV',
|
|
109
|
+
symbian: 'SYMBIAN',
|
|
110
|
+
tizen: 'TIZEN',
|
|
111
|
+
webos: 'WEBOS',
|
|
112
|
+
wii: 'WII',
|
|
113
|
+
windows: 'WINDOWS',
|
|
114
|
+
windows_mobile: 'WINDOWS_MOBILE',
|
|
115
|
+
xbox: 'XBOX'
|
|
116
|
+
}
|
|
117
|
+
|
|
59
118
|
attr_writer :metrics
|
|
60
119
|
|
|
61
|
-
def within(days_range, country, state, dimension, videos,
|
|
120
|
+
def within(days_range, country, state, dimension, videos, historical, max_retries = 3)
|
|
62
121
|
@days_range = days_range
|
|
63
|
-
@dimension = dimension
|
|
64
122
|
@country = country
|
|
65
123
|
@state = state
|
|
124
|
+
@dimension = dimension
|
|
66
125
|
@videos = videos
|
|
126
|
+
@historical = historical
|
|
67
127
|
if dimension == :gender_age_group # array of array
|
|
68
128
|
Hash.new{|h,k| h[k] = Hash.new 0.0}.tap do |hash|
|
|
69
129
|
each{|gender, age_group, value| hash[gender][age_group[3..-1]] = value}
|
|
@@ -86,10 +146,10 @@ module Yt
|
|
|
86
146
|
end
|
|
87
147
|
elsif dimension == :day
|
|
88
148
|
hash = hash.transform_values{|h| h.sort_by{|day, v| day}.to_h}
|
|
89
|
-
elsif dimension.in? [:traffic_source, :country, :state, :playback_location, :device_type]
|
|
149
|
+
elsif dimension.in? [:traffic_source, :country, :state, :playback_location, :device_type, :operating_system, :subscribed_status]
|
|
90
150
|
hash = hash.transform_values{|h| h.sort_by{|range, v| -v}.to_h}
|
|
91
151
|
end
|
|
92
|
-
(@metrics.one? || @metrics.keys == [:
|
|
152
|
+
(@metrics.one? || @metrics.keys == [:estimated_revenue, :estimated_minutes_watched]) ? hash[@metrics.keys.first] : hash
|
|
93
153
|
end
|
|
94
154
|
# NOTE: Once in a while, YouTube responds with 400 Error and the message
|
|
95
155
|
# "Invalid query. Query did not conform to the expectations."; in this
|
|
@@ -98,7 +158,7 @@ module Yt
|
|
|
98
158
|
# same query is a workaround that works and can hardly cause any damage.
|
|
99
159
|
# Similarly, once in while YouTube responds with a random 503 error.
|
|
100
160
|
rescue Yt::Error => e
|
|
101
|
-
|
|
161
|
+
(max_retries > 0) && rescue?(e) ? sleep(3) && within(days_range, country, state, dimension, videos, historical, max_retries - 1) : raise
|
|
102
162
|
end
|
|
103
163
|
|
|
104
164
|
private
|
|
@@ -117,7 +177,8 @@ module Yt
|
|
|
117
177
|
# @see https://developers.google.com/youtube/analytics/v1/content_owner_reports
|
|
118
178
|
def list_params
|
|
119
179
|
super.tap do |params|
|
|
120
|
-
params[:
|
|
180
|
+
params[:host] = 'youtubeanalytics.googleapis.com'
|
|
181
|
+
params[:path] = '/v2/reports'
|
|
121
182
|
params[:params] = reports_params
|
|
122
183
|
params[:camelize_params] = false
|
|
123
184
|
end
|
|
@@ -125,15 +186,16 @@ module Yt
|
|
|
125
186
|
|
|
126
187
|
def reports_params
|
|
127
188
|
@parent.reports_params.tap do |params|
|
|
128
|
-
params['
|
|
129
|
-
params['
|
|
189
|
+
params['startDate'] = @days_range.begin
|
|
190
|
+
params['endDate'] = @days_range.end
|
|
130
191
|
params['metrics'] = @metrics.keys.join(',').to_s.camelize(:lower)
|
|
131
192
|
params['dimensions'] = DIMENSIONS[@dimension][:name] unless @dimension == :range
|
|
132
|
-
params['
|
|
133
|
-
params['
|
|
193
|
+
params['includeHistoricalChannelData'] = @historical if @historical
|
|
194
|
+
params['maxResults'] = 50 if @dimension.in? [:playlist, :video]
|
|
195
|
+
params['maxResults'] = 25 if @dimension.in? [:embedded_player_location, :related_video, :search_term, :referrer]
|
|
134
196
|
if @dimension.in? [:video, :playlist, :embedded_player_location, :related_video, :search_term, :referrer]
|
|
135
|
-
if @metrics.keys == [:
|
|
136
|
-
params['sort'] = '-
|
|
197
|
+
if @metrics.keys == [:estimated_revenue, :estimated_minutes_watched]
|
|
198
|
+
params['sort'] = '-estimatedRevenue'
|
|
137
199
|
else
|
|
138
200
|
params['sort'] = "-#{@metrics.keys.join(',').to_s.camelize(:lower)}"
|
|
139
201
|
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'yt/collections/authentications'
|
|
2
|
+
require 'yt/models/revocation'
|
|
3
|
+
|
|
4
|
+
module Yt
|
|
5
|
+
module Collections
|
|
6
|
+
class Revocations < Authentications
|
|
7
|
+
attr_accessor :auth_params
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
# This overrides the parent mehthod defined in Authentications
|
|
12
|
+
def attributes_for_new_item(data)
|
|
13
|
+
{data: data}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def list_params
|
|
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
|
|
22
|
+
params[:auth] = nil
|
|
23
|
+
params[:body] = nil
|
|
24
|
+
params[:camelize_body] = false
|
|
25
|
+
params[:params] = auth_params
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'yt/collections/base'
|
|
2
|
+
require 'yt/models/video_group'
|
|
3
|
+
require 'yt/models/group_info'
|
|
4
|
+
|
|
5
|
+
module Yt
|
|
6
|
+
module Collections
|
|
7
|
+
# @private
|
|
8
|
+
class VideoGroups < Base
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def attributes_for_new_item(data)
|
|
13
|
+
{id: data['id'], auth: @auth, group_info: Yt::GroupInfo.new(data: data)}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def new_item(data)
|
|
17
|
+
super if data['contentDetails']['itemType'] == 'youtube#video'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def list_params
|
|
21
|
+
super.tap do |params|
|
|
22
|
+
params[:host] = 'youtubeanalytics.googleapis.com'
|
|
23
|
+
params[:path] = "/v2/groups"
|
|
24
|
+
params[:params] = @parent.video_groups_params
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -10,6 +10,7 @@ module Yt
|
|
|
10
10
|
class Videos < Base
|
|
11
11
|
def where(requirements = {})
|
|
12
12
|
@published_before = nil
|
|
13
|
+
@halt_list = false
|
|
13
14
|
super
|
|
14
15
|
end
|
|
15
16
|
|
|
@@ -25,18 +26,23 @@ module Yt
|
|
|
25
26
|
attributes[:content_details] = data['contentDetails']
|
|
26
27
|
attributes[:statistics] = data['statistics']
|
|
27
28
|
attributes[:video_category] = data['videoCategory']
|
|
29
|
+
attributes[:claim] = data['claim']
|
|
28
30
|
attributes[:auth] = @auth
|
|
29
31
|
end
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
def eager_load_items_from(items)
|
|
33
35
|
if included_relationships.any?
|
|
34
|
-
|
|
35
|
-
included_relationships
|
|
36
|
+
associations = [:claim, :category]
|
|
37
|
+
if (included_relationships & associations).any?
|
|
38
|
+
included_relationships.append(:snippet).uniq!
|
|
39
|
+
end
|
|
36
40
|
|
|
37
41
|
ids = items.map{|item| item['id']['videoId']}
|
|
38
|
-
parts = included_relationships.map
|
|
39
|
-
|
|
42
|
+
parts = (included_relationships - associations).map do |r|
|
|
43
|
+
r.to_s.camelize(:lower)
|
|
44
|
+
end
|
|
45
|
+
conditions = { id: ids.join(','), part: parts.join(',') }
|
|
40
46
|
videos = Collections::Videos.new(auth: @auth).where conditions
|
|
41
47
|
|
|
42
48
|
items.each do |item|
|
|
@@ -51,7 +57,20 @@ module Yt
|
|
|
51
57
|
end if video
|
|
52
58
|
end
|
|
53
59
|
|
|
54
|
-
if
|
|
60
|
+
if included_relationships.include? :claim
|
|
61
|
+
video_ids = items.map{|item| item['id']['videoId']}.uniq
|
|
62
|
+
conditions = {
|
|
63
|
+
video_id: video_ids.join(','),
|
|
64
|
+
include_third_party_claims: false
|
|
65
|
+
}
|
|
66
|
+
claims = @parent.claims.includes(:asset).where conditions
|
|
67
|
+
items.each do |item|
|
|
68
|
+
claim = claims.find { |c| c.video_id == item['id']['videoId']}
|
|
69
|
+
item['claim'] = claim
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
if included_relationships.include? :category
|
|
55
74
|
category_ids = items.map{|item| item['snippet']['categoryId']}.uniq
|
|
56
75
|
conditions = {id: category_ids.join(',')}
|
|
57
76
|
video_categories = Collections::VideoCategories.new(auth: @auth).where conditions
|
|
@@ -77,7 +96,7 @@ module Yt
|
|
|
77
96
|
def next_page
|
|
78
97
|
super.tap do |items|
|
|
79
98
|
halt_list if use_list_endpoint? && items.empty? && @page_token.nil?
|
|
80
|
-
add_offset_to(items) if !use_list_endpoint? &&
|
|
99
|
+
add_offset_to(items) if !use_list_endpoint? && videos_params[:order] == 'date' && !(videos_params[:for_mine] || videos_params[:for_content_owner])
|
|
81
100
|
end
|
|
82
101
|
end
|
|
83
102
|
|
|
@@ -86,9 +105,15 @@ module Yt
|
|
|
86
105
|
# that limit, the query is restarted with a publishedBefore filter in
|
|
87
106
|
# case there are more videos to be listed for a channel
|
|
88
107
|
def add_offset_to(items)
|
|
89
|
-
|
|
108
|
+
@fetched_items ||= 0
|
|
109
|
+
if (@fetched_items += items.count) >= 500
|
|
90
110
|
last_published = items.last['snippet']['publishedAt']
|
|
91
|
-
|
|
111
|
+
last_published = DateTime.rfc3339(last_published) - 1.second
|
|
112
|
+
last_published = last_published.strftime '%FT%T.999Z'
|
|
113
|
+
@page_token, @published_before, @fetched_items = '', last_published, 0
|
|
114
|
+
elsif (1...50) === @last_index % 50
|
|
115
|
+
@halt_list, @page_token = true, nil
|
|
116
|
+
@last_index += items.size
|
|
92
117
|
end
|
|
93
118
|
end
|
|
94
119
|
|
|
@@ -134,4 +159,4 @@ module Yt
|
|
|
134
159
|
end
|
|
135
160
|
end
|
|
136
161
|
end
|
|
137
|
-
end
|
|
162
|
+
end
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
require 'active_support'
|
|
2
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
|
3
|
+
|
|
4
|
+
module Yt
|
|
5
|
+
# The list of country codes and names used by the YouTube Analytics API.
|
|
6
|
+
# @see https://developers.google.com/youtube/analytics/v1/dimsmets/dims#country
|
|
7
|
+
COUNTRIES = {
|
|
8
|
+
AC: 'Ascension',
|
|
9
|
+
AD: 'Andorra',
|
|
10
|
+
AE: 'United Arab Emirates',
|
|
11
|
+
AF: 'Afghanistan',
|
|
12
|
+
AG: 'Antigua and Barbuda',
|
|
13
|
+
AI: 'Anguilla',
|
|
14
|
+
AL: 'Albania',
|
|
15
|
+
AM: 'Armenia',
|
|
16
|
+
AN: 'Netherlands Antilles',
|
|
17
|
+
AO: 'Angola',
|
|
18
|
+
AQ: 'Antarctic Territory',
|
|
19
|
+
AR: 'Argentina',
|
|
20
|
+
AS: 'American Samoa',
|
|
21
|
+
AT: 'Austria',
|
|
22
|
+
AU: 'Australia',
|
|
23
|
+
AW: 'Aruba',
|
|
24
|
+
AX: 'Aland',
|
|
25
|
+
AZ: 'Azerbaijan',
|
|
26
|
+
BA: 'Bosnia and Herzegovina',
|
|
27
|
+
BB: 'Barbados',
|
|
28
|
+
BD: 'Bangladesh',
|
|
29
|
+
BE: 'Belgium',
|
|
30
|
+
BF: 'Burkina Faso',
|
|
31
|
+
BG: 'Bulgaria',
|
|
32
|
+
BH: 'Bahrain',
|
|
33
|
+
BI: 'Burundi',
|
|
34
|
+
BJ: 'Benin',
|
|
35
|
+
BL: 'Saint Barthélemy',
|
|
36
|
+
BM: 'Bermuda',
|
|
37
|
+
BN: 'Brunei',
|
|
38
|
+
BO: 'Bolivia',
|
|
39
|
+
BQ: 'Bonaire, Sint Eustatius and Saba',
|
|
40
|
+
BR: 'Brazil',
|
|
41
|
+
BS: 'Bahamas',
|
|
42
|
+
BT: 'Bhutan',
|
|
43
|
+
BV: 'Bouvet Island',
|
|
44
|
+
BW: 'Botswana',
|
|
45
|
+
BY: 'Belarus',
|
|
46
|
+
BZ: 'Belize',
|
|
47
|
+
CA: 'Canada',
|
|
48
|
+
CC: 'Cocos (Keeling) Islands',
|
|
49
|
+
CD: 'Congo',
|
|
50
|
+
CF: 'Central African Republic',
|
|
51
|
+
CG: 'Congo',
|
|
52
|
+
CH: 'Switzerland',
|
|
53
|
+
CI: 'Ivory Coast',
|
|
54
|
+
CK: 'Cook Islands',
|
|
55
|
+
CL: 'Chile',
|
|
56
|
+
CM: 'Cameroon',
|
|
57
|
+
CN: 'China',
|
|
58
|
+
CO: 'Colombia',
|
|
59
|
+
CR: 'Costa Rica',
|
|
60
|
+
CU: 'Cuba',
|
|
61
|
+
CV: 'Cape Verde',
|
|
62
|
+
CW: 'Curaçao',
|
|
63
|
+
CX: 'Christmas Island',
|
|
64
|
+
CY: 'Cyprus',
|
|
65
|
+
CZ: 'Czech Republic',
|
|
66
|
+
DE: 'Germany',
|
|
67
|
+
DJ: 'Djibouti',
|
|
68
|
+
DK: 'Denmark',
|
|
69
|
+
DM: 'Dominica',
|
|
70
|
+
DO: 'Dominican Republic',
|
|
71
|
+
DZ: 'Algeria',
|
|
72
|
+
EC: 'Ecuador',
|
|
73
|
+
EE: 'Estonia',
|
|
74
|
+
EG: 'Egypt',
|
|
75
|
+
EH: 'Western Sahara',
|
|
76
|
+
ER: 'Eritrea',
|
|
77
|
+
ES: 'Spain',
|
|
78
|
+
ET: 'Ethiopia',
|
|
79
|
+
FI: 'Finland',
|
|
80
|
+
FJ: 'Fiji',
|
|
81
|
+
FK: 'Falkland Islands',
|
|
82
|
+
FM: 'Micronesia',
|
|
83
|
+
FO: 'Faroe Islands',
|
|
84
|
+
FR: 'France',
|
|
85
|
+
GA: 'Gabon',
|
|
86
|
+
GB: 'United Kingdom',
|
|
87
|
+
GD: 'Grenada',
|
|
88
|
+
GE: 'Georgia',
|
|
89
|
+
GF: 'French Guiana',
|
|
90
|
+
GG: 'Guernsey',
|
|
91
|
+
GH: 'Ghana',
|
|
92
|
+
GI: 'Gibraltar',
|
|
93
|
+
GL: 'Greenland',
|
|
94
|
+
GM: 'Gambia',
|
|
95
|
+
GN: 'Guinea',
|
|
96
|
+
GP: 'Guadeloupe',
|
|
97
|
+
GQ: 'Equatorial Guinea',
|
|
98
|
+
GR: 'Greece',
|
|
99
|
+
GS: 'South Georgia & South Sandwich Islands',
|
|
100
|
+
GT: 'Guatemala',
|
|
101
|
+
GU: 'Guam',
|
|
102
|
+
GW: 'Guinea-Bissau',
|
|
103
|
+
GY: 'Guyana',
|
|
104
|
+
HK: 'Hong Kong',
|
|
105
|
+
HM: 'Heard Island and McDonald Islands',
|
|
106
|
+
HN: 'Honduras',
|
|
107
|
+
HR: 'Croatia',
|
|
108
|
+
HT: 'Haiti',
|
|
109
|
+
HU: 'Hungary',
|
|
110
|
+
ID: 'Indonesia',
|
|
111
|
+
IE: 'Ireland',
|
|
112
|
+
IL: 'Israel',
|
|
113
|
+
IM: 'Isle of Man',
|
|
114
|
+
IN: 'India',
|
|
115
|
+
IO: 'British Indian Ocean Territory',
|
|
116
|
+
IQ: 'Iraq',
|
|
117
|
+
IR: 'Iran',
|
|
118
|
+
IS: 'Iceland',
|
|
119
|
+
IT: 'Italy',
|
|
120
|
+
JE: 'Jersey',
|
|
121
|
+
JM: 'Jamaica',
|
|
122
|
+
JO: 'Jordan',
|
|
123
|
+
JP: 'Japan',
|
|
124
|
+
KE: 'Kenya',
|
|
125
|
+
KG: 'Kyrgyzstan',
|
|
126
|
+
KH: 'Cambodia',
|
|
127
|
+
KI: 'Kiribati',
|
|
128
|
+
KM: 'Comoros',
|
|
129
|
+
KN: 'Saint Kitts and Nevis',
|
|
130
|
+
KP: 'North Korea',
|
|
131
|
+
KR: 'South Korea',
|
|
132
|
+
KW: 'Kuwait',
|
|
133
|
+
KY: 'Cayman Islands',
|
|
134
|
+
KZ: 'Kazakhstan',
|
|
135
|
+
LA: 'Laos',
|
|
136
|
+
LB: 'Lebanon',
|
|
137
|
+
LC: 'Saint Lucia',
|
|
138
|
+
LI: 'Liechtenstein',
|
|
139
|
+
LK: 'Sri Lanka',
|
|
140
|
+
LR: 'Liberia',
|
|
141
|
+
LS: 'Lesotho',
|
|
142
|
+
LT: 'Lithuania',
|
|
143
|
+
LU: 'Luxembourg',
|
|
144
|
+
LV: 'Latvia',
|
|
145
|
+
LY: 'Libya',
|
|
146
|
+
MA: 'Morocco',
|
|
147
|
+
MC: 'Monaco',
|
|
148
|
+
MD: 'Moldova',
|
|
149
|
+
ME: 'Montenegro',
|
|
150
|
+
MF: 'Saint Martin',
|
|
151
|
+
MG: 'Madagascar',
|
|
152
|
+
MH: 'Marshall Islands',
|
|
153
|
+
MK: 'Macedonia',
|
|
154
|
+
ML: 'Mali',
|
|
155
|
+
MM: 'Myanmar',
|
|
156
|
+
MN: 'Mongolia',
|
|
157
|
+
MO: 'Macau',
|
|
158
|
+
MP: 'Northern Mariana Islands',
|
|
159
|
+
MQ: 'Martinique',
|
|
160
|
+
MR: 'Mauritania',
|
|
161
|
+
MS: 'Montserrat',
|
|
162
|
+
MT: 'Malta',
|
|
163
|
+
MU: 'Mauritius',
|
|
164
|
+
MV: 'Maldives',
|
|
165
|
+
MW: 'Malawi',
|
|
166
|
+
MX: 'Mexico',
|
|
167
|
+
MY: 'Malaysia',
|
|
168
|
+
MZ: 'Mozambique',
|
|
169
|
+
NA: 'Namibia',
|
|
170
|
+
NC: 'New Caledonia',
|
|
171
|
+
NE: 'Niger',
|
|
172
|
+
NF: 'Norfolk Island',
|
|
173
|
+
NG: 'Nigeria',
|
|
174
|
+
NI: 'Nicaragua',
|
|
175
|
+
NL: 'Netherlands',
|
|
176
|
+
NO: 'Norway',
|
|
177
|
+
NP: 'Nepal',
|
|
178
|
+
NR: 'Nauru',
|
|
179
|
+
NU: 'Niue',
|
|
180
|
+
NZ: 'New Zealand',
|
|
181
|
+
OM: 'Oman',
|
|
182
|
+
PA: 'Panama',
|
|
183
|
+
PE: 'Peru',
|
|
184
|
+
PF: 'French Polynesia',
|
|
185
|
+
PG: 'Papua New Guinea',
|
|
186
|
+
PH: 'Philippines',
|
|
187
|
+
PK: 'Pakistan',
|
|
188
|
+
PL: 'Poland',
|
|
189
|
+
PM: 'Saint Pierre and Miquelon',
|
|
190
|
+
PN: 'Pitcairn Islands',
|
|
191
|
+
PR: 'Puerto Rico',
|
|
192
|
+
PS: 'Palestinian Territory',
|
|
193
|
+
PT: 'Portugal',
|
|
194
|
+
PW: 'Palau',
|
|
195
|
+
PY: 'Paraguay',
|
|
196
|
+
QA: 'Qatar',
|
|
197
|
+
RE: 'Reunion',
|
|
198
|
+
RO: 'Romania',
|
|
199
|
+
RS: 'Serbia',
|
|
200
|
+
RU: 'Russia',
|
|
201
|
+
RW: 'Rwanda',
|
|
202
|
+
SA: 'Saudi Arabia',
|
|
203
|
+
SB: 'Solomon Islands',
|
|
204
|
+
SC: 'Seychelles',
|
|
205
|
+
SD: 'Sudan',
|
|
206
|
+
SE: 'Sweden',
|
|
207
|
+
SG: 'Singapore',
|
|
208
|
+
SH: 'Saint Helena',
|
|
209
|
+
SI: 'Slovenia',
|
|
210
|
+
SJ: 'Svalbard',
|
|
211
|
+
SK: 'Slovakia',
|
|
212
|
+
SL: 'Sierra Leone',
|
|
213
|
+
SM: 'San Marino',
|
|
214
|
+
SN: 'Senegal',
|
|
215
|
+
SO: 'Somalia',
|
|
216
|
+
SR: 'Suriname',
|
|
217
|
+
SS: 'South Sudan',
|
|
218
|
+
ST: 'Sao Tome and Principe',
|
|
219
|
+
SV: 'El Salvador',
|
|
220
|
+
SX: 'Sint Maarten',
|
|
221
|
+
SY: 'Syria',
|
|
222
|
+
SZ: 'Swaziland',
|
|
223
|
+
TA: 'Tristan da Cunha',
|
|
224
|
+
TC: 'Turks and Caicos Islands',
|
|
225
|
+
TD: 'Chad',
|
|
226
|
+
TF: 'French Southern and Antarctic Lands',
|
|
227
|
+
TG: 'Togo',
|
|
228
|
+
TH: 'Thailand',
|
|
229
|
+
TJ: 'Tajikistan',
|
|
230
|
+
TK: 'Tokelau',
|
|
231
|
+
TL: 'East Timor',
|
|
232
|
+
TM: 'Turkmenistan',
|
|
233
|
+
TN: 'Tunisia',
|
|
234
|
+
TO: 'Tonga',
|
|
235
|
+
TR: 'Turkey',
|
|
236
|
+
TT: 'Trinidad and Tobago',
|
|
237
|
+
TV: 'Tuvalu',
|
|
238
|
+
TW: 'Taiwan',
|
|
239
|
+
TZ: 'Tanzania',
|
|
240
|
+
UA: 'Ukraine',
|
|
241
|
+
UG: 'Uganda',
|
|
242
|
+
UM: 'Midway Islands',
|
|
243
|
+
US: 'United States',
|
|
244
|
+
UY: 'Uruguay',
|
|
245
|
+
UZ: 'Uzbekistan',
|
|
246
|
+
VA: 'Vatican City',
|
|
247
|
+
VC: 'Saint Vincent and the Grenadines',
|
|
248
|
+
VE: 'Venezuela',
|
|
249
|
+
VG: 'British Virgin Islands',
|
|
250
|
+
VI: 'U.S. Virgin Islands',
|
|
251
|
+
VN: 'Vietnam',
|
|
252
|
+
VU: 'Vanuatu',
|
|
253
|
+
XK: 'Kosovo',
|
|
254
|
+
WF: 'Wallis and Futuna',
|
|
255
|
+
WS: 'Samoa',
|
|
256
|
+
YE: 'Yemen',
|
|
257
|
+
YT: 'Mayotte',
|
|
258
|
+
ZA: 'South Africa',
|
|
259
|
+
ZM: 'Zambia',
|
|
260
|
+
ZW: 'Zimbabwe',
|
|
261
|
+
ZZ: 'Unknown Region'
|
|
262
|
+
}.with_indifferent_access
|
|
263
|
+
|
|
264
|
+
# The list of U.S. state codes and names used by the YouTube Analytics API.
|
|
265
|
+
# @see https://developers.google.com/youtube/analytics/v1/dimsmets/dims#province
|
|
266
|
+
US_STATES = {
|
|
267
|
+
AL: 'Alabama',
|
|
268
|
+
AK: 'Alaska',
|
|
269
|
+
AZ: 'Arizona',
|
|
270
|
+
AR: 'Arkansas',
|
|
271
|
+
CA: 'California',
|
|
272
|
+
CO: 'Colorado',
|
|
273
|
+
CT: 'Connecticut',
|
|
274
|
+
DE: 'Delaware',
|
|
275
|
+
FL: 'Florida',
|
|
276
|
+
GA: 'Georgia',
|
|
277
|
+
HI: 'Hawaii',
|
|
278
|
+
ID: 'Idaho',
|
|
279
|
+
IL: 'Illinois',
|
|
280
|
+
IN: 'Indiana',
|
|
281
|
+
IA: 'Iowa',
|
|
282
|
+
KS: 'Kansas',
|
|
283
|
+
KY: 'Kentucky',
|
|
284
|
+
LA: 'Louisiana',
|
|
285
|
+
ME: 'Maine',
|
|
286
|
+
MD: 'Maryland',
|
|
287
|
+
MA: 'Massachusetts',
|
|
288
|
+
MI: 'Michigan',
|
|
289
|
+
MN: 'Minnesota',
|
|
290
|
+
MS: 'Mississippi',
|
|
291
|
+
MO: 'Missouri',
|
|
292
|
+
MT: 'Montana',
|
|
293
|
+
NE: 'Nebraska',
|
|
294
|
+
NV: 'Nevada',
|
|
295
|
+
NH: 'New Hampshire',
|
|
296
|
+
NJ: 'New Jersey',
|
|
297
|
+
NM: 'New Mexico',
|
|
298
|
+
NY: 'New York',
|
|
299
|
+
NC: 'North Carolina',
|
|
300
|
+
ND: 'North Dakota',
|
|
301
|
+
OH: 'Ohio',
|
|
302
|
+
OK: 'Oklahoma',
|
|
303
|
+
OR: 'Oregon',
|
|
304
|
+
PA: 'Pennsylvania',
|
|
305
|
+
RI: 'Rhode Island',
|
|
306
|
+
SC: 'South Carolina',
|
|
307
|
+
SD: 'South Dakota',
|
|
308
|
+
TN: 'Tennessee',
|
|
309
|
+
TX: 'Texas',
|
|
310
|
+
UT: 'Utah',
|
|
311
|
+
VT: 'Vermont',
|
|
312
|
+
VA: 'Virginia',
|
|
313
|
+
WA: 'Washington',
|
|
314
|
+
WV: 'West Virginia',
|
|
315
|
+
WI: 'Wisconsin',
|
|
316
|
+
WY: 'Wyoming',
|
|
317
|
+
DC: 'District of Columbia',
|
|
318
|
+
AS: 'American Samoa',
|
|
319
|
+
GU: 'Guam',
|
|
320
|
+
MP: 'Northern Mariana Islands',
|
|
321
|
+
PR: 'Puerto Rico',
|
|
322
|
+
UM: 'United States Minor Outlying Islands',
|
|
323
|
+
VI: 'Virgin Islands, U.S.',
|
|
324
|
+
ZZ: 'Unknown Region'
|
|
325
|
+
}.with_indifferent_access
|
|
326
|
+
end
|