yt 0.7.2 → 0.7.3
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 +4 -4
- data/Gemfile.lock +1 -1
- data/HISTORY.md +1 -0
- data/README.md +89 -103
- data/lib/yt/associations/authentications.rb +2 -1
- data/lib/yt/associations/earnings.rb +9 -17
- data/lib/yt/associations/views.rb +10 -18
- data/lib/yt/collections/annotations.rb +2 -1
- data/lib/yt/collections/channels.rb +1 -0
- data/lib/yt/collections/videos.rb +3 -1
- data/lib/yt/models/annotation.rb +4 -5
- data/lib/yt/models/authentication.rb +9 -2
- data/lib/yt/models/rating.rb +1 -1
- data/lib/yt/models/snippet.rb +96 -55
- data/lib/yt/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 280089714e1281d849dcb959a4de6e8bed69b76f
|
4
|
+
data.tar.gz: 8d2482b21d1ba9827c9a8172aab4475c36348c51
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14db211427304d5eb03b6d62f50190eb50f614e8e0c9c68d6d7ff26c19ae88378f8feb4502cfaafb2e0ee15e0be0c7aa1d7aa01ff3fc211481b59b4257261a2b
|
7
|
+
data.tar.gz: 811037e6baf6cfc47c73cb3efd4a64ed5cb1b7c0f1aa0dfffa06ec4ee73106dbb7f26fe92b1b040b3ff5a72026c2076f5d05a3b5d2b4b7143fb22d8e652385a8
|
data/Gemfile.lock
CHANGED
data/HISTORY.md
CHANGED
@@ -9,6 +9,7 @@ v0.7 - 2014/06/18
|
|
9
9
|
* More snippet methods for PlaylistItem (channel_id, channel_title, playlist_id, video_id)
|
10
10
|
* More status methods for PlaylistItem (privacy_status, public?, private?, unlisted?)
|
11
11
|
* Add video.update to update title, description, tags and categoryId of a video
|
12
|
+
* Sort channel.videos by most recent first
|
12
13
|
|
13
14
|
v0.6 - 2014/06/05
|
14
15
|
-----------------
|
data/README.md
CHANGED
@@ -19,23 +19,14 @@ channel = Yt::Channel.new id: 'UCxO1tY8h1AhOz0T4ENwmpow'
|
|
19
19
|
channel.title #=> "Fullscreen"
|
20
20
|
channel.public? #=> true
|
21
21
|
channel.comment_count #=> 773
|
22
|
-
channel.videos.count #=>
|
22
|
+
channel.videos.count #=> 12
|
23
23
|
```
|
24
24
|
|
25
25
|
```ruby
|
26
26
|
video = Yt::Video.new id: 'MESycYJytkU'
|
27
27
|
video.title #=> "Fullscreen Creator Platform"
|
28
|
-
video.public? #=> true
|
29
|
-
video.view_count #=> 55843
|
30
28
|
video.comment_count #=> 308
|
31
|
-
video.like_count #=> 556
|
32
|
-
video.dislike_count #=> 78
|
33
|
-
video.favorite_count #=> 0
|
34
|
-
video.duration #=> 86
|
35
29
|
video.hd? #=> true
|
36
|
-
video.stereoscopic? #=> false
|
37
|
-
video.captioned? #=> true
|
38
|
-
video.licensed? #=> false
|
39
30
|
video.annotations.count #=> 1
|
40
31
|
```
|
41
32
|
|
@@ -51,14 +42,18 @@ Use [Yt::Account](http://rubydoc.info/github/Fullscreen/yt/master/Yt/Models/Acco
|
|
51
42
|
|
52
43
|
* authenticate as a YouTube account
|
53
44
|
* read the attributes of the account
|
54
|
-
* access the
|
45
|
+
* access the channel managed by the account
|
46
|
+
* access the videos uploaded by the account
|
55
47
|
|
56
48
|
```ruby
|
57
|
-
#
|
49
|
+
# Accounts can be initialized with access token, refresh token or an authorization code
|
58
50
|
account = Yt::Account.new access_token: 'ya29.1.ABCDEFGHIJ'
|
59
51
|
|
60
52
|
account.email #=> .. your e-mail address..
|
61
53
|
account.channel #=> #<Yt::Models::Channel @id=...>
|
54
|
+
|
55
|
+
account.videos.count #=> 12
|
56
|
+
account.videos.first #=> #<Yt::Models::Video @id=...>
|
62
57
|
```
|
63
58
|
|
64
59
|
*All the above methods require authentication (see below).*
|
@@ -72,7 +67,7 @@ Use [Yt::ContentOwner](http://rubydoc.info/github/Fullscreen/yt/master/Yt/Models
|
|
72
67
|
* list the channels partnered with a YouTube content owner
|
73
68
|
|
74
69
|
```ruby
|
75
|
-
#
|
70
|
+
# Content owners can be initialized with access token, refresh token or an authorization code
|
76
71
|
content_owner = Yt::ContentOwner.new owner_name: 'CMSname', access_token: 'ya29.1.ABCDEFGHIJ'
|
77
72
|
|
78
73
|
content_owner.partnered_channels.count #=> 12
|
@@ -99,13 +94,13 @@ channel = Yt::Channel.new id: 'UCxO1tY8h1AhOz0T4ENwmpow'
|
|
99
94
|
channel.title #=> "Fullscreen"
|
100
95
|
channel.description #=> "The first media company for the connected generation."
|
101
96
|
channel.description.has_link_to_playlist? #=> false
|
102
|
-
channel.thumbnail_url #=> "https://yt3.ggpht.com/-KMnbKDBl60w
|
97
|
+
channel.thumbnail_url #=> "https://yt3.ggpht.com/-KMnbKDBl60w/.../photo.jpg"
|
103
98
|
channel.published_at #=> 2006-03-23 06:13:25 UTC
|
104
99
|
channel.public? #=> true
|
105
100
|
|
106
101
|
channel.view_count #=> 421619
|
107
102
|
channel.comment_count #=> 773
|
108
|
-
channel.video_count #=>
|
103
|
+
channel.video_count #=> 12
|
109
104
|
channel.subscriber_count #=> 136925
|
110
105
|
channel.subscriber_count_visible? #=> true
|
111
106
|
|
@@ -127,7 +122,6 @@ channel.subscribe #=> true
|
|
127
122
|
|
128
123
|
channel.create_playlist title: 'New playlist' #=> true
|
129
124
|
channel.delete_playlists title: 'New playlist' #=> [true]
|
130
|
-
|
131
125
|
```
|
132
126
|
|
133
127
|
*The methods above require to be authenticated as a YouTube account (see below).*
|
@@ -137,10 +131,10 @@ content_owner = Yt::ContentOwner.new owner_name: 'CMSname', access_token: 'ya29.
|
|
137
131
|
channel = Yt::Channel.new id: 'UCxO1tY8h1AhOz0T4ENwmpow', auth: content_owner
|
138
132
|
|
139
133
|
channel.earnings_on 5.days.ago #=> 12.23
|
140
|
-
channel.earnings
|
134
|
+
channel.earnings until: 2.days.ago #=> {Wed, 28 May 2014 => 1.34, Thu, 29 May 2014 => 0.47}
|
141
135
|
|
142
136
|
channel.views_on 5.days.ago #=> 44
|
143
|
-
channel.views since: 3.days.ago
|
137
|
+
channel.views since: 3.days.ago #=> {Wed, 28 May 2014 => 12, Thu, 29 May 2014 => 3}
|
144
138
|
```
|
145
139
|
|
146
140
|
*The methods above require to be authenticated as the channel’s content owner (see below).*
|
@@ -159,7 +153,7 @@ Use [Yt::Video](http://rubydoc.info/github/Fullscreen/yt/master/Yt/Models/Video)
|
|
159
153
|
video = Yt::Video.new id: 'MESycYJytkU'
|
160
154
|
|
161
155
|
video.title #=> "Fullscreen Creator Platform"
|
162
|
-
video.description #=> "The new Fullscreen Creator Platform gives creators and brands a suite
|
156
|
+
video.description #=> "The new Fullscreen Creator Platform gives creators and brands a suite..."
|
163
157
|
video.description.has_link_to_channel? #=> true
|
164
158
|
video.thumbnail_url #=> "https://i1.ytimg.com/vi/MESycYJytkU/default.jpg"
|
165
159
|
video.published_at #=> 2013-07-09 16:27:32 UTC
|
@@ -193,7 +187,7 @@ video.like #=> true
|
|
193
187
|
*The methods above require to be authenticated as a YouTube account (see below).*
|
194
188
|
|
195
189
|
```ruby
|
196
|
-
video.update title: '
|
190
|
+
video.update title: 'A title', description: 'A description', tags: ['a tag'], categoryId: '21'
|
197
191
|
```
|
198
192
|
|
199
193
|
*The methods above require to be authenticated as the video’s owner (see below).*
|
@@ -213,7 +207,7 @@ Use [Yt::Playlist](http://rubydoc.info/github/Fullscreen/yt/master/Yt/Models/Pla
|
|
213
207
|
playlist = Yt::Playlist.new id: 'PLSWYkYzOrPMRCK6j0UgryI8E0NHhoVdRc'
|
214
208
|
|
215
209
|
playlist.title #=> "Fullscreen Features"
|
216
|
-
playlist.description #=> "You send us your best videos and we feature our favorite ones
|
210
|
+
playlist.description #=> "You send us your best videos and we feature our favorite ones..."
|
217
211
|
playlist.description.has_link_to_subscribe? #=> false
|
218
212
|
playlist.thumbnail_url #=> "https://i1.ytimg.com/vi/36kL2alg7Jk/default.jpg"
|
219
213
|
playlist.published_at #=> 2012-11-27 21:23:38 UTC
|
@@ -224,14 +218,12 @@ playlist.channel_title #=> "Fullscreen"
|
|
224
218
|
|
225
219
|
playlist.playlist_items.count #=> 1
|
226
220
|
playlist.playlist_items.first #=> #<Yt::Models::PlaylistItem @id=...>
|
227
|
-
playlist.playlist_items.first.position #=> 0
|
228
|
-
playlist.playlist_items.first.video.title #=> "Fullscreen Creator Platform"
|
229
221
|
```
|
230
222
|
|
231
223
|
*The methods above do not require authentication.*
|
232
224
|
|
233
225
|
```ruby
|
234
|
-
playlist.update title: '
|
226
|
+
playlist.update title: 'title', description: 'desc', tags: ['new tag'], privacy_status: 'private'
|
235
227
|
playlist.add_video 'MESycYJytkU'
|
236
228
|
playlist.add_videos ['MESycYJytkU', 'MESycYJytkU']
|
237
229
|
playlist.delete_playlist_items title: 'Fullscreen Creator Platform' #=> [true]
|
@@ -262,7 +254,6 @@ item.playlist_id #=> "PLSWYkYzOrPMRCK6j0UgryI8E0NHhoVdRc"
|
|
262
254
|
item.position #=> 0
|
263
255
|
item.video_id #=> "W4GhTprSsOY"
|
264
256
|
item.video #=> #<Yt::Models::Video @id=...>
|
265
|
-
|
266
257
|
```
|
267
258
|
|
268
259
|
*The methods above do not require authentication.*
|
@@ -296,23 +287,34 @@ Configuring your app
|
|
296
287
|
====================
|
297
288
|
|
298
289
|
In order to use Yt you must register your app in the [Google Developers Console](https://console.developers.google.com).
|
299
|
-
|
290
|
+
|
291
|
+
If you don’t have a registered app, browse to the console and select "Create Project":
|
292
|
+

|
293
|
+
|
294
|
+
When your project is ready, select APIs & Auth in the menu and enable Google+, YouTube Analytics and YouTube Data API:
|
295
|
+

|
296
|
+
|
297
|
+
The next step is to create an API key. Depending on the nature of your app, you should pick one of the following strategies.
|
300
298
|
|
301
299
|
Apps that do not require user interactions
|
302
300
|
------------------------------------------
|
303
301
|
|
304
302
|
If you are building a read-only app that fetches public data from YouTube, then
|
305
|
-
|
306
|
-
|
303
|
+
all you need is a **Public API access**.
|
304
|
+
|
305
|
+
Click on "Create new Key" in the Public API section and select "Server Key":
|
306
|
+

|
307
|
+

|
308
|
+
|
309
|
+
Once the key for server application is created, copy the API key and add it
|
310
|
+
to your code with the following snippet of code (replacing with your own key):
|
307
311
|
|
308
312
|
```ruby
|
309
313
|
Yt.configure do |config|
|
310
|
-
config.api_key = '
|
314
|
+
config.api_key = 'AIzaSyAO8dXpvZcaP2XSDFBD91H8yQ'
|
311
315
|
end
|
312
316
|
```
|
313
317
|
|
314
|
-
replacing the value above with your own key for server application.
|
315
|
-
|
316
318
|
Remember: this kind of app is not allowed to perform any destructive operation,
|
317
319
|
so you won’t be able to like a video, subscribe to a channel or delete a
|
318
320
|
playlist from a specific account. You will only be able to retrieve read-only
|
@@ -330,14 +332,15 @@ Just pass that access token to the account initializer, such as:
|
|
330
332
|
```ruby
|
331
333
|
account = Yt::Account.new access_token: 'ya29.1.ABCDEFGHIJ'
|
332
334
|
account.email #=> (retrieves the account’s e-mail address)
|
333
|
-
account.
|
335
|
+
account.videos #=> (lists a video to an account’s playlist)
|
334
336
|
```
|
335
337
|
|
336
338
|
Scenario 2. If you don’t have the account’s access token, but you have the
|
337
339
|
**refresh token**, then it’s almost as easy.
|
338
|
-
|
339
|
-
find the
|
340
|
-
|
340
|
+
In the [Google Developers Console](https://console.developers.google.com),
|
341
|
+
find the web application that was used to obtain the refresh token, copy the
|
342
|
+
Client ID and Client secret and add them to you code with the following snippet
|
343
|
+
of code (replacing with your own keys):
|
341
344
|
|
342
345
|
```ruby
|
343
346
|
Yt.configure do |config|
|
@@ -345,38 +348,53 @@ Yt.configure do |config|
|
|
345
348
|
config.client_secret = '1234567890'
|
346
349
|
end
|
347
350
|
```
|
348
|
-
|
349
|
-
replacing the values above with the client ID and secret for web application.
|
350
351
|
Then you can manage a YouTube account by passing the refresh token to the
|
351
352
|
account initializer, such as:
|
352
353
|
|
353
354
|
```ruby
|
354
355
|
account = Yt::Account.new refresh_token: '1/1234567890'
|
355
356
|
account.email #=> (retrieves the account’s e-mail address)
|
356
|
-
account.
|
357
|
+
account.videos #=> (lists a video to an account’s playlist)
|
357
358
|
```
|
358
359
|
|
359
360
|
Scenario 3. If you don’t have any account’s token, then you can get one by
|
360
|
-
having the user authorize your app through the Google OAuth page.
|
361
|
-
|
361
|
+
having the user authorize your app through the Google OAuth page.
|
362
|
+
|
363
|
+
In the [Google Developers Console](https://console.developers.google.com),
|
364
|
+
click on "Create new Client ID" in the OAuth section and select "Web application":
|
365
|
+

|
366
|
+
|
367
|
+
Fill the "Authorized Redirect URI" textarea with the URL of your app where you
|
368
|
+
want to redirect users after they authorize their YouTube account.
|
369
|
+
|
370
|
+
Once the Client ID for web application is created, copy the Client ID and secret
|
371
|
+
and add them to your code with the following snippet of code (replacing with your own keys):
|
372
|
+
|
373
|
+
```ruby
|
374
|
+
Yt.configure do |config|
|
375
|
+
config.client_id = '49781862760-4t610gtk35462g.apps.googleusercontent.com'
|
376
|
+
config.client_secret = 'NtFHjZkJcwYZDfYVz9mp8skz9'
|
377
|
+
end
|
378
|
+
```
|
379
|
+
|
380
|
+
Finally, in your web app, add a link to the URL generated by running
|
362
381
|
|
363
382
|
```ruby
|
364
383
|
Yt::Account.new(scopes: scopes, redirect_uri: redirect_uri).authentication_url
|
365
384
|
```
|
366
385
|
|
367
|
-
where `
|
368
|
-
|
369
|
-
|
370
|
-
Sample scopes are: `youtube`, `youtube.readonly` `userinfo.email`.
|
386
|
+
where `redirect_uri` is the URL you entered in the form above, and `scopes` is
|
387
|
+
the list of YouTube scopes you want the user to authorize. Depending on the
|
388
|
+
nature of your app, you can pick one or more among `youtube`, `youtube.readonly` `userinfo.email`.
|
371
389
|
|
372
|
-
|
390
|
+
Every user who authorizes your app will be redirected to the `redirect_uri`
|
373
391
|
with an extra `code` parameter that looks something like `4/Ja60jJ7_Kw0`.
|
374
392
|
Just pass the code to the following method to authenticate and initialize the account:
|
375
393
|
|
376
394
|
```ruby
|
377
395
|
account = Yt::Account.new authorization_code: '4/Ja60jJ7_Kw0'
|
378
396
|
account.email #=> (retrieves the account’s e-mail address)
|
379
|
-
account.
|
397
|
+
account.videos #=> (lists a video to an account’s playlist)
|
380
398
|
```
|
381
399
|
|
382
400
|
Configuring with environment variables
|
@@ -386,7 +404,6 @@ As an alternative to the approach above, you can configure your app with
|
|
386
404
|
variables. Setting the following environment variables:
|
387
405
|
|
388
406
|
```bash
|
389
|
-
export YT_CLIENT_SCENARIO="device_app"
|
390
407
|
export YT_CLIENT_ID="1234567890.apps.googleusercontent.com"
|
391
408
|
export YT_CLIENT_SECRET="1234567890"
|
392
409
|
export YT_API_KEY="123456789012345678901234567890"
|
@@ -405,7 +422,6 @@ end
|
|
405
422
|
so use the approach that you prefer.
|
406
423
|
If a variable is set in both places, then `Yt.configure` takes precedence.
|
407
424
|
|
408
|
-
|
409
425
|
How to install
|
410
426
|
==============
|
411
427
|
|
@@ -415,7 +431,7 @@ To install on your system, run
|
|
415
431
|
|
416
432
|
To use inside a bundled Ruby project, add this line to the Gemfile:
|
417
433
|
|
418
|
-
gem 'yt', '~> 0.7.
|
434
|
+
gem 'yt', '~> 0.7.3'
|
419
435
|
|
420
436
|
Since the gem follows [Semantic Versioning](http://semver.org),
|
421
437
|
indicating the full version in your Gemfile (~> *major*.*minor*.*patch*)
|
@@ -442,15 +458,9 @@ How to test
|
|
442
458
|
|
443
459
|
Yt comes with two different sets of tests:
|
444
460
|
|
445
|
-
1. tests in `spec/models` and `spec/
|
461
|
+
1. tests in `spec/models`, `spec/collections` and `spec/errors` **do not hit** the YouTube API
|
446
462
|
1. tests in `spec/associations` **hit** the YouTube API and require authentication
|
447
463
|
|
448
|
-
To run all the tests, type:
|
449
|
-
|
450
|
-
```bash
|
451
|
-
rspec
|
452
|
-
```
|
453
|
-
|
454
464
|
The reason why some tests actually hit the YouTube API is because they are
|
455
465
|
meant to really integrate Yt with YouTube. YouTube API is not exactly
|
456
466
|
*the most reliable* API out there, so we need to make sure that the responses
|
@@ -460,70 +470,46 @@ You don’t have to run all the tests every time you change code.
|
|
460
470
|
Travis CI is already set up to do this for when whenever you push a branch
|
461
471
|
or create a pull request for this project.
|
462
472
|
|
463
|
-
|
464
|
-
------------------------------
|
465
|
-
|
466
|
-
To only run tests against models and collections (which do not hit the API), type:
|
473
|
+
To only run tests against models, collections and errors (which do not hit the API), type:
|
467
474
|
|
468
475
|
```bash
|
469
|
-
rspec spec/models spec/collections
|
476
|
+
rspec spec/models spec/collections spec/errors
|
470
477
|
```
|
471
478
|
|
472
|
-
|
473
|
-
--------------------
|
474
|
-
|
475
|
-
To only run tests against associations (which hit the API), type:
|
479
|
+
To also run live-tests against the YouTube API, type:
|
476
480
|
|
477
481
|
```bash
|
478
|
-
rspec
|
482
|
+
rspec
|
479
483
|
```
|
480
484
|
|
481
|
-
This
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
Browse to the Console, then create a new app that you will only use for testing.
|
485
|
+
This will fail unless you have set up a test YouTube application and some
|
486
|
+
tests YouTube accounts to hit the API. Once again, you probably don’t need
|
487
|
+
this, since Travis CI already takes care of running this kind of tests.
|
486
488
|
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
Under the "Credentials" tab of this app, create a new 'Key for server
|
491
|
-
application' and a new 'Client ID' and 'Client Secret' for **native** application.
|
492
|
-
|
493
|
-
It’s important that you pick 'native application' instead of 'web application',
|
494
|
-
otherwise running your tests will require you to open a browser and launch a
|
495
|
-
local webserver… and you don’t need to do any of that.
|
496
|
-
|
497
|
-
Finally, copy the given values and set the following environment variables:
|
498
|
-
|
499
|
-
```bash
|
500
|
-
export YT_TEST_DEVICE_CLIENT_ID="1234567890.apps.googleusercontent.com"
|
501
|
-
export YT_TEST_DEVICE_CLIENT_SECRET="1234567890"
|
502
|
-
export YT_TEST_SERVER_API_KEY="123456789012345678901234567890"
|
503
|
-
```
|
504
|
-
|
505
|
-
[ TODO:
|
506
|
-
Complete this section.
|
507
|
-
Explain how get and store the refresh token, making sure all the required scopes are authorized:
|
508
|
-
'https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile'
|
509
|
-
]
|
489
|
+
How to contribute
|
490
|
+
=================
|
510
491
|
|
492
|
+
Yt needs your support!
|
493
|
+
The goal of Yt is to provide a Ruby interface for all the methods exposed by
|
494
|
+
the [YouTube Data API (v3)](https://developers.google.com/youtube/v3) and by
|
495
|
+
the [YouTube Analytics API](https://developers.google.com/youtube/analytics).
|
511
496
|
|
497
|
+
If you find that a method is missing, fork the project, add the missing code,
|
498
|
+
write the appropriate tests, then submit a pull request, and it will gladly
|
499
|
+
be merged!
|
512
500
|
|
513
|
-
How to
|
514
|
-
|
501
|
+
How to release new versions
|
502
|
+
===========================
|
515
503
|
|
516
|
-
|
517
|
-
|
504
|
+
If you are a manager of this project, remember to upgrade the [Yt gem](http://rubygems.org/gems/yt)
|
505
|
+
whenever a new feature is added or a bug gets fixed.
|
518
506
|
|
519
|
-
|
507
|
+
Make sure all the tests are passing on [Travis CI](https://travis-ci.org/Fullscreen/yt),
|
508
|
+
document the changes in HISTORY.md and README.md, bump the version, then run
|
520
509
|
|
521
510
|
rake release
|
522
511
|
|
523
|
-
Remember
|
524
|
-
your changes in HISTORY.md and README.md if required.
|
525
|
-
|
526
|
-
The yt gem follows [Semantic Versioning](http://semver.org).
|
512
|
+
Remember that the yt gem follows [Semantic Versioning](http://semver.org).
|
527
513
|
Any new release that is fully backward-compatible should bump the *patch* version (0.0.x).
|
528
514
|
Any new version that breaks compatibility should bump the *minor* version (0.x.0)
|
529
515
|
|
@@ -7,7 +7,8 @@ module Yt
|
|
7
7
|
module Associations
|
8
8
|
# Provides authentication methods to YouTube resources, which
|
9
9
|
# allows to access to content detail set-specific methods like `access_token`.
|
10
|
-
#
|
10
|
+
#
|
11
|
+
# YouTube resources with authentication are: {Yt::Models::Account accounts}.
|
11
12
|
module Authentications
|
12
13
|
delegate :access_token, :refresh_token, :expires_at, to: :authentication
|
13
14
|
|
@@ -2,32 +2,24 @@ require 'yt/collections/earnings'
|
|
2
2
|
|
3
3
|
module Yt
|
4
4
|
module Associations
|
5
|
-
# Provides the
|
6
|
-
#
|
7
|
-
# YouTube resources with earning are: channels.
|
5
|
+
# Provides methods which allows to access the earnings generated by a resource.
|
6
|
+
#
|
7
|
+
# YouTube resources with earning are: {Yt::Models::Channel channels}.
|
8
8
|
module Earnings
|
9
|
-
#
|
10
|
-
#
|
9
|
+
# @return [Float] the estimated earnings for one specific day in USD.
|
11
10
|
# @param [Date or Time or DateTime or String] date The date to obtain
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# @return [Float] The estimated earnings in USD.
|
11
|
+
# the estimated earnings for. If +String+, must be Date-parseable.
|
15
12
|
def earnings_on(date)
|
16
13
|
earnings(from: date, to: date).values.first
|
17
14
|
end
|
18
15
|
|
19
|
-
#
|
20
|
-
#
|
16
|
+
# @return [Hash] the estimated earnings for a range of days. Each +key+ is a +Date+
|
17
|
+
# and each +value+ is a +Float+, representing estimated earnings in USD.
|
21
18
|
# @param [Hash] options the range of days to get the earnings for.
|
22
19
|
# @option options [Date or Time or DateTime or String] :since The start
|
23
|
-
#
|
24
|
-
# @note options[:since] is aliased as options[:from]
|
20
|
+
# of the days range. If +String+, must be Date-parseable. Also aliased as *:from*.
|
25
21
|
# @option options [Date or Time or DateTime or String] :until The end
|
26
|
-
#
|
27
|
-
# @note options[:until] is aliased as options[:to]
|
28
|
-
#
|
29
|
-
# @return [Hash] The estimated earnings by day. Each :key is a Date
|
30
|
-
# and each :value is a Float, representing estimated earnings in USD.
|
22
|
+
# of the days range. If +String+, must be Date-parseable. Also aliased as *:to*.
|
31
23
|
def earnings(options = {})
|
32
24
|
from = options[:since] || options[:from] || 6.days.ago
|
33
25
|
to = options[:until] || options[:to] || 2.days.ago
|
@@ -2,32 +2,24 @@ require 'yt/collections/views'
|
|
2
2
|
|
3
3
|
module Yt
|
4
4
|
module Associations
|
5
|
-
# Provides
|
6
|
-
#
|
7
|
-
# YouTube resources with
|
5
|
+
# Provides methods which allows to access the view count of a resource.
|
6
|
+
#
|
7
|
+
# YouTube resources with view counts are: {Yt::Models::Channel channels}.
|
8
8
|
module Views
|
9
|
-
#
|
10
|
-
#
|
9
|
+
# @return [Integer, nil] the view count for one specific day.
|
11
10
|
# @param [Date or Time or DateTime or String] date The date to obtain
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# @return [Integer or Nil] The estimated views.
|
11
|
+
# the views for. If +String+, must be Date-parseable.
|
15
12
|
def views_on(date)
|
16
13
|
views(from: date, to: date).values.first
|
17
14
|
end
|
18
15
|
|
19
|
-
#
|
20
|
-
#
|
21
|
-
# @param [Hash] options the range of days to get the
|
16
|
+
# @return [Hash] the view counts for a range of days. Each +key+ is a +Date+
|
17
|
+
# and each +value+ is an +Integer+ or +nil+, representing the number of views.
|
18
|
+
# @param [Hash] options the range of days to get the view for.
|
22
19
|
# @option options [Date or Time or DateTime or String] :since The start
|
23
|
-
#
|
24
|
-
# @note options[:since] is aliased as options[:from]
|
20
|
+
# of the days range. If +String+, must be Date-parseable. Also aliased as *:from*.
|
25
21
|
# @option options [Date or Time or DateTime or String] :until The end
|
26
|
-
#
|
27
|
-
# @note options[:until] is aliased as options[:to]
|
28
|
-
#
|
29
|
-
# @return [Hash] The view count by day. Each :key is a Date
|
30
|
-
# and each :value is an Integer or nil, representing the number of views.
|
22
|
+
# of the days range. If +String+, must be Date-parseable. Also aliased as *:to*.
|
31
23
|
def views(options = {})
|
32
24
|
from = options[:since] || options[:from] || 5.days.ago
|
33
25
|
to = options[:until] || options[:to] || 1.day.ago
|
@@ -4,9 +4,10 @@ require 'yt/models/annotation'
|
|
4
4
|
module Yt
|
5
5
|
module Collections
|
6
6
|
# Provides methods to interact with a collection of YouTube annotations.
|
7
|
+
#
|
7
8
|
# Resources with annotations are: {Yt::Models::Video videos}.
|
8
9
|
# @note Since there is no (authenticable) API endpoint to retrieve
|
9
|
-
# annotations, only annotations of
|
10
|
+
# annotations, only annotations of public videos can be retrieved.
|
10
11
|
class Annotations < Base
|
11
12
|
|
12
13
|
private
|
@@ -4,6 +4,7 @@ require 'yt/models/video'
|
|
4
4
|
module Yt
|
5
5
|
module Collections
|
6
6
|
# Provides methods to interact with a collection of YouTube videos.
|
7
|
+
#
|
7
8
|
# Resources with videos are: {Yt::Models::Channel channels} and
|
8
9
|
# {Yt::Models::Account accounts}.
|
9
10
|
class Videos < Base
|
@@ -27,8 +28,9 @@ module Yt
|
|
27
28
|
end
|
28
29
|
|
29
30
|
def videos_params
|
31
|
+
params = {type: :video, maxResults: 50, part: 'snippet', order: 'date'}
|
30
32
|
@extra_params ||= {}
|
31
|
-
|
33
|
+
params.merge @extra_params
|
32
34
|
end
|
33
35
|
end
|
34
36
|
end
|
data/lib/yt/models/annotation.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
module Yt
|
2
2
|
module Models
|
3
3
|
# Provides methods to interact with YouTube annotations.
|
4
|
+
# @note YouTube API V3 does not provide access to video annotations,
|
5
|
+
# therefore a legacy XML endpoint is used to retrieve annotations.
|
4
6
|
# @see https://www.youtube.com/yt/playbook/annotations.html
|
5
7
|
class Annotation
|
6
8
|
# @param [Hash] options the options to initialize an Annotation.
|
7
9
|
# @option options [String] :data The XML representation of an annotation
|
8
|
-
# @note YouTube API V3 does not provide access to video annotations,
|
9
|
-
# therefore the XML endpoint is used to retrieve them and its response
|
10
|
-
# is passed to the Annotation initializer.
|
11
10
|
def initialize(options = {})
|
12
11
|
@data = options[:data]
|
13
12
|
end
|
@@ -58,7 +57,7 @@ module Yt
|
|
58
57
|
# @return [Boolean] whether the annotation starts after the number of
|
59
58
|
# seconds indicated.
|
60
59
|
# @note This is broken for invideo programming, because they do not
|
61
|
-
#
|
60
|
+
# have the timestamp in the region, but in the "data" field
|
62
61
|
def starts_after?(seconds)
|
63
62
|
timestamps.first > seconds if timestamps.any?
|
64
63
|
end
|
@@ -67,7 +66,7 @@ module Yt
|
|
67
66
|
# @return [Boolean] whether the annotation starts before the number of
|
68
67
|
# seconds indicated.
|
69
68
|
# @note This is broken for invideo programming, because they do not
|
70
|
-
#
|
69
|
+
# have the timestamp in the region, but in the "data" field
|
71
70
|
def starts_before?(seconds)
|
72
71
|
timestamps.first < seconds if timestamps.any?
|
73
72
|
end
|
@@ -6,11 +6,14 @@ module Yt
|
|
6
6
|
|
7
7
|
# Before your application can access private data using a Google API,
|
8
8
|
# it must obtain an access token that grants access to that API.
|
9
|
+
#
|
9
10
|
# A single access token can grant varying degrees of access to multiple
|
10
11
|
# APIs. A variable parameter called scope controls the set of resources
|
11
12
|
# and operations that an access token permits.
|
13
|
+
#
|
12
14
|
# After an application obtains an access token, it sends the token to a
|
13
15
|
# Google API in an HTTP authorization header.
|
16
|
+
#
|
14
17
|
# Access tokens are valid only for the set of operations and resources
|
15
18
|
# described in the scope of the token request. For example, if an access
|
16
19
|
# token is issued for the Google+ API, it does not grant access to the
|
@@ -23,12 +26,14 @@ module Yt
|
|
23
26
|
# to a Google API beyond the lifetime of a single access token, it can
|
24
27
|
# obtain a refresh token. A refresh token allows your application to
|
25
28
|
# obtain new access tokens.
|
26
|
-
#
|
29
|
+
#
|
30
|
+
# Save refresh tokens in secure long-term storage and continue to
|
27
31
|
# use them as long as they remain valid. Limits apply to the number of
|
28
32
|
# refresh tokens that are issued per client-user combination, and per
|
29
33
|
# user across all clients, and these limits are different. If your
|
30
34
|
# application requests enough refresh tokens to go over one of the
|
31
35
|
# limits, older refresh tokens stop working.
|
36
|
+
#
|
32
37
|
# There is currently a 25-token limit per Google user account.
|
33
38
|
# If a user account has 25 valid tokens, the next authentication request
|
34
39
|
# succeeds, but quietly invalidates the oldest outstanding token without
|
@@ -39,7 +44,9 @@ module Yt
|
|
39
44
|
|
40
45
|
# Access tokens have limited lifetimes. If your application needs access
|
41
46
|
# to a Google API beyond the lifetime of a single access token, it can
|
42
|
-
# obtain a refresh token.
|
47
|
+
# obtain a refresh token.
|
48
|
+
#
|
49
|
+
# A refresh token allows your application to
|
43
50
|
# obtain new access tokens.
|
44
51
|
#
|
45
52
|
# @return [Time] the time when access token no longer works.
|
data/lib/yt/models/rating.rb
CHANGED
@@ -6,7 +6,7 @@ module Yt
|
|
6
6
|
# @see https://developers.google.com/youtube/v3/docs/videos/rate
|
7
7
|
# @see https://developers.google.com/youtube/v3/docs/videos/getRating
|
8
8
|
class Rating < Base
|
9
|
-
# @return [Symbol
|
9
|
+
# @return [Symbol, nil] the rating of a video (if present).
|
10
10
|
# Valid values are: :dislike, :like, :none, :unspecified
|
11
11
|
attr_reader :rating
|
12
12
|
|
data/lib/yt/models/snippet.rb
CHANGED
@@ -3,119 +3,160 @@ require 'yt/models/description'
|
|
3
3
|
module Yt
|
4
4
|
module Models
|
5
5
|
# Contains basic information about the resource. The details of the snippet
|
6
|
-
# are different for the different types of resources.
|
7
|
-
#
|
6
|
+
# are different for the different types of resources.
|
7
|
+
#
|
8
|
+
# Resources with a
|
9
|
+
# snippet are: channels, playlists, playlist items and videos.
|
8
10
|
# @see https://developers.google.com/youtube/v3/docs/channels#resource
|
9
11
|
# @see https://developers.google.com/youtube/v3/docs/videos#resource
|
12
|
+
# @see https://developers.google.com/youtube/v3/docs/playlists#resource
|
13
|
+
# @see https://developers.google.com/youtube/v3/docs/playlistItems#resource
|
10
14
|
class Snippet
|
11
15
|
def initialize(options = {})
|
12
16
|
@data = options[:data]
|
13
17
|
@auth = options[:auth]
|
14
18
|
end
|
15
19
|
|
16
|
-
# @return [String] the resource’s title.
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
20
|
+
# @return [String] if the resource is a channel, the channel’s title.
|
21
|
+
# @return [String] if the resource is a playlist, the playlist’s title.
|
22
|
+
# @return [String] if the resource is a playlist item, the item’s title.
|
23
|
+
# @return [String] if the resource is a video, the video’s title. Has a
|
24
|
+
# maximum of 100 characters and may contain all valid UTF-8 characters
|
25
|
+
# except < and >.
|
22
26
|
def title
|
23
27
|
@title ||= @data.fetch 'title', ''
|
24
28
|
end
|
25
29
|
|
26
|
-
# @return [Yt::Models::Description] the resource
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
30
|
+
# @return [Yt::Models::Description] if the resource is a channel, the
|
31
|
+
# channel’s description. Has a maximum of 1000 characters.
|
32
|
+
# @return [Yt::Models::Description] if the resource is a playlist, the
|
33
|
+
# playlist’s description.
|
34
|
+
# @return [Yt::Models::Description] if the resource is a playlist item,
|
35
|
+
# the item’s description.
|
36
|
+
# @return [Yt::Models::Description] if the resource is a video, the
|
37
|
+
# video’s description. Has a maximum of 5000 bytes and may contain all
|
38
|
+
# valid UTF-8 characters except < and >.
|
33
39
|
def description
|
34
40
|
@description ||= Description.new @data.fetch('description', '')
|
35
41
|
end
|
36
42
|
|
37
|
-
# @return [Time] the date and time that the
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
+
# @return [Time] if the resource is a channel, the date and time that the
|
44
|
+
# channel was created.
|
45
|
+
# @return [Time] if the resource is a playlist, the date and time that
|
46
|
+
# the playlist was created.
|
47
|
+
# @return [Time] if the resource is a playlist item, the date and time
|
48
|
+
# that the item was added to the playlist.
|
49
|
+
# @return [Time] if the resource is a video, the date and time that the
|
50
|
+
# video was published.
|
43
51
|
def published_at
|
44
52
|
@published_at ||= Time.parse @data['publishedAt']
|
45
53
|
end
|
46
54
|
|
47
|
-
# @param [Symbol
|
48
|
-
# @return [String
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
55
|
+
# @param [Symbol, String] size The size of the thumbnail to retrieve.
|
56
|
+
# @return [String] if the resource is a channel and +size+ is +default+,
|
57
|
+
# the URL of an 88x88px image.
|
58
|
+
# @return [String] if the resource is a playlist, a PlaylistItem or a
|
59
|
+
# Video and +size+ is +default+, the URL of an 120x90px image.
|
60
|
+
# @return [String] if the resource is a channel and +size+ is +medium+,
|
61
|
+
# the URL of an 240x240px image.
|
62
|
+
# @return [String] if the resource is a playlist, a PlaylistItem or a
|
63
|
+
# Video and +size+ is +medium+, the URL of an 320x180px image.
|
64
|
+
# @return [String] if the resource is a channel and +size+ is +high+,
|
65
|
+
# the URL of an 800x800px image.
|
66
|
+
# @return [String] if the resource is a playlist, a PlaylistItem or a
|
67
|
+
# Video and +size+ is +high+, the URL of an 480x360px image.
|
68
|
+
# @return [nil] if the +size+ is not +default+, +medium+ or +high+.
|
53
69
|
def thumbnail_url(size = :default)
|
54
70
|
@thumbnails ||= @data.fetch 'thumbnails', {}
|
55
71
|
@thumbnails.fetch(size.to_s, {})['url']
|
56
72
|
end
|
57
73
|
|
58
|
-
# @return [String
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
74
|
+
# @return [String] if the resource is a playlist, the ID that YouTube
|
75
|
+
# uses to uniquely identify the channel that the playlist belongs to.
|
76
|
+
# @return [String] if the resource is a playlist item, the ID that YouTube
|
77
|
+
# uses to uniquely identify the channel that the playlist belongs to.
|
78
|
+
# @return [String] if the resource is a video, the ID that YouTube uses
|
79
|
+
# to uniquely identify the channel that the video was uploaded to.
|
80
|
+
# @return [nil] if the resource is a channel.
|
65
81
|
def channel_id
|
66
82
|
@channel_id ||= @data['channelId']
|
67
83
|
end
|
68
84
|
|
69
|
-
# @return [String
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
85
|
+
# @return [String] if the resource is a playlist, the title of the
|
86
|
+
# channel that the playlist belongs to.
|
87
|
+
# @return [String] if the resource is a playlist item, the title of the
|
88
|
+
# channel that the playlist item belongs to.
|
89
|
+
# @return [String] if the resource is a video, the title of the channel
|
90
|
+
# that the video was uploaded to.
|
91
|
+
# @return [nil] if the resource is a channel.
|
74
92
|
def channel_title
|
75
93
|
@channel_title ||= @data['channelTitle']
|
76
94
|
end
|
77
95
|
|
78
|
-
# @return [Array<Yt::Models::Tag>]
|
79
|
-
#
|
80
|
-
#
|
96
|
+
# @return [Array<Yt::Models::Tag>] if the resource is a channel, an
|
97
|
+
# empty array.
|
98
|
+
# @return [Array<Yt::Models::Tag>] if the resource is a playlist, the
|
99
|
+
# list of keyword tags associated with the playlist.
|
100
|
+
# @return [Array<Yt::Models::Tag>] if the resource is a playlist item,
|
101
|
+
# an empty array.
|
102
|
+
# @return [Array<Yt::Models::Tag>] if the resource is a video, the list
|
103
|
+
# of keyword tags associated with the video.
|
81
104
|
def tags
|
82
105
|
@tags ||= @data.fetch 'tags', []
|
83
106
|
end
|
84
107
|
|
85
|
-
# @return [String
|
86
|
-
#
|
108
|
+
# @return [String] if the resource is a video, the YouTube video
|
109
|
+
# category associated with the video.
|
110
|
+
# @return [nil] if the resource is a channel.
|
111
|
+
# @return [nil] if the resource is a playlist.
|
112
|
+
# @return [nil] if the resource is a playlist item.
|
87
113
|
# @see https://developers.google.com/youtube/v3/docs/videoCategories/list
|
88
114
|
def category_id
|
89
115
|
@category_id ||= @data['categoryId']
|
90
116
|
end
|
91
117
|
|
92
|
-
# @return [String
|
93
|
-
# broadcast. Valid values are: live, none, upcoming
|
118
|
+
# @return [String] if the resource is a video, whether the resource is a
|
119
|
+
# live broadcast. Valid values are: live, none, upcoming.
|
120
|
+
# @return [nil] if the resource is a channel.
|
121
|
+
# @return [nil] if the resource is a playlist.
|
122
|
+
# @return [nil] if the resource is a playlist item.
|
94
123
|
def live_broadcast_content
|
95
124
|
@live_broadcast_content ||= @data['liveBroadcastContent']
|
96
125
|
end
|
97
126
|
|
98
|
-
# @return [String
|
99
|
-
# the playlist that the item is in
|
127
|
+
# @return [String] if the resource is a playlist item, the ID that
|
128
|
+
# YouTube uses to uniquely identify the playlist that the item is in.
|
129
|
+
# @return [nil] if the resource is a channel.
|
130
|
+
# @return [nil] if the resource is a playlist.
|
131
|
+
# @return [nil] if the resource is a video.
|
100
132
|
def playlist_id
|
101
133
|
@playlist_id ||= @data['playlistId']
|
102
134
|
end
|
103
135
|
|
104
|
-
# @return [Integer
|
105
|
-
# playlist. The value is zero-based, so the
|
106
|
-
# of 0, the second item of 1, and so forth
|
136
|
+
# @return [Integer] if the resource is a playlist item, the order in
|
137
|
+
# which the item appears in a playlist. The value is zero-based, so the
|
138
|
+
# first item has a position of 0, the second item of 1, and so forth.
|
139
|
+
# @return [nil] if the resource is a channel.
|
140
|
+
# @return [nil] if the resource is a playlist.
|
141
|
+
# @return [nil] if the resource is a video.
|
107
142
|
def position
|
108
143
|
@position ||= @data['position'].to_i
|
109
144
|
end
|
110
145
|
|
111
|
-
# @return [String
|
112
|
-
#
|
146
|
+
# @return [String] if the resource is a playlist item, the ID of the
|
147
|
+
# video the playlist item represents in the playlist.
|
148
|
+
# @return [nil] if the resource is a channel.
|
149
|
+
# @return [nil] if the resource is a playlist.
|
150
|
+
# @return [nil] if the resource is a video.
|
113
151
|
def video_id
|
114
152
|
@video_id ||= @data.fetch('resourceId', {})['videoId']
|
115
153
|
end
|
116
154
|
|
117
|
-
# @return [Yt::Models::Video
|
118
|
-
#
|
155
|
+
# @return [Yt::Models::Video] the video the playlist item represents in
|
156
|
+
# the playlist.
|
157
|
+
# @return [nil] if the resource is a channel.
|
158
|
+
# @return [nil] if the resource is a playlist.
|
159
|
+
# @return [nil] if the resource is a video.
|
119
160
|
def video
|
120
161
|
@video ||= Video.new id: video_id, auth: @auth if video_id
|
121
162
|
end
|
data/lib/yt/version.rb
CHANGED
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.7.
|
4
|
+
version: 0.7.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Claudio Baccigalupo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|