yt 0.25.26 → 0.25.27

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: 78dee68c38b98a14d9213c8f01b507425e25cca2
4
- data.tar.gz: f859f557aef4fa1a76940ddaa5488af2515cb0df
3
+ metadata.gz: c5e0f3c2d22ca139c343e25b12d546f27fab7426
4
+ data.tar.gz: ab8d1de072cd33417b2276923dcef81f40fa5063
5
5
  SHA512:
6
- metadata.gz: a98d8b324a2c866fb4ad872e22f7eda31c69dbfc4ce66e11abf5f63fa9a9e497b489a3554ba09baf1c4102b746829ca5fa29eecff3e93dea2887288e4a4ab88d
7
- data.tar.gz: 8f0da58402c694c51f1b229bf4fd9afe0f2c638893d9086311bb82734639ae523c73b28d6ae441359dc309a2883d0ddfb549bfef56c95468b3648fc4a6cea3f1
6
+ metadata.gz: c9817c82f21347ab5b0b5f2d1b866ae5de343ece03e8abfd51902a141618eb766bfa4499c2248d124a38cbd7493eb47cd743698db9eca637fdfeefb6b552573a
7
+ data.tar.gz: 9687e59b2d140f368083380fe593c18818c60f5d03c1184c6b4d604c5f7f2420b57d64138ba6b8b2427cf097527b90e493598aa64cc3899799f4ec7cf97f2c69
@@ -6,6 +6,11 @@ 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.27 - 2016-03-28
10
+
11
+ * [FEATURE] Add `comment_threads` association to Yt::Video.
12
+ * [FEATURE] Add `top_level_comment` and delegate its attributes (`text_display`, `author_display_name`, `like_count`, `updated_at`) to Yt::CommentThread.
13
+
9
14
  ## 0.25.26 - 2016-03-24
10
15
 
11
16
  * [FEATURE] Add Yt::Comment resource.
data/README.md CHANGED
@@ -28,6 +28,9 @@ video.title #=> "Fullscreen Creator Platform"
28
28
  video.comment_count #=> 308
29
29
  video.hd? #=> true
30
30
  video.annotations.count #=> 1
31
+ video.comment_threads #=> #<Yt::Collections::CommentThreads ...>
32
+ # Use #take to limit the number of pages need to fetch from server
33
+ video.comment_threads.take(99).map(&:author_display_name) #=> ["Paul", "Tommy", ...]
31
34
  ```
32
35
 
33
36
  The **full documentation** is available at [rubydoc.info](http://www.rubydoc.info/gems/yt/frames).
@@ -130,6 +133,12 @@ comment_thread.video_id #=> "1234"
130
133
  comment_thread.total_reply_count #=> 1
131
134
  comment_thread.can_reply? #=> true
132
135
  comment_thread.public? #=> true
136
+
137
+ comment_thread.top_level_comment #=> #<Yt::Models::Comment ...>
138
+ comment_thread.text_display #=> "funny video!"
139
+ comment_thread.like_count #=> 9
140
+ comment_thread.updated_at #=> 2016-03-22 12:56:56 UTC
141
+ comment_thread.author_display_name #=> "Joe"
133
142
  ```
134
143
 
135
144
  Yt::Comment
@@ -6,7 +6,7 @@ require 'yt/config'
6
6
  module Yt
7
7
  module Actions
8
8
  module List
9
- delegate :any?, :count, :each, :each_cons, :each_slice, :find, :first,
9
+ delegate :any?, :count, :each, :each_cons, :each_slice, :find, :first, :take,
10
10
  :flat_map, :map, :select, :size, to: :list
11
11
 
12
12
  def first!
@@ -136,4 +136,4 @@ module Yt
136
136
  end
137
137
  end
138
138
  end
139
- end
139
+ end
@@ -0,0 +1,41 @@
1
+ require 'yt/collections/base'
2
+ require 'yt/models/video'
3
+ require 'yt/models/channel'
4
+
5
+ module Yt
6
+ module Collections
7
+ # @private
8
+ class CommentThreads < Base
9
+
10
+ private
11
+
12
+ def attributes_for_new_item(data)
13
+ {}.tap do |attributes|
14
+ attributes[:id] = data['id']
15
+ attributes[:snippet] = data['snippet']
16
+ attributes[:auth] = @auth
17
+ end
18
+ end
19
+
20
+ # @return [Hash] the parameters to submit to YouTube to get the resource.
21
+ # @see https://developers.google.com/youtube/v3/docs/commentThreads#resource
22
+ def list_params
23
+ super.tap do |params|
24
+ params[:path] = "/youtube/v3/commentThreads"
25
+ params[:params] = comments_params
26
+ end
27
+ end
28
+
29
+ def comments_params
30
+ apply_where_params!({max_results: 100, part: 'snippet'}).tap do |params|
31
+ case @parent
32
+ when Yt::Video
33
+ params[:videoId] = @parent.id
34
+ when Yt::Channel
35
+ params[:channelId] = @parent.id
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -2,21 +2,21 @@ require 'yt/models/resource'
2
2
 
3
3
  module Yt
4
4
  module Models
5
- # Provides methods to interact with YouTube channels.
5
+ # Provides methods to interact with YouTube comment thread.
6
6
  # @see https://developers.google.com/youtube/v3/docs/commentThreads
7
7
  class CommentThread < Resource
8
8
 
9
9
  ### SNIPPET ###
10
10
 
11
11
  # @!attribute [r] video_id
12
- # @return [String] the ID of the video that the comments refer to, if
13
- # any. If this property is not present or does not have a value, then
14
- # the thread applies to the channel and not to a specific video.
12
+ # @return [String] the ID of the video that the comment thread referto, if
13
+ # any. If this property is not present or does not have a value, then the
14
+ # thread applies to the channel and not to a specific video.
15
15
  delegate :video_id, to: :snippet
16
16
 
17
17
  # @!attribute [r] total_reply_count
18
18
  # @return [String] The total number of replies that have been submitted
19
- # in response to the top-level comment.
19
+ # in response to the top level comment.
20
20
  delegate :total_reply_count, to: :snippet
21
21
 
22
22
  # @return [Boolean] whether the thread, including all of its comments and
@@ -25,6 +25,26 @@ module Yt
25
25
 
26
26
  # @return [Boolean] whether the current viewer can reply to the thread.
27
27
  delegate :can_reply?, to: :snippet
28
+
29
+ # @!attribute [r] top_level_comment
30
+ # @return [Yt::TopLevelComment] the top level comment object.
31
+ delegate :top_level_comment, to: :snippet
32
+
33
+ # @!attribute [r] text_display
34
+ # @return [String] the top level comment's display text.
35
+ delegate :text_display, to: :top_level_comment
36
+
37
+ # @!attribute [r] author_display_name
38
+ # @return [String] the top level comment's author name.
39
+ delegate :author_display_name, to: :top_level_comment
40
+
41
+ # @!attribute [r] like_count
42
+ # @return [String] the top level comment's likes count.
43
+ delegate :like_count, to: :top_level_comment
44
+
45
+ # @!attribute [r] updated_at
46
+ # @return [String] the top level comment's last updated time.
47
+ delegate :updated_at, to: :top_level_comment
28
48
  end
29
49
  end
30
50
  end
@@ -1,4 +1,5 @@
1
1
  require 'yt/models/description'
2
+ require 'yt/models/comment'
2
3
 
3
4
  module Yt
4
5
  module Models
@@ -38,7 +39,6 @@ module Yt
38
39
  has_attribute :like_count, type: Integer
39
40
  has_attribute :updated_at, type: Time
40
41
 
41
-
42
42
  def thumbnail_url(size = :default)
43
43
  thumbnails.fetch(size.to_s, {})['url']
44
44
  end
@@ -51,6 +51,10 @@ module Yt
51
51
  @can_reply ||= data.fetch 'canReply', false
52
52
  end
53
53
 
54
+ def top_level_comment
55
+ @top_level_comment ||= Yt::Comment.new data['topLevelComment'].symbolize_keys
56
+ end
57
+
54
58
  # Returns whether YouTube API includes all attributes in this snippet.
55
59
  # For instance, YouTube API only returns tags and categoryId on
56
60
  # Videos#list, not on Videos#search. And returns position on
@@ -369,6 +369,9 @@ module Yt
369
369
  delegate :concurrent_viewers, to: :live_streaming_detail
370
370
 
371
371
  ### ASSOCIATIONS ###
372
+ # @!attribute [r] comments
373
+ # @return [Yt::Collections::Comments] the video’s comments.
374
+ has_many :comment_threads
372
375
 
373
376
  # @!attribute [r] annotations
374
377
  # @return [Yt::Collections::Annotations] the video’s annotations.
@@ -1,3 +1,3 @@
1
1
  module Yt
2
- VERSION = '0.25.26'
2
+ VERSION = '0.25.27'
3
3
  end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+ require 'yt/collections/comment_threads'
3
+ require 'yt/models/video'
4
+ require 'yt/models/channel'
5
+
6
+ describe Yt::Collections::CommentThreads do
7
+ subject(:collection) { Yt::Collections::CommentThreads.new parent: parent}
8
+
9
+ describe '#size', :ruby2 do
10
+ describe 'sends only one request and return the total results' do
11
+ let(:total_results) { 1234 }
12
+ let(:parent) { Yt::Video.new id: 'any-id' }
13
+
14
+ before do
15
+ expect_any_instance_of(Yt::Request).to receive(:run).once do
16
+ double(body: {'pageInfo'=>{'totalResults'=>total_results}})
17
+ end
18
+ end
19
+ it { expect(collection.size).to be total_results }
20
+ end
21
+ end
22
+
23
+ describe '#count' do
24
+ let(:query) { {q: 'search string'} }
25
+ let(:parent) { Yt::Video.new id: 'any-id' }
26
+ let(:page) { {items: [], token: 'any-token'} }
27
+
28
+ context 'called once with .where(query) and once without' do
29
+ after do
30
+ collection.where(query).count
31
+ collection.count
32
+ end
33
+
34
+ it 'only applies the query on the first call' do
35
+ expect(collection).to receive(:fetch_page) do |options|
36
+ expect(options[:params]).to include query
37
+ page
38
+ end
39
+ expect(collection).to receive(:fetch_page) do |options|
40
+ expect(options[:params]).not_to include query
41
+ page
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -23,6 +23,38 @@ describe Yt::CommentThread do
23
23
  end
24
24
  end
25
25
 
26
+ describe '#top_level_comment' do
27
+ context 'given a snippet with a top level comment' do
28
+ let(:attrs) { {snippet: {"topLevelComment"=> {}}} }
29
+ it { expect(comment_thread.top_level_comment).to be_a Yt::Comment }
30
+ end
31
+ end
32
+
33
+ describe 'attributes from #top_level_comment delegations' do
34
+ context 'with values' do
35
+ let(:attrs) { {snippet: {"topLevelComment"=> {"id" => "xyz123", "snippet" => {
36
+ "textDisplay" => "funny video!",
37
+ "authorDisplayName" => "fullscreen",
38
+ "likeCount" => 99,
39
+ "updatedAt" => "2016-03-22T12:56:56.3Z"}}}} }
40
+
41
+ it { expect(comment_thread.top_level_comment.id).to eq 'xyz123' }
42
+ it { expect(comment_thread.text_display).to eq 'funny video!' }
43
+ it { expect(comment_thread.author_display_name).to eq 'fullscreen' }
44
+ it { expect(comment_thread.like_count).to eq 99 }
45
+ it { expect(comment_thread.updated_at).to eq Time.parse('2016-03-22T12:56:56.3Z') }
46
+ end
47
+
48
+ context 'without values' do
49
+ let(:attrs) { {snippet: {"topLevelComment"=> {"snippet" => {}}}} }
50
+
51
+ it { expect(comment_thread.text_display).to be_nil }
52
+ it { expect(comment_thread.author_display_name).to be_nil }
53
+ it { expect(comment_thread.like_count).to be_nil }
54
+ it { expect(comment_thread.updated_at).to be_nil }
55
+ end
56
+ end
57
+
26
58
  describe '#total_reply_count' do
27
59
  context 'given a snippet with a total reply count' do
28
60
  let(:attrs) { {snippet: {"totalReplyCount"=>1}} }
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
  require 'yt/models/comment_thread'
3
+ require 'yt/models/comment'
3
4
 
4
5
  describe Yt::CommentThread, :server_app do
5
6
  subject(:comment_thread) { Yt::CommentThread.new attrs }
@@ -11,6 +12,12 @@ describe Yt::CommentThread, :server_app do
11
12
  it { expect(comment_thread.total_reply_count).to be_an Integer }
12
13
  it { expect(comment_thread.can_reply?).to be false }
13
14
  it { expect(comment_thread).to be_public }
15
+
16
+ it { expect(comment_thread.top_level_comment).to be_a Yt::Comment }
17
+ it { expect(comment_thread.text_display).not_to be_empty }
18
+ it { expect(comment_thread.author_display_name).not_to be_empty }
19
+ it { expect(comment_thread.updated_at).to be_a Time }
20
+ it { expect(comment_thread.like_count).to be_a Integer }
14
21
  end
15
22
 
16
23
  context 'given an comment thread ID about a video' do
@@ -0,0 +1,41 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+ require 'yt/collections/comment_threads'
4
+ require 'yt/models/video'
5
+ require 'yt/models/channel'
6
+
7
+ describe Yt::Collections::CommentThreads, :server_app do
8
+ context "without parent association", :ruby2 do
9
+ subject(:comment_threads) { Yt::Collections::CommentThreads.new }
10
+
11
+ specify 'without given any of id, videoId, channelId or allThreadsRelatedToChannelId param, raise request error', :ruby2 do
12
+ expect{ comment_threads.size }.to raise_error(Yt::Errors::RequestError)
13
+ end
14
+
15
+ specify 'with a id param, only return one comment thread' do
16
+ expect(comment_threads.where(id: 'z13zytsilxbexh30e233gdyyttngfjfz104').size).to eq 1
17
+ end
18
+
19
+ specify 'with a videoId param, returns comment threads for the video', focus: true do
20
+ expect(comment_threads.where(videoId: 'MsplPPW7tFo').size).to be > 0
21
+ end
22
+
23
+ specify 'with a channelId param, returns comment threads for the channel' do
24
+ expect(comment_threads.where(channelId: 'UC-lHJZR3Gqxm24_Vd_AJ5Yw').size).to be > 0
25
+ end
26
+ end
27
+
28
+ context "with parent association", :ruby2 do
29
+ subject(:comment_threads) { Yt::Collections::CommentThreads.new parent: parent}
30
+
31
+ context "parent as video" do
32
+ let(:parent) { Yt::Models::Video.new id: 'MsplPPW7tFo' }
33
+ it { expect(comment_threads.size).to be > 0 }
34
+ end
35
+
36
+ context "parent as channel" do
37
+ let(:parent) { Yt::Models::Channel.new id: 'UC-lHJZR3Gqxm24_Vd_AJ5Yw' }
38
+ it { expect(comment_threads.size).to be > 0 }
39
+ end
40
+ end
41
+ end
@@ -1,11 +1,12 @@
1
1
  require 'spec_helper'
2
2
  require 'yt/models/video'
3
+ require 'yt/collections/comment_threads'
3
4
 
4
5
  describe Yt::Video, :server_app do
5
6
  subject(:video) { Yt::Video.new attrs }
6
7
 
7
8
  context 'given an existing video ID' do
8
- let(:attrs) { {id: 'MESycYJytkU'} }
9
+ let(:attrs) { {id: 'L3JDXvz7G6c'} }
9
10
 
10
11
  it { expect(video.content_detail).to be_a Yt::ContentDetail }
11
12
 
@@ -27,11 +28,11 @@ describe Yt::Video, :server_app do
27
28
  end
28
29
 
29
30
  context 'given an existing video URL' do
30
- let(:attrs) { {url: 'https://www.youtube.com/watch?v=MESycYJytkU&list=LLxO1tY8h1AhOz0T4ENwmpow'} }
31
+ let(:attrs) { {url: 'https://www.youtube.com/watch?v=L3JDXvz7G6c'} }
31
32
 
32
33
  specify 'provides access to its data' do
33
- expect(video.id).to eq 'MESycYJytkU'
34
- expect(video.title).to eq 'Fullscreen Creator Platform'
34
+ expect(video.id).to eq 'L3JDXvz7G6c'
35
+ expect(video.title).to eq "you’re in fullscreen"
35
36
  expect(video.privacy_status).to eq 'public'
36
37
  end
37
38
  end
@@ -55,4 +56,24 @@ describe Yt::Video, :server_app do
55
56
  end
56
57
  end
57
58
 
58
- end
59
+ describe 'associations' do
60
+ let(:attrs) { {id: 'MsplPPW7tFo'} }
61
+
62
+ describe '#comment_threads' do
63
+ it { expect(video.comment_threads).to be_a Yt::Collections::CommentThreads }
64
+ it { expect(video.comment_threads.first.top_level_comment).to be_a Yt::Models::Comment }
65
+ end
66
+
67
+ describe '#comment_threads.each_cons' do
68
+ it {
69
+ comment_threads = []
70
+ video.comment_threads.each_cons(2).take_while do |items|
71
+ comment_threads += items
72
+ comment_threads.size < 6
73
+ end
74
+ expect(comment_threads.size).to be 6
75
+ }
76
+ end
77
+ end
78
+ end
79
+
@@ -22,7 +22,7 @@ describe Yt::Collections::Videos, :server_app do
22
22
  end
23
23
 
24
24
  specify 'with a chart parameter, only returns videos of that chart', :ruby2 do
25
- expect(videos.where(chart: 'mostPopular').size).to be 30
25
+ expect(videos.where(chart: 'mostPopular').size).to be 200
26
26
  end
27
27
 
28
28
  context 'with a list of parts' do
@@ -37,4 +37,4 @@ describe Yt::Collections::Videos, :server_app do
37
37
  expect(video.instance_variable_defined? :@content_detail).to be true
38
38
  end
39
39
  end
40
- end
40
+ end
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.26
4
+ version: 0.25.27
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-03-24 00:00:00.000000000 Z
11
+ date: 2016-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -137,6 +137,7 @@ files:
137
137
  - lib/yt/collections/channels.rb
138
138
  - lib/yt/collections/claim_histories.rb
139
139
  - lib/yt/collections/claims.rb
140
+ - lib/yt/collections/comment_threads.rb
140
141
  - lib/yt/collections/content_details.rb
141
142
  - lib/yt/collections/content_owner_details.rb
142
143
  - lib/yt/collections/content_owners.rb
@@ -229,6 +230,7 @@ files:
229
230
  - lib/yt/request.rb
230
231
  - lib/yt/version.rb
231
232
  - spec/collections/claims_spec.rb
233
+ - spec/collections/comment_threads_spec.rb
232
234
  - spec/collections/playlist_items_spec.rb
233
235
  - spec/collections/playlists_spec.rb
234
236
  - spec/collections/policies_spec.rb
@@ -300,6 +302,7 @@ files:
300
302
  - spec/requests/as_server_app/channel_spec.rb
301
303
  - spec/requests/as_server_app/comment_spec.rb
302
304
  - spec/requests/as_server_app/comment_thread_spec.rb
305
+ - spec/requests/as_server_app/comment_threads_spec.rb
303
306
  - spec/requests/as_server_app/playlist_item_spec.rb
304
307
  - spec/requests/as_server_app/playlist_spec.rb
305
308
  - spec/requests/as_server_app/video_spec.rb
@@ -336,6 +339,7 @@ summary: Yt makes it easy to interact with Youtube V3 API by providing a modular
336
339
  intuitive and tested Ruby-style API.
337
340
  test_files:
338
341
  - spec/collections/claims_spec.rb
342
+ - spec/collections/comment_threads_spec.rb
339
343
  - spec/collections/playlist_items_spec.rb
340
344
  - spec/collections/playlists_spec.rb
341
345
  - spec/collections/policies_spec.rb
@@ -407,6 +411,7 @@ test_files:
407
411
  - spec/requests/as_server_app/channel_spec.rb
408
412
  - spec/requests/as_server_app/comment_spec.rb
409
413
  - spec/requests/as_server_app/comment_thread_spec.rb
414
+ - spec/requests/as_server_app/comment_threads_spec.rb
410
415
  - spec/requests/as_server_app/playlist_item_spec.rb
411
416
  - spec/requests/as_server_app/playlist_spec.rb
412
417
  - spec/requests/as_server_app/video_spec.rb