link_thumbnailer 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG.md +26 -0
- data/README.md +8 -1
- data/lib/generators/templates/initializer.rb +1 -1
- data/lib/link_thumbnailer/configuration.rb +1 -1
- data/lib/link_thumbnailer/models/video.rb +42 -0
- data/lib/link_thumbnailer/models/website.rb +14 -2
- data/lib/link_thumbnailer/scraper.rb +5 -5
- data/lib/link_thumbnailer/scrapers/base.rb +2 -0
- data/lib/link_thumbnailer/scrapers/default/videos.rb +16 -0
- data/lib/link_thumbnailer/scrapers/opengraph/image.rb +8 -8
- data/lib/link_thumbnailer/scrapers/opengraph/video.rb +30 -0
- data/lib/link_thumbnailer/scrapers/opengraph/videos.rb +16 -0
- data/lib/link_thumbnailer/version.rb +1 -1
- data/lib/link_thumbnailer/video_parser.rb +45 -0
- data/link_thumbnailer.gemspec +1 -0
- data/spec/configuration_spec.rb +1 -1
- data/spec/fixture_spec.rb +16 -0
- data/spec/fixtures/og_valid_example.html +1 -0
- data/spec/fixtures/og_valid_multi_video_example.html +13 -0
- data/spec/models/image_spec.rb +22 -0
- data/spec/models/video_spec.rb +47 -0
- data/spec/scraper_spec.rb +7 -34
- data/spec/video_parser_spec.rb +146 -0
- metadata +27 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MmMxNTZhYWFkN2E4N2JjN2NkNjRlMmFlMjU3YWYxMDJlOWVmNzBhMw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MDMwOWQ2NWYyYmUxMGExOWI0MzM5YjA2ZTkwZTNlY2ViZmVlOGFhYQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YmM4MDg1ZTFlZTJlZGJiZTYxMzc2MWI5N2FkYjkxMDc4NmEzNjdmYjVjMDJj
|
10
|
+
ZDQxMTc5YTY3ZjY3MzY5MWRjNjk4ODFmYWJjNTE4ZmQwMGI2YTI2ZjhiMjU3
|
11
|
+
ZGFhMzNlNzcwNjIzZWFhYTNkYWQ3NWY5OTU1M2Q0NDM0ZjQxYzU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MDRlNWY3MGQ1ZWI4MTYyNzY0ZmY0MGIxY2U2NDA5NTg4Zjc2MGI5NDgxNzBl
|
14
|
+
MzRiOTUwNmVlMTdjZmFiMGFkZThmODFkYjllN2QxMWZlOTI5NWM1MzNmMDA1
|
15
|
+
MmU5YjcxYWY3Y2RjZGE5ZjJmNDU5NjBkMzc1MjNiODA5YjIxMGI=
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
# 2.2.0
|
2
|
+
|
3
|
+
- Add support for `og:video`
|
4
|
+
- Add support for multiple `og:video` as well
|
5
|
+
|
6
|
+
LinkThumbnailer will return the following json for example:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
{
|
10
|
+
id: 'x7lni3',
|
11
|
+
src: 'http://www.dailymotion.com/video/x7lni3',
|
12
|
+
size: [640, 360],
|
13
|
+
duration: 136,
|
14
|
+
provider: 'Dailymotion',
|
15
|
+
embed_code: '<iframe src="//www.dailymotion.com/embed/video/x7lni3" frameborder="0" allowfullscreen="allowfullscreen"></iframe>'
|
16
|
+
}
|
17
|
+
```
|
18
|
+
|
19
|
+
Add `:videos` into your `config/initializers/link_thumbnailer.rb` `attributes` config in order to start scraping videos.
|
20
|
+
|
21
|
+
Ex:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
config.attributes = [:title, :images, :description, :videos]
|
25
|
+
```
|
26
|
+
|
1
27
|
# 2.1.0
|
2
28
|
|
3
29
|
- Increased `og:image` scraping performance by parsing `og:image:width` and `og:image:height` attribute if specified
|
data/README.md
CHANGED
@@ -108,7 +108,7 @@ In `config/initializers/link_thumbnailer.rb`
|
|
108
108
|
|
109
109
|
# List of attributes you want LinkThumbnailer to fetch on a website.
|
110
110
|
#
|
111
|
-
# config.attributes = [:title, :images, :description]
|
111
|
+
# config.attributes = [:title, :images, :description, :videos]
|
112
112
|
|
113
113
|
# List of procedures used to rate the website description. Add you custom class
|
114
114
|
# here. Note that the order matter to compute the score. See wiki for more details
|
@@ -153,6 +153,13 @@ Note that runtime options will override default global configuration.
|
|
153
153
|
|
154
154
|
See [Configuration Options Explained](https://github.com/gottfrois/link_thumbnailer/wiki/Configuration-options-explained) for more details on each configuration options.
|
155
155
|
|
156
|
+
## Exceptions
|
157
|
+
|
158
|
+
LinkThumbnailer defines a list of custom exceptions you may want to rescue in your code. All the following exceptions inherit from `LinkThumbnailer::Exceptions`:
|
159
|
+
|
160
|
+
* `RedirectLimit` -- raised when redirection threshold defined in config is reached
|
161
|
+
* `BadUriFormat` -- raised when url given is not a valid HTTP url
|
162
|
+
|
156
163
|
## Contributing
|
157
164
|
|
158
165
|
1. Fork it
|
@@ -31,7 +31,7 @@ LinkThumbnailer.configure do |config|
|
|
31
31
|
|
32
32
|
# List of attributes you want LinkThumbnailer to fetch on a website.
|
33
33
|
#
|
34
|
-
# config.attributes = [:title, :images, :description]
|
34
|
+
# config.attributes = [:title, :images, :description, :videos]
|
35
35
|
|
36
36
|
# List of procedures used to rate the website description. Add you custom class
|
37
37
|
# here. Note that the order matter to compute the score. See wiki for more details
|
@@ -41,7 +41,7 @@ module LinkThumbnailer
|
|
41
41
|
%r{^http://pixel\.quantserve\.com/},
|
42
42
|
%r{^http://s7\.addthis\.com/}
|
43
43
|
]
|
44
|
-
@attributes = [:title, :images, :description]
|
44
|
+
@attributes = [:title, :images, :description, :videos]
|
45
45
|
@graders = [
|
46
46
|
->(description) { ::LinkThumbnailer::Graders::Length.new(description) },
|
47
47
|
->(description) { ::LinkThumbnailer::Graders::HtmlAttribute.new(description, :class) },
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'link_thumbnailer/model'
|
2
|
+
require 'link_thumbnailer/video_parser'
|
3
|
+
|
4
|
+
module LinkThumbnailer
|
5
|
+
module Models
|
6
|
+
class Video < ::LinkThumbnailer::Model
|
7
|
+
|
8
|
+
attr_reader :src, :size, :duration, :provider, :id, :embed_code
|
9
|
+
|
10
|
+
def initialize(src)
|
11
|
+
@src = src
|
12
|
+
@id = parser.id
|
13
|
+
@size = parser.size
|
14
|
+
@duration = parser.duration
|
15
|
+
@provider = parser.provider
|
16
|
+
@embed_code = parser.embed_code
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
src.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
def as_json(*)
|
24
|
+
{
|
25
|
+
id: id,
|
26
|
+
src: src.to_s,
|
27
|
+
size: size,
|
28
|
+
duration: duration,
|
29
|
+
provider: provider,
|
30
|
+
embed_code: embed_code
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def parser
|
37
|
+
@parser ||= ::LinkThumbnailer::VideoParser.new(self)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -4,10 +4,21 @@ module LinkThumbnailer
|
|
4
4
|
module Models
|
5
5
|
class Website < ::LinkThumbnailer::Model
|
6
6
|
|
7
|
-
attr_accessor :url, :title, :description, :images
|
7
|
+
attr_accessor :url, :title, :description, :images, :videos
|
8
8
|
|
9
9
|
def initialize
|
10
10
|
@images = []
|
11
|
+
@videos = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def video=(video)
|
15
|
+
self.videos = video
|
16
|
+
end
|
17
|
+
|
18
|
+
def videos=(videos)
|
19
|
+
Array(videos).each do |video|
|
20
|
+
@videos << video
|
21
|
+
end
|
11
22
|
end
|
12
23
|
|
13
24
|
def image=(image)
|
@@ -30,7 +41,8 @@ module LinkThumbnailer
|
|
30
41
|
url: url.to_s,
|
31
42
|
title: title,
|
32
43
|
description: description,
|
33
|
-
images: images
|
44
|
+
images: images,
|
45
|
+
videos: videos
|
34
46
|
}
|
35
47
|
end
|
36
48
|
|
@@ -10,6 +10,8 @@ require 'link_thumbnailer/scrapers/default/description'
|
|
10
10
|
require 'link_thumbnailer/scrapers/opengraph/description'
|
11
11
|
require 'link_thumbnailer/scrapers/default/images'
|
12
12
|
require 'link_thumbnailer/scrapers/opengraph/images'
|
13
|
+
require 'link_thumbnailer/scrapers/default/videos'
|
14
|
+
require 'link_thumbnailer/scrapers/opengraph/videos'
|
13
15
|
|
14
16
|
module LinkThumbnailer
|
15
17
|
class Scraper < ::SimpleDelegator
|
@@ -30,9 +32,7 @@ module LinkThumbnailer
|
|
30
32
|
def call
|
31
33
|
config.attributes.each do |name|
|
32
34
|
scrapers.each do |scraper_prefix|
|
33
|
-
|
34
|
-
scraper.call(website, name.to_s) if scraper.applicable?
|
35
|
-
|
35
|
+
scraper_class(scraper_prefix, name).new(document).call(website, name.to_s)
|
36
36
|
break unless website.send(name).blank?
|
37
37
|
end
|
38
38
|
end
|
@@ -44,8 +44,8 @@ module LinkThumbnailer
|
|
44
44
|
|
45
45
|
def scrapers
|
46
46
|
[
|
47
|
-
|
48
|
-
|
47
|
+
'::LinkThumbnailer::Scrapers::Opengraph',
|
48
|
+
'::LinkThumbnailer::Scrapers::Default'
|
49
49
|
]
|
50
50
|
end
|
51
51
|
|
@@ -2,6 +2,7 @@ require 'delegate'
|
|
2
2
|
require 'link_thumbnailer/models/title'
|
3
3
|
require 'link_thumbnailer/models/description'
|
4
4
|
require 'link_thumbnailer/models/image'
|
5
|
+
require 'link_thumbnailer/models/video'
|
5
6
|
|
6
7
|
module LinkThumbnailer
|
7
8
|
module Scrapers
|
@@ -17,6 +18,7 @@ module LinkThumbnailer
|
|
17
18
|
end
|
18
19
|
|
19
20
|
def call(website, attribute_name)
|
21
|
+
return false unless applicable?
|
20
22
|
@website = website
|
21
23
|
@attribute_name = attribute_name
|
22
24
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'link_thumbnailer/scrapers/default/base'
|
2
|
+
require 'link_thumbnailer/models/video'
|
3
|
+
|
4
|
+
module LinkThumbnailer
|
5
|
+
module Scrapers
|
6
|
+
module Default
|
7
|
+
class Videos < ::LinkThumbnailer::Scrapers::Default::Base
|
8
|
+
|
9
|
+
def value
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -5,12 +5,12 @@ module LinkThumbnailer
|
|
5
5
|
module Opengraph
|
6
6
|
class Image < ::LinkThumbnailer::Scrapers::Opengraph::Base
|
7
7
|
|
8
|
-
private
|
9
|
-
|
10
8
|
def value
|
11
9
|
model
|
12
10
|
end
|
13
11
|
|
12
|
+
private
|
13
|
+
|
14
14
|
def model
|
15
15
|
nodes.map { |n| modelize(n, n.attributes['content'].to_s) }
|
16
16
|
end
|
@@ -36,12 +36,16 @@ module LinkThumbnailer
|
|
36
36
|
Height.new(document).value
|
37
37
|
end
|
38
38
|
|
39
|
-
class
|
39
|
+
class Base < ::LinkThumbnailer::Scrapers::Opengraph::Base
|
40
40
|
|
41
41
|
def value
|
42
42
|
node.attributes['content'].to_s if node
|
43
43
|
end
|
44
44
|
|
45
|
+
end
|
46
|
+
|
47
|
+
class Width < Base
|
48
|
+
|
45
49
|
private
|
46
50
|
|
47
51
|
def attribute
|
@@ -50,11 +54,7 @@ module LinkThumbnailer
|
|
50
54
|
|
51
55
|
end
|
52
56
|
|
53
|
-
class Height <
|
54
|
-
|
55
|
-
def value
|
56
|
-
node.attributes['content'].to_s if node
|
57
|
-
end
|
57
|
+
class Height < Base
|
58
58
|
|
59
59
|
private
|
60
60
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'link_thumbnailer/scrapers/opengraph/base'
|
2
|
+
|
3
|
+
module LinkThumbnailer
|
4
|
+
module Scrapers
|
5
|
+
module Opengraph
|
6
|
+
class Video < ::LinkThumbnailer::Scrapers::Opengraph::Base
|
7
|
+
|
8
|
+
def value
|
9
|
+
model
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def model
|
15
|
+
nodes.map { |n| modelize(n, n.attributes['content'].to_s) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def modelize(node, text = nil)
|
19
|
+
model_class.new(text)
|
20
|
+
end
|
21
|
+
|
22
|
+
def nodes
|
23
|
+
nodes = meta_xpaths(attribute: attribute)
|
24
|
+
nodes.empty? ? meta_xpaths(attribute: attribute, key: :name) : nodes
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'link_thumbnailer/scrapers/opengraph/base'
|
2
|
+
require 'link_thumbnailer/scrapers/opengraph/video'
|
3
|
+
|
4
|
+
module LinkThumbnailer
|
5
|
+
module Scrapers
|
6
|
+
module Opengraph
|
7
|
+
class Videos < ::LinkThumbnailer::Scrapers::Opengraph::Base
|
8
|
+
|
9
|
+
def call(website, attribute_name)
|
10
|
+
::LinkThumbnailer::Scrapers::Opengraph::Video.new(document).call(website, 'video')
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'video_info'
|
2
|
+
|
3
|
+
module LinkThumbnailer
|
4
|
+
class VideoParser
|
5
|
+
|
6
|
+
attr_reader :parser
|
7
|
+
|
8
|
+
def initialize(video)
|
9
|
+
@parser = ::VideoInfo.new(video.src.to_s)
|
10
|
+
rescue ::VideoInfo::UrlError
|
11
|
+
@parser = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def id
|
15
|
+
parser.video_id
|
16
|
+
rescue NoMethodError
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def size
|
21
|
+
[parser.width, parser.height]
|
22
|
+
rescue NoMethodError
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
|
26
|
+
def duration
|
27
|
+
parser.duration
|
28
|
+
rescue NoMethodError
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def provider
|
33
|
+
parser.provider
|
34
|
+
rescue NoMethodError
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def embed_code
|
39
|
+
parser.embed_code
|
40
|
+
rescue NoMethodError
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
data/link_thumbnailer.gemspec
CHANGED
data/spec/configuration_spec.rb
CHANGED
@@ -9,7 +9,7 @@ describe LinkThumbnailer::Configuration do
|
|
9
9
|
it { expect(instance.verify_ssl).to eq(true) }
|
10
10
|
it { expect(instance.http_timeout).to eq(5) }
|
11
11
|
it { expect(instance.blacklist_urls).to_not be_empty }
|
12
|
-
it { expect(instance.attributes).
|
12
|
+
it { expect(instance.attributes).to eq([:title, :images, :description, :videos]) }
|
13
13
|
it { expect(instance.graders).to_not be_empty }
|
14
14
|
it { expect(instance.description_min_length).to eq(25) }
|
15
15
|
it { expect(instance.positive_regex).to_not be_nil }
|
data/spec/fixture_spec.rb
CHANGED
@@ -4,6 +4,7 @@ describe 'Fixture' do
|
|
4
4
|
|
5
5
|
let(:url) { 'http://foo.com' }
|
6
6
|
let(:png_url) { 'http://foo.com/foo.png' }
|
7
|
+
let(:video_url) { 'http://foo.com/foo.swf' }
|
7
8
|
let(:png) { File.open(File.dirname(__FILE__) + '/fixtures/foo.png') }
|
8
9
|
let(:action) { LinkThumbnailer.generate(url) }
|
9
10
|
|
@@ -26,6 +27,8 @@ describe 'Fixture' do
|
|
26
27
|
it { expect(action.images.count).to eq(1) }
|
27
28
|
it { expect(action.images.first.src.to_s).to eq(png_url) }
|
28
29
|
it { expect(action.images.first.size).to eq([100, 100]) }
|
30
|
+
it { expect(action.videos.count).to eq(1) }
|
31
|
+
it { expect(action.videos.first.src.to_s).to eq(video_url) }
|
29
32
|
|
30
33
|
end
|
31
34
|
|
@@ -47,6 +50,19 @@ describe 'Fixture' do
|
|
47
50
|
|
48
51
|
end
|
49
52
|
|
53
|
+
context 'with multi video' do
|
54
|
+
|
55
|
+
let(:video_url_2) { 'http://foo.com/bar.swf' }
|
56
|
+
let(:html) { File.open(File.dirname(__FILE__) + '/fixtures/og_valid_multi_video_example.html').read() }
|
57
|
+
|
58
|
+
it { expect(action.title).to eq(title) }
|
59
|
+
it { expect(action.description).to eq(description) }
|
60
|
+
it { expect(action.videos.count).to eq(2) }
|
61
|
+
it { expect(action.videos.first.src.to_s).to eq(video_url) }
|
62
|
+
it { expect(action.videos.last.src.to_s).to eq(video_url_2) }
|
63
|
+
|
64
|
+
end
|
65
|
+
|
50
66
|
context 'when not valid' do
|
51
67
|
|
52
68
|
let(:html) { File.open(File.dirname(__FILE__) + '/fixtures/og_not_valid_example.html').read() }
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<html xmlns:og="http://opengraphprotocol.org/schema/">
|
2
|
+
<head>
|
3
|
+
<meta charset="utf-8"/>
|
4
|
+
<meta property="og:type" content="website"/>
|
5
|
+
<meta property="og:site_name" content="foo.com">
|
6
|
+
<meta property="og:title" content="Title from og">
|
7
|
+
<meta property="og:description" content="Description from og">
|
8
|
+
<meta property="og:video" content="http://foo.com/foo.swf">
|
9
|
+
<meta property="og:video" content="http://foo.com/bar.swf">
|
10
|
+
<title>Title</title>
|
11
|
+
</head>
|
12
|
+
|
13
|
+
</html>
|
data/spec/models/image_spec.rb
CHANGED
@@ -68,4 +68,26 @@ describe LinkThumbnailer::Models::Image do
|
|
68
68
|
|
69
69
|
end
|
70
70
|
|
71
|
+
describe '#as_json' do
|
72
|
+
|
73
|
+
let(:action) { instance.as_json }
|
74
|
+
let(:size) { [1, 1] }
|
75
|
+
let(:type) { 'foo' }
|
76
|
+
let(:result) {
|
77
|
+
{
|
78
|
+
src: src,
|
79
|
+
size: size,
|
80
|
+
type: type
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
before do
|
85
|
+
instance.stub(:size).and_return(size)
|
86
|
+
instance.stub(:type).and_return(type)
|
87
|
+
end
|
88
|
+
|
89
|
+
it { expect(action).to eq(result) }
|
90
|
+
|
91
|
+
end
|
92
|
+
|
71
93
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LinkThumbnailer::Models::Video do
|
4
|
+
|
5
|
+
let(:src) { 'http://foo.com/foo.swf' }
|
6
|
+
let(:instance) { described_class.new(src) }
|
7
|
+
|
8
|
+
describe '#to_s' do
|
9
|
+
|
10
|
+
let(:action) { instance.to_s }
|
11
|
+
|
12
|
+
it { expect(action).to eq(src) }
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#as_json' do
|
17
|
+
|
18
|
+
let(:action) { instance.as_json }
|
19
|
+
let(:id) { 1 }
|
20
|
+
let(:size) { [1, 1] }
|
21
|
+
let(:duration) { 10 }
|
22
|
+
let(:provider) { 'foo' }
|
23
|
+
let(:embed_code) { 'bar' }
|
24
|
+
let(:result) {
|
25
|
+
{
|
26
|
+
id: id,
|
27
|
+
src: src,
|
28
|
+
size: size,
|
29
|
+
duration: duration,
|
30
|
+
provider: provider,
|
31
|
+
embed_code: embed_code
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
before do
|
36
|
+
instance.stub(:id).and_return(id)
|
37
|
+
instance.stub(:size).and_return(size)
|
38
|
+
instance.stub(:duration).and_return(duration)
|
39
|
+
instance.stub(:provider).and_return(provider)
|
40
|
+
instance.stub(:embed_code).and_return(embed_code)
|
41
|
+
end
|
42
|
+
|
43
|
+
it { expect(action).to eq(result) }
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
data/spec/scraper_spec.rb
CHANGED
@@ -18,8 +18,7 @@ describe LinkThumbnailer::Scraper do
|
|
18
18
|
let(:prefix_1) { 'prefix_1' }
|
19
19
|
let(:prefix_2) { 'prefix_2' }
|
20
20
|
let(:scraper_class) { double('scraper_class') }
|
21
|
-
let(:
|
22
|
-
let(:not_applicable_scraper) { double(applicable?: false) }
|
21
|
+
let(:scraper) { double('scraper', call: true) }
|
23
22
|
let(:attributes) { [:bar] }
|
24
23
|
let(:scrapers) { [prefix_1, prefix_2] }
|
25
24
|
let(:action) { instance.call }
|
@@ -29,36 +28,10 @@ describe LinkThumbnailer::Scraper do
|
|
29
28
|
instance.stub(:scrapers).and_return(scrapers)
|
30
29
|
end
|
31
30
|
|
32
|
-
context 'when first
|
31
|
+
context 'when first one return a result' do
|
33
32
|
|
34
|
-
|
35
|
-
|
36
|
-
expect(applicable_scraper).to receive(:call).with(website, 'bar')
|
37
|
-
expect(scraper_class).to receive(:new).with(document).and_return(applicable_scraper)
|
38
|
-
expect(instance).to receive(:scraper_class).with(prefix_1, :bar).and_return(scraper_class)
|
39
|
-
end
|
40
|
-
|
41
|
-
it { expect(action).to eq(website) }
|
42
|
-
|
43
|
-
end
|
44
|
-
|
45
|
-
context 'when first scraper applicable' do
|
46
|
-
|
47
|
-
before do
|
48
|
-
expect(website).to receive(:bar).and_return('bar')
|
49
|
-
expect(not_applicable_scraper).to_not receive(:call).with(website, 'bar')
|
50
|
-
expect(scraper_class).to receive(:new).with(document).and_return(not_applicable_scraper)
|
51
|
-
expect(instance).to receive(:scraper_class).with(prefix_1, :bar).and_return(scraper_class)
|
52
|
-
end
|
53
|
-
|
54
|
-
it { expect(action).to eq(website) }
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
|
-
context 'when all scrapers applicable and first one return a result' do
|
59
|
-
|
60
|
-
let(:valid_scraper) { double('scraper', applicable?: true) }
|
61
|
-
let(:not_valid_scraper) { double('scraper', applicable?: true) }
|
33
|
+
let(:valid_scraper) { double('scraper') }
|
34
|
+
let(:not_valid_scraper) { double('scraper') }
|
62
35
|
|
63
36
|
before do
|
64
37
|
expect(website).to receive(:bar).once.and_return('bar')
|
@@ -72,10 +45,10 @@ describe LinkThumbnailer::Scraper do
|
|
72
45
|
|
73
46
|
end
|
74
47
|
|
75
|
-
context 'when
|
48
|
+
context 'when first one does not return any result' do
|
76
49
|
|
77
|
-
let(:valid_scraper) { double('scraper'
|
78
|
-
let(:not_valid_scraper) { double('scraper'
|
50
|
+
let(:valid_scraper) { double('scraper') }
|
51
|
+
let(:not_valid_scraper) { double('scraper') }
|
79
52
|
|
80
53
|
before do
|
81
54
|
expect(website).to receive(:bar).and_return('', 'bar')
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LinkThumbnailer::VideoParser do
|
4
|
+
|
5
|
+
let(:src) { 'http://foo.com/foo.swf' }
|
6
|
+
let(:video) { double(src: src) }
|
7
|
+
let(:parser) { double('parser') }
|
8
|
+
let(:instance) { described_class.new(video) }
|
9
|
+
|
10
|
+
before do
|
11
|
+
instance.stub(:parser).and_return(parser)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#id' do
|
15
|
+
|
16
|
+
let(:action) { instance.id }
|
17
|
+
|
18
|
+
context 'when respond to video_id' do
|
19
|
+
|
20
|
+
before do
|
21
|
+
parser.stub(:video_id).and_return(1)
|
22
|
+
end
|
23
|
+
|
24
|
+
it { expect(action).to eq(parser.video_id) }
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when do not respond to video_id' do
|
29
|
+
|
30
|
+
before do
|
31
|
+
parser.stub(:video_id).and_raise(NoMethodError)
|
32
|
+
end
|
33
|
+
|
34
|
+
it { expect(action).to be_nil }
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#size' do
|
41
|
+
|
42
|
+
let(:action) { instance.size }
|
43
|
+
|
44
|
+
context 'when respond to width and height' do
|
45
|
+
|
46
|
+
before do
|
47
|
+
parser.stub(:width).and_return(1)
|
48
|
+
parser.stub(:height).and_return(1)
|
49
|
+
end
|
50
|
+
|
51
|
+
it { expect(action).to eq([parser.width, parser.height]) }
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'when do not respond to width and height' do
|
56
|
+
|
57
|
+
before do
|
58
|
+
parser.stub(:width).and_raise(NoMethodError)
|
59
|
+
parser.stub(:height).and_raise(NoMethodError)
|
60
|
+
end
|
61
|
+
|
62
|
+
it { expect(action).to be_empty }
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#duration' do
|
69
|
+
|
70
|
+
let(:action) { instance.duration }
|
71
|
+
|
72
|
+
context 'when respond to duration' do
|
73
|
+
|
74
|
+
before do
|
75
|
+
parser.stub(:duration).and_return(1)
|
76
|
+
end
|
77
|
+
|
78
|
+
it { expect(action).to eq(parser.duration) }
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'when do not respond to duration' do
|
83
|
+
|
84
|
+
before do
|
85
|
+
parser.stub(:duration).and_raise(NoMethodError)
|
86
|
+
end
|
87
|
+
|
88
|
+
it { expect(action).to be_nil }
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '#provider' do
|
95
|
+
|
96
|
+
let(:action) { instance.provider }
|
97
|
+
|
98
|
+
context 'when respond to provider' do
|
99
|
+
|
100
|
+
before do
|
101
|
+
parser.stub(:provider).and_return(1)
|
102
|
+
end
|
103
|
+
|
104
|
+
it { expect(action).to eq(parser.provider) }
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'when do not respond to provider' do
|
109
|
+
|
110
|
+
before do
|
111
|
+
parser.stub(:provider).and_raise(NoMethodError)
|
112
|
+
end
|
113
|
+
|
114
|
+
it { expect(action).to be_nil }
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
describe '#embed_code' do
|
121
|
+
|
122
|
+
let(:action) { instance.embed_code }
|
123
|
+
|
124
|
+
context 'when respond to embed_code' do
|
125
|
+
|
126
|
+
before do
|
127
|
+
parser.stub(:embed_code).and_return('')
|
128
|
+
end
|
129
|
+
|
130
|
+
it { expect(action).to eq(parser.embed_code) }
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'when do not respond to embed_code' do
|
135
|
+
|
136
|
+
before do
|
137
|
+
parser.stub(:embed_code).and_raise(NoMethodError)
|
138
|
+
end
|
139
|
+
|
140
|
+
it { expect(action).to be_nil }
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: link_thumbnailer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pierre-Louis Gottfrois
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -100,6 +100,20 @@ dependencies:
|
|
100
100
|
- - ~>
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: '1.6'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: video_info
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '2.3'
|
110
|
+
type: :runtime
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ~>
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '2.3'
|
103
117
|
description: Ruby gem generating thumbnail images from a given URL.
|
104
118
|
email:
|
105
119
|
- pierrelouis.gottfrois@gmail.com
|
@@ -137,6 +151,7 @@ files:
|
|
137
151
|
- lib/link_thumbnailer/models/description.rb
|
138
152
|
- lib/link_thumbnailer/models/image.rb
|
139
153
|
- lib/link_thumbnailer/models/title.rb
|
154
|
+
- lib/link_thumbnailer/models/video.rb
|
140
155
|
- lib/link_thumbnailer/models/website.rb
|
141
156
|
- lib/link_thumbnailer/page.rb
|
142
157
|
- lib/link_thumbnailer/parser.rb
|
@@ -148,12 +163,16 @@ files:
|
|
148
163
|
- lib/link_thumbnailer/scrapers/default/description.rb
|
149
164
|
- lib/link_thumbnailer/scrapers/default/images.rb
|
150
165
|
- lib/link_thumbnailer/scrapers/default/title.rb
|
166
|
+
- lib/link_thumbnailer/scrapers/default/videos.rb
|
151
167
|
- lib/link_thumbnailer/scrapers/opengraph/base.rb
|
152
168
|
- lib/link_thumbnailer/scrapers/opengraph/description.rb
|
153
169
|
- lib/link_thumbnailer/scrapers/opengraph/image.rb
|
154
170
|
- lib/link_thumbnailer/scrapers/opengraph/images.rb
|
155
171
|
- lib/link_thumbnailer/scrapers/opengraph/title.rb
|
172
|
+
- lib/link_thumbnailer/scrapers/opengraph/video.rb
|
173
|
+
- lib/link_thumbnailer/scrapers/opengraph/videos.rb
|
156
174
|
- lib/link_thumbnailer/version.rb
|
175
|
+
- lib/link_thumbnailer/video_parser.rb
|
157
176
|
- link_thumbnailer.gemspec
|
158
177
|
- spec/configuration_spec.rb
|
159
178
|
- spec/examples/empty_og_image_example.html
|
@@ -166,6 +185,7 @@ files:
|
|
166
185
|
- spec/fixtures/og_not_valid_example.html
|
167
186
|
- spec/fixtures/og_valid_example.html
|
168
187
|
- spec/fixtures/og_valid_multi_image_example.html
|
188
|
+
- spec/fixtures/og_valid_multi_video_example.html
|
169
189
|
- spec/grader_spec.rb
|
170
190
|
- spec/graders/base_spec.rb
|
171
191
|
- spec/graders/html_attribute_spec.rb
|
@@ -179,6 +199,7 @@ files:
|
|
179
199
|
- spec/models/description_spec.rb
|
180
200
|
- spec/models/image_spec.rb
|
181
201
|
- spec/models/title_spec.rb
|
202
|
+
- spec/models/video_spec.rb
|
182
203
|
- spec/models/website_spec.rb
|
183
204
|
- spec/page_spec.rb
|
184
205
|
- spec/processor_spec.rb
|
@@ -186,6 +207,7 @@ files:
|
|
186
207
|
- spec/scrapers/base_spec.rb
|
187
208
|
- spec/scrapers/opengraph/base_spec.rb
|
188
209
|
- spec/spec_helper.rb
|
210
|
+
- spec/video_parser_spec.rb
|
189
211
|
homepage: https://github.com/gottfrois/link_thumbnailer
|
190
212
|
licenses: []
|
191
213
|
metadata: {}
|
@@ -222,6 +244,7 @@ test_files:
|
|
222
244
|
- spec/fixtures/og_not_valid_example.html
|
223
245
|
- spec/fixtures/og_valid_example.html
|
224
246
|
- spec/fixtures/og_valid_multi_image_example.html
|
247
|
+
- spec/fixtures/og_valid_multi_video_example.html
|
225
248
|
- spec/grader_spec.rb
|
226
249
|
- spec/graders/base_spec.rb
|
227
250
|
- spec/graders/html_attribute_spec.rb
|
@@ -235,6 +258,7 @@ test_files:
|
|
235
258
|
- spec/models/description_spec.rb
|
236
259
|
- spec/models/image_spec.rb
|
237
260
|
- spec/models/title_spec.rb
|
261
|
+
- spec/models/video_spec.rb
|
238
262
|
- spec/models/website_spec.rb
|
239
263
|
- spec/page_spec.rb
|
240
264
|
- spec/processor_spec.rb
|
@@ -242,3 +266,4 @@ test_files:
|
|
242
266
|
- spec/scrapers/base_spec.rb
|
243
267
|
- spec/scrapers/opengraph/base_spec.rb
|
244
268
|
- spec/spec_helper.rb
|
269
|
+
- spec/video_parser_spec.rb
|