yt 0.25.17 → 0.25.18

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4740a6f0d76647ecc9d2fc04ed46fb6386a5c31d
4
- data.tar.gz: f2b37bb5f0b81f4bd597079d75342d35d665871e
3
+ metadata.gz: 326f3adf4a4e1e7bbf64930125f77a404276d391
4
+ data.tar.gz: 26c77d99c92fc26b67b085bb1a453dc297f95a90
5
5
  SHA512:
6
- metadata.gz: eba0b93123998b7a17377f6f3353c00da95ac0c8738d5f8319ae04fa74d1a6b54ad7fcae361dc893fe2c7537a298311859105a8cc08ba8ec89e250e6010610df
7
- data.tar.gz: 87e76462320bedeee2e77d82071cad3c40ff0793963805797561e24737018f416f74b6f75fd5fe795cf8b9ebff42ad71eee1ac8851e0f58906d0b0afd988d676
6
+ metadata.gz: c07e83a315d72de93ec39e4c24b953b7aa65f96cfa7fda272d0f6bc7f18819ba065a407374aef07571b811c5baed4c4bd993c3895c19d39c3d54a0c9eb6c7291
7
+ data.tar.gz: 17cab126cf09804f07a3025f4daab542ae0a5cbb54ee6026953ec9e67e53784b972560fefd74cb66e5c629808c28114adf9080379e820bba7bf8c51cdac9ce8b
@@ -6,6 +6,14 @@ 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.25.18 - 2016-01-08
10
+
11
+ * [FEATURE] Add Yt::COUNTRIES and Yt::US_STATES
12
+ * [FEATURE] Add YouTube Analytics Video Groups
13
+ * [FEATURE] Add `:video_groups` to Yt::Account (list video-groups created by an account)
14
+ * [FEATURE] Add `:video_groups` to Yt::ContentOwner (list video-groups on behalf of a content owner)
15
+ * [FEATURE] Add reports by video-group
16
+
9
17
  ## 0.25.17 - 2016-01-05
10
18
 
11
19
  * [FEATURE] Add `:videos` to Yt::ContentOwner to list videos in network with a content owner
data/lib/yt.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'yt/config'
2
2
  require 'yt/version'
3
+ require 'yt/constants/geography'
3
4
  require 'yt/models/account'
4
5
  require 'yt/models/channel'
5
6
  require 'yt/models/claim'
@@ -9,6 +10,7 @@ require 'yt/models/match_policy'
9
10
  require 'yt/models/playlist'
10
11
  require 'yt/models/playlist_item'
11
12
  require 'yt/models/video'
13
+ require 'yt/models/video_group'
12
14
  require 'yt/models/ownership'
13
15
  require 'yt/models/advertising_options_set'
14
16
 
@@ -47,7 +47,7 @@ module Yt
47
47
  def find_next
48
48
  @items ||= []
49
49
  if @items[@last_index].nil? && more_pages?
50
- more_items = next_page.map{|data| new_item data}
50
+ more_items = next_page.map{|data| new_item data}.compact
51
51
  @items.concat more_items
52
52
  end
53
53
  @items[(@last_index +=1) -1]
@@ -0,0 +1,26 @@
1
+ require 'yt/collections/base'
2
+ require 'yt/models/snippet'
3
+
4
+ module Yt
5
+ module Collections
6
+ # @private
7
+ class GroupInfos < Base
8
+
9
+ private
10
+
11
+ def attributes_for_new_item(data)
12
+ {data: data, auth: @auth}
13
+ end
14
+
15
+ def list_params
16
+ super.tap do |params|
17
+ params[:path] = "/youtube/analytics/v1/groups"
18
+ params[:params] = {id: @parent.id}
19
+ if @auth.owner_name
20
+ params[:params][:on_behalf_of_content_owner] = @auth.owner_name
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,28 @@
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[:path] = "/youtube/analytics/v1/groups"
23
+ params[:params] = @parent.video_groups_params
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,323 @@
1
+ module Yt
2
+ # The list of country codes and names used by the YouTube Analytics API.
3
+ # @see https://developers.google.com/youtube/analytics/v1/dimsmets/dims#country
4
+ COUNTRIES = {
5
+ AC: 'Ascension',
6
+ AD: 'Andorra',
7
+ AE: 'United Arab Emirates',
8
+ AF: 'Afghanistan',
9
+ AG: 'Antigua and Barbuda',
10
+ AI: 'Anguilla',
11
+ AL: 'Albania',
12
+ AM: 'Armenia',
13
+ AN: 'Netherlands Antilles',
14
+ AO: 'Angola',
15
+ AQ: 'Antarctic Territory',
16
+ AR: 'Argentina',
17
+ AS: 'American Samoa',
18
+ AT: 'Austria',
19
+ AU: 'Australia',
20
+ AW: 'Aruba',
21
+ AX: 'Aland',
22
+ AZ: 'Azerbaijan',
23
+ BA: 'Bosnia and Herzegovina',
24
+ BB: 'Barbados',
25
+ BD: 'Bangladesh',
26
+ BE: 'Belgium',
27
+ BF: 'Burkina Faso',
28
+ BG: 'Bulgaria',
29
+ BH: 'Bahrain',
30
+ BI: 'Burundi',
31
+ BJ: 'Benin',
32
+ BL: 'Saint Barthélemy',
33
+ BM: 'Bermuda',
34
+ BN: 'Brunei',
35
+ BO: 'Bolivia',
36
+ BQ: 'Bonaire, Sint Eustatius and Saba',
37
+ BR: 'Brazil',
38
+ BS: 'Bahamas',
39
+ BT: 'Bhutan',
40
+ BV: 'Bouvet Island',
41
+ BW: 'Botswana',
42
+ BY: 'Belarus',
43
+ BZ: 'Belize',
44
+ CA: 'Canada',
45
+ CC: 'Cocos (Keeling) Islands',
46
+ CD: 'Congo',
47
+ CF: 'Central African Republic',
48
+ CG: 'Congo',
49
+ CH: 'Switzerland',
50
+ CI: 'Ivory Coast',
51
+ CK: 'Cook Islands',
52
+ CL: 'Chile',
53
+ CM: 'Cameroon',
54
+ CN: 'China',
55
+ CO: 'Colombia',
56
+ CR: 'Costa Rica',
57
+ CU: 'Cuba',
58
+ CV: 'Cape Verde',
59
+ CW: 'Curaçao',
60
+ CX: 'Christmas Island',
61
+ CY: 'Cyprus',
62
+ CZ: 'Czech Republic',
63
+ DE: 'Germany',
64
+ DJ: 'Djibouti',
65
+ DK: 'Denmark',
66
+ DM: 'Dominica',
67
+ DO: 'Dominican Republic',
68
+ DZ: 'Algeria',
69
+ EC: 'Ecuador',
70
+ EE: 'Estonia',
71
+ EG: 'Egypt',
72
+ EH: 'Western Sahara',
73
+ ER: 'Eritrea',
74
+ ES: 'Spain',
75
+ ET: 'Ethiopia',
76
+ FI: 'Finland',
77
+ FJ: 'Fiji',
78
+ FK: 'Falkland Islands',
79
+ FM: 'Micronesia',
80
+ FO: 'Faroe Islands',
81
+ FR: 'France',
82
+ GA: 'Gabon',
83
+ GB: 'United Kingdom',
84
+ GD: 'Grenada',
85
+ GE: 'Georgia',
86
+ GF: 'French Guiana',
87
+ GG: 'Guernsey',
88
+ GH: 'Ghana',
89
+ GI: 'Gibraltar',
90
+ GL: 'Greenland',
91
+ GM: 'Gambia',
92
+ GN: 'Guinea',
93
+ GP: 'Guadeloupe',
94
+ GQ: 'Equatorial Guinea',
95
+ GR: 'Greece',
96
+ GS: 'South Georgia & South Sandwich Islands',
97
+ GT: 'Guatemala',
98
+ GU: 'Guam',
99
+ GW: 'Guinea-Bissau',
100
+ GY: 'Guyana',
101
+ HK: 'Hong Kong',
102
+ HM: 'Heard Island and McDonald Islands',
103
+ HN: 'Honduras',
104
+ HR: 'Croatia',
105
+ HT: 'Haiti',
106
+ HU: 'Hungary',
107
+ ID: 'Indonesia',
108
+ IE: 'Ireland',
109
+ IL: 'Israel',
110
+ IM: 'Isle of Man',
111
+ IN: 'India',
112
+ IO: 'British Indian Ocean Territory',
113
+ IQ: 'Iraq',
114
+ IR: 'Iran',
115
+ IS: 'Iceland',
116
+ IT: 'Italy',
117
+ JE: 'Jersey',
118
+ JM: 'Jamaica',
119
+ JO: 'Jordan',
120
+ JP: 'Japan',
121
+ KE: 'Kenya',
122
+ KG: 'Kyrgyzstan',
123
+ KH: 'Cambodia',
124
+ KI: 'Kiribati',
125
+ KM: 'Comoros',
126
+ KN: 'Saint Kitts and Nevis',
127
+ KP: 'North Korea',
128
+ KR: 'South Korea',
129
+ KW: 'Kuwait',
130
+ KY: 'Cayman Islands',
131
+ KZ: 'Kazakhstan',
132
+ LA: 'Laos',
133
+ LB: 'Lebanon',
134
+ LC: 'Saint Lucia',
135
+ LI: 'Liechtenstein',
136
+ LK: 'Sri Lanka',
137
+ LR: 'Liberia',
138
+ LS: 'Lesotho',
139
+ LT: 'Lithuania',
140
+ LU: 'Luxembourg',
141
+ LV: 'Latvia',
142
+ LY: 'Libya',
143
+ MA: 'Morocco',
144
+ MC: 'Monaco',
145
+ MD: 'Moldova',
146
+ ME: 'Montenegro',
147
+ MF: 'Saint Martin',
148
+ MG: 'Madagascar',
149
+ MH: 'Marshall Islands',
150
+ MK: 'Macedonia',
151
+ ML: 'Mali',
152
+ MM: 'Myanmar',
153
+ MN: 'Mongolia',
154
+ MO: 'Macau',
155
+ MP: 'Northern Mariana Islands',
156
+ MQ: 'Martinique',
157
+ MR: 'Mauritania',
158
+ MS: 'Montserrat',
159
+ MT: 'Malta',
160
+ MU: 'Mauritius',
161
+ MV: 'Maldives',
162
+ MW: 'Malawi',
163
+ MX: 'Mexico',
164
+ MY: 'Malaysia',
165
+ MZ: 'Mozambique',
166
+ NA: 'Namibia',
167
+ NC: 'New Caledonia',
168
+ NE: 'Niger',
169
+ NF: 'Norfolk Island',
170
+ NG: 'Nigeria',
171
+ NI: 'Nicaragua',
172
+ NL: 'Netherlands',
173
+ NO: 'Norway',
174
+ NP: 'Nepal',
175
+ NR: 'Nauru',
176
+ NU: 'Niue',
177
+ NZ: 'New Zealand',
178
+ OM: 'Oman',
179
+ PA: 'Panama',
180
+ PE: 'Peru',
181
+ PF: 'French Polynesia',
182
+ PG: 'Papua New Guinea',
183
+ PH: 'Philippines',
184
+ PK: 'Pakistan',
185
+ PL: 'Poland',
186
+ PM: 'Saint Pierre and Miquelon',
187
+ PN: 'Pitcairn Islands',
188
+ PR: 'Puerto Rico',
189
+ PS: 'Palestinian Territory',
190
+ PT: 'Portugal',
191
+ PW: 'Palau',
192
+ PY: 'Paraguay',
193
+ QA: 'Qatar',
194
+ RE: 'Reunion',
195
+ RO: 'Romania',
196
+ RS: 'Serbia',
197
+ RU: 'Russia',
198
+ RW: 'Rwanda',
199
+ SA: 'Saudi Arabia',
200
+ SB: 'Solomon Islands',
201
+ SC: 'Seychelles',
202
+ SD: 'Sudan',
203
+ SE: 'Sweden',
204
+ SG: 'Singapore',
205
+ SH: 'Saint Helena',
206
+ SI: 'Slovenia',
207
+ SJ: 'Svalbard',
208
+ SK: 'Slovakia',
209
+ SL: 'Sierra Leone',
210
+ SM: 'San Marino',
211
+ SN: 'Senegal',
212
+ SO: 'Somalia',
213
+ SR: 'Suriname',
214
+ SS: 'South Sudan',
215
+ ST: 'Sao Tome and Principe',
216
+ SV: 'El Salvador',
217
+ SX: 'Sint Maarten',
218
+ SY: 'Syria',
219
+ SZ: 'Swaziland',
220
+ TA: 'Tristan da Cunha',
221
+ TC: 'Turks and Caicos Islands',
222
+ TD: 'Chad',
223
+ TF: 'French Southern and Antarctic Lands',
224
+ TG: 'Togo',
225
+ TH: 'Thailand',
226
+ TJ: 'Tajikistan',
227
+ TK: 'Tokelau',
228
+ TL: 'East Timor',
229
+ TM: 'Turkmenistan',
230
+ TN: 'Tunisia',
231
+ TO: 'Tonga',
232
+ TR: 'Turkey',
233
+ TT: 'Trinidad and Tobago',
234
+ TV: 'Tuvalu',
235
+ TW: 'Taiwan',
236
+ TZ: 'Tanzania',
237
+ UA: 'Ukraine',
238
+ UG: 'Uganda',
239
+ UM: 'Midway Islands',
240
+ US: 'United States',
241
+ UY: 'Uruguay',
242
+ UZ: 'Uzbekistan',
243
+ VA: 'Vatican City',
244
+ VC: 'Saint Vincent and the Grenadines',
245
+ VE: 'Venezuela',
246
+ VG: 'British Virgin Islands',
247
+ VI: 'U.S. Virgin Islands',
248
+ VN: 'Vietnam',
249
+ VU: 'Vanuatu',
250
+ XK: 'Kosovo',
251
+ WF: 'Wallis and Futuna',
252
+ WS: 'Samoa',
253
+ YE: 'Yemen',
254
+ YT: 'Mayotte',
255
+ ZA: 'South Africa',
256
+ ZM: 'Zambia',
257
+ ZW: 'Zimbabwe',
258
+ ZZ: 'Unknown Region'
259
+ }.with_indifferent_access
260
+
261
+ # The list of U.S. state codes and names used by the YouTube Analytics API.
262
+ # @see https://developers.google.com/youtube/analytics/v1/dimsmets/dims#province
263
+ US_STATES = {
264
+ AL: 'Alabama',
265
+ AK: 'Alaska',
266
+ AZ: 'Arizona',
267
+ AR: 'Arkansas',
268
+ CA: 'California',
269
+ CO: 'Colorado',
270
+ CT: 'Connecticut',
271
+ DE: 'Delaware',
272
+ FL: 'Florida',
273
+ GA: 'Georgia',
274
+ HI: 'Hawaii',
275
+ ID: 'Idaho',
276
+ IL: 'Illinois',
277
+ IN: 'Indiana',
278
+ IA: 'Iowa',
279
+ KS: 'Kansas',
280
+ KY: 'Kentucky',
281
+ LA: 'Louisiana',
282
+ ME: 'Maine',
283
+ MD: 'Maryland',
284
+ MA: 'Massachusetts',
285
+ MI: 'Michigan',
286
+ MN: 'Minnesota',
287
+ MS: 'Mississippi',
288
+ MO: 'Missouri',
289
+ MT: 'Montana',
290
+ NE: 'Nebraska',
291
+ NV: 'Nevada',
292
+ NH: 'New Hampshire',
293
+ NJ: 'New Jersey',
294
+ NM: 'New Mexico',
295
+ NY: 'New York',
296
+ NC: 'North Carolina',
297
+ ND: 'North Dakota',
298
+ OH: 'Ohio',
299
+ OK: 'Oklahoma',
300
+ OR: 'Oregon',
301
+ PA: 'Pennsylvania',
302
+ RI: 'Rhode Island',
303
+ SC: 'South Carolina',
304
+ SD: 'South Dakota',
305
+ TN: 'Tennessee',
306
+ TX: 'Texas',
307
+ UT: 'Utah',
308
+ VT: 'Vermont',
309
+ VA: 'Virginia',
310
+ WA: 'Washington',
311
+ WV: 'West Virginia',
312
+ WI: 'Wisconsin',
313
+ WY: 'Wyoming',
314
+ DC: 'District of Columbia',
315
+ AS: 'American Samoa',
316
+ GU: 'Guam',
317
+ MP: 'Northern Mariana Islands',
318
+ PR: 'Puerto Rico',
319
+ UM: 'United States Minor Outlying Islands',
320
+ VI: 'Virgin Islands, U.S.',
321
+ ZZ: 'Unknown Region'
322
+ }.with_indifferent_access
323
+ 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
@@ -30,6 +30,11 @@ module Yt
30
30
  # @return [String] The display name of the content owner.
31
31
  attr_reader :display_name
32
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
+
33
38
  def initialize(options = {})
34
39
  super options
35
40
  @owner_name = options[:owner_name]
@@ -56,6 +61,13 @@ module Yt
56
61
  def videos_params
57
62
  {for_content_owner: true, on_behalf_of_content_owner: @owner_name}
58
63
  end
64
+
65
+ # @private
66
+ # Tells `has_many :video_groups` that content_owner.video_groups should
67
+ # return all the video-groups *on behalf of* the content owner
68
+ def video_groups_params
69
+ {on_behalf_of_content_owner: @owner_name}
70
+ end
59
71
  end
60
72
  end
61
73
  end
@@ -0,0 +1,16 @@
1
+ module Yt
2
+ module Models
3
+ class GroupInfo < Base
4
+ attr_reader :data
5
+
6
+ def initialize(options = {})
7
+ @data = options[:data]['snippet'].merge options[:data]['contentDetails']
8
+ @auth = options[:auth]
9
+ end
10
+
11
+ has_attribute :title, default: ''
12
+ has_attribute :item_count, type: Integer
13
+ has_attribute :published_at, type: Time
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,127 @@
1
+ require 'yt/models/base'
2
+
3
+ module Yt
4
+ module Models
5
+ # Provides methods to interact with YouTube Analytics video-groups.
6
+ # @see https://developers.google.com/youtube/analytics/v1/reference/groups
7
+ class VideoGroup < Base
8
+ # @private
9
+ attr_reader :id, :auth
10
+
11
+ ### GROUP INFO ###
12
+
13
+ has_one :group_info
14
+
15
+ # @!attribute [r] title
16
+ # @return [String] the title of the group.
17
+ delegate :title, to: :group_info
18
+
19
+ # @!attribute [r] item_count
20
+ # @return [Integer] the number of resources in the group.
21
+ delegate :item_count, to: :group_info
22
+
23
+ # @!attribute [r] published_at
24
+ # @return [Time] the date and time when the group was created.
25
+ delegate :published_at, to: :group_info
26
+
27
+ ### ANALYTICS ###
28
+
29
+ # @macro reports
30
+
31
+ # @macro report_by_video_dimensions
32
+ has_report :views, Integer
33
+
34
+ # @macro report_by_day
35
+ has_report :uniques, Integer
36
+
37
+ # @macro report_by_video_dimensions
38
+ has_report :estimated_minutes_watched, Integer
39
+
40
+ # @macro report_by_gender_and_age_group
41
+ has_report :viewer_percentage, Float
42
+
43
+ # @macro report_by_day_and_country
44
+ has_report :comments, Integer
45
+
46
+ # @macro report_by_day_and_country
47
+ has_report :likes, Integer
48
+
49
+ # @macro report_by_day_and_country
50
+ has_report :dislikes, Integer
51
+
52
+ # @macro report_by_day_and_country
53
+ has_report :shares, Integer
54
+
55
+ # @note This is not the total number of subscribers gained by the video’s
56
+ # channel, but the subscribers gained *from* the video’s page.
57
+ # @macro report_by_day_and_country
58
+ has_report :subscribers_gained, Integer
59
+
60
+ # @note This is not the total number of subscribers lost by the video’s
61
+ # channel, but the subscribers lost *from* the video’s page.
62
+ # @macro report_by_day_and_country
63
+ has_report :subscribers_lost, Integer
64
+
65
+ # @macro report_by_day_and_country
66
+ has_report :favorites_added, Integer
67
+
68
+ # @macro report_by_day_and_country
69
+ has_report :favorites_removed, Integer
70
+
71
+ # @macro report_by_day_and_country
72
+ has_report :videos_added_to_playlists, Integer
73
+
74
+ # @macro report_by_day_and_country
75
+ has_report :videos_removed_from_playlists, Integer
76
+
77
+ # @macro report_by_day_and_state
78
+ has_report :average_view_duration, Integer
79
+
80
+ # @macro report_by_day_and_state
81
+ has_report :average_view_percentage, Float
82
+
83
+ # @macro report_by_day_and_state
84
+ has_report :annotation_clicks, Integer
85
+
86
+ # @macro report_by_day_and_state
87
+ has_report :annotation_click_through_rate, Float
88
+
89
+ # @macro report_by_day_and_state
90
+ has_report :annotation_close_rate, Float
91
+
92
+ # @macro report_by_day_and_country
93
+ has_report :earnings, Float
94
+
95
+ # @macro report_by_day_and_country
96
+ has_report :impressions, Integer
97
+
98
+ # @macro report_by_day_and_country
99
+ has_report :monetized_playbacks, Integer
100
+
101
+ # @macro report_by_day_and_country
102
+ has_report :playback_based_cpm, Float
103
+
104
+ ### PRIVATE API ###
105
+
106
+ # @private
107
+ def initialize(options = {})
108
+ @id = options[:id]
109
+ @auth = options[:auth]
110
+ @group_info = options[:group_info] if options[:group_info]
111
+ end
112
+
113
+ # @private
114
+ # Tells `has_reports` to retrieve group reports from the Analytics API.
115
+ def reports_params
116
+ {}.tap do |params|
117
+ if auth.owner_name
118
+ params[:ids] = "contentOwner==#{auth.owner_name}"
119
+ else
120
+ params[:ids] = "channel==mine"
121
+ end
122
+ params[:filters] = "group==#{id}"
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -210,6 +210,7 @@ module Yt
210
210
  Errno::ENETUNREACH,
211
211
  Errno::ECONNRESET,
212
212
  Net::OpenTimeout,
213
+ SocketError,
213
214
  Net::HTTPServerError
214
215
  ] + extra_server_errors
215
216
  end
@@ -233,7 +234,7 @@ module Yt
233
234
  @retries_so_far += 1
234
235
  if (@retries_so_far < max_retries)
235
236
  @response = @http_request = @uri = nil
236
- sleep 3
237
+ sleep 3 + (10 * @retries_so_far)
237
238
  end
238
239
  end
239
240
 
@@ -1,3 +1,3 @@
1
1
  module Yt
2
- VERSION = '0.25.17'
2
+ VERSION = '0.25.18'
3
3
  end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+ require 'yt/constants/geography'
3
+
4
+ describe 'Yt::COUNTRIES' do
5
+ it 'returns all country codes and names' do
6
+ expect(Yt::COUNTRIES[:US]).to eq 'United States'
7
+ expect(Yt::COUNTRIES['IT']).to eq 'Italy'
8
+ end
9
+ end
10
+
11
+ describe 'Yt::US_STATES' do
12
+ it 'returns all U.S. state codes and names' do
13
+ expect(Yt::US_STATES[:CA]).to eq 'California'
14
+ expect(Yt::US_STATES['CO']).to eq 'Colorado'
15
+ end
16
+ end
@@ -178,6 +178,27 @@ describe Yt::Request do
178
178
  it { expect{request.run}.not_to fail }
179
179
  end
180
180
  end
181
+
182
+ # NOTE: This test is just a reflection of YouTube irrational behavior of
183
+ # being unavailable once in a while, and therefore causing Net::HTTP to
184
+ # fail, although retrying after some seconds works.
185
+ context 'a SocketError', ruby21: true do
186
+ let(:http_error) { SocketError.new }
187
+
188
+ context 'every time' do
189
+ before { expect(Net::HTTP).to receive(:start).at_least(:once).and_raise http_error }
190
+
191
+ it { expect{request.run}.to fail }
192
+ end
193
+
194
+ context 'but works the second time' do
195
+ before { expect(Net::HTTP).to receive(:start).at_least(:once).and_return retry_response }
196
+ before { allow(retry_response).to receive(:body) }
197
+ let(:retry_response) { Net::HTTPOK.new nil, nil, nil }
198
+
199
+ it { expect{request.run}.not_to fail }
200
+ end
201
+ end
181
202
  end
182
203
  end
183
204
  end
@@ -97,6 +97,21 @@ describe Yt::Account, :device_app do
97
97
  end
98
98
  end
99
99
 
100
+ describe '.video_groups' do
101
+ let(:video_group) { $account.video_groups.first }
102
+
103
+ specify 'returns the first video-group created by the account' do
104
+ expect(video_group).to be_a Yt::VideoGroup
105
+ expect(video_group.title).to be_a String
106
+ expect(video_group.item_count).to be_an Integer
107
+ expect(video_group.published_at).to be_a Time
108
+ end
109
+
110
+ specify 'allows to run reports against each video-group' do
111
+ expect(video_group.views).to be
112
+ end
113
+ end
114
+
100
115
  describe '.upload_video' do
101
116
  let(:video_params) { {title: 'Test Yt upload', privacy_status: 'private', category_id: 17} }
102
117
  let(:video) { $account.upload_video path_or_url, video_params }
@@ -51,6 +51,20 @@ describe Yt::ContentOwner, :partner do
51
51
  end
52
52
  end
53
53
 
54
+ describe '.video_groups' do
55
+ let(:video_group) { $content_owner.video_groups.first }
56
+
57
+ specify 'returns the first video-group created by the account' do
58
+ expect(video_group).to be_a Yt::VideoGroup
59
+ expect(video_group.title).to be_a String
60
+ expect(video_group.item_count).to be_an Integer
61
+ expect(video_group.published_at).to be_a Time
62
+ end
63
+
64
+ specify 'allows to run reports against each video-group' do
65
+ expect(video_group.views).to be
66
+ end
67
+ end
54
68
 
55
69
  describe 'claims' do
56
70
  let(:asset_id) { ENV['YT_TEST_PARTNER_ASSET_ID'] }
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+ require 'yt/models/video_group'
3
+
4
+ describe Yt::VideoGroup, :partner do
5
+ subject(:video_group) { Yt::VideoGroup.new id: id, auth: $content_owner }
6
+
7
+ context 'given a video-group', :partner do
8
+ context 'managed by the authenticated Content Owner' do
9
+ let(:id) { ENV['YT_TEST_PARTNER_VIDEO_GROUP_ID'] }
10
+
11
+ specify 'the title can be retrieved' do
12
+ expect(video_group.title).to be_a(String)
13
+ expect(video_group.title).not_to be_empty
14
+ end
15
+
16
+ specify 'the number of videos in the group can be retrieved' do
17
+ expect(video_group.item_count).to be_an(Integer)
18
+ expect(video_group.item_count).not_to be_zero
19
+ end
20
+
21
+ describe 'multiple reports can be retrieved at once' do
22
+ metrics = {views: Integer, uniques: Integer,
23
+ estimated_minutes_watched: Integer, comments: Integer, likes: Integer,
24
+ dislikes: Integer, shares: Integer, subscribers_gained: Integer,
25
+ subscribers_lost: Integer, favorites_added: Integer,
26
+ videos_added_to_playlists: Integer, videos_removed_from_playlists: Integer,
27
+ favorites_removed: Integer, average_view_duration: Integer,
28
+ average_view_percentage: Float, annotation_clicks: Integer,
29
+ annotation_click_through_rate: Float,
30
+ annotation_close_rate: Float, earnings: Float, impressions: Integer,
31
+ monetized_playbacks: Integer}
32
+
33
+ specify 'by day, and are chronologically sorted' do
34
+ range = {since: 5.days.ago.to_date, until: 3.days.ago.to_date}
35
+ result = video_group.reports range.merge(only: metrics, by: :day)
36
+ metrics.each do |metric, type|
37
+ expect(result[metric].keys).to all(be_a Date)
38
+ expect(result[metric].values).to all(be_a type)
39
+ expect(result[metric].keys.sort).to eq result[metric].keys
40
+ end
41
+ end
42
+
43
+ # NOTE: all the other filters also apply, not tested for brevity
44
+ end
45
+
46
+ describe 'viewer_percentage can be grouped by age group' do
47
+ let(:range) { {since: 1.year.ago.to_date, until: 1.week.ago.to_date} }
48
+ let(:keys) { range.values }
49
+
50
+ specify 'with the :by option set to :age_group' do
51
+ viewer_percentage = video_group.viewer_percentage range.merge by: :age_group
52
+ expect(viewer_percentage.keys - %w(65- 35-44 45-54 13-17 25-34 55-64 18-24)).to be_empty
53
+ expect(viewer_percentage.values).to all(be_instance_of Float)
54
+ end
55
+ end
56
+ end
57
+
58
+ context 'not managed by the authenticated Content Owner' do
59
+ let(:id) { 'ABExJp9gAAA' }
60
+
61
+ specify 'views cannot be retrieved' do
62
+ expect{video_group.views}.to raise_error Yt::Error
63
+ end
64
+ end
65
+ end
66
+ end
@@ -1,7 +1,7 @@
1
1
  require 'simplecov'
2
2
  require 'coveralls'
3
3
 
4
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new [
5
5
  SimpleCov::Formatter::HTMLFormatter,
6
6
  Coveralls::SimpleCov::Formatter
7
7
  ]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.25.17
4
+ version: 0.25.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claudio Baccigalupo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-05 00:00:00.000000000 Z
11
+ date: 2016-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -142,6 +142,7 @@ files:
142
142
  - lib/yt/collections/content_owners.rb
143
143
  - lib/yt/collections/device_flows.rb
144
144
  - lib/yt/collections/file_details.rb
145
+ - lib/yt/collections/group_infos.rb
145
146
  - lib/yt/collections/ids.rb
146
147
  - lib/yt/collections/live_streaming_details.rb
147
148
  - lib/yt/collections/ownerships.rb
@@ -165,8 +166,10 @@ files:
165
166
  - lib/yt/collections/subscriptions.rb
166
167
  - lib/yt/collections/user_infos.rb
167
168
  - lib/yt/collections/video_categories.rb
169
+ - lib/yt/collections/video_groups.rb
168
170
  - lib/yt/collections/videos.rb
169
171
  - lib/yt/config.rb
172
+ - lib/yt/constants/geography.rb
170
173
  - lib/yt/errors/forbidden.rb
171
174
  - lib/yt/errors/missing_auth.rb
172
175
  - lib/yt/errors/no_items.rb
@@ -192,6 +195,7 @@ files:
192
195
  - lib/yt/models/description.rb
193
196
  - lib/yt/models/device_flow.rb
194
197
  - lib/yt/models/file_detail.rb
198
+ - lib/yt/models/group_info.rb
195
199
  - lib/yt/models/id.rb
196
200
  - lib/yt/models/iterator.rb
197
201
  - lib/yt/models/live_streaming_detail.rb
@@ -217,6 +221,7 @@ files:
217
221
  - lib/yt/models/user_info.rb
218
222
  - lib/yt/models/video.rb
219
223
  - lib/yt/models/video_category.rb
224
+ - lib/yt/models/video_group.rb
220
225
  - lib/yt/request.rb
221
226
  - lib/yt/version.rb
222
227
  - spec/collections/claims_spec.rb
@@ -227,6 +232,7 @@ files:
227
232
  - spec/collections/reports_spec.rb
228
233
  - spec/collections/subscriptions_spec.rb
229
234
  - spec/collections/videos_spec.rb
235
+ - spec/constants/geography_spec.rb
230
236
  - spec/errors/forbidden_spec.rb
231
237
  - spec/errors/missing_auth_spec.rb
232
238
  - spec/errors/no_items_spec.rb
@@ -283,6 +289,7 @@ files:
283
289
  - spec/requests/as_content_owner/match_policy_spec.rb
284
290
  - spec/requests/as_content_owner/ownership_spec.rb
285
291
  - spec/requests/as_content_owner/playlist_spec.rb
292
+ - spec/requests/as_content_owner/video_group_spec.rb
286
293
  - spec/requests/as_content_owner/video_spec.rb
287
294
  - spec/requests/as_server_app/channel_spec.rb
288
295
  - spec/requests/as_server_app/playlist_item_spec.rb
@@ -328,6 +335,7 @@ test_files:
328
335
  - spec/collections/reports_spec.rb
329
336
  - spec/collections/subscriptions_spec.rb
330
337
  - spec/collections/videos_spec.rb
338
+ - spec/constants/geography_spec.rb
331
339
  - spec/errors/forbidden_spec.rb
332
340
  - spec/errors/missing_auth_spec.rb
333
341
  - spec/errors/no_items_spec.rb
@@ -384,6 +392,7 @@ test_files:
384
392
  - spec/requests/as_content_owner/match_policy_spec.rb
385
393
  - spec/requests/as_content_owner/ownership_spec.rb
386
394
  - spec/requests/as_content_owner/playlist_spec.rb
395
+ - spec/requests/as_content_owner/video_group_spec.rb
387
396
  - spec/requests/as_content_owner/video_spec.rb
388
397
  - spec/requests/as_server_app/channel_spec.rb
389
398
  - spec/requests/as_server_app/playlist_item_spec.rb