yt 0.25.3 → 0.25.4

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: 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