yt 0.28.5 → 0.29.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|