yt 0.25.3 → 0.25.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 05e206f51ac4f37552e7061a22d0fcc7c092b539
4
- data.tar.gz: 60cbc93e088a51afba4fc91f6d25653564065d6d
3
+ metadata.gz: b97dd069350cac3eb417bd71f95e954002f18e95
4
+ data.tar.gz: 967cb4ed7350c7b451097d25e021e2b1deaa0543
5
5
  SHA512:
6
- metadata.gz: aa9742e5e3b4899c4261ce280e69eab478c3cdcfcc442e9706fe19ce06cbc51802d90a801f3d6031e21aafe33076c8e3b4a3f1060defc038c44fac81bfd29c16
7
- data.tar.gz: 328373548870b075b7cc542bb1b4736c0b7748985e912212d3f38cbe5c66431369eded41c80881e5ff7c0377a2d46bbc93a4f88f7307187eb5564ff410ff3ec7
6
+ metadata.gz: 573902e507215412b8fd4481ed9446a84cb6f57fe068f0e41ea9c52b7136c35a7da06b6ca2f48e4a5ba962b3715d63ac0d361dd93079fd45b410d105ed23f015
7
+ data.tar.gz: 09c85fe37c9cdec1b9d9037f0cd60b05135544db9e8a125e11769f652889ab42899184bff45607b38434f7a98b408701c859cb7eed745d5fb845beef91063973
data/CHANGELOG.md CHANGED
@@ -6,6 +6,10 @@ 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.4 - 2015-07-27
10
+
11
+ * [FEATURE] Add `channel.related_playlist` and `account.related_playlists` to access "Liked Videos", "Uploads", etc.
12
+
9
13
  ## 0.25.3 - 2015-07-23
10
14
 
11
15
  * [BUGFIX] Don’t run an infinite loop when calling `.playlist_items.includes(:video)` on a playlist with only private or deleted videos
data/README.md CHANGED
@@ -41,7 +41,7 @@ To install on your system, run
41
41
 
42
42
  To use inside a bundled Ruby project, add this line to the Gemfile:
43
43
 
44
- gem 'yt', '~> 0.25.3'
44
+ gem 'yt', '~> 0.25.4'
45
45
 
46
46
  Since the gem follows [Semantic Versioning](http://semver.org),
47
47
  indicating the full version in your Gemfile (~> *major*.*minor*.*patch*)
data/YOUTUBE_IT.md CHANGED
@@ -180,38 +180,19 @@ channel = Yt::Channel.new url: 'youtube.com/liz'
180
180
  channel.videos.where(q: 'penguin')
181
181
  ```
182
182
 
183
- <!--
184
-
185
- TODO: Although FAVORITE is somehow deprecated, it can still be retrieved with
186
- V3. First, get the contentDetails of the account's channel and you'll get
187
-
188
- {"relatedPlaylists"=>
189
- {"likes"=>"LLrWYT-_Xncr1BLPfPNr50sQ",
190
- "favorites"=>"FLrWYT-_Xncr1BLPfPNr50sQ",
191
- "uploads"=>"UUrWYT-_Xncr1BLPfPNr50sQ",
192
- "watchHistory"=>"HLrWYT-_Xncr1BLPfPNr50sQ",
193
- "watchLater"=>"WLrWYT-_Xncr1BLPfPNr50sQ"},
194
-
195
- Then you can list the videos of the "favorites" playlist. That playlist does
196
- not exist for new YouTube account, but you can still add a video to it, and
197
- it will magically appear (and also, DELETE PLAYLIST will be disabled)
198
-
199
183
  List videos favorited by user:
200
184
 
201
185
  ```ruby
202
186
  # with youtube_it
203
187
  client = YouTubeIt::Client.new
204
188
  client.videos_by(:favorites, :user => 'liz')
205
- # with yt: not supported (was removed from YouTube API V3)
206
-
207
- or maybe add .liked_videos and .disliked_videos here !!!!!
208
-
189
+ # with yt: note that only *old* channels have a "Favorites" playlist, since
190
+ # "Favorites" has been deprecated by YouTube in favor of "Liked Videos".
191
+ channel = Yt::Channel.new url: 'youtube.com/liz'
192
+ channel.related_playlists.find{|p| p.title == 'Favorites'}
209
193
  ```
210
194
 
211
195
 
212
-
213
- -->
214
-
215
196
  Retrieve video by ID:
216
197
 
217
198
  ```ruby
@@ -509,32 +490,16 @@ client.delete_comment(video_id, comment_id)
509
490
  # with yt: not supported (was removed from YouTube API V3)
510
491
  ```
511
492
 
512
- <!--
513
493
  List Favorites:
514
494
 
515
-
516
- TODO: Although FAVORITE is somehow deprecated, it can still be retrieved with
517
- V3. First, get the contentDetails of the account's channel and you'll get
518
-
519
- {"relatedPlaylists"=>
520
- {"likes"=>"LLrWYT-_Xncr1BLPfPNr50sQ",
521
- "favorites"=>"FLrWYT-_Xncr1BLPfPNr50sQ",
522
- "uploads"=>"UUrWYT-_Xncr1BLPfPNr50sQ",
523
- "watchHistory"=>"HLrWYT-_Xncr1BLPfPNr50sQ",
524
- "watchLater"=>"WLrWYT-_Xncr1BLPfPNr50sQ"},
525
-
526
- Then you can list the videos of the "favorites" playlist. That playlist does
527
- not exist for new YouTube account, but you can still add a video to it, and
528
- it will magically appear (and also, DELETE PLAYLIST will be disabled)
529
-
530
-
531
495
  ```ruby
532
496
  # with youtube_it
533
497
  client = # new client initialized with either OAuth or AuthSub
534
498
  client.favorites(user) # default: current user
535
- # with yt
536
-
537
- # TODO: ADD account.liked_videos and .disliked_videos
499
+ # with yt: note that only *old* channels have a "Favorites" playlist, since
500
+ # "Favorites" has been deprecated by YouTube in favor of "Liked Videos".
501
+ account = Yt::Account.new access_token: 'access_token'
502
+ account.related_playlists.find{|p| p.title == 'Favorites'}
538
503
  ```
539
504
 
540
505
  Add Favorite:
@@ -723,36 +688,39 @@ playlist_item = Yt::PlaylistItem.new id: playlist_entry_id, auth: account
723
688
  playlist_item.update position: position
724
689
  ```
725
690
 
726
- <!--
727
-
728
-
729
- TODO: Although WATCHLATER is somehow deprecated, it can still be retrieved with
730
- V3. First, get the contentDetails of the account's channel and you'll get
731
-
732
- {"relatedPlaylists"=>
733
- {"likes"=>"LLrWYT-_Xncr1BLPfPNr50sQ",
734
- "favorites"=>"FLrWYT-_Xncr1BLPfPNr50sQ",
735
- "uploads"=>"UUrWYT-_Xncr1BLPfPNr50sQ",
736
- "watchHistory"=>"HLrWYT-_Xncr1BLPfPNr50sQ",
737
- "watchLater"=>"WLrWYT-_Xncr1BLPfPNr50sQ"},
738
-
739
- Then you can list the videos of the "watch later" playlist. That playlist does
740
- not exist for new YouTube account, but you can still add a video to it, and
741
- it will magically appear (and also, DELETE PLAYLIST will be disabled)
742
-
743
-
744
691
  Select All Videos From your Watch Later Playlist:
745
- $ watcher_later = client.watcherlater(user) #default: current user
746
- $ watcher_later.videos
692
+
693
+ ```ruby
694
+ # with youtube_it
695
+ watcher_later = client.watcherlater(user) #default: current user
696
+ watcher_later.videos
697
+ # with yt
698
+ account = Yt::Account.new access_token: 'access_token'
699
+ watch_later = account.related_playlists.find{|p| p.title == 'Watch Later'}
700
+ watch_later.playlist_items.map{|item| item.video}
701
+ ```
747
702
 
748
703
  Add Video To Watcher Later Playlist:
749
- $ client.add_video_to_watchlater(video_id)
750
704
 
751
- Remove Video From Watch Later Playlist:
752
- $ client.delete_video_from_watchlater(watchlater_entry_id)
705
+ ```ruby
706
+ # with youtube_it
707
+ client.add_video_to_watchlater(video_id)
708
+ # with yt
709
+ account = Yt::Account.new access_token: 'access_token'
710
+ watch_later = account.related_playlists.find{|p| p.title == 'Watch Later'}
711
+ watch_later.add_video video_id
712
+ ```
753
713
 
754
- -->
714
+ Remove Video From Watch Later Playlist:
755
715
 
716
+ ```ruby
717
+ # with youtube_it
718
+ client.delete_video_from_watchlater(watchlater_entry_id)
719
+ # with yt
720
+ account = Yt::Account.new access_token: 'access_token'
721
+ watch_later = account.related_playlists.find{|p| p.title == 'Watch Later'}
722
+ watch_later.delete_playlist_items video_id: video_id
723
+ ```
756
724
 
757
725
  <!-- TODO: Add using https://developers.google.com/youtube/v3/docs/search/list#relatedToVideoId
758
726
 
@@ -7,7 +7,7 @@ module Yt
7
7
  module Actions
8
8
  module List
9
9
  delegate :any?, :count, :each, :each_cons, :each_slice, :find, :first,
10
- :flat_map, :map, :size, to: :list
10
+ :flat_map, :map, :select, :size, to: :list
11
11
 
12
12
  def first!
13
13
  first.tap{|item| raise Errors::NoItems, error_message unless item}
@@ -41,7 +41,7 @@ module Yt
41
41
  def total_results
42
42
  response = list_request(list_params).run
43
43
  total_results = response.body.fetch('pageInfo', {})['totalResults']
44
- total_results ||= response.body.fetch(items_key, []).size
44
+ total_results ||= extract_items(response.body).size
45
45
  end
46
46
 
47
47
  def find_next
@@ -93,7 +93,7 @@ module Yt
93
93
  def fetch_page(params = {})
94
94
  @last_response = list_request(params).run
95
95
  token = @last_response.body['nextPageToken']
96
- items = @last_response.body.fetch items_key, []
96
+ items = extract_items @last_response.body
97
97
  {items: items, token: token}
98
98
  end
99
99
 
@@ -123,6 +123,10 @@ module Yt
123
123
  end
124
124
  end
125
125
 
126
+ def extract_items(list)
127
+ list.fetch items_key, []
128
+ end
129
+
126
130
  def items_key
127
131
  'items'
128
132
  end
@@ -0,0 +1,43 @@
1
+ require 'yt/collections/playlists'
2
+
3
+ module Yt
4
+ module Collections
5
+ class RelatedPlaylists < Playlists
6
+
7
+ private
8
+
9
+ # Retrieving related playlists requires to hit the /channels endpoint.
10
+ def list_resources
11
+ 'channels'
12
+ end
13
+
14
+ # The related playlists are included in the content details of a channel.
15
+ def playlists_params
16
+ {part: 'contentDetails', id: @parent.id}
17
+ end
18
+
19
+ # The object to create is "Yt::Models::Playlist", not "RelatedPlaylist"
20
+ def resource_class
21
+ Yt::Models::Playlist
22
+ end
23
+
24
+ # The related playlists are nested inside the "relatedPlaylists" key.
25
+ def extract_items(list)
26
+ if (items = super).any?
27
+ items.first['contentDetails'].fetch 'relatedPlaylists', {}
28
+ end
29
+ end
30
+
31
+ # Since there are at most 5 related playlists, they can be eager-loaded.
32
+ def eager_load_items_from(items)
33
+ conditions = {id: items.values.join(','), part: 'snippet,status'}
34
+ Collections::Playlists.new(auth: @auth).where conditions
35
+ end
36
+
37
+ # Related playlists are eager-loaded, there’s no need to load them again.
38
+ def new_item(playlist)
39
+ playlist
40
+ end
41
+ end
42
+ end
43
+ end
@@ -134,6 +134,12 @@ module Yt
134
134
  # @return [Yt::Collections::Playlists] the playlists owned by the account.
135
135
  delegate :playlists, to: :channel
136
136
 
137
+ # @!attribute [r] related_playlists
138
+ # @return [Yt::Collections::Playlists] the playlists associated with the
139
+ # account, such as the playlist of uploaded or liked videos.
140
+ # @see https://developers.google.com/youtube/v3/docs/channels#contentDetails.relatedPlaylists
141
+ delegate :related_playlists, to: :channel
142
+
137
143
  # @!attribute [r] subscribed_channels
138
144
  # @return [Yt::Collections::SubscribedChannels] the channels that the
139
145
  # account is subscribed to.
@@ -94,6 +94,12 @@ module Yt
94
94
  # @return [Yt::Collections::Playlists] the channel’s playlists.
95
95
  has_many :playlists
96
96
 
97
+ # @!attribute [r] related_playlists
98
+ # @return [Yt::Collections::Playlists] the playlists associated with the
99
+ # channel, such as the playlist of uploaded or liked videos.
100
+ # @see https://developers.google.com/youtube/v3/docs/channels#contentDetails.relatedPlaylists
101
+ has_many :related_playlists
102
+
97
103
  # @!attribute [r] subscribed_channels
98
104
  # @return [Yt::Collections::SubscribedChannels] the channels that this
99
105
  # channel is subscribed to.
data/lib/yt/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Yt
2
- VERSION = '0.25.3'
2
+ VERSION = '0.25.4'
3
3
  end
@@ -15,6 +15,27 @@ describe Yt::Account, :device_app do
15
15
  it { expect($account.subscribed_channels.first).to be_a Yt::Channel }
16
16
  it { expect($account.user_info).to be_a Yt::UserInfo }
17
17
 
18
+ describe '.related_playlists' do
19
+ let(:related_playlists) { $account.related_playlists }
20
+
21
+ specify 'returns the list of associated playlist (Liked Videos, Uploads, ...)' do
22
+ expect(related_playlists.first).to be_a Yt::Playlist
23
+ end
24
+
25
+ specify 'includes public related playlists (such as Liked Videos)' do
26
+ uploads = related_playlists.select{|p| p.title.starts_with? 'Uploads'}
27
+ expect(uploads).not_to be_empty
28
+ end
29
+
30
+ specify 'includes private playlists (such as Watch Later or History)' do
31
+ watch_later = related_playlists.select{|p| p.title == 'Watch Later'}
32
+ expect(watch_later).not_to be_empty
33
+
34
+ history = related_playlists.select{|p| p.title == 'History'}
35
+ expect(history).not_to be_empty
36
+ end
37
+ end
38
+
18
39
  describe '.videos' do
19
40
  let(:video) { $account.videos.where(order: 'viewCount').first }
20
41
 
@@ -102,6 +102,24 @@ describe Yt::Channel, :device_app do
102
102
  it { expect(channel.playlists.first).to be_a Yt::Playlist }
103
103
  it { expect{channel.delete_playlists}.to raise_error Yt::Errors::RequestError }
104
104
 
105
+ describe '.related_playlists' do
106
+ let(:related_playlists) { channel.related_playlists }
107
+
108
+ specify 'returns the list of associated playlist (Liked Videos, Uploads, ...)' do
109
+ expect(related_playlists.first).to be_a Yt::Playlist
110
+ end
111
+
112
+ specify 'includes public related playlists (such as Liked Videos)' do
113
+ uploads = related_playlists.select{|p| p.title.starts_with? 'Uploads'}
114
+ expect(uploads).not_to be_empty
115
+ end
116
+
117
+ specify 'does not includes private playlists (such as Watch Later)' do
118
+ watch_later = related_playlists.select{|p| p.title.starts_with? 'Watch'}
119
+ expect(watch_later).to be_empty
120
+ end
121
+ end
122
+
105
123
  specify 'with a public list of subscriptions' do
106
124
  expect(channel.subscribed_channels.first).to be_a Yt::Channel
107
125
  end
@@ -21,6 +21,8 @@ describe Yt::Channel, :server_app do
21
21
  it { expect(channel.videos.first).to be_a Yt::Video }
22
22
  it { expect(channel.playlists).to be_a Yt::Collections::Playlists }
23
23
  it { expect(channel.playlists.first).to be_a Yt::Playlist }
24
+ it { expect(channel.related_playlists).to be_a Yt::Collections::Playlists }
25
+ it { expect(channel.related_playlists.first).to be_a Yt::Playlist }
24
26
 
25
27
  specify 'with a public list of subscriptions' do
26
28
  expect(channel.subscribed_channels.first).to be_a Yt::Channel
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.25.3
4
+ version: 0.25.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claudio Baccigalupo
@@ -152,6 +152,7 @@ files:
152
152
  - lib/yt/collections/policies.rb
153
153
  - lib/yt/collections/ratings.rb
154
154
  - lib/yt/collections/references.rb
155
+ - lib/yt/collections/related_playlists.rb
155
156
  - lib/yt/collections/reports.rb
156
157
  - lib/yt/collections/resources.rb
157
158
  - lib/yt/collections/resumable_sessions.rb