FIX: Display Instagram Oneboxes in an iframe (#14789)
We are no longer able to display the image returned by Instagram directly within a Discourse site (either in the composer, or within a cooked post within a topic), so: - Display an image placeholder in the composer preview - A cooked post should use an iframe to display the Instagram 'embed' content
This commit is contained in:
parent
8d73730c44
commit
aec125b617
|
@ -866,6 +866,14 @@ aside.onebox.xkcd .onebox-body img {
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&.image {
|
||||
&:before {
|
||||
opacity: 0.8;
|
||||
content: svg-uri(
|
||||
'<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="grey" d="M464 448H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h416c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48zM112 120c-30.928 0-56 25.072-56 56s25.072 56 56 56 56-25.072 56-56-25.072-56-56-56zM64 384h384V272l-87.515-87.515c-4.686-4.686-12.284-4.686-16.971 0L208 320l-55.515-55.515c-4.686-4.686-12.284-4.686-16.971 0L64 336v48z"></path></svg>'
|
||||
);
|
||||
}
|
||||
}
|
||||
&.video {
|
||||
&:before {
|
||||
opacity: 0.8;
|
||||
|
|
|
@ -1633,7 +1633,7 @@ security:
|
|||
allow_any: false
|
||||
choices: "['*'] + Onebox::Engine.all_iframe_origins"
|
||||
allowed_iframes:
|
||||
default: "https://www.google.com/maps/embed?|https://www.openstreetmap.org/export/embed.html?|https://calendar.google.com/calendar/embed?|https://codepen.io/"
|
||||
default: "https://www.google.com/maps/embed?|https://www.openstreetmap.org/export/embed.html?|https://calendar.google.com/calendar/embed?|https://codepen.io/|https://www.instagram.com"
|
||||
type: list
|
||||
list_type: simple
|
||||
client: true
|
||||
|
|
|
@ -9,22 +9,41 @@ module Onebox
|
|||
|
||||
matches_regexp(/^https?:\/\/(?:www\.)?(?:instagram\.com|instagr\.am)\/?(?:.*)\/(?:p|tv)\/[a-zA-Z\d_-]+/)
|
||||
always_https
|
||||
requires_iframe_origins "https://www.instagram.com"
|
||||
|
||||
def clean_url
|
||||
url.scan(/^https?:\/\/(?:www\.)?(?:instagram\.com|instagr\.am)\/?(?:.*)\/(?:p|tv)\/[a-zA-Z\d_-]+/).flatten.first
|
||||
end
|
||||
|
||||
def data
|
||||
oembed = get_oembed
|
||||
raise "No oEmbed data found. Ensure 'facebook_app_access_token' is valid" if oembed.data.empty?
|
||||
@data ||= begin
|
||||
oembed = get_oembed
|
||||
raise "No oEmbed data found. Ensure 'facebook_app_access_token' is valid" if oembed.data.empty?
|
||||
|
||||
{
|
||||
link: clean_url.gsub("/#{oembed.author_name}/", "/"),
|
||||
title: "@#{oembed.author_name}",
|
||||
image: oembed.thumbnail_url,
|
||||
description: Onebox::Helpers.truncate(oembed.title, 250),
|
||||
}
|
||||
{
|
||||
link: clean_url.gsub("/#{oembed.author_name}/", "/") + '/embed',
|
||||
title: "@#{oembed.author_name}",
|
||||
image: oembed.thumbnail_url,
|
||||
image_width: oembed.data[:thumbnail_width],
|
||||
image_height: oembed.data[:thumbnail_height],
|
||||
description: Onebox::Helpers.truncate(oembed.title, 250),
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def placeholder_html
|
||||
::Onebox::Helpers.image_placeholder_html
|
||||
end
|
||||
|
||||
def to_html
|
||||
<<-HTML
|
||||
<iframe
|
||||
src="#{data[:link]}"
|
||||
width="#{data[:image_width]}"
|
||||
height="#{data[:image_height].to_i + 98}"
|
||||
frameborder="0"
|
||||
></iframe>
|
||||
HTML
|
||||
end
|
||||
|
||||
protected
|
||||
|
|
|
@ -234,6 +234,10 @@ module Onebox
|
|||
Addressable::URI.unencode(url)
|
||||
end
|
||||
|
||||
def self.image_placeholder_html
|
||||
"<div class='onebox-placeholder-container'><span class='placeholder-icon image'></span></div>"
|
||||
end
|
||||
|
||||
def self.video_placeholder_html
|
||||
"<div class='onebox-placeholder-container'><span class='placeholder-icon video'></span></div>"
|
||||
end
|
||||
|
|
|
@ -308,7 +308,7 @@ describe Oneboxer do
|
|||
end
|
||||
end
|
||||
|
||||
context 'facebook_app_access_token' do
|
||||
context 'instagram' do
|
||||
it 'providing a token should attempt to use new endpoint' do
|
||||
url = "https://www.instagram.com/p/CHLkBERAiLa"
|
||||
access_token = 'abc123'
|
||||
|
@ -318,7 +318,7 @@ describe Oneboxer do
|
|||
stub_request(:head, url)
|
||||
stub_request(:get, "https://graph.facebook.com/v9.0/instagram_oembed?url=#{url}&access_token=#{access_token}").to_return(body: response("instagram_new"))
|
||||
|
||||
expect(Oneboxer.preview(url, invalidate_oneboxes: true)).not_to include('instagram-description')
|
||||
expect(Oneboxer.preview(url, invalidate_oneboxes: true)).to include('placeholder-icon image')
|
||||
end
|
||||
|
||||
it 'unconfigured token should attempt to use old endpoint' do
|
||||
|
@ -326,7 +326,15 @@ describe Oneboxer do
|
|||
stub_request(:head, url)
|
||||
stub_request(:get, "https://api.instagram.com/oembed/?url=#{url}").to_return(body: response("instagram_old"))
|
||||
|
||||
expect(Oneboxer.preview(url, invalidate_oneboxes: true)).to include('instagram-description')
|
||||
expect(Oneboxer.preview(url, invalidate_oneboxes: true)).to include('placeholder-icon image')
|
||||
end
|
||||
|
||||
it 'renders result using an iframe' do
|
||||
url = "https://www.instagram.com/p/CHLkBERAiLa"
|
||||
stub_request(:head, url)
|
||||
stub_request(:get, "https://api.instagram.com/oembed/?url=#{url}").to_return(body: response("instagram_old"))
|
||||
|
||||
expect(Oneboxer.onebox(url, invalidate_oneboxes: true)).to include('iframe')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -5,22 +5,23 @@ require "rails_helper"
|
|||
describe Onebox::Engine::InstagramOnebox do
|
||||
let(:access_token) { 'abc123' }
|
||||
let(:link) { "https://www.instagram.com/p/CARbvuYDm3Q" }
|
||||
let(:onebox_options) { { allowed_iframe_regexes: Onebox::Engine.origins_to_regexes(["https://www.instagram.com"]) } }
|
||||
|
||||
it 'oneboxes links that include the username' do
|
||||
link_with_profile = 'https://www.instagram.com/bennyblood24/p/CARbvuYDm3Q/'
|
||||
onebox_klass = Onebox::Matcher.new(link_with_profile).oneboxed
|
||||
onebox_klass = Onebox::Matcher.new(link_with_profile, onebox_options).oneboxed
|
||||
expect(onebox_klass.name).to eq(described_class.name)
|
||||
end
|
||||
|
||||
it 'oneboxes photo links' do
|
||||
photo_link = 'https://www.instagram.com/p/CARbvuYDm3Q/'
|
||||
onebox_klass = Onebox::Matcher.new(photo_link).oneboxed
|
||||
onebox_klass = Onebox::Matcher.new(photo_link, onebox_options).oneboxed
|
||||
expect(onebox_klass.name).to eq(described_class.name)
|
||||
end
|
||||
|
||||
it 'oneboxes tv links' do
|
||||
tv_link = "https://www.instagram.com/tv/CIlM7UzMgXO/?hl=en"
|
||||
onebox_klass = Onebox::Matcher.new(tv_link).oneboxed
|
||||
onebox_klass = Onebox::Matcher.new(tv_link, onebox_options).oneboxed
|
||||
expect(onebox_klass.name).to eq(described_class.name)
|
||||
end
|
||||
|
||||
|
@ -28,6 +29,7 @@ describe Onebox::Engine::InstagramOnebox do
|
|||
let(:api_link) { "https://graph.facebook.com/v9.0/instagram_oembed?url=#{link}&access_token=#{access_token}" }
|
||||
|
||||
before do
|
||||
stub_request(:head, link)
|
||||
stub_request(:get, api_link).to_return(status: 200, body: onebox_response("instagram"))
|
||||
stub_request(:get, "https://api.instagram.com/oembed/?url=https://www.instagram.com/p/CARbvuYDm3Q")
|
||||
.to_return(status: 200, body: onebox_response("instagram"))
|
||||
|
@ -39,18 +41,15 @@ describe Onebox::Engine::InstagramOnebox do
|
|||
Onebox.options = @previous_options
|
||||
end
|
||||
|
||||
it "includes title" do
|
||||
onebox = described_class.new(link)
|
||||
html = onebox.to_html
|
||||
|
||||
expect(html).to include('<a href="https://www.instagram.com/p/CARbvuYDm3Q" target="_blank" rel="noopener">@natgeo</a>')
|
||||
it "renders preview with a placeholder" do
|
||||
expect(Oneboxer.preview(link, invalidate_oneboxes: true)).to include('placeholder-icon image')
|
||||
end
|
||||
|
||||
it "includes image" do
|
||||
it "renders html using an iframe" do
|
||||
onebox = described_class.new(link)
|
||||
html = onebox.to_html
|
||||
|
||||
expect(html).to include("https://scontent.cdninstagram.com/v/t51.2885-15/sh0.08/e35/s640x640/97565241_163250548553285_9172168193050746487_n.jpg")
|
||||
expect(html).to include('<iframe')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -59,7 +58,8 @@ describe Onebox::Engine::InstagramOnebox do
|
|||
let(:html) { described_class.new(link).to_html }
|
||||
|
||||
before do
|
||||
stub_request(:get, api_link).to_return(status: 200, body: onebox_response("instagram_old_onebox"))
|
||||
stub_request(:head, link)
|
||||
stub_request(:get, api_link).to_return(status: 200, body: onebox_response("instagram_old"))
|
||||
@previous_options = Onebox.options.to_h
|
||||
Onebox.options = {}
|
||||
end
|
||||
|
@ -68,12 +68,12 @@ describe Onebox::Engine::InstagramOnebox do
|
|||
Onebox.options = @previous_options
|
||||
end
|
||||
|
||||
it "includes title" do
|
||||
expect(html).to include('<a href="https://www.instagram.com/p/CARbvuYDm3Q" target="_blank" rel="noopener">@natgeo</a>')
|
||||
it "renders preview with a placeholder" do
|
||||
expect(Oneboxer.preview(link, invalidate_oneboxes: true)).to include('placeholder-icon image')
|
||||
end
|
||||
|
||||
it "includes image" do
|
||||
expect(html).to include("https://scontent-yyz1-1.cdninstagram.com/v/t51.2885-15/sh0.08/e35/s640x640/97565241_163250548553285_9172168193050746487_n.jpg")
|
||||
it "renders html using an iframe" do
|
||||
expect(html).to include('<iframe')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue