yt 0.28.5 → 0.29.0
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/CHANGELOG.md +22 -0
- data/MIT-LICENSE +1 -1
- data/YOUTUBE_IT.md +3 -3
- data/lib/yt/models/resource.rb +3 -10
- data/lib/yt/models/right_owner.rb +0 -2
- data/lib/yt/models/snippet.rb +1 -2
- data/lib/yt/version.rb +1 -1
- data/spec/models/resource_spec.rb +0 -15
- data/spec/requests/as_server_app/channel_spec.rb +1 -21
- data/spec/requests/as_server_app/playlist_item_spec.rb +1 -1
- data/spec/requests/as_server_app/playlist_spec.rb +1 -22
- data/spec/requests/as_server_app/video_spec.rb +1 -21
- metadata +3 -12
- data/lib/yt/collections/ids.rb +0 -27
- data/lib/yt/models/description.rb +0 -58
- data/lib/yt/models/url.rb +0 -91
- data/spec/models/description_spec.rb +0 -94
- data/spec/models/url_spec.rb +0 -84
- data/spec/requests/as_account/resource_spec.rb +0 -18
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e22a0e31744f1671b9ecb506921d0adfd61f1c9b
|
|
4
|
+
data.tar.gz: 730c92a149f9fd7c00c23a13fef0c5f37ea43d2b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1475b00ac7c0abed681ffa39c173d7a6a80507f09434c66ca27444ab65e6a0e399045a9d1a6a8d9cb0a9dfcccd5183ced1fa041bcd8b35b771eb05105c6ab631
|
|
7
|
+
data.tar.gz: 8b6bfa677ddc77b178bc38d6db634e03cb51a1d1b04d8a1b1a47f1e5595ce32a75ed7e236b5588b64ce413883095bf50b88c0dc4e70d1306ee4446b5476ca214
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,28 @@ 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.29.0 - 2017-02-17
|
|
10
|
+
|
|
11
|
+
**How to upgrade**
|
|
12
|
+
|
|
13
|
+
If your code uses `Yt::URL` then you must include the `yt-url` gem, since
|
|
14
|
+
`Yt::URL` has been extracted into a separate repository.
|
|
15
|
+
Please read the documentation of `Yt::URL` and notice that the `subscription`
|
|
16
|
+
pattern has been dropped, so URLs such as the following will not be recognized
|
|
17
|
+
anymore: `subscription_center?add_user=...`, `subscribe_widget?p=...`.
|
|
18
|
+
|
|
19
|
+
Note that this also removes the option of initializing a resource by URL.
|
|
20
|
+
You can achieve the same result with the `yt-url` gem, as detailed in its
|
|
21
|
+
documentation.
|
|
22
|
+
|
|
23
|
+
Finally note that this also remove the class `Yt::Description`. This class
|
|
24
|
+
was private API, so this change should not affect developers.
|
|
25
|
+
|
|
26
|
+
* [REMOVAL] Remove the option to initialize resources by URL.
|
|
27
|
+
* [REMOVAL] Remove 'Yt::Resource.username`
|
|
28
|
+
* [REMOVAL] Remove `Yt::URL` (extracted into separate gem)
|
|
29
|
+
* [REMOVAL] Remove `Yt::Description` (now simply a String).
|
|
30
|
+
|
|
9
31
|
## 0.28.5 - 2017-01-18
|
|
10
32
|
|
|
11
33
|
* [BUGFIX] Don't crash when Yt::VideoGroup is initialized with a group of playlists.
|
data/MIT-LICENSE
CHANGED
data/YOUTUBE_IT.md
CHANGED
|
@@ -141,7 +141,7 @@ client = YouTubeIt::Client.new
|
|
|
141
141
|
client.videos_by(:query => "penguin", :author => "liz")
|
|
142
142
|
# with yt: the 'author' filter was removed from YouTube API V3, so the
|
|
143
143
|
# request must be done using the channel of the requested author
|
|
144
|
-
channel = Yt::Channel.new
|
|
144
|
+
channel = Yt::Channel.new id: 'UCxxxxxxxxx'
|
|
145
145
|
channel.videos.where(q: 'penguin')
|
|
146
146
|
```
|
|
147
147
|
|
|
@@ -176,7 +176,7 @@ client = YouTubeIt::Client.new
|
|
|
176
176
|
client.videos_by(:user => 'liz')
|
|
177
177
|
# with yt: the 'author' filter was removed from YouTube API V3, so the
|
|
178
178
|
# request must be done using the channel of the requested author
|
|
179
|
-
channel = Yt::Channel.new
|
|
179
|
+
channel = Yt::Channel.new id: 'UCxxxxxxxxx'
|
|
180
180
|
channel.videos.where(q: 'penguin')
|
|
181
181
|
```
|
|
182
182
|
|
|
@@ -188,7 +188,7 @@ client = YouTubeIt::Client.new
|
|
|
188
188
|
client.videos_by(:favorites, :user => 'liz')
|
|
189
189
|
# with yt: note that only *old* channels have a "Favorites" playlist, since
|
|
190
190
|
# "Favorites" has been deprecated by YouTube in favor of "Liked Videos".
|
|
191
|
-
channel = Yt::Channel.new
|
|
191
|
+
channel = Yt::Channel.new id: 'UCxxxxxxxxx'
|
|
192
192
|
channel.related_playlists.find{|p| p.title == 'Favorites'}
|
|
193
193
|
```
|
|
194
194
|
|
data/lib/yt/models/resource.rb
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
2
|
|
|
3
3
|
require 'yt/models/base'
|
|
4
|
-
require 'yt/models/url'
|
|
5
4
|
|
|
6
5
|
module Yt
|
|
7
6
|
module Models
|
|
@@ -13,7 +12,7 @@ module Yt
|
|
|
13
12
|
|
|
14
13
|
# @!attribute [r] id
|
|
15
14
|
# @return [String] the ID that YouTube uses to identify each resource.
|
|
16
|
-
|
|
15
|
+
attr_reader :id
|
|
17
16
|
|
|
18
17
|
### STATUS ###
|
|
19
18
|
|
|
@@ -43,8 +42,7 @@ module Yt
|
|
|
43
42
|
|
|
44
43
|
# @private
|
|
45
44
|
def initialize(options = {})
|
|
46
|
-
@
|
|
47
|
-
@id = options[:id] || (@url.id if @url)
|
|
45
|
+
@id = options[:id]
|
|
48
46
|
@auth = options[:auth]
|
|
49
47
|
@snippet = Snippet.new(data: options[:snippet]) if options[:snippet]
|
|
50
48
|
@status = Status.new(data: options[:status]) if options[:status]
|
|
@@ -52,12 +50,7 @@ module Yt
|
|
|
52
50
|
|
|
53
51
|
# @private
|
|
54
52
|
def kind
|
|
55
|
-
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# @private
|
|
59
|
-
def username
|
|
60
|
-
@url.username if @url
|
|
53
|
+
self.class.to_s.demodulize.underscore
|
|
61
54
|
end
|
|
62
55
|
|
|
63
56
|
# @private
|
data/lib/yt/models/snippet.rb
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
require 'yt/models/description'
|
|
2
1
|
require 'yt/models/comment'
|
|
3
2
|
|
|
4
3
|
module Yt
|
|
@@ -20,7 +19,7 @@ module Yt
|
|
|
20
19
|
end
|
|
21
20
|
|
|
22
21
|
has_attribute :title, default: ''
|
|
23
|
-
has_attribute
|
|
22
|
+
has_attribute :description, default: ''
|
|
24
23
|
has_attribute :published_at, type: Time
|
|
25
24
|
has_attribute :channel_id
|
|
26
25
|
has_attribute :channel_title
|
data/lib/yt/version.rb
CHANGED
|
@@ -4,21 +4,6 @@ require 'yt/models/resource'
|
|
|
4
4
|
describe Yt::Resource do
|
|
5
5
|
subject(:resource) { Yt::Resource.new attrs }
|
|
6
6
|
|
|
7
|
-
context 'given a resource initialized with a URL (containing an ID)' do
|
|
8
|
-
let(:attrs) { {url: 'youtu.be/9bZkp7q19f0'} }
|
|
9
|
-
|
|
10
|
-
it { expect(resource.id).to eq '9bZkp7q19f0' }
|
|
11
|
-
it { expect(resource.kind).to eq 'video' }
|
|
12
|
-
it { expect(resource.username).to be_nil }
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
context 'given a resource initialized with a URL (containing a username)' do
|
|
16
|
-
let(:attrs) { {url: 'youtube.com/fullscreen'} }
|
|
17
|
-
|
|
18
|
-
it { expect(resource.kind).to eq 'channel' }
|
|
19
|
-
it { expect(resource.username).to eq 'fullscreen' }
|
|
20
|
-
end
|
|
21
|
-
|
|
22
7
|
describe '#public?' do
|
|
23
8
|
context 'given fetching a status returns privacyStatus "public"' do
|
|
24
9
|
let(:attrs) { {status: {"privacyStatus"=>"public"}} }
|
|
@@ -10,7 +10,7 @@ describe Yt::Channel, :server_app do
|
|
|
10
10
|
it 'returns valid snippet data' do
|
|
11
11
|
expect(channel.snippet).to be_a Yt::Snippet
|
|
12
12
|
expect(channel.title).to be_a String
|
|
13
|
-
expect(channel.description).to be_a
|
|
13
|
+
expect(channel.description).to be_a String
|
|
14
14
|
expect(channel.thumbnail_url).to be_a String
|
|
15
15
|
expect(channel.published_at).to be_a Time
|
|
16
16
|
end
|
|
@@ -34,16 +34,6 @@ describe Yt::Channel, :server_app do
|
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
context 'given an existing channel URL' do
|
|
38
|
-
let(:attrs) { {url: 'youtube.com/fullscreen'} }
|
|
39
|
-
|
|
40
|
-
specify 'provides access to its data' do
|
|
41
|
-
expect(channel.id).to eq 'UCxO1tY8h1AhOz0T4ENwmpow'
|
|
42
|
-
expect(channel.title).to eq 'Fullscreen'
|
|
43
|
-
expect(channel.privacy_status).to eq 'public'
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
37
|
context 'given an unknown channel ID' do
|
|
48
38
|
let(:attrs) { {id: 'not-a-channel-id'} }
|
|
49
39
|
|
|
@@ -61,14 +51,4 @@ describe Yt::Channel, :server_app do
|
|
|
61
51
|
it { expect(channel.videos.size).to be_zero }
|
|
62
52
|
end
|
|
63
53
|
end
|
|
64
|
-
|
|
65
|
-
context 'given an unknown channel URL' do
|
|
66
|
-
let(:attrs) { {url: 'youtube.com/--not-a-valid-url--'} }
|
|
67
|
-
|
|
68
|
-
specify 'accessing its data raises an error' do
|
|
69
|
-
expect{channel.id}.to raise_error Yt::Errors::NoItems
|
|
70
|
-
expect{channel.title}.to raise_error Yt::Errors::NoItems
|
|
71
|
-
expect{channel.status}.to raise_error Yt::Errors::NoItems
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
54
|
end
|
|
@@ -10,7 +10,7 @@ describe Yt::PlaylistItem, :server_app do
|
|
|
10
10
|
it 'returns valid snippet data' do
|
|
11
11
|
expect(item.snippet).to be_a Yt::Snippet
|
|
12
12
|
expect(item.title).to be_a String
|
|
13
|
-
expect(item.description).to be_a
|
|
13
|
+
expect(item.description).to be_a String
|
|
14
14
|
expect(item.thumbnail_url).to be_a String
|
|
15
15
|
expect(item.published_at).to be_a Time
|
|
16
16
|
expect(item.channel_id).to be_a String
|
|
@@ -10,7 +10,7 @@ describe Yt::Playlist, :server_app do
|
|
|
10
10
|
it 'returns valid snippet data' do
|
|
11
11
|
expect(playlist.snippet).to be_a Yt::Snippet
|
|
12
12
|
expect(playlist.title).to be_a String
|
|
13
|
-
expect(playlist.description).to be_a
|
|
13
|
+
expect(playlist.description).to be_a String
|
|
14
14
|
expect(playlist.thumbnail_url).to be_a String
|
|
15
15
|
expect(playlist.published_at).to be_a Time
|
|
16
16
|
expect(playlist.tags).to be_an Array
|
|
@@ -24,31 +24,10 @@ describe Yt::Playlist, :server_app do
|
|
|
24
24
|
it { expect(playlist.playlist_items.first).to be_a Yt::PlaylistItem }
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
context 'given an existing playlist URL' do
|
|
28
|
-
let(:attrs) { {url: 'https://www.youtube.com/playlist?list=LLxO1tY8h1AhOz0T4ENwmpow'} }
|
|
29
|
-
|
|
30
|
-
specify 'provides access to its data' do
|
|
31
|
-
expect(playlist.id).to eq 'LLxO1tY8h1AhOz0T4ENwmpow'
|
|
32
|
-
expect(playlist.title).to eq 'Liked videos'
|
|
33
|
-
expect(playlist.privacy_status).to eq 'public'
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
27
|
context 'given an unknown playlist' do
|
|
38
28
|
let(:attrs) { {id: 'not-a-playlist-id'} }
|
|
39
29
|
|
|
40
30
|
it { expect{playlist.snippet}.to raise_error Yt::Errors::NoItems }
|
|
41
31
|
it { expect{playlist.status}.to raise_error Yt::Errors::NoItems }
|
|
42
32
|
end
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
context 'given an unknown playlist URL' do
|
|
46
|
-
let(:attrs) { {url: 'youtube.com/--not-a-valid-url--'} }
|
|
47
|
-
|
|
48
|
-
specify 'accessing its data raises an error' do
|
|
49
|
-
expect{playlist.id}.to raise_error Yt::Errors::NoItems
|
|
50
|
-
expect{playlist.title}.to raise_error Yt::Errors::NoItems
|
|
51
|
-
expect{playlist.status}.to raise_error Yt::Errors::NoItems
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
33
|
end
|
|
@@ -13,7 +13,7 @@ describe Yt::Video, :server_app do
|
|
|
13
13
|
it 'returns valid snippet data' do
|
|
14
14
|
expect(video.snippet).to be_a Yt::Snippet
|
|
15
15
|
expect(video.title).to be_a String
|
|
16
|
-
expect(video.description).to be_a
|
|
16
|
+
expect(video.description).to be_a String
|
|
17
17
|
expect(video.thumbnail_url).to be_a String
|
|
18
18
|
expect(video.published_at).to be_a Time
|
|
19
19
|
expect(video.tags).to be_an Array
|
|
@@ -28,16 +28,6 @@ describe Yt::Video, :server_app do
|
|
|
28
28
|
it { expect(video.statistics_set).to be_a Yt::StatisticsSet }
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
context 'given an existing video URL' do
|
|
32
|
-
let(:attrs) { {url: 'https://www.youtube.com/watch?v=9bZkp7q19f0'} }
|
|
33
|
-
|
|
34
|
-
specify 'provides access to its data' do
|
|
35
|
-
expect(video.id).to eq '9bZkp7q19f0'
|
|
36
|
-
expect(video.title).to eq "PSY - GANGNAM STYLE(강남스타일) M/V"
|
|
37
|
-
expect(video.privacy_status).to eq 'public'
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
31
|
context 'given an unknown video ID' do
|
|
42
32
|
let(:attrs) { {id: 'not-a-video-id'} }
|
|
43
33
|
|
|
@@ -47,16 +37,6 @@ describe Yt::Video, :server_app do
|
|
|
47
37
|
it { expect{video.statistics_set}.to raise_error Yt::Errors::NoItems }
|
|
48
38
|
end
|
|
49
39
|
|
|
50
|
-
context 'given an unknown video URL' do
|
|
51
|
-
let(:attrs) { {url: 'youtube.com/--not-a-valid-url--'} }
|
|
52
|
-
|
|
53
|
-
specify 'accessing its data raises an error' do
|
|
54
|
-
expect{video.id}.to raise_error Yt::Errors::NoItems
|
|
55
|
-
expect{video.title}.to raise_error Yt::Errors::NoItems
|
|
56
|
-
expect{video.status}.to raise_error Yt::Errors::NoItems
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
40
|
describe 'associations' do
|
|
61
41
|
let(:attrs) { {id: 'MsplPPW7tFo'} }
|
|
62
42
|
|
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.
|
|
4
|
+
version: 0.29.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Claudio Baccigalupo
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-
|
|
11
|
+
date: 2017-02-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -145,7 +145,6 @@ files:
|
|
|
145
145
|
- lib/yt/collections/file_details.rb
|
|
146
146
|
- lib/yt/collections/group_infos.rb
|
|
147
147
|
- lib/yt/collections/group_items.rb
|
|
148
|
-
- lib/yt/collections/ids.rb
|
|
149
148
|
- lib/yt/collections/live_streaming_details.rb
|
|
150
149
|
- lib/yt/collections/ownerships.rb
|
|
151
150
|
- lib/yt/collections/partnered_channels.rb
|
|
@@ -196,7 +195,6 @@ files:
|
|
|
196
195
|
- lib/yt/models/content_detail.rb
|
|
197
196
|
- lib/yt/models/content_owner.rb
|
|
198
197
|
- lib/yt/models/content_owner_detail.rb
|
|
199
|
-
- lib/yt/models/description.rb
|
|
200
198
|
- lib/yt/models/device_flow.rb
|
|
201
199
|
- lib/yt/models/file_detail.rb
|
|
202
200
|
- lib/yt/models/group_info.rb
|
|
@@ -222,7 +220,6 @@ files:
|
|
|
222
220
|
- lib/yt/models/status.rb
|
|
223
221
|
- lib/yt/models/subscription.rb
|
|
224
222
|
- lib/yt/models/timestamp.rb
|
|
225
|
-
- lib/yt/models/url.rb
|
|
226
223
|
- lib/yt/models/user_info.rb
|
|
227
224
|
- lib/yt/models/video.rb
|
|
228
225
|
- lib/yt/models/video_category.rb
|
|
@@ -257,7 +254,6 @@ files:
|
|
|
257
254
|
- spec/models/configuration_spec.rb
|
|
258
255
|
- spec/models/content_detail_spec.rb
|
|
259
256
|
- spec/models/content_owner_detail_spec.rb
|
|
260
|
-
- spec/models/description_spec.rb
|
|
261
257
|
- spec/models/file_detail_spec.rb
|
|
262
258
|
- spec/models/live_streaming_detail_spec.rb
|
|
263
259
|
- spec/models/ownership_spec.rb
|
|
@@ -275,7 +271,6 @@ files:
|
|
|
275
271
|
- spec/models/statistics_set_spec.rb
|
|
276
272
|
- spec/models/status_spec.rb
|
|
277
273
|
- spec/models/subscription_spec.rb
|
|
278
|
-
- spec/models/url_spec.rb
|
|
279
274
|
- spec/models/video_category_spec.rb
|
|
280
275
|
- spec/models/video_spec.rb
|
|
281
276
|
- spec/requests/as_account/account_spec.rb
|
|
@@ -284,7 +279,6 @@ files:
|
|
|
284
279
|
- spec/requests/as_account/channels_spec.rb
|
|
285
280
|
- spec/requests/as_account/playlist_item_spec.rb
|
|
286
281
|
- spec/requests/as_account/playlist_spec.rb
|
|
287
|
-
- spec/requests/as_account/resource_spec.rb
|
|
288
282
|
- spec/requests/as_account/thumbnail.jpg
|
|
289
283
|
- spec/requests/as_account/video.mp4
|
|
290
284
|
- spec/requests/as_account/video_spec.rb
|
|
@@ -332,7 +326,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
332
326
|
version: '0'
|
|
333
327
|
requirements: []
|
|
334
328
|
rubyforge_project:
|
|
335
|
-
rubygems_version: 2.6.
|
|
329
|
+
rubygems_version: 2.6.10
|
|
336
330
|
signing_key:
|
|
337
331
|
specification_version: 4
|
|
338
332
|
summary: Yt makes it easy to interact with Youtube V3 API by providing a modular,
|
|
@@ -366,7 +360,6 @@ test_files:
|
|
|
366
360
|
- spec/models/configuration_spec.rb
|
|
367
361
|
- spec/models/content_detail_spec.rb
|
|
368
362
|
- spec/models/content_owner_detail_spec.rb
|
|
369
|
-
- spec/models/description_spec.rb
|
|
370
363
|
- spec/models/file_detail_spec.rb
|
|
371
364
|
- spec/models/live_streaming_detail_spec.rb
|
|
372
365
|
- spec/models/ownership_spec.rb
|
|
@@ -384,7 +377,6 @@ test_files:
|
|
|
384
377
|
- spec/models/statistics_set_spec.rb
|
|
385
378
|
- spec/models/status_spec.rb
|
|
386
379
|
- spec/models/subscription_spec.rb
|
|
387
|
-
- spec/models/url_spec.rb
|
|
388
380
|
- spec/models/video_category_spec.rb
|
|
389
381
|
- spec/models/video_spec.rb
|
|
390
382
|
- spec/requests/as_account/account_spec.rb
|
|
@@ -393,7 +385,6 @@ test_files:
|
|
|
393
385
|
- spec/requests/as_account/channels_spec.rb
|
|
394
386
|
- spec/requests/as_account/playlist_item_spec.rb
|
|
395
387
|
- spec/requests/as_account/playlist_spec.rb
|
|
396
|
-
- spec/requests/as_account/resource_spec.rb
|
|
397
388
|
- spec/requests/as_account/thumbnail.jpg
|
|
398
389
|
- spec/requests/as_account/video.mp4
|
|
399
390
|
- spec/requests/as_account/video_spec.rb
|
data/lib/yt/collections/ids.rb
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
require 'yt/collections/base'
|
|
2
|
-
require 'yt/models/id'
|
|
3
|
-
|
|
4
|
-
module Yt
|
|
5
|
-
module Collections
|
|
6
|
-
# @private
|
|
7
|
-
class Ids < Base
|
|
8
|
-
|
|
9
|
-
private
|
|
10
|
-
|
|
11
|
-
def attributes_for_new_item(data)
|
|
12
|
-
data['id']
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def list_params
|
|
16
|
-
super.tap do |params|
|
|
17
|
-
params[:params] = ids_params
|
|
18
|
-
params[:path] = "/youtube/v3/#{@parent.kind.pluralize}"
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def ids_params
|
|
23
|
-
{for_username: @parent.username, part: 'id'}
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
require 'yt/models/url'
|
|
2
|
-
|
|
3
|
-
module Yt
|
|
4
|
-
module Models
|
|
5
|
-
# Encapsulates information about the description of a resource, for
|
|
6
|
-
# instance a channel.
|
|
7
|
-
# @see https://developers.google.com/youtube/v3/docs/channels#resource
|
|
8
|
-
#
|
|
9
|
-
# The value has a maximum length of 1000 characters.
|
|
10
|
-
class Description < String
|
|
11
|
-
# @return [Boolean] whether the description includes a link to a video
|
|
12
|
-
# @example
|
|
13
|
-
# description = Yt::Models::Description.new 'Link to video: youtube.com/watch?v=9bZkp7q19f0'
|
|
14
|
-
# description.has_link_to_video? #=> true
|
|
15
|
-
#
|
|
16
|
-
# @todo add an option to match the link to a specific video
|
|
17
|
-
def has_link_to_video?
|
|
18
|
-
links.any?{|link| link.kind == :video}
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# @return [Boolean] whether the description includes a link to a channel
|
|
22
|
-
# @example
|
|
23
|
-
# description = Yt::Description.new 'Link to channel: youtube.com/fullscreen'
|
|
24
|
-
# description.has_link_to_channel? #=> true
|
|
25
|
-
#
|
|
26
|
-
# @todo add an option to match the link to a specific channel
|
|
27
|
-
def has_link_to_channel?(options = {})
|
|
28
|
-
links.any?{|link| link.kind == :channel}
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# @return [Boolean] whether the description includes a link to subscribe
|
|
32
|
-
# @example
|
|
33
|
-
# description = Yt::Description.new 'Link to subscribe: youtube.com/subscription_center?add_user=fullscreen'
|
|
34
|
-
# description.has_link_to_subscribe? #=> true
|
|
35
|
-
#
|
|
36
|
-
# @todo add an option to match the link to subscribe to a specific channel
|
|
37
|
-
def has_link_to_subscribe?(options = {})
|
|
38
|
-
links.any?{|link| link.kind == :subscription}
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# @return [Boolean] whether the description includes a link to a playlist
|
|
42
|
-
# @example
|
|
43
|
-
# description = Yt::Description.new 'Link to playlist: youtube.com/playlist?list=LLxO1tY8h1AhOz0T4ENwmpow'
|
|
44
|
-
# description.has_link_to_playlist? #=> true
|
|
45
|
-
#
|
|
46
|
-
# @todo add an option to match the link to a specific playlist
|
|
47
|
-
def has_link_to_playlist?
|
|
48
|
-
links.any?{|link| link.kind == :playlist}
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
private
|
|
52
|
-
|
|
53
|
-
def links
|
|
54
|
-
@links ||= self.split(' ').map{|word| URL.new word}
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
data/lib/yt/models/url.rb
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
module Yt
|
|
2
|
-
module Models
|
|
3
|
-
# @private
|
|
4
|
-
class URL
|
|
5
|
-
attr_reader :kind
|
|
6
|
-
|
|
7
|
-
def initialize(url)
|
|
8
|
-
@url = url
|
|
9
|
-
@kind ||= parse url
|
|
10
|
-
@match_data ||= {}
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def id
|
|
14
|
-
@match_data[:id]
|
|
15
|
-
rescue IndexError
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def username
|
|
19
|
-
@match_data[:username]
|
|
20
|
-
rescue IndexError
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
private
|
|
24
|
-
|
|
25
|
-
def parse(url)
|
|
26
|
-
matching_pattern = patterns.find do |pattern|
|
|
27
|
-
@match_data = url.match pattern[:regex]
|
|
28
|
-
end
|
|
29
|
-
matching_pattern[:kind] if matching_pattern
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def patterns
|
|
33
|
-
# @note: :channel *must* be the last since one of its regex eats the
|
|
34
|
-
# remaining patterns. In short, don't change the following order
|
|
35
|
-
|
|
36
|
-
@patterns ||= patterns_for :playlist, :subscription, :video, :channel
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def patterns_for(*kinds)
|
|
40
|
-
prefix = '^(?:https?://)?(?:www\.)?'
|
|
41
|
-
suffix = '(?:|/)'
|
|
42
|
-
kinds.map do |kind|
|
|
43
|
-
patterns = send "#{kind}_patterns" # meta programming :/
|
|
44
|
-
patterns.map do |pattern|
|
|
45
|
-
{kind: kind, regex: %r{#{prefix}#{pattern}#{suffix}}}
|
|
46
|
-
end
|
|
47
|
-
end.flatten
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def subscription_patterns
|
|
51
|
-
name = '(?:[a-zA-Z0-9&_=-]*)'
|
|
52
|
-
|
|
53
|
-
%W{
|
|
54
|
-
subscription_center\\?add_user=#{name}
|
|
55
|
-
subscribe_widget\\?p=#{name}
|
|
56
|
-
channel/#{name}\\?sub_confirmation=1
|
|
57
|
-
}.map{|path| "youtube\\.com/#{path}"}
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def playlist_patterns
|
|
61
|
-
playlist_id = '(?<id>[a-zA-Z0-9_-]+)'
|
|
62
|
-
|
|
63
|
-
%W{
|
|
64
|
-
playlist\\?list=#{playlist_id}
|
|
65
|
-
}.map{|path| "youtube\\.com/#{path}"}
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def video_patterns
|
|
69
|
-
video_id = '(?<id>[a-zA-Z0-9_-]+)'
|
|
70
|
-
|
|
71
|
-
%W{
|
|
72
|
-
youtube\\.com/watch\\?v=#{video_id}
|
|
73
|
-
youtu\\.be/#{video_id}
|
|
74
|
-
youtube\\.com/embed/#{video_id}
|
|
75
|
-
youtube\\.com/v/#{video_id}
|
|
76
|
-
}
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def channel_patterns
|
|
80
|
-
channel_id = '(?<id>[a-zA-Z0-9_-]+)'
|
|
81
|
-
username = '(?<username>[a-zA-Z0-9_-]+)'
|
|
82
|
-
|
|
83
|
-
%W{
|
|
84
|
-
channel/#{channel_id}
|
|
85
|
-
user/#{username}
|
|
86
|
-
#{username}
|
|
87
|
-
}.map{|path| "youtube\\.com/#{path}"}
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'yt/models/description'
|
|
3
|
-
|
|
4
|
-
describe Yt::Description do
|
|
5
|
-
subject(:description) { Yt::Description.new text }
|
|
6
|
-
|
|
7
|
-
describe '#text' do
|
|
8
|
-
let(:text) { 'this is a description' }
|
|
9
|
-
it { expect(description).to eq 'this is a description' }
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
describe '#length' do
|
|
13
|
-
let(:text) { 'twenty one characters' }
|
|
14
|
-
it { expect(description.length).to eq 21 }
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
describe '#has_link_to_video?' do
|
|
18
|
-
context 'without a video URL' do
|
|
19
|
-
let(:text) { 'Link to channel: youtube.com/fullscreen' }
|
|
20
|
-
it { expect(description).not_to have_link_to_video }
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
context 'with a video long URL' do
|
|
24
|
-
let(:text) { 'example.com and Link to video: youtube.com/watch?v=9bZkp7q19f0' }
|
|
25
|
-
it { expect(description).to have_link_to_video }
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
context 'with a video short URL' do
|
|
29
|
-
let(:text) { 'Link to video: youtu.be/9bZkp7q19f0' }
|
|
30
|
-
it { expect(description).to have_link_to_video }
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
context 'with a playlist-embedded video URL' do
|
|
34
|
-
let(:text) { 'Link to video in playlist: youtube.com/watch?v=9bZkp7q19f0&index=619&list=LLxO1tY8h1AhOz0T4ENwmpow' }
|
|
35
|
-
it { expect(description).to have_link_to_video }
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
describe '#has_link_to_channel?' do
|
|
40
|
-
context 'without a channel URL' do
|
|
41
|
-
let(:text) { 'youtu.be/9bZkp7q19f0 is a video link' }
|
|
42
|
-
it { expect(description).not_to have_link_to_channel }
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
context 'with a channel long URL' do
|
|
46
|
-
let(:text) { 'Link to channel: youtube.com/channel/UCxO1tY8h1AhOz0T4ENwmpow' }
|
|
47
|
-
it { expect(description).to have_link_to_channel }
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
context 'with a channel short URL' do
|
|
51
|
-
let(:text) { 'Link to channel: youtube.com/fullscreen' }
|
|
52
|
-
it { expect(description).to have_link_to_channel }
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
context 'with a channel user URL' do
|
|
56
|
-
let(:text) { 'Link to channel: youtube.com/user/fullscreen' }
|
|
57
|
-
it { expect(description).to have_link_to_channel }
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
describe '#has_link_to_subscribe?' do
|
|
62
|
-
context 'without a subscribe URL' do
|
|
63
|
-
let(:text) { 'Link to video: youtu.be/9bZkp7q19f0' }
|
|
64
|
-
it { expect(description).not_to have_link_to_subscribe }
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
context 'with a subscribe center URL' do
|
|
68
|
-
let(:text) { 'Link to subscribe: youtube.com/subscription_center?add_user=fullscreen' }
|
|
69
|
-
it { expect(description).to have_link_to_subscribe }
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
context 'with a subscribe short URL' do
|
|
73
|
-
let(:text) { 'Link to subscribe: youtube.com/subscribe_widget?p=fullscreen' }
|
|
74
|
-
it { expect(description).to have_link_to_subscribe }
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
context 'with a subscribe confirm URL' do
|
|
78
|
-
let(:text) { 'Link to subscribe: youtube.com/channel/UCxO1tY8h1AhOz0T4ENwmpow?sub_confirmation=1' }
|
|
79
|
-
it { expect(description).to have_link_to_subscribe }
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
describe '#has_link_to_playlist?' do
|
|
84
|
-
context 'without a playlist URL' do
|
|
85
|
-
let(:text) { 'Link to video: youtu.be/9bZkp7q19f0' }
|
|
86
|
-
it { expect(description).not_to have_link_to_playlist }
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
context 'with a playlist long URL' do
|
|
90
|
-
let(:text) { 'Link to playlist: youtube.com/playlist?list=LLxO1tY8h1AhOz0T4ENwmpow' }
|
|
91
|
-
it { expect(description).to have_link_to_playlist }
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
data/spec/models/url_spec.rb
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
# encoding: UTF-8
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
require 'yt/models/url'
|
|
5
|
-
|
|
6
|
-
describe Yt::URL do
|
|
7
|
-
subject(:url) { Yt::URL.new text }
|
|
8
|
-
|
|
9
|
-
context 'given a long video URL' do
|
|
10
|
-
let(:text) { 'youtube.com/watch?v=9bZkp7q19f0' }
|
|
11
|
-
it {expect(url.kind).to eq :video }
|
|
12
|
-
it {expect(url.id).to eq '9bZkp7q19f0' }
|
|
13
|
-
it {expect(url.username).to be_nil }
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
context 'given a short video URL' do
|
|
17
|
-
let(:text) { 'https://youtu.be/9bZkp7q19f0' }
|
|
18
|
-
it {expect(url.kind).to eq :video }
|
|
19
|
-
it {expect(url.id).to eq '9bZkp7q19f0' }
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
context 'given an embed video URL' do
|
|
23
|
-
let(:text) { 'https://www.youtube.com/embed/9bZkp7q19f0' }
|
|
24
|
-
it {expect(url.kind).to eq :video }
|
|
25
|
-
it {expect(url.id).to eq '9bZkp7q19f0' }
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
context 'given a v video URL' do
|
|
29
|
-
let(:text) { 'https://www.youtube.com/v/9bZkp7q19f0' }
|
|
30
|
-
it {expect(url.kind).to eq :video }
|
|
31
|
-
it {expect(url.id).to eq '9bZkp7q19f0' }
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
context 'given a playlist-embedded video URL' do
|
|
35
|
-
let(:text) { 'youtube.com/watch?v=9bZkp7q19f0&list=LLxO1tY8h1AhOz0T4ENwmpow' }
|
|
36
|
-
it {expect(url.kind).to eq :video }
|
|
37
|
-
it {expect(url.id).to eq '9bZkp7q19f0' }
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
context 'given a long channel URL' do
|
|
41
|
-
let(:text) { 'http://youtube.com/channel/UCxO1tY8h1AhOz0T4ENwmpow' }
|
|
42
|
-
it {expect(url.kind).to eq :channel }
|
|
43
|
-
it {expect(url.id).to eq 'UCxO1tY8h1AhOz0T4ENwmpow' }
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
context 'given a short channel URL' do
|
|
47
|
-
let(:text) { 'https://www.youtube.com/Fullscreen' }
|
|
48
|
-
it {expect(url.kind).to eq :channel }
|
|
49
|
-
it {expect(url.username).to eq 'Fullscreen' }
|
|
50
|
-
it {expect(url.id).to be_nil }
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
context 'given a user’s channel URL' do
|
|
54
|
-
let(:text) { 'https://www.youtube.com/user/Fullscreen' }
|
|
55
|
-
it {expect(url.kind).to eq :channel }
|
|
56
|
-
it {expect(url.username).to eq 'Fullscreen' }
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
context 'given a subscription center URL' do
|
|
60
|
-
let(:text) { 'youtube.com/subscription_center?add_user=Fullscreen' }
|
|
61
|
-
it {expect(url.kind).to eq :subscription }
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
context 'given a subscription widget URL' do
|
|
65
|
-
let(:text) { 'youtube.com/subscribe_widget?p=Fullscreen' }
|
|
66
|
-
it {expect(url.kind).to eq :subscription }
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
context 'given a subscription confirmation URL' do
|
|
70
|
-
let(:text) { 'youtube.com/channel/UCxO1tY8h1AhOz0T4ENwmpow?sub_confirmation=1' }
|
|
71
|
-
it {expect(url.kind).to eq :subscription }
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
context 'given a long playlist URL' do
|
|
75
|
-
let(:text) { 'youtube.com/playlist?list=LLxO1tY8h1AhOz0T4ENwmpow' }
|
|
76
|
-
it {expect(url.kind).to eq :playlist }
|
|
77
|
-
it {expect(url.id).to eq 'LLxO1tY8h1AhOz0T4ENwmpow' }
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
context 'given a valid URL with a trailing slash' do
|
|
81
|
-
let(:text) { 'https://www.youtube.com/user/Fullscreen/' }
|
|
82
|
-
it {expect(url.kind).to eq :channel }
|
|
83
|
-
end
|
|
84
|
-
end
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'yt/models/resource'
|
|
3
|
-
|
|
4
|
-
describe Yt::Resource, :device_app do
|
|
5
|
-
subject(:resource) { Yt::Resource.new url: url, auth: $account }
|
|
6
|
-
|
|
7
|
-
describe '#id' do
|
|
8
|
-
context 'given a URL containing an existing username' do
|
|
9
|
-
let(:url) { 'youtube.com/fullscreen' }
|
|
10
|
-
it { expect(resource.id).to eq 'UCxO1tY8h1AhOz0T4ENwmpow' }
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
context 'given a URL containing an unknown username' do
|
|
14
|
-
let(:url) { 'youtube.com/--not--a--valid--username' }
|
|
15
|
-
it { expect{resource.id}.to raise_error Yt::Errors::NoItems }
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|