onebox 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +7 -452
- data/Gemfile +1 -1
- data/README.md +23 -45
- data/lib/onebox.rb +21 -13
- data/lib/onebox/engine.rb +53 -43
- data/lib/onebox/engine/amazon_onebox.rb +34 -7
- data/lib/onebox/engine/classic_google_maps_onebox.rb +37 -0
- data/lib/onebox/engine/github_blob_onebox.rb +27 -7
- data/lib/onebox/engine/github_commit_onebox.rb +8 -15
- data/lib/onebox/engine/github_gist_onebox.rb +10 -10
- data/lib/onebox/engine/github_pullrequest_onebox.rb +7 -15
- data/lib/onebox/engine/google_play_app_onebox.rb +30 -0
- data/lib/onebox/engine/html.rb +10 -1
- data/lib/onebox/engine/image_onebox.rb +13 -0
- data/lib/onebox/engine/stack_exchange_onebox.rb +25 -11
- data/lib/onebox/engine/standard_embed.rb +48 -0
- data/lib/onebox/engine/twitter_status_onebox.rb +100 -0
- data/lib/onebox/engine/whitelisted_generic_onebox.rb +223 -0
- data/lib/onebox/engine/wikipedia_onebox.rb +27 -5
- data/lib/onebox/engine/youtube_onebox.rb +22 -0
- data/lib/onebox/helpers.rb +24 -0
- data/lib/onebox/layout.rb +67 -0
- data/lib/onebox/layout_support.rb +16 -0
- data/lib/onebox/matcher.rb +6 -1
- data/lib/onebox/preview.rb +19 -6
- data/lib/onebox/version.rb +1 -1
- data/lib/onebox/view.rb +7 -12
- data/onebox.gemspec +7 -5
- data/spec/fixtures/amazon.response +1336 -2971
- data/spec/fixtures/githubblob.response +49 -921
- data/spec/fixtures/{android.response → googleplayapp.response} +1 -1
- data/spec/fixtures/stackexchange.response +1 -1889
- data/spec/fixtures/twitterstatus.response +3006 -0
- data/spec/fixtures/youtube-json.response +1 -0
- data/spec/fixtures/youtube.response +1625 -0
- data/spec/lib/onebox/engine/amazon_onebox_spec.rb +5 -20
- data/spec/lib/onebox/engine/classic_google_maps_onebox_spec.rb +28 -0
- data/spec/lib/onebox/engine/github_blob_onebox_spec.rb +6 -15
- data/spec/lib/onebox/engine/github_commit_onebox_spec.rb +14 -22
- data/spec/lib/onebox/engine/github_gist_onebox_spec.rb +6 -14
- data/spec/lib/onebox/engine/github_pullrequest_onebox_spec.rb +14 -26
- data/spec/lib/onebox/engine/google_play_app_onebox_spec.rb +28 -0
- data/spec/lib/onebox/engine/html_spec.rb +4 -6
- data/spec/lib/onebox/engine/json_spec.rb +4 -6
- data/spec/lib/onebox/engine/stack_exchange_onebox_spec.rb +4 -17
- data/spec/lib/onebox/engine/twitter_status_onebox_spec.rb +103 -0
- data/spec/lib/onebox/engine/whitelisted_generic_onebox_spec.rb +51 -0
- data/spec/lib/onebox/engine/wikipedia_onebox_spec.rb +4 -17
- data/spec/lib/onebox/engine/youtube_onebox_spec.rb +17 -0
- data/spec/lib/onebox/engine_spec.rb +35 -32
- data/spec/lib/onebox/layout_spec.rb +77 -0
- data/spec/lib/onebox/matcher_spec.rb +0 -15
- data/spec/lib/onebox/preview_spec.rb +39 -9
- data/spec/lib/onebox_spec.rb +15 -11
- data/spec/spec_helper.rb +60 -4
- data/spec/support/html_spec_helper.rb +2 -1
- data/templates/_layout.mustache +11 -4
- data/templates/amazon.mustache +4 -3
- data/templates/githubblob.mustache +7 -5
- data/templates/githubcommit.mustache +20 -11
- data/templates/githubpullrequest.mustache +19 -12
- data/templates/googleplayapp.mustache +4 -0
- data/templates/stackexchange.mustache +19 -3
- data/templates/twitterstatus.mustache +12 -0
- data/templates/whitelistedgeneric.mustache +5 -0
- data/templates/wikipedia.mustache +4 -3
- metadata +57 -166
- data/lib/onebox/engine/bliptv_onebox.rb +0 -28
- data/lib/onebox/engine/clikthrough_onebox.rb +0 -25
- data/lib/onebox/engine/college_humor_onebox.rb +0 -27
- data/lib/onebox/engine/dailymotion_onebox.rb +0 -28
- data/lib/onebox/engine/dotsub_onebox.rb +0 -27
- data/lib/onebox/engine/example_onebox.rb +0 -24
- data/lib/onebox/engine/flickr_onebox.rb +0 -26
- data/lib/onebox/engine/funny_or_die_onebox.rb +0 -28
- data/lib/onebox/engine/hulu_onebox.rb +0 -29
- data/lib/onebox/engine/imgur_image_onebox.rb +0 -26
- data/lib/onebox/engine/itunes_onebox.rb +0 -28
- data/lib/onebox/engine/kinomap_onebox.rb +0 -27
- data/lib/onebox/engine/nfb_onebox.rb +0 -28
- data/lib/onebox/engine/open_graph.rb +0 -11
- data/lib/onebox/engine/qik_onebox.rb +0 -25
- data/lib/onebox/engine/revision3_onebox.rb +0 -27
- data/lib/onebox/engine/slideshare_onebox.rb +0 -27
- data/lib/onebox/engine/sound_cloud_onebox.rb +0 -27
- data/lib/onebox/engine/spotify_onebox.rb +0 -27
- data/lib/onebox/engine/ted_onebox.rb +0 -28
- data/lib/onebox/engine/twitter_onebox.rb +0 -31
- data/lib/onebox/engine/viddler_onebox.rb +0 -28
- data/lib/onebox/engine/vimeo_onebox.rb +0 -27
- data/lib/onebox/engine/yfrog_onebox.rb +0 -28
- data/spec/fixtures/bliptv.response +0 -724
- data/spec/fixtures/clikthrough.response +0 -1472
- data/spec/fixtures/collegehumor.response +0 -1272
- data/spec/fixtures/dailymotion.response +0 -575
- data/spec/fixtures/dotsub.response +0 -1257
- data/spec/fixtures/example.response +0 -50
- data/spec/fixtures/flickr.response +0 -1292
- data/spec/fixtures/funnyordie.response +0 -2010
- data/spec/fixtures/githubgist.response +0 -468
- data/spec/fixtures/hulu.response +0 -339
- data/spec/fixtures/imguralbum.response +0 -941
- data/spec/fixtures/imgurimage.response +0 -872
- data/spec/fixtures/itunes.response +0 -402
- data/spec/fixtures/kinomap.response +0 -299
- data/spec/fixtures/nfb.response +0 -810
- data/spec/fixtures/opengraph.response +0 -27
- data/spec/fixtures/qik.response +0 -371
- data/spec/fixtures/revision3.response +0 -985
- data/spec/fixtures/rottentomatoesfresh.response +0 -3275
- data/spec/fixtures/rottentomatoesincomplete.response +0 -2313
- data/spec/fixtures/rottentomatoesrotten.response +0 -3549
- data/spec/fixtures/slideshare.response +0 -1745
- data/spec/fixtures/soundcloud.response +0 -1409
- data/spec/fixtures/spotify.response +0 -250
- data/spec/fixtures/ted.response +0 -1341
- data/spec/fixtures/twitter.response +0 -1712
- data/spec/fixtures/viddler.response +0 -442
- data/spec/fixtures/vimeo.response +0 -571
- data/spec/fixtures/yfrog.response +0 -464
- data/spec/lib/onebox/engine/bliptv_onebox_spec.rb +0 -37
- data/spec/lib/onebox/engine/clikthrough_onebox_spec.rb +0 -29
- data/spec/lib/onebox/engine/college_humor_onebox_spec.rb +0 -37
- data/spec/lib/onebox/engine/dailymotion_onebox_spec.rb +0 -39
- data/spec/lib/onebox/engine/dotsub_onebox_spec.rb +0 -39
- data/spec/lib/onebox/engine/example_onebox_spec.rb +0 -21
- data/spec/lib/onebox/engine/flickr_onebox_spec.rb +0 -33
- data/spec/lib/onebox/engine/funny_or_die_onebox_spec.rb +0 -37
- data/spec/lib/onebox/engine/hulu_onebox_spec.rb +0 -37
- data/spec/lib/onebox/engine/imgur_image_onebox_spec.rb +0 -29
- data/spec/lib/onebox/engine/itunes_onebox_spec.rb +0 -29
- data/spec/lib/onebox/engine/kinomap_onebox_spec.rb +0 -37
- data/spec/lib/onebox/engine/nfb_onebox_spec.rb +0 -38
- data/spec/lib/onebox/engine/open_graph_spec.rb +0 -27
- data/spec/lib/onebox/engine/qik_onebox_spec.rb +0 -38
- data/spec/lib/onebox/engine/revision3_onebox_spec.rb +0 -39
- data/spec/lib/onebox/engine/slideshare_onebox_spec.rb +0 -33
- data/spec/lib/onebox/engine/sound_cloud_onebox_spec.rb +0 -39
- data/spec/lib/onebox/engine/spotify_onebox_spec.rb +0 -36
- data/spec/lib/onebox/engine/ted_onebox_spec.rb +0 -33
- data/spec/lib/onebox/engine/twitter_onebox_spec.rb +0 -47
- data/spec/lib/onebox/engine/viddler_onebox_spec.rb +0 -39
- data/spec/lib/onebox/engine/vimeo_onebox_spec.rb +0 -37
- data/spec/lib/onebox/engine/yfrog_onebox_spec.rb +0 -33
- data/spec/lib/onebox/view_spec.rb +0 -16
- data/templates/bliptv.mustache +0 -5
- data/templates/clikthrough.mustache +0 -4
- data/templates/collegehumor.mustache +0 -5
- data/templates/dailymotion.mustache +0 -5
- data/templates/dotsub.mustache +0 -5
- data/templates/example.mustache +0 -2
- data/templates/flickr.mustache +0 -4
- data/templates/funnyordie.mustache +0 -6
- data/templates/githubgist.mustache +0 -3
- data/templates/hulu.mustache +0 -6
- data/templates/imgurimage.mustache +0 -3
- data/templates/itunes.mustache +0 -4
- data/templates/kinomap.mustache +0 -5
- data/templates/nfb.mustache +0 -5
- data/templates/qik.mustache +0 -4
- data/templates/revision3.mustache +0 -5
- data/templates/slideshare.mustache +0 -4
- data/templates/soundcloud.mustache +0 -5
- data/templates/spotify.mustache +0 -4
- data/templates/ted.mustache +0 -5
- data/templates/twitter.mustache +0 -7
- data/templates/viddler.mustache +0 -5
- data/templates/vimeo.mustache +0 -5
- data/templates/yfrog.mustache +0 -4
@@ -2,6 +2,7 @@ module Onebox
|
|
2
2
|
module Engine
|
3
3
|
class GithubCommitOnebox
|
4
4
|
include Engine
|
5
|
+
include LayoutSupport
|
5
6
|
include JSON
|
6
7
|
|
7
8
|
matches do
|
@@ -14,29 +15,21 @@ module Onebox
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def url
|
17
|
-
"https://api.github.com/repos/#{match[:owner]}/#{match[:
|
18
|
+
"https://api.github.com/repos/#{match[:owner]}/#{match[:repository]}/commits/#{match[:sha]}"
|
18
19
|
end
|
19
20
|
|
20
21
|
private
|
21
22
|
|
22
23
|
def match
|
23
|
-
@url.match(
|
24
|
+
@match ||= @url.match(%{github\.com/(?<owner>[^/]+)/(?<repository>[^/]+)/commit/(?<sha>[^/]+)})
|
24
25
|
end
|
25
26
|
|
26
27
|
def data
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
gravatar: raw["author"]["avatar_url"],
|
33
|
-
message: raw["commit"]["message"],
|
34
|
-
author: raw["author"]["login"],
|
35
|
-
time_date: raw["commit"]["committer"]["date"],
|
36
|
-
files_changed: raw["files"].length,
|
37
|
-
additions: raw["stats"]["additions"],
|
38
|
-
deletions: raw["stats"]["deletions"]
|
39
|
-
}
|
28
|
+
result = raw.clone
|
29
|
+
result['link'] = link
|
30
|
+
result['title'] = result['commit']['message']
|
31
|
+
result['commit_date'] = Time.parse(result['commit']['author']['date']).strftime("%I:%M%p - %d %b %y")
|
32
|
+
result
|
40
33
|
end
|
41
34
|
end
|
42
35
|
end
|
@@ -2,7 +2,6 @@ module Onebox
|
|
2
2
|
module Engine
|
3
3
|
class GithubGistOnebox
|
4
4
|
include Engine
|
5
|
-
include JSON
|
6
5
|
|
7
6
|
matches do
|
8
7
|
http
|
@@ -12,22 +11,23 @@ module Onebox
|
|
12
11
|
end
|
13
12
|
|
14
13
|
def url
|
15
|
-
"https://api.github.com/gists/#{match[:
|
14
|
+
"https://api.github.com/gists/#{match[:sha]}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_html
|
18
|
+
"<script src=\"http://gist.github.com/#{match[:sha]}.js\"></script>"
|
16
19
|
end
|
17
20
|
|
18
21
|
private
|
19
22
|
|
20
|
-
def
|
21
|
-
|
23
|
+
def data
|
24
|
+
{ sha: match[:sha], title: match[:sha], link: @url }
|
22
25
|
end
|
23
26
|
|
24
|
-
def
|
25
|
-
{
|
26
|
-
url: @url,
|
27
|
-
content: raw["files"].first[1]["content"],
|
28
|
-
author: raw["user"]["login"]
|
29
|
-
}
|
27
|
+
def match
|
28
|
+
@match ||= @url.match(%r{gist\.github\.com/([^/]+/)?(?<sha>[0-9a-f]+)})
|
30
29
|
end
|
30
|
+
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -2,6 +2,7 @@ module Onebox
|
|
2
2
|
module Engine
|
3
3
|
class GithubPullRequestOnebox
|
4
4
|
include Engine
|
5
|
+
include LayoutSupport
|
5
6
|
include JSON
|
6
7
|
|
7
8
|
matches do
|
@@ -14,29 +15,20 @@ module Onebox
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def url
|
17
|
-
"https://api.github.com/repos/#{match[:owner]}/#{match[:
|
18
|
+
"https://api.github.com/repos/#{match[:owner]}/#{match[:repository]}/pulls/#{match[:number]}"
|
18
19
|
end
|
19
20
|
|
20
21
|
private
|
21
22
|
|
22
23
|
def match
|
23
|
-
@url.match(
|
24
|
+
@match ||= @url.match(%r{github\.com/(?<owner>[^/]+)/(?<repository>[^/]+)/pull/(?<number>[^/]+)})
|
24
25
|
end
|
25
26
|
|
26
27
|
def data
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
title: raw["title"],
|
32
|
-
repo: raw["base"]["repo"]["full_name"],
|
33
|
-
time_date: raw["created_at"],
|
34
|
-
commits: raw["commits"],
|
35
|
-
additions: raw["additions"],
|
36
|
-
deletions: raw["deletions"],
|
37
|
-
changed_files: raw["changed_files"],
|
38
|
-
description: raw["body"]
|
39
|
-
}
|
28
|
+
result = raw.clone
|
29
|
+
result['link'] = link
|
30
|
+
result['created_at'] = Time.parse(result['created_at']).strftime("%I:%M%p - %d %b %y")
|
31
|
+
result
|
40
32
|
end
|
41
33
|
end
|
42
34
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Onebox
|
2
|
+
module Engine
|
3
|
+
class GooglePlayAppOnebox
|
4
|
+
include Engine
|
5
|
+
include LayoutSupport
|
6
|
+
include HTML
|
7
|
+
|
8
|
+
matches do
|
9
|
+
http
|
10
|
+
with("play.")
|
11
|
+
domain("google")
|
12
|
+
tld("com")
|
13
|
+
with("/store/apps/")
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def data
|
19
|
+
{
|
20
|
+
link: link,
|
21
|
+
title: raw.css(".document-title div").inner_text,
|
22
|
+
developer: raw.css(".document-subtitle.primary").inner_text,
|
23
|
+
image: raw.css(".cover-image").first["src"],
|
24
|
+
description: raw.css(".text-body div").inner_text,
|
25
|
+
price: raw.css(".price.buy meta[itemprop=price]").first["content"]
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/onebox/engine/html.rb
CHANGED
@@ -3,8 +3,17 @@ module Onebox
|
|
3
3
|
module HTML
|
4
4
|
private
|
5
5
|
|
6
|
+
# Overwrite for any custom headers
|
7
|
+
def http_params
|
8
|
+
{}
|
9
|
+
end
|
10
|
+
|
6
11
|
def raw
|
7
|
-
@raw ||= Nokogiri::HTML(open(url, read_timeout: timeout))
|
12
|
+
@raw ||= Nokogiri::HTML(open(url, {read_timeout: timeout}.merge(http_params)).read)
|
13
|
+
end
|
14
|
+
|
15
|
+
def html?
|
16
|
+
raw.respond_to(:css)
|
8
17
|
end
|
9
18
|
end
|
10
19
|
end
|
@@ -2,23 +2,37 @@ module Onebox
|
|
2
2
|
module Engine
|
3
3
|
class StackExchangeOnebox
|
4
4
|
include Engine
|
5
|
-
include
|
5
|
+
include LayoutSupport
|
6
|
+
include JSON
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
domain("stackoverflow")
|
10
|
-
tld("com")
|
11
|
-
with("/questions/")
|
8
|
+
def self.domains
|
9
|
+
%w(stackexchange stackoverflow superuser serverfault askubuntu)
|
12
10
|
end
|
13
11
|
|
12
|
+
matches_regexp /^http:\/\/(?:(?:(?<subsubdomain>\w*)\.)?(?<subdomain>\w*)\.)?(?<domain>#{domains.join('|')})\.com\/(?:questions|q)\/(?<question>\d*)/
|
13
|
+
|
14
14
|
private
|
15
15
|
|
16
|
+
def match
|
17
|
+
@match ||= @url.match(@@matcher)
|
18
|
+
end
|
19
|
+
|
20
|
+
def url
|
21
|
+
domain = match[:subsubdomain] || match[:subdomain] || match[:domain]
|
22
|
+
"http://api.stackexchange.com/2.1/questions/#{match[:question]}?site=#{domain}"
|
23
|
+
end
|
24
|
+
|
16
25
|
def data
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
26
|
+
return @data if @data
|
27
|
+
|
28
|
+
result = raw['items'][0]
|
29
|
+
if result
|
30
|
+
result['creation_date'] =
|
31
|
+
Time.at(result['creation_date'].to_i).strftime("%I:%M%p - %d %b %y")
|
32
|
+
|
33
|
+
result['tags'] = result['tags'].take(4).join(', ')
|
34
|
+
end
|
35
|
+
@data = result
|
22
36
|
end
|
23
37
|
end
|
24
38
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Onebox
|
2
|
+
module Engine
|
3
|
+
module StandardEmbed
|
4
|
+
|
5
|
+
def raw
|
6
|
+
return @raw if @raw
|
7
|
+
response = fetch_response(url)
|
8
|
+
|
9
|
+
html_doc = Nokogiri::HTML(response.body)
|
10
|
+
|
11
|
+
# Determine if we should use OEmbed or OpenGraph
|
12
|
+
oembed_alternate = html_doc.at("//link[@type='application/json+oembed']") || html_doc.at("//link[@type='text/json+oembed']")
|
13
|
+
if oembed_alternate
|
14
|
+
# If the oembed request fails, we can still try the opengraph below.
|
15
|
+
begin
|
16
|
+
@raw = Onebox::Helpers.symbolize_keys(::MultiJson.load(fetch_response(oembed_alternate['href']).body))
|
17
|
+
rescue Errno::ECONNREFUSED, Net::HTTPError, MultiJson::LoadError
|
18
|
+
@raw = nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
open_graph = OpenGraph.new(response.body, false)
|
23
|
+
if @raw
|
24
|
+
@raw[:image] = open_graph.images.first if @raw[:image].nil? && open_graph && open_graph.images
|
25
|
+
|
26
|
+
return @raw
|
27
|
+
end
|
28
|
+
|
29
|
+
@raw = open_graph
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def fetch_response(location, limit = 3)
|
35
|
+
raise Net::HTTPError.new('HTTP redirect too deep', location) if limit == 0
|
36
|
+
|
37
|
+
response = Net::HTTP.get_response(URI(location))
|
38
|
+
case response
|
39
|
+
when Net::HTTPSuccess then response
|
40
|
+
when Net::HTTPRedirection then fetch_response(response['location'], limit - 1)
|
41
|
+
else
|
42
|
+
response.error!
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Onebox
|
2
|
+
module Engine
|
3
|
+
class TwitterStatusOnebox
|
4
|
+
include Engine
|
5
|
+
include LayoutSupport
|
6
|
+
include HTML
|
7
|
+
|
8
|
+
matches do
|
9
|
+
http
|
10
|
+
maybe("www.")
|
11
|
+
domain("twitter")
|
12
|
+
tld("com")
|
13
|
+
anything
|
14
|
+
has("/status/")
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def match
|
20
|
+
@match ||= @url.match(%r{twitter\.com/.+?/status/(?<id>\d+)})
|
21
|
+
end
|
22
|
+
|
23
|
+
def client
|
24
|
+
Onebox.options.twitter_client
|
25
|
+
end
|
26
|
+
|
27
|
+
def raw
|
28
|
+
if client
|
29
|
+
@raw ||= OpenStruct.new(client.status(match[:id]).to_hash)
|
30
|
+
else
|
31
|
+
super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def access(*keys)
|
36
|
+
keys.reduce(raw) do |memo, key|
|
37
|
+
memo[key] || memo[key.to_s]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def tweet
|
42
|
+
if raw.html?
|
43
|
+
raw.css(".tweet-text")[0].inner_text
|
44
|
+
else
|
45
|
+
access(:text)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def timestamp
|
50
|
+
if raw.html?
|
51
|
+
raw.css(".metadata span").inner_text
|
52
|
+
else
|
53
|
+
access(:created_at)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def title
|
58
|
+
if raw.html?
|
59
|
+
raw.css(".stream-item-header .username").inner_text
|
60
|
+
else
|
61
|
+
access(:user, :screen_name)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def avatar
|
66
|
+
if raw.html?
|
67
|
+
raw.css(".avatar")[2]["src"]
|
68
|
+
else
|
69
|
+
access(:user, :profile_image_url)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def favorites
|
74
|
+
if raw.html?
|
75
|
+
raw.css(".stats li .request-favorited-popup").inner_text
|
76
|
+
else
|
77
|
+
access(:favorite_count)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def retweets
|
82
|
+
if raw.html?
|
83
|
+
raw.css(".stats li .request-retweeted-popup").inner_text
|
84
|
+
else
|
85
|
+
access(:retweet_count)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def data
|
90
|
+
{ link: link,
|
91
|
+
tweet: tweet,
|
92
|
+
timestamp: timestamp,
|
93
|
+
title: title,
|
94
|
+
avatar: avatar,
|
95
|
+
favorites: favorites,
|
96
|
+
retweets: retweets }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,223 @@
|
|
1
|
+
module Onebox
|
2
|
+
module Engine
|
3
|
+
class WhitelistedGenericOnebox
|
4
|
+
include Engine
|
5
|
+
include StandardEmbed
|
6
|
+
include LayoutSupport
|
7
|
+
|
8
|
+
def self.whitelist=(list)
|
9
|
+
@whitelist = list
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.whitelist
|
13
|
+
@whitelist ||= default_whitelist.dup
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.default_whitelist
|
17
|
+
%w(500px.com
|
18
|
+
about.com
|
19
|
+
answers.com
|
20
|
+
ask.com
|
21
|
+
battle.net
|
22
|
+
bbc.co.uk
|
23
|
+
bbs.boingboing.net
|
24
|
+
bestbuy.ca
|
25
|
+
bestbuy.com
|
26
|
+
blip.tv
|
27
|
+
bloomberg.com
|
28
|
+
businessinsider.com
|
29
|
+
clikthrough.com
|
30
|
+
cnet.com
|
31
|
+
cnn.com
|
32
|
+
collegehumor.com
|
33
|
+
coursera.org
|
34
|
+
cracked.com
|
35
|
+
dailymail.co.uk
|
36
|
+
dailymotion.com
|
37
|
+
deadline.com
|
38
|
+
dell.com
|
39
|
+
digg.com
|
40
|
+
dotsub.com
|
41
|
+
ebay.ca
|
42
|
+
ebay.co.uk
|
43
|
+
ebay.com
|
44
|
+
ehow.com
|
45
|
+
espn.go.com
|
46
|
+
etsy.com
|
47
|
+
findery.com
|
48
|
+
flickr.com
|
49
|
+
forbes.com
|
50
|
+
foxnews.com
|
51
|
+
funnyordie.com
|
52
|
+
groupon.com
|
53
|
+
howtogeek.com
|
54
|
+
huffingtonpost.com
|
55
|
+
huffingtonpost.ca
|
56
|
+
hulu.com
|
57
|
+
ign.com
|
58
|
+
ikea.com
|
59
|
+
imgur.com
|
60
|
+
indiatimes.com
|
61
|
+
instagr.am
|
62
|
+
instagram.com
|
63
|
+
itunes.apple.com
|
64
|
+
khanacademy.org
|
65
|
+
kickstarter.com
|
66
|
+
kinomap.com
|
67
|
+
mashable.com
|
68
|
+
mlb.com
|
69
|
+
myspace.com
|
70
|
+
nba.com
|
71
|
+
npr.org
|
72
|
+
photobucket.com
|
73
|
+
pinterest.com
|
74
|
+
reference.com
|
75
|
+
revision3.com
|
76
|
+
rottentomatoes.com
|
77
|
+
samsung.com
|
78
|
+
screenr.com
|
79
|
+
scribd.com
|
80
|
+
slideshare.net
|
81
|
+
soundcloud.com
|
82
|
+
sourceforge.net
|
83
|
+
spotify.com
|
84
|
+
squidoo.com
|
85
|
+
techcrunch.com
|
86
|
+
ted.com
|
87
|
+
thefreedictionary.com
|
88
|
+
theglobeandmail.com
|
89
|
+
theonion.com
|
90
|
+
thestar.com
|
91
|
+
thesun.co.uk
|
92
|
+
thinkgeek.com
|
93
|
+
tmz.com
|
94
|
+
torontosun.com
|
95
|
+
tumblr.com
|
96
|
+
twitpic.com
|
97
|
+
usatoday.com
|
98
|
+
vimeo.com
|
99
|
+
walmart.com
|
100
|
+
washingtonpost.com
|
101
|
+
wikia.com
|
102
|
+
wikihow.com
|
103
|
+
wired.com
|
104
|
+
wistia.com
|
105
|
+
wi.st
|
106
|
+
wonderhowto.com
|
107
|
+
wsj.com
|
108
|
+
zappos.com
|
109
|
+
zillow.com)
|
110
|
+
end
|
111
|
+
|
112
|
+
# A re-written URL coverts https:// -> // - it is useful on HTTPS sites that embed
|
113
|
+
# youtube for example
|
114
|
+
def self.rewrites
|
115
|
+
@rewrites ||= default_rewrites.dup
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.rewrites=(new_list)
|
119
|
+
@rewrites = new_list
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.default_rewrites
|
123
|
+
%w()
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.host_matches(uri, list)
|
127
|
+
!!list.find {|h| %r((^|\.)#{Regexp.escape(h)}$).match(uri.host) }
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.===(other)
|
131
|
+
if other.kind_of?(URI)
|
132
|
+
return WhitelistedGenericOnebox.host_matches(other, WhitelistedGenericOnebox.whitelist)
|
133
|
+
else
|
134
|
+
super
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Generates the HTML for the embedded content
|
139
|
+
def photo_type?
|
140
|
+
data[:type] =~ /photo/ || data[:type] =~ /image/
|
141
|
+
end
|
142
|
+
|
143
|
+
def rewrite_agnostic(html)
|
144
|
+
return html unless html
|
145
|
+
uri = URI(@url)
|
146
|
+
if WhitelistedGenericOnebox.host_matches(uri, WhitelistedGenericOnebox.rewrites)
|
147
|
+
html.gsub!(/https?:\/\//, '//')
|
148
|
+
end
|
149
|
+
html
|
150
|
+
end
|
151
|
+
|
152
|
+
def generic_html
|
153
|
+
return data[:html] if data[:html]
|
154
|
+
return html_for_video(data[:video]) if data[:video]
|
155
|
+
return image_html if photo_type?
|
156
|
+
return nil unless data[:title]
|
157
|
+
layout.to_html
|
158
|
+
end
|
159
|
+
|
160
|
+
def to_html
|
161
|
+
rewrite_agnostic(generic_html)
|
162
|
+
end
|
163
|
+
|
164
|
+
def placeholder_html
|
165
|
+
result = nil
|
166
|
+
result = image_html if data[:html] || data[:video] || photo_type?
|
167
|
+
result || to_html
|
168
|
+
end
|
169
|
+
|
170
|
+
def data
|
171
|
+
return raw if raw.is_a?(Hash)
|
172
|
+
|
173
|
+
data_hash = { link: link, title: raw.title, description: raw.description }
|
174
|
+
data_hash[:image] = raw.images.first if raw.images && raw.images.first
|
175
|
+
data_hash[:type] = raw.type if raw.type
|
176
|
+
|
177
|
+
if raw.metadata && raw.metadata[:video] && raw.metadata[:video].first
|
178
|
+
data_hash[:video] = raw.metadata[:video].first
|
179
|
+
end
|
180
|
+
|
181
|
+
data_hash
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
def image_html
|
187
|
+
return @image_html if @image_html
|
188
|
+
|
189
|
+
return @image_html = "<img src=\"#{data[:image]}\">" if data[:image]
|
190
|
+
|
191
|
+
if data[:thumbnail_url]
|
192
|
+
@image_html = "<img src=\"#{data[:thumbnail_url]}\""
|
193
|
+
@image_html << " width=\"#{data[:thumbnail_width]}\"" if data[:thumbnail_width]
|
194
|
+
@image_html << " height=\"#{data[:thumbnail_height]}\"" if data[:thumbnail_height]
|
195
|
+
@image_html << ">"
|
196
|
+
end
|
197
|
+
|
198
|
+
@image_html
|
199
|
+
end
|
200
|
+
|
201
|
+
def html_for_video(video)
|
202
|
+
video_url = video[:_value]
|
203
|
+
|
204
|
+
if video_url
|
205
|
+
html = "<iframe src=\"#{video_url}\" frameborder=\"0\" title=\"#{data[:title]}\""
|
206
|
+
|
207
|
+
append_attribute(:width, html, video)
|
208
|
+
append_attribute(:height, html, video)
|
209
|
+
|
210
|
+
html << "></iframe>"
|
211
|
+
return html
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def append_attribute(attribute, html, video)
|
216
|
+
if video[attribute] && video[attribute].first
|
217
|
+
val = video[attribute].first[:_value]
|
218
|
+
html << " #{attribute.to_s}=\"#{val}\""
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|