mirror of
https://github.com/zulip/zulip.git
synced 2025-11-20 22:48:16 +00:00
bugdown: Add preview for vimeo videos.
This also amends a commit from Brock Whittaker <brock@zulipchat.com> that merges two separate functions for YouTube videos and Vimeo videos into a generic video recall function. Fixes #7550.
This commit is contained in:
committed by
showell
parent
9fe284b442
commit
b0fb7aa6b2
@@ -53,19 +53,28 @@ function display_image(payload, options) {
|
||||
$(".image-actions .open, .image-actions .download").attr("href", payload.source);
|
||||
}
|
||||
|
||||
function display_youtube_video(payload) {
|
||||
function display_video(payload) {
|
||||
render_lightbox_list_images(payload.preview);
|
||||
|
||||
$("#lightbox_overlay .image-preview, .image-description, .download, .lightbox-canvas-trigger").hide();
|
||||
|
||||
var source;
|
||||
if (payload.type === "youtube-video") {
|
||||
source = "https://www.youtube.com/embed/" + payload.source;
|
||||
} else if (payload.type === "vimeo-video") {
|
||||
source = "https://player.vimeo.com/video/" + payload.source;
|
||||
}
|
||||
|
||||
var iframe = $("<iframe></iframe>", {
|
||||
src: "https://www.youtube.com/embed/" + payload.source,
|
||||
src: source,
|
||||
frameborder: 0,
|
||||
allowfullscreen: true,
|
||||
});
|
||||
|
||||
$("#lightbox_overlay .player-container").html(iframe).show();
|
||||
$(".image-actions .open").attr("href", "https://youtu.be/" + payload.source);
|
||||
|
||||
var url = (payload.type === "youtube-video" ? "https://youtu.be/" : "https://vimeo.com/") + payload.source;
|
||||
$(".image-actions .open").attr("href", url);
|
||||
}
|
||||
|
||||
// the image param is optional, but required on the first preview of an image.
|
||||
@@ -84,6 +93,7 @@ exports.open = function (image, options) {
|
||||
// if wrapped in the .youtube-video class, it will be length = 1, and therefore
|
||||
// cast to true.
|
||||
var is_youtube_video = !!$image.closest(".youtube-video").length;
|
||||
var is_vimeo_video = !!$image.closest(".vimeo-video").length;
|
||||
|
||||
var payload;
|
||||
// if the asset_map already contains the metadata required to display the
|
||||
@@ -94,20 +104,32 @@ exports.open = function (image, options) {
|
||||
} else {
|
||||
var $parent = $image.parent();
|
||||
var $message = $parent.closest("[zid]");
|
||||
var $type;
|
||||
var $source;
|
||||
if (is_youtube_video) {
|
||||
$type = "youtube-video";
|
||||
$source = $parent.attr("data-id");
|
||||
} else if (is_vimeo_video) {
|
||||
$type = "vimeo-video";
|
||||
$source = $parent.attr("data-id");
|
||||
} else {
|
||||
$type = "image";
|
||||
$source = $image.attr("src");
|
||||
}
|
||||
|
||||
payload = {
|
||||
user: message_store.get($message.attr("zid")).sender_full_name,
|
||||
title: $image.parent().attr("title"),
|
||||
type: is_youtube_video ? "youtube-video" : "image",
|
||||
type: $type,
|
||||
preview: $image.attr("src"),
|
||||
source: is_youtube_video ? $parent.attr("data-id") : $image.attr("src"),
|
||||
source: $source,
|
||||
};
|
||||
|
||||
asset_map[payload.preview] = payload;
|
||||
}
|
||||
|
||||
if (payload.type === "youtube-video") {
|
||||
display_youtube_video(payload);
|
||||
if (payload.type.match("-video")) {
|
||||
display_video(payload);
|
||||
} else if (payload.type === "image") {
|
||||
display_image(payload, options);
|
||||
}
|
||||
|
||||
@@ -253,13 +253,31 @@ def add_embed(root: Element, link: Text, extracted_data: Dict[Text, Any]) -> Non
|
||||
a.set("target", "_blank")
|
||||
a.set("title", title)
|
||||
a.text = title
|
||||
|
||||
description = extracted_data.get('description')
|
||||
if description:
|
||||
description_elm = markdown.util.etree.SubElement(data_container, "div")
|
||||
description_elm.set("class", "message_embed_description")
|
||||
description_elm.text = description
|
||||
|
||||
def add_vimeo_preview(root: Element, link: Text, extracted_data: Dict[Text, Any], vm_id: Text) -> None:
|
||||
container = markdown.util.etree.SubElement(root, "div")
|
||||
container.set("class", "vimeo-video message_inline_image")
|
||||
|
||||
img_link = extracted_data.get('image')
|
||||
if img_link:
|
||||
parsed_img_link = urllib.parse.urlparse(img_link)
|
||||
# Append domain where relative img_link url is given
|
||||
if not parsed_img_link.netloc:
|
||||
parsed_url = urllib.parse.urlparse(link)
|
||||
domain = '{url.scheme}://{url.netloc}/'.format(url=parsed_url)
|
||||
img_link = urllib.parse.urljoin(domain, img_link)
|
||||
anchor = markdown.util.etree.SubElement(container, "a")
|
||||
anchor.set("href", link)
|
||||
anchor.set("target", "_blank")
|
||||
anchor.set("data-id", vm_id)
|
||||
anchor.set("title", link)
|
||||
img = markdown.util.etree.SubElement(anchor, "img")
|
||||
img.set("src", img_link)
|
||||
|
||||
@cache_with_key(lambda tweet_id: tweet_id, cache_name="database", with_statsd_key="tweet_data")
|
||||
def fetch_tweet_data(tweet_id: Text) -> Optional[Dict[Text, Any]]:
|
||||
@@ -327,13 +345,11 @@ def fetch_open_graph_image(url: Text) -> Optional[Dict[str, Any]]:
|
||||
# a closing tag if it has not been closed yet.
|
||||
last_closed = True
|
||||
head = []
|
||||
|
||||
# TODO: What if response content is huge? Should we get headers first?
|
||||
try:
|
||||
content = requests.get(url, timeout=1).text
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
# Extract the head and meta tags
|
||||
# All meta tags are self closing, have no children or are closed
|
||||
# automatically.
|
||||
@@ -529,6 +545,27 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||
return "https://i.ytimg.com/vi/%s/default.jpg" % (yt_id,)
|
||||
return None
|
||||
|
||||
def vimeo_id(self, url: Text) -> Optional[Text]:
|
||||
if not image_preview_enabled_for_realm():
|
||||
return None
|
||||
#(http|https)?:\/\/(www\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|)(\d+)(?:|\/\?)
|
||||
# If it matches, match.group('id') is the video id.
|
||||
|
||||
vimeo_re = r'^((http|https)?:\/\/(www\.)?vimeo.com\/' + \
|
||||
r'(?:channels\/(?:\w+\/)?|groups\/' + \
|
||||
r'([^\/]*)\/videos\/|)(\d+)(?:|\/\?))$'
|
||||
match = re.match(vimeo_re, url)
|
||||
if match is None:
|
||||
return None
|
||||
return match.group(5)
|
||||
|
||||
def vimeo_image(self, url: Text) -> Optional[Text]:
|
||||
vm_id = self.vimeo_id(url)
|
||||
|
||||
if vm_id is not None:
|
||||
return "http://i.vimeocdn.com/video/%s.jpg" % (vm_id,)
|
||||
return None
|
||||
|
||||
def twitter_text(self, text: Text,
|
||||
urls: List[Dict[Text, Text]],
|
||||
user_mentions: List[Dict[Text, Any]],
|
||||
@@ -841,8 +878,14 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||
except NotFoundInCache:
|
||||
current_message.links_for_preview.add(url)
|
||||
continue
|
||||
vimeo = self.vimeo_image(url)
|
||||
if extracted_data:
|
||||
add_embed(root, url, extracted_data)
|
||||
if vimeo is not None:
|
||||
vm_id = self.vimeo_id(url)
|
||||
add_vimeo_preview(root, url, extracted_data, vm_id)
|
||||
continue
|
||||
else:
|
||||
add_embed(root, url, extracted_data)
|
||||
|
||||
|
||||
class Avatar(markdown.inlinepatterns.Pattern):
|
||||
|
||||
@@ -290,6 +290,17 @@ class BugdownTest(ZulipTestCase):
|
||||
|
||||
self.assertEqual(converted, '<p><a href="http://www.youtube.com/watch?v=hx1mjT73xYE" target="_blank" title="http://www.youtube.com/watch?v=hx1mjT73xYE">http://www.youtube.com/watch?v=hx1mjT73xYE</a></p>\n<div class="youtube-video message_inline_image"><a data-id="hx1mjT73xYE" href="http://www.youtube.com/watch?v=hx1mjT73xYE" target="_blank" title="http://www.youtube.com/watch?v=hx1mjT73xYE"><img src="https://i.ytimg.com/vi/hx1mjT73xYE/default.jpg"></a></div>')
|
||||
|
||||
def test_inline_vimeo(self) -> None:
|
||||
msg = 'Check out the debate: https://vimeo.com/246979354'
|
||||
converted = bugdown_convert(msg)
|
||||
|
||||
self.assertEqual(converted, '<p>Check out the debate: <a href="https://vimeo.com/246979354" target="_blank" title="https://vimeo.com/246979354">https://vimeo.com/246979354</a></p>')
|
||||
|
||||
msg = 'https://vimeo.com/246979354'
|
||||
converted = bugdown_convert(msg)
|
||||
|
||||
self.assertEqual(converted, '<p><a href="https://vimeo.com/246979354" target="_blank" title="https://vimeo.com/246979354">https://vimeo.com/246979354</a></p>')
|
||||
|
||||
@override_settings(INLINE_IMAGE_PREVIEW=True)
|
||||
def test_inline_image_preview(self) -> None:
|
||||
with_preview = '<p>Test: <a href="http://cdn.wallpapersafari.com/13/6/16eVjx.jpeg" target="_blank" title="http://cdn.wallpapersafari.com/13/6/16eVjx.jpeg">http://cdn.wallpapersafari.com/13/6/16eVjx.jpeg</a></p>\n<div class="message_inline_image"><a href="http://cdn.wallpapersafari.com/13/6/16eVjx.jpeg" target="_blank" title="http://cdn.wallpapersafari.com/13/6/16eVjx.jpeg"><img src="https://external-content.zulipcdn.net/389b5d7148a0cbc7475ed564e1b03ceb476bdacb/687474703a2f2f63646e2e77616c6c70617065727361666172692e636f6d2f31332f362f313665566a782e6a706567"></a></div>'
|
||||
|
||||
Reference in New Issue
Block a user